CVE-2026-31533Linux内核net/tls模块在 tls_do_encryption 函数的 -EBUSY 错误处理路径中存在一个严重的释放后重用漏洞。该漏洞由双重清理操作引起,具体涉及 encrypt_pending 和 scatterlist 条目。当加密请求因设备繁忙返回 -EBUSY 时,请求被排队,异步回调 tls_encrypt_done 会处理后续清理。然而,若 tls_encrypt_async_wait 返回错误,同步错误路径会重复执行相同的清理逻辑。这种双重递减会破坏 encrypt_pending 哨兵值,导致异步等待被永久跳过。随后的 sendmsg 操作可能在加密回调仍在待处理时释放 tls_rec,从而触发释放后重用,攻击者可利用此漏洞执行任意代码或导致内核崩溃。
该漏洞的核心在于Linux内核TLS子系统处理异步加密请求时的竞态条件和状态管理错误。漏洞触发点位于 tls_do_encryption 函数。当 crypto_aead_encrypt 返回 -EBUSY 时,内核将请求加入 cryptd 积压队列,并依赖 tls_encrypt_done 回调在完成时恢复 scatterlist 并递减 ctx->encrypt_pending。问题在于,如果 tls_encrypt_async_wait() 发生错误,代码会进入同步错误路径,此时错误地认为需要手动清理,于是再次恢复 scatterlist 并递减 encrypt_pending。由于 encrypt_pending 初始为1,双重递减使其变为非预期值。一旦 encrypt_pending 被破坏,后续调用 tls_encrypt_async_wait 时会错误地认为没有待处理的异步操作,从而直接跳过等待。此时,如果应用程序调用 sendmsg,内核会通过 bpf_exec_tx_verdict() 释放 tls_rec 内存。然而,之前积压的加密请求的回调 tls_encrypt_done 可能随后在另一个上下文中被触发,尝试访问已被释放的 tls_rec,导致内核内存破坏。利用此漏洞需要通过特定的网络数据包发送时序来触发竞态条件,进而实现本地提权或拒绝服务攻击。