android缺陷分析:内核空指针

高通Android 7.1平台出现内核崩溃,log如下:

(红色是关键信息)

[ 65.862388] msm_isp_get_buf: bug mgr open cnt = 0

[ 65.871767] Unable to handle kernel NULL pointer dereference at virtual address 00000000

[ 65.879833] pgd = ffffffc02718f000

[ 65.883217] [00000000] *pgd=0000000000000000

[ 66.148672] , *pud=0000000000000000

[ 66.152318] Internal error: Oops: 96000005 [#1] PREEMPT SMP

[ 66.157870] Modules linked in: wlan(O) streamax_jiami(O)

[ 66.163169] CPU: 0 PID: 3450 Comm: AVStreamManager Tainted: G W O 3.18.31 #9

[ 66.171063] Hardware name: Qualcomm Technologies, Inc. MSM8953 QRD NOPMI SKU3 (DT)

[ 66.178618] task: ffffffc012672940 ti: ffffffc027188000 task.ti: ffffffc027188000

[ 66.186092]PC is at msm_isp_cfg_ping_pong_address+0x240/0x5fc

[ 66.191898] LR is at msm_isp_cfg_ping_pong_address+0x214/0x5fc

[ 66.197714]pc : [(ffffffc00088ebb0>] lr : [(ffffffc00088eb84>] pstate: 000001c5

[ 66.205093] sp : ffffffc02718b9f0

[ 66.208391] x29: ffffffc02718b9f0 x28: ffffffc067765098

[ 66.213686] x27: ffffffc067760000 x26: 0000000000000003

[ 66.230003] x25: 0000000000000003 x24: ffffffc067764ec8

[ 66.235299] x23: ffffffc067764648 x22: 0000000001000300

[ 66.240595] x21: 0000000000000000 x20: 0000000000000000

[ 66.245890] x19: ffffffc067764ec8 x18: 0000000000000000

[ 66.251185] x17: 0000000000000000 x16: ffffffc0002021a0

[ 66.256481] x15: 0000000000000000 x14: 0ffffffffffffffe

[ 66.261775] x13: 0000000000000038 x12: 0101010101010101

[ 66.267071] x11: 7f7f7f7f7f7f7f7f x10: 5e6f72685e6c726c

[ 66.272364] x9 : 7f7f7f7f7f7f7f7f x8 : 6e63206e65706f20

[ 66.277660] x7 : 72676d2067756220 x6 : ffffffc001b027cc

[ 66.282955] x5 : 0000000000000000 x4 : 0000000000000000

[ 66.288251] x3 : 0000000000000000 x2 : cb88537fdc8cb01f

[ 66.293546] x1 : cb88537fdc8cb01f x0 : 0000000000000001

[ 66.298844]

[ 66.298844] PC: 0xffffffc00088eab0:

[ 66.303789] eab0 b9414800 34000160 7100109f 54000128 f9400760 d2804314 f9401801 2a1903e0

[ 66.705352]

[ 66.706829]Process Stream (pid: 3450, stack limit = 0xffffffc027188058)

[ 66.714293] Call trace:

[66.716728][(ffffffc00088ebb0>] msm_isp_cfg_ping_pong_address+0x240/0x5fc

[66.723583][(ffffffc00088f034>] msm_isp_init_stream_ping_pong_reg+0xc8/0x138

[ 66.730700] [(ffffffc000890670>] msm_isp_cfg_axi_stream+0x37c/0xdfc

[ 66.736954] [(ffffffc00088ac64>] msm_isp_ioctl+0x520/0xc08

[ 66.742424] [(ffffffc0008a2a74>] msm_isp_subdev_do_ioctl+0xf0/0xfc

[ 66.748585] [(ffffffc0007e30c8>] video_usercopy+0x2d4/0x574

问题分析

1、反编译内核

aarch64-linux-android-objdump -S -l -z vmlinux > vmlinux.txt

aarch64-linux-android-objdump:prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-objdump

vmlinux是带符号表的kernel:out/target/product/msm8953_64/obj/KERNEL_OBJ/vmlinux。需要在内核config加入: CONFIG_DEBUG_INFO=y CONFIG_DEBUG_INFO_REDUCED=y。

2、在vmlinux.txt中找到PC地址对应的代码行

/home3/liutao2/8953_MG/SLM758C_AIBOX2/8953_MG/kernel/msm-3.18/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c:1726

         return buf;

 

if (buf->num_planes != stream_info->num_planes) {

ffffffc00088ebac:    39403260    ldrb    w0, [x19,#12]

ffffffc00088ebb0:    b9400281    ldr    w1, [x20]

ffffffc00088ebb4:    6b00003f    cmp    w1, w0

ffffffc00088ebb8:    54ffff20    b.eq    ffffffc00088eb9c (msm_isp_cfg_ping_pong_address+0x22c>

 

问题点在文件msm_isp_axi_util.c的1726行代码

if (buf->num_planes != stream_info->num_planes) {

在vmlinux.txt查找函数msm_isp_cfg_ping_pong_address的PC地址:

ffffffc00088e970 (msm_isp_cfg_ping_pong_address>:

msm_isp_cfg_ping_pong_address():

/home3/liutao2/8953_MG/SLM758C_AIBOX2/8953_MG/kernel/msm-3.18/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c:1815

 

msm_isp_cfg_ping_pong_address的PC地址是ffffffc00088e970,msm_isp_cfg_ping_pong_address+0x240 =ffffffc00088ebb0

3、代码分析

函数msm_isp_cfg_ping_pong_address代码段:

rc = vfe_dev->buf_mgr->ops->get_buf(vfe_dev->buf_mgr,
vfe_dev->pdev->id, bufq_handle, buf_index,&buf);
 
if (rc == -EFAULT) {
    msm_isp_halt_send_error(vfe_dev, ISP_EVENT_BUF_FATAL_ERROR);
    return buf;
}
 
if (rc < 0)
    return buf;
 
if (buf->num_planes != stream_info->num_planes) {
    pr_err("%s: Invalid buffer\n", __func__);
    vfe_dev->buf_mgr->ops->put_buf(vfe_dev->buf_mgr,
    bufq_handle, buf->buf_idx);
    buf = NULL;
}

从问题行if (buf->num_planes != stream_info->num_planes)判断buf或者stream_info为NULL,阅读代码逻辑后stream_info不会是NULL。rc >= 0时,走到问题代码行。

再看get_buf函数:

static int msm_isp_get_buf(struct msm_isp_buf_mgr *buf_mgr, uint32_t id,
uint32_t bufq_handle, uint32_t buf_index,
 
struct msm_isp_buffer **buf_info)
 
{
    ......
    // open_count == 0,返回0
    if (buf_mgr->open_count == 0) {
        pr_err_ratelimited("%s: bug mgr open cnt = 0\n",
            __func__);
        return 0;
    }
    ......
    // buf != NULL,返回0
    if (!(*buf_info)) {
        rc = -ENOMEM;
    } else {
        (*buf_info)->state = MSM_ISP_BUFFER_STATE_DEQUEUED;
        rc = 0;
    }
}

问题出现在open_count == 0,再看内核日志,有bug mgr open cnt = 0的log。确认了获取的buf是NULL。

解决方法

if (buf_mgr->open_count == 0) {
    pr_err_ratelimited("%s: bug mgr open cnt = 0\n", __func__);
-    return 0;
+   return rc;
}

 

你可能感兴趣的:(Android)