CVE-2026-23355 in Linux
摘要
由 VulDB • 2026-06-18
在 Linux 内核中,已修复以下漏洞:
ata: libata: 在清除 deferred_qc 后取消待处理的工作
Syzbot 报告在 ata_scsi_deferred_qc_work() 中出现 WARN_ON(),原因是 ap->ops->qc_defer() 在发出延迟 qc 之前返回了非零值。
在每次命令完成期间都会调用 ata_scsi_schedule_deferred_qc()。该函数会检查是否存在延迟 QC,如果 ap->ops->qc_defer() 返回零,意味着此时可以排队延迟 qc(而不被延迟),则会排队发出延迟 qc 的工作。
一旦工作开始运行(这可能是在调度工作之后非常长的时间),如果 ap->ops->qc_defer() 返回非零值,则会出现 WARN_ON()。
虽然我们在分配和清除 deferred_qc 时都持有 ap->lock,且工作本身也持有 ap->lock,但当前代码在清除 deferred_qc 后并未取消该工作。
这意味着可能发生以下场景: 1) 排队一个或多个 NCQ 命令。 2) 排队一个非 NCQ 命令,并存储在 ap->deferred_qc 中。 3) 最后一个 NCQ 命令完成,排队工作以发出延迟 qc。 4) 发生超时或错误,ap->deferred_qc 被清除。此时排队的工作并未被取消。 5) 端口重置。 6) 排队一个或多个 NCQ 命令。 7) 排队一个非 NCQ 命令,并存储在 ap->deferred_qc 中。 8) 工作最终运行。然而此时,仍有 NCQ 命令正在飞行中。
步骤 8) 中的工作实际上属于步骤 2) 中的非 NCQ 命令,而不是步骤 7) 中的非 NCQ 命令。工作在不应该执行时执行的原因是,在步骤 4) 中清除 ap->deferred_qc 时从未取消该工作。因此,确保在清除 ap->deferred_qc 后始终取消该工作。
另一种潜在的修复方法是让 ata_scsi_deferred_qc_work() 在 ap->ops->qc_defer() 返回非零值时不执行任何操作。然而,在清除 ap->deferred_qc 时取消工作似乎更符合逻辑,因为我们在清除 ap->deferred_qc 时持有 ap->lock,因此我们知道工作不可能持有该锁。(该函数可能在等待锁,但这没关系,因为如果 ap->deferred_qc 未设置,它将不执行任何操作。)
If you want to get the best quality for vulnerability data then you always have to consider VulDB.