CVE-2026-98260 内核 UAF 提权复现
松杨网络安全资料库
2026年10月29日 17:27
广东
去阅读
内核里有个很常见的分工:一个对象负责\"记账\",另一个对象负责\"占位\",两边各自维护自己的生命周期,靠引用计数或者锁对齐。只要有一边提前放手,另一边手里的指针就变成了没人认领的地址。
CVE-2026-98260 就是这种错位。POSIX CPU 定时器把节点挂在线程的 timerqueue 上,同时又把定时器对象挂在进程的链表里。两条链各有各的释放路径,而 exec() 在中间插了一脚,把线程 ID 换掉了。换完之后再失败退出,清理函数按旧 ID 找不到线程,链没摘、对象却释放了。
本文记录Ubuntu 26.04(内核 7.0.0-27-generic)上的完整复现:从普通用户 luo 起手,在没有 sudo 的前提下拿到 root shell。
一、漏洞背景
| 项 | 内容 |
|---|---|
| 编号 | CVE-2026-98260 |
| 类型 | 释放后使用(CWE-416),本地提权 |
| 位置 | fs/exec.c 的 begin_new_exec() 与 kernel/time/posix-cpu-timers.c 的清理逻辑 |
| 引入提交 | 55e8c8eb2c7b |
| 修复提交 | acb03d3881818581052924a9bbbe92b8741ed448 (exec: Cleanup POSIX timers right after de_thread()) |
| 修复版本 | 6.6.158 / 6.12.112 / 6.18.54 / 7.2.8 / 7.3 及以后 |
| 评分 | CVSS v3.1 = 7.8(CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H) |
| 利用前提 | 能在目标上以低权限用户执行本地代码,且内核在受影响区间 |
| 公开利用 | 上游 PoC 仓库 V4bel/InfinityCore 的 timer 分支 |
受影响范围按主线分支切分:5.7 引入之后、低于上表修复版本的内核都算在内。厂商分支是否回移补丁,需要单独看各自的安全公告。
二、漏洞原理
根子在引用的对象不对等:timer_create(CLOCK_THREAD_CPUTIME_ID) 只把目标线程的struct pid存进cpu_timer,没有持有task_struct,所以de_thread()交换 TID 并回收旧 leader 之后,这条线索就断了。而 POSIX timer 的清理被排在unshare_files()、exec_mmap()、exec_task_namespaces()之后,此时bprm->point_of_no_return已置位,任何一步失败都直接进入退出路径,清理被整体跳过。
退出时posix_cpu_timer_del()拿旧 PID 查不到 task,disarm_timer()与timerqueue_del()都不执行,节点原样留在存活线程的 timerqueue 上,但posix_timer_unhash_and_free()照样把它kfree_rcu()掉。
等僵尸 task 被回收,release_task()→__exit_signal()→posix_cpu_timers_exit()→cleanup_timerqueue()会再摘一次这个节点,写下的是已释放内存里的head 指针——谁占住这块内存,谁就换来对指定地址的一次写。
三、漏洞复现
3.1 环境
| 项 | 值 |
|---|---|
| 系统 | Ubuntu 26.04 LTS |
| 内核 | 7.0.0-27-generic #27-Ubuntu SMP PREEMPT_DYNAMIC ,构建于 2026-06-18 |
| 规格 | 4 vCPU / 8 GB,VMware 虚拟机 |
| 起手权限 | 普通用户 luo,uid 1000,未使用 sudo |
| 利用代码 | 上游 PoC V4bel/InfinityCore timer 分支的 CVE-2026-98260-ubuntu.c |
编译只需一条命令,全程无警告:
gcc -O2 -pthread -o exp CVE-2026-98260-ubuntu.c
3. 2触发与提权
以普通用户执行,提权后的 bash 通过标准输入接收命令:
./exp < cmds.txt
触发后约 30 秒,内核侧先给出信号——18 条 __list_add_valid_or_report 告警集中在 4 毫秒内冒出来:
[ 115.781690] WARNING: lib/list_debug.c:35 at __list_add_valid_or_report+0x9e/0xc0, CPU#1: exp/4987
[ 115.781909] RIP: 0010:__list_add_valid_or_report+0xa7/0xc0
[ 115.781948] RAX: ffff8b0581af2e90 RBX: ffff8b0581af2e90
[ 115.781958] RDX: ffff8b0581af2e90 RSI: ffff8b0581af2e90
四个寄存器全等于同一个地址,这是自引用节点的典型特征——链表校验发现\"新节点的 next 指向自己\",说明被插进队列的那块内存已经被人重写过了。
紧接着拿到 root:
【图 2】复现结果:普通用户到 root 的完整过程
四、修复方式
4.1 官方修复措施
修复提交 acb03d3881818581052924a9bbbe92b8741ed448 新增了一个 helper posixtimer_exec(me),并在 de_thread() 成功后立刻调用。即:在 me->sighand->siglock 保护下,把当前 task 的 POSIX CPU timerqueue 清空,然后删除进程拥有的 POSIX timer 对象并刷新 timer signal。
关键在于顺序。清理从\"exec_task_namespaces() 之后\"提前到\"de_thread() 之后\",后面无论 exec_mmap() 还是 exec_task_namespaces() 怎么失败,k_itimer 被释放时 cpu_timer.node 都已经脱离 task timerqueue,退出路径再也不会踩到悬空节点。
4.2 排查与缓解
排查已经中招的机器,看内核日志里的链表校验告警:
dmesg | grep -E '__list_add_valid_or_report|list_debug'
journalctl -k --since \"7 days ago\" | grep -c list_debug
五、参考资料
| 用途 | 地址 |
|---|---|
| CVE 官方记录 (编号、CVSS、受影响与修复版本) | https://www.cve.org/ CVERecord?id=CVE-2026-98260 |
| CVE 记录原始数据(CVE Services 接口) | https://cveawg.mitre.org /api/cve/CVE-2026-98260 |
| Ubuntu 安全追踪(各发行版状态) | https://ubuntu.com/security/CVE-2026-98260 |
修复提交 acb03d388181(内核主线) |
https://git.kernel.org/pub/scm/ linux/kernel/git/torvalds/linux.git/commit/ ?id=acb03d388181858105 2924a9bbbe92b8741ed448 |
引入提交 55e8c8eb2c7b(内核主线) |
https://git.kernel.org/pub/scm/ linux/kernel/git/torvalds/ linux.git/commit/?id=55e8c8eb2c7b |
| 上游 PoC 仓库 | https://github.com/V4bel/InfinityCore |
---
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论