CVE-2022-50530CVE-2022-50530是Linux内核块设备多队列(blk-mq)子系统中存在的一个空指针解引用漏洞。该漏洞由syzkaller模糊测试工具发现,存在于blk_mq_clear_rq_mapping()函数中。问题的根本原因在于提交63064be150e4("blk-mq: Add blk_mq_alloc_map_and_rqs()")将原本分两步完成的标签分配操作合并为一步后,未充分处理内存分配失败(OOM)的情况。具体而言,当blk_mq_alloc_rqs()因内存不足而失败时,set->tags[hctx_idx]仍然为NULL指针,随后在blk_mq_free_rqs()的错误处理路径中调用blk_mq_clear_rq_mapping()时,会对NULL指针进行解引用操作,从而触发内核崩溃。该漏洞的CVSS评分为5.5,属于中危级别,攻击者需要本地低权限访问权限即可触发,无需用户交互。漏洞主要影响系统的可用性,可能导致内核panic或系统拒绝服务。虽然不需要特殊权限即可触发,但需要能够加载块设备或触发块设备分配操作,因此实际利用门槛相对较高。此漏洞已在Linux内核稳定版本中通过在blk_mq_clear_rq_mapping()函数中添加NULL指针检查进行修复。
该漏洞的技术原理涉及Linux内核blk-mq子系统的标签分配机制。在原始实现中,标签分配分为两个独立步骤:首先调用blk_mq_alloc_rq_map()分配标签映射并将其赋值给set->tags[hctx_idx],然后调用blk_mq_alloc_rqs()分配请求队列。如果第二步失败,set->tags[hctx_idx]已经包含有效的标签映射指针,错误处理路径可以正常工作。
然而,在提交63064be150e4引入blk_mq_alloc_map_and_rqs()函数后,这两个步骤被合并为一个原子操作。当blk_mq_alloc_map_and_rqs()内部调用blk_mq_alloc_rqs()失败时(例如由于alloc_pages_node()因OOM失败),函数返回NULL给set->tags[hctx_idx],但错误处理路径blk_mq_free_rqs()仍然尝试通过set->tags[hctx_idx]获取drv_tags指针并调用blk_mq_clear_rq_mapping(drv_tags, ...),此时drv_tags为NULL,导致空指针解引用。
利用方式方面,攻击者可以通过以下方式触发该漏洞:1)在内存压力较大的环境下加载块设备驱动或创建块设备队列;2)通过cgroup或其他机制人为制造内存分配失败条件;3)触发__blk_mq_alloc_map_and_rqs()的调用路径。触发后,内核会因空指针解引用而崩溃(kernel panic),导致系统拒绝服务。由于该漏洞位于内核态,攻击者只需本地普通用户权限即可触发,但需要能够触发块设备分配操作的环境。