• 疑似CPU或者内存故障导致进程崩溃


    我们有一个服务跑在微软云的所有宿主机上。最近发现某一台机器上该服务进程持续崩溃。
    崩溃原因是访问了一个无效指针,对应的代码如下


    serviceListIniBuffer.AppendF("ServerList=%s ",
                                                   m_newServiceList.config->GetStringParameter("Manifest", "ServerList", "").c_str());

    从dump和live repo中发现,无效指针的来自AppendF函数的第一个参数。
    但奇怪的,该参数是一个写死的字符串,这怎么会发生呢?

    看汇编代码

    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 "????????????????????????????????"

    果然,rdx就是无效啊。

    仔细看一下前面的汇编,比如在调用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:Appgetandrunservices.ap_10_09_10_8_5003_2510GetAndRunServices.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读取流水线遇上某二进制规律的时候触发数据损坏。

    这就是我目前的推断。下周和有经验的工程师聊一下看看这样分析对不对。以前也遇上过疑似硬件问题导致的崩溃,但今天是第一次现场抓住!
    如果你有类似经历或者经验,请指点和分享。

  • 相关阅读:
    Azure Application Gateway (6) 使用OpenSSL创建SAN证书
    MySQL常用函数整理,建议收藏!
    设计一个接口至少要考虑这14点!
    SpringBoot 常用读取配置文件的 3 种方法!
    MyBatisPlus常用功能总结!(附项目示例)
    接口测试神器Apifox,亲测好用!
    huey在windows下使用的坑
    sublimeCodeIntel在windows下安装的坑
    字符串生成二维码
    android中EditText有光标不弹出软键盘处理(转)
  • 原文地址:https://www.cnblogs.com/lixiong/p/7818247.html
Copyright © 2020-2023  润新知