CVE-2022-50552CVE-2022-50552是Linux内核块设备多队列(blk-mq)子系统中的一个高危竞争条件漏洞。该漏洞位于内核块I/O调度器的elevator切换逻辑中,当重新初始化硬件队列时,hctx(硬件上下文)的run_work可能与elevator切换操作产生竞争。问题在于,在重新初始化硬件队列的上下文中,队列仅被冻结(frozen),冻结机制仅阻止新的请求分配,但无法阻止hctx工作队列的继续运行。正在运行的hctx工作可能获取到正在被销毁的elevator指针,从而导致释放后重用(Use-After-Free)错误和内核崩溃(kernel panic)。该漏洞的CVSS评分为7.8,属于高危级别,攻击向量为本地攻击,需要低权限即可触发,无需用户交互。该漏洞影响机密性、完整性和可用性三个方面,均为高影响。漏洞在NVMe控制器重置等场景下容易被触发,崩溃日志显示在kyber_has_work函数中发生NULL指针解引用,调用栈涉及__blk_mq_do_dispatch_sched、__blk_mq_sched_dispatch_requests等调度相关函数。该漏洞已在多个Linux内核稳定版本中修复,修复方案是使用quiesced elevator switch替代原有的切换逻辑,并将原函数设为static以限制其作用域。
该漏洞的核心技术原理在于blk-mq子系统中elevator(I/O调度器)的切换机制与hctx run_work之间的竞争条件。
**漏洞原理:**
1. 在Linux内核blk-mq框架中,每个硬件队列(hctx)都有一个关联的工作队列(run_work),用于异步处理请求调度。
2. 当系统需要重新初始化硬件队列时(例如NVMe控制器重置),会执行elevator切换操作。
3. 原始代码在切换elevator时仅冻结(freeze)队列,冻结操作通过percpu_ref机制阻止新的请求分配,但不会停止已经在运行中的hctx工作。
4. hctx的run_work可能正在执行调度操作,此时它通过elevator指针访问调度器数据结构和回调函数。
5. 如果在run_work执行期间elevator被切换并释放,run_work将访问已被释放的内存,导致Use-After-Free。
6. 实际崩溃表现为NULL指针解引用,发生在kyber_has_work函数中(偏移量0x29/0x70),因为elevator指针或其内部数据已被置空。
**利用方式:**
攻击者可以通过以下方式触发该漏洞:
1. 本地拥有低权限用户访问权限(PR:L)。
2. 触发NVMe控制器重置操作(例如通过热插拔、设备错误处理、或sysfs接口)。
3. 在elevator切换和hctx run_work执行之间制造竞争窗口。
4. 当竞争条件触发时,内核将发生panic,导致系统拒绝服务(DoS)。
5. 在某些场景下,攻击者可能利用Use-After-Free实现权限提升。
**修复方案:**
使用quiesced elevator switch(静态化的elevator_switch函数)替代原有的elevator_switch实现,确保在切换elevator时完全静默(quiesce)所有hctx的工作,避免竞争条件的发生。