咱們有一個服務跑在微軟雲的全部宿主機上。最近發現某一臺機器上該服務進程持續崩潰。
崩潰緣由是訪問了一個無效指針,對應的代碼以下函數
serviceListIniBuffer.AppendF("ServerList=%s\r\n",
m_newServiceList.config->GetStringParameter("Manifest", "ServerList", "").c_str());this
從dump和live repo中發現,無效指針的來自AppendF函數的第一個參數。
但奇怪的,該參數是一個寫死的字符串,這怎麼會發生呢?spa
看彙編代碼debug
00007ff6`36961907 4889442420 mov qword ptr [rsp+20h],rax
00007ff6`3696190c 4c8d0d45270b00 lea r9,[GetAndRunServices!`string'+0xfd8 (00007ff6`36a14058)]
00007ff6`36961913 4c8d054e270b00 lea r8,[GetAndRunServices!`string'+0xfe8 (00007ff6`36a14068)]
00007ff6`3696191a 488d5500 lea rdx,[rbp]
00007ff6`3696191e 488b8f98030000 mov rcx,qword ptr [rdi+398h]
00007ff6`36961925 e8f649f3ff call GetAndRunServices!apsdk::configuration::IConfiguration::GetStringParameter (00007ff6`36896320)
00007ff6`3696192a 90 nop
00007ff6`3696192b 4883781810 cmp qword ptr [rax+18h],10h
00007ff6`36961930 7203 jb GetAndRunServices!GetAndRunServices2::GenerateOMNewServiceListFile+0x9e5 (00007ff6`36961935)
00007ff6`36961932 488b00 mov rax,qword ptr [rax]
00007ff6`36961935 4c8bc0 mov r8,rax
00007ff6`36961938 488d1541270b01 lea rdx,[00007ff6`37a14080]
00007ff6`3696193f 488d4d20 lea rcx,[rbp+20h]
>>>>>>>>>>>>>>>>>>>>00007ff6`36961943 e8981ef3ff call GetAndRunServices!apsdk::DynStringT<127>::AppendF (00007ff6`368937e0)指針
具體的崩潰發生在AppendF裏面。但問題是無效指針致使的,和被調函數AppendF無關。爲了省略篇幅就略過AppendF部分了。進程
這裏能夠看到,rcx應該保存的是serviceListIniBuffer的this指針。由於C默認從右向左壓參數,因此rdx對應的應該是第一個參數,r8對應的應該是第二個參數。內存
0:000> da r8
00000001`0a3a48c0 "25.66.164.187:25.66.164.4:25.66."
00000001`0a3a48e0 "164.251:25.66.165.4"字符串
0:000> da rdx
00007ff6`37a14080 "????????????????????????????????"get
果真,rdx就是無效啊。string
仔細看一下前面的彙編,好比在調用GetStringParameter的時候,也會用到寫死的字符串。好比下面兩句就是
00007ff6`3696190c 4c8d0d45270b00 lea r9,[GetAndRunServices!`string'+0xfd8 (00007ff6`36a14058)]
00007ff6`36961913 4c8d054e270b00 lea r8,[GetAndRunServices!`string'+0xfe8 (00007ff6`36a14068)]
能夠看到,這些字符串都是從GetAndRunServices!`string'這個全局表裏面讀入的。 這兩個地址也都準確落入了執行文件的地址範圍:
0:000> lmf
start end module name
00007ff6`36880000 00007ff6`36bda000 GetAndRunServices C:\App\getandrunservices.ap_10_09_10_8_5003_2510\GetAndRunServices.exe
而出問題的地址是00007ff6`37a14080,的確也在執行文件地址範圍外。
但仔細看一下,00007ff6`37a14080這個地址和合法區間比較,只有一個bit不同:
00007ff6`3[7]a14080 00007ff6`3[6]a14080
這裏7和6在二進制上面就差了末尾的bit。 若是我手動換一成6看看呢:
0:000> da 00007ff6`36a14080
00007ff6`36a14080 "ServerList=%s.."
果真就和源代碼match了。
這個迷如何解釋呢?首先可能的是這個執行文件有損害。可是如今執行文件默認都有完整性和簽名保護,可能性不大。把文件拷貝出來和其它沒有問題的文件比,的確也如出一轍。
還多是病毒?可是雲上的宿主機器都是絕對隔離的。從live debug過程當中看,沒見到用戶態有什麼注入。
剩下的緣由是硬件問題。內存或者CPU讀取流水線趕上某二進制規律的時候觸發數據損壞。
這就是我目前的推斷。下週和有經驗的工程師聊一下看看這樣分析對不對。之前也趕上過疑似硬件問題致使的崩潰,但今天是第一次現場抓住!
若是你有相似經歷或者經驗,請指點和分享。