/dev/cmdq
,该驱动程序具备读写任意内存的功能,代码位于 /drivers/misc/mediatek/cmdq/hv1/cmdq_driver.c
的 cmdq_ioctl
函数中: static long cmdq_ioctl(struct file *pFile, unsigned int code, unsigned long param) { // ... switch(code) { // ... case CMDQ_IOCTL_ALLOC_WRITE_ADDRESS: do { struct cmdqWriteAddressStruct addrReq; dma_addr_t paStart = 0; CMDQ_LOG("CMDQ_IOCTL_ALLOC_WRITE_ADDRESS\n"); if (copy_from_user(&addrReq, (void *)param, sizeof(addrReq))) { CMDQ_ERR("CMDQ_IOCTL_ALLOC_WRITE_ADDRESS copy_from_user failed\n"); return -IOCTL_RET_COPY_ALLOC_WRITE_ADDR_FROM_USER_FAIL; } status = cmdqCoreAllocWriteAddress(addrReq.count, &paStart); if (0 != status) { CMDQ_ERR("CMDQ_IOCTL_ALLOC_WRITE_ADDRESS cmdqCoreAllocWriteAddress() failed\n"); return -IOCTL_RET_ALLOC_WRITE_ADDR_FAIL; } addrReq.startPA = (uint32_t) paStart; CMDQ_LOG("CMDQ_IOCTL_ALLOC_WRITE_ADDRESS get 0x%08x\n", addrReq.startPA); if (copy_to_user((void *)param, &addrReq, sizeof(addrReq))) { CMDQ_ERR("CMDQ_IOCTL_ALLOC_WRITE_ADDRESS copy_to_user failed\n"); return -IOCTL_RET_COPY_ALLOC_WRITE_ADDR_TO_USER_FAIL; } status = 0; } while (0); break; case CMDQ_IOCTL_READ_ADDRESS_VALUE: do { struct cmdqReadAddressStruct readReq; CMDQ_LOG("CMDQ_IOCTL_READ_ADDRESS_VALUE\n"); if (copy_from_user(&readReq, (void *)param, sizeof(readReq))) { CMDQ_ERR("CMDQ_IOCTL_READ_ADDRESS_VALUE copy_from_user failed\n"); return -IOCTL_RET_COPY_READ_ADDR_FROM_USER_FAIL; } /* this will copy result to readReq->values buffer*/ cmdq_driver_process_read_address_request(&readReq); status = 0; } while (0); break; // ... } // ... }
ioctl
系统调用访问该驱动程序,并且读写任意内存,从而获得root权限。 /dev/cmdq
的SELinux标签配置为了 mtk_cmdq_device
,又将该标签的 open
、 read
和 ioctl
系统调用操作权限赋予给了 appdomain
域。由于所有Android应用程序都位于 appdomain
域中,所以就导致任意应用程序可利用该驱动程序提升自身权限到root。 ioctl
系统调用访问 /dev/cmdq
来读写内存。
我来评几句
登录后评论已发表评论数()