Android缺陷分析:cnss-daemo进程崩溃

高通Android 7.1遇到cnss-daemo进程崩溃,分析过程如下:

Log信息:(红色是关键信息)
pid: 6577, tid: 6577, name: cnss-daemon  >>> /system/bin/cnss-daemon <<<
signal 6 (SIGABRT) , code -6 (SI_TKILL), fault addr --------
    x0   0000000000000000  x1   00000000000019b1  x2   0000000000000006  x3   0000000000000008
x4   000000000000006e  x5   0000000000800000  x6   0000007fb7736000  x7   0000000000000000
......
backtrace:
    #00 pc 000000000006b790  /system/lib64/libc.so (tgkill+8)
    #01 pc 0000000000068c14  /system/lib64/libc.so (pthread_kill+64)
    #02 pc 0000000000024180  /system/lib64/libc.so (raise+24)
    #03 pc 000000000001cbec  /system/lib64/libc.so (abort+52)
    #04 pc 0000000000002a4c  /system/bin/cnss-daemon
    #05 pc 00000000000004dc  [vdso:0000007fb7737000]
    #06 pc 0000000000002730  /system/bin/cnss-daemon
    #07 pc 0000000000002058  /system/bin/cnss-daemon
    #08 pc 000000000001a7d8  /system/lib64/libc.so (__libc_init+88)
    #09 pc 0000000000001e40  /system/bin/cnss-daemon

问题分析:

1、addr2line找问题代码行:
   addr2line -e cnss-daemon -f (pc地址)
执行命令
prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-addr2line -e out/target/product/msm8953_64_box3/obj/EXECUTABLES/cnss-daemon_intermediates/PACKED/cnss-daemon -f 0000000000002a4c
    wsvc_debug_init
/proc/self/cwd/vendor/qcom/proprietary/wlan/cnss-daemon/debug.c:139
定位代码在文件debug.c,函数wsvc_debug_init的139行。

debug.c文件

static void wsvc_debug_sigsegv_handler(int signum)
{
    wsvc_printf_err("SIGSEGV Crashed! %d\n", signum);
     abort();  // 139行
    return;
}

cnss-daemon截取了signal,看不到真正崩溃的位置,拿掉signal截取部分,复现问题,获取tombstone。
tombstone片段:
Fatal signal 11 (SIGSEGV), code 1,
      fault addr 0x8015912764 in tid 19936 (cnss-daemon)
继续使用addr2line找崩溃的代码行。
    nl_loop_process_msg

vendor/qcom/proprietary/wlan/cnss-daemon/nl_loop.c:261

                                                                (图:修改前后对比差异)

2、代码分析

崩溃在函数NLMSG_OK:
宏NLMSG_OK(nlh,len)用于判断消息是否有len这么长。

#define NLMSG_OK(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))
#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
#define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(sizeof(struct nlmsghdr)))

从函数NLMSG_OK 判断nlh指向非法内存地址,nlh从NLMSG_NEXT取到。宏NLMSG_NEXT(nlh,len)用于得到下一个消息的首地址,同时len也减少为剩余消息的总长度。

#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
 (struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))

当len<=(nlh)->nlmsg_len,获取nlh指向非法地址。

3、解决方法

获取nlh前比较len和nlh->nlmsg_len。

if (u_len <= NLMSG_ALIGN(nlh->nlmsg_len)) {
    wsvc_printf_err("%s: no enough message, len: %u, nlmsg_len: %u",
        __func__,
        u_len, nlh->nlmsg_len);
    break;
}
 
nlh = NLMSG_NEXT(nlh, u_len);

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值