現網環境出現了crash,原因是"general protection fault: 0000 [#1] ",也就是說訪問了異常位址導致。
檢視異常呼叫棧。
//...省略部分
#6 [ffff88041fd43830] general_protection at ffffffff8168ef68
[exception rip: put_page+10]
rip: ffffffff8118edaa rsp: ffff88041fd438e8 rflags: 00010202
rax: 0000000000000040 rbx: 0000000000000002 rcx: 0000000000000010
rdx: ffffea000a758960 rsi: ffff88041fd5a0a8 rdi: 2f302009302f3020
rbp: ffff88041fd438f0 r8: ffffea000a758960 r9: ffff88041fb78980
r10: 00000000000000cc r11: 000000000000004e r12: ffff8800775db4c0
r13: ffff88020cf2c900 r14: ffff8800775db46a r15: ffff8800775db44e
orig_rax: ffffffffffffffff cs: 0010 ss: 0018
#7 [ffff88041fd438f8] skb_release_data at ffffffff8155ea0f
#8 [ffff88041fd43920] skb_release_all at ffffffff8155eae4
#9 [ffff88041fd43938] consume_skb at ffffffff8155efdc
#10 [ffff88041fd43958] __dev_kfree_skb_any at ffffffff8156ee5d
#11 [ffff88041fd43980] tm_wanrx at ffffffffa03374d8 [testmod]
//...省略部分
crash> dis -r put_page+10
0xffffffff8118edb0 : data32 data32 data32 xchg %ax,%ax [ftrace nop]
0xffffffff8118edb5 : push %rbp
0xffffffff8118edb6 : mov %rsp,%rbp
0xffffffff8118edb9 : push %rbx
0xffffffff8118edba : testq $0xc000,(%rdi) //訪問page
在skb_release_data處理中將skb指標儲存在暫存器$13中,且put_page並未對其改動,所以我們可以指導skb指標位址為 r13: ffff88020cf2c900。
crash> sk_buff ffff88020cf2c900
struct sk_buff \364\f\220\036
進而得到 skb_shared_info的內容 skb->head + skb->end = 0xffff8800775db400 + c0 = 0xffff8800775db4c0。
crash> skb_shared_info 0xffff8800775db4c0
struct skb_shared_info ,
syststamp =
}, ip6_frag_id = 0,
dataref =
, destructor_arg = 0x945424f52502009,
frags =
, page_offset = 140,
size = 1350
}, ,
page_offset = 807405872,
size = 808398895
},//...
}
可以看到是在釋放frags[1]的page時出現異常的。
skb->data_len = 0表示沒有分片,所以skb_shared_info的nr_frags = 102 是異常值。
由於 skb_shared_info是緊跟在資料buffer的end之後,懷疑是修改資料buffer時異常將buffer之後的內容也修改了。
檢視業務**邏輯,我們在 tm_wanrx 處理中會對payload進行解密操作,使用的是aes對稱解密,blocksize是16位元組。
但是payload的長度是76位元組,由於業務處理邏輯不嚴謹,導致會解密16 * 5 = 80位元組,也就是tail之後多操作了4個位元組。
//錯誤邏輯會導致將skb->tail之後的位元組也當作密文解密了
for(i =
0; i < skb->len; i +
=crypto_cipher_blocksize
(tfm)
)
skb->tail=190 , skb->end = 192,也就是說會把end之後2個位元組寫壞。剛好是 nr_frags和tx_flags,然後在釋放skb時,因為nr_frags不為0,依次釋放page時,導致異常。
crash> rd 0xffff8800775db472 16 //檢視payload內容
ffff8800775db472: 3403a58d819d566b 050a63aafa6fb6e1 kv..
...4..o..c..
ffff8800775db482: bdcf9439980168d5 8d64ed8067bebebd .h..9..
....g..d.
ffff8800775db492: 27cecee77191c13f e7d5fb356007b55c ?..q...'\..`5...
ffff8800775db4a2: 7d31b864d0a64319 7858d97b1e900cf4 .c..d.1}
....
{.xx
ffff8800775db4b2: fad7522b284cd211 de66b565321f9356 ..l(+r..v..2e.f. //66是nr_frags de是tx_flags
ffff8800775db4c2: 0000000000000000 0000000000000000 ..
....
....
....
..ffff8800775db4d2: 0000000000000000 0000000000000000 ..
....
....
....
..crash> rd 0xffff8800775db4c0 -8 //skb_shared_info開始
ffff8800775db4c0: 66 //nr_frags
crash> rd 0xffff8800775db4c1 -8
ffff8800775db4c1: de //tx_flags .
觸發問題的場景找到了,但是有個小問題。正常情況下對端加密後payload應該是16位元組的整數倍,然後這邊正常解密。什麼情況導致payload長度錯誤呢?
檢視系統log發現,在crash前有個配置變更,將報文傳輸方式由不加密修改為加密。配置是發向連線的兩端裝置,但是存在時間差,在這時收到了對端發來的不加密報文,被當作加密報文處理了,從而導致了該問題的發生。
使用密碼解密TACACS 的報文
本測試是在裝置登入的時候,抓取的tacacs資訊。裝置的ip為10.8.8.150,tacacs server的ip為10.1.1.200,如下是登陸裝置的過程。username adminuser password 這裡輸入了錯誤的密碼ccisco 123 authentication faile...
分析 crash 報告的方法
從這裡只能初步判斷是因為訪問了空的記憶體。但是具體的就不知道了。因為下面的程序呼叫都是堆疊資訊,在網上找了很久終於找到了解決的辦法。分析crash報告 2 下面我們需要 找到 symbolicatecrash developer platforms iphoneos.platform develop...
分析 crash 報告的方法
從這裡只能初步判斷是因為訪問了空的記憶體。但是具體的就不知道了。因為下面的程序呼叫都是堆疊資訊,在網上找了很久終於找到了解決的辦法。分析crash報告 2 下面我們需要 找到 symbolicatecrash developer platforms iphoneos.platform develop...