flawopen.com/Teardowns/cve-2024-26585-linux-tls-tx-work-close-race
●
CVE-2024-26585 · CVSS 4.7 · 中危
安全研究 · FlawOpen
CVE-2024-26585:Linux TLS 关闭竞态
Linux kTLS 的完成回调可能先唤醒 sendmsg/recvmsg,再排入 TX 工作。补丁调整顺序,先调度工作。
💡 通俗易懂的原理解析 (ELI5)
一名工人先告诉等待的同事“完成了”,却还没把最后一项任务放进共享队列。同事可能趁此关店并取消队列中的任务,工人随后才补入任务。内核补丁先排入 TLS 发送工作,再发出完成信号。
核心概念与专有名词
kTLS- Linux 内核中的 TLS 功能,在内核网络路径中处理 TLS 记录。
异步加密完成- TLS 异步加密操作结束后运行的回调。
`complete()`- Linux completion 原语,用于唤醒等待操作结束的线程。
延迟 TX 工作- 排入内核队列、在加密完成后继续发送 TLS 记录的工作项。
框架映射
- 本指南所述弱点的 CWE 参考: CWE-362
根本原因剖析 (Root Cause)
在 net/tls/tls_sw.c 中,tls_encrypt_done() 可能先对等待中的 sendmsg()/recvmsg() 线程调用 complete(),再为队首记录调度延迟 TX 工作。被唤醒的线程可能返回并关闭 socket,而回调仍准备排入该工作,因此 socket 关闭与 TX 工作调度会发生竞态。上游提交 e01e3934a1b2 调整顺序:若记录位于 ctx->tx_list 队首,就先调度 ctx->tx_work,再调用 complete()。CVE 公告描述的是竞态;引用来源并未证实先前关于 MSG_ZEROCOPY、网络页释放、内存覆盖或 refcount_inc_not_zero() 修复的说法。
攻击执行流程分解
步骤 1
1. TLS 发送开始
进程使用 kTLS 发送路径,记录加密可能异步完成。
步骤 2
2. 回调检查顺序
tls_encrypt_done() 检查已完成的记录是否位于 ctx->tx_list 队首。
步骤 3
3. 唤醒与关闭发生竞态
补丁前,回调可能先通过 complete() 唤醒线程,之后才排入 TX 工作;线程可能在间隙中关闭 socket。
步骤 4
4. 补丁调整交接顺序
修复先排入延迟 TX 工作,再发出完成信号,避免线程在调度完成前继续执行。
源代码对比:漏洞与安全实现
存在漏洞的实现
// e01e3934a1b2 之前 net/tls/tls_sw.c 中的相关顺序
bool ready = false;
if (rec == first_rec)
ready = true;
if (atomic_dec_and_test(&ctx->encrypt_pending))
complete(&ctx->async_wait.completion);
if (!ready)
return;
if (!test_and_set_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask))
schedule_delayed_work(&ctx->tx_work.work, 1);
加固后的安全修复
// e01e3934a1b2 之后 net/tls/tls_sw.c 中的相关顺序
if (rec == first_rec) {
// 先将发送工作加入队列,再唤醒提交该工作的线程。
if (!test_and_set_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask))
schedule_delayed_work(&ctx->tx_work.work, 1);
}
if (atomic_dec_and_test(&ctx->encrypt_pending))
complete(&ctx->async_wait.completion);
工程与系统安全加固清单
- ✓更新到包含
CVE-2024-26585回移补丁的受支持发行版内核;稳定分支常回移修复,应核对发行版公告。 - ✓审查异步回调时,如果被唤醒的线程可能关闭共享对象,应先排入后续工作,再发出完成信号。
- ✓关闭时同步取消或排空回调工作,确保取消点之后回调无法再排入新工作。
- ✓添加受控并发回归测试,让 TLS 异步完成与 socket 关闭竞争,并验证工作调度顺序。
- ✓不要把
MSG_ZEROCOPY或硬件加密视为此 CVE 的前提;上游说明的是异步加密完成和 TX 工作调度。