CVE-2022-50554CVE-2022-50554是Linux内核块设备多队列(blk-mq)子系统中的一个高危竞态条件漏洞。该漏洞由David Jeffery发现,主要影响虚拟机使用场景。当虚拟机退出延迟过长、vCPU线程的抢占延迟过长或vCPU线程发生长时间页面错误时,块IO请求可能在调用blk_mq_start_request()之后但在请求实际排队到硬件之前就被超时处理。超时处理程序可能通过重新入队(requeue)来处理该请求,从而导致对->queue_rq()的重复调用,最终引发内核崩溃(kernel panic)。该漏洞的根本原因在于超时处理和请求完成之间的竞态条件,虽然理论上应由驱动程序负责处理该竞态,但由于这是一个非常普遍的问题,许多驱动程序都可能存在类似缺陷,且在驱动程序层面修复并不容易。因此,社区选择在blk-mq层面通过排空(draining)正在进行的->queue_rq()来解决此问题。CVSS评分为5.5,属于中危级别,攻击者需要本地低权限访问即可触发该漏洞,导致系统可用性完全丧失。
该漏洞的技术原理涉及Linux内核blk-mq子系统中超时处理与请求排队之间的竞态条件。具体来说,在->queue_rq()回调函数执行过程中,驱动程序会调用blk_mq_start_request()来标记请求已开始,但此时请求尚未实际提交到硬件。在虚拟机环境中,由于vmexit延迟、vCPU线程抢占延迟或长时间页面错误等原因,请求可能在blk_mq_start_request()调用之后但在硬件排队之前就达到超时阈值。超时处理程序随后会处理该请求并尝试重新入队(requeue),这导致对同一个请求的->queue_rq()被调用两次,产生双重队列请求。第二次调用可能导致内核数据结构不一致,最终触发内核崩溃。修复方案是在blk-mq层面实现排空机制,确保在处理超时之前等待正在进行的->queue_rq()调用完成,从而避免竞态条件。该漏洞的触发需要满足以下条件:1)系统运行在虚拟化环境中;2)存在导致vCPU线程长时间阻塞的因素(如长vmexit、抢占延迟、页面错误等);3)块IO请求的正常处理时间超过超时阈值。