| 项目 | 值 |
|---|---|
| 漏洞类型 | rt_mutex / futex PI 路径中的栈上 Use-After-Free |
| 引入版本 | Linux 2.6.39-rc1 (2011年5月,commit 8161239a8bcc) |
| 修复版本 | 主线 7.1 (commit 3bfdc63936dd),各稳定分支:6.1.175 / 6.6.140 / 6.12.86 / 6.18.27 / 7.0.4 |
| 前置条件 | CONFIG_FUTEX_PI=y(主流内核默认开启) |
| CVSS | 7.8 High |
| 利用稳定性 | NebuSec 原链 97%,约 5 秒获取 root |
| kernelCTF 奖金 | $92,337 USD |
受影响内核范围:
| 项目 | 值 |
|---|---|
| SoC | Qualcomm SM8475 (Snapdragon 8 Gen 1 Plus) |
| 内核版本 | 5.10.233-gki-g6e61de9f5b58 #1 SMP PREEMPT (Nov 24 2025) |
| Android 版本 | 15 (OriginOS 5) |
| 编译时间 | 2025/11/25 |
| 安卓补丁 | 2025/11/01 |
CONFIG_FUTEX_PI | y ✅ |
CONFIG_UNMAP_KERNEL_AT_EL0 | y (KPTI 开启) |
kptr_restrict | enforced |
CONFIG_IO_URING | y ✅(vmlinux 符号确认,且 seccomp 未拦截 io_uring_setup) |
1. KASLR 绕过 → prefetch timing / PR_SET_MM_MAP auxv
2. UAF 触发 → 三线程 PI 依赖死锁 → FUTEX_CMP_REQUEUE_PI 返回 -EDEADLK
3. 栈回收 → PR_SET_MM_MAP 将 auxv 拷贝到 waiter 栈帧
4. rb_erase 受限写 → 覆写 inet6_protos[IPPROTO_UDP]
5. CEA + ROP → 控制流劫持
6. core_pattern 翻转 → root shell (97% 成功率)
| 阶段 | 状态 | 说明 |
|---|---|---|
| 1. KASLR 绕过 | ✅ 已实现 | perf_event_open + callchain sampling 侧信道(与 OPPO Find X6 Pro 5.15.149 适配方法一致) |
| 2. UAF 触发 | ✅ 已实现 | 三线程 PI 死锁成功,FUTEX_CMP_REQUEUE_PI 返回 -EDEADLK |
| 3. 栈回收原语 | ❌ 架构性失败 | 所有已知 syscall 的栈帧与 waiter 不重叠(详见第三节) |
| 4. rb_erase 受限写 | ❌ 阻塞中 | 前置条件未满足 |
| 5. inet6_protos 覆写 | ❌ 未开始 | 依赖阶段 4 |
| 6. ROP / 控制流劫持 | ❌ 未开始 | 依赖阶段 5 |
| 7. root shell | ❌ 未开始 | 依赖阶段 6 |
futex 路径总深度:
__arm64_sys_futex 0x90
+ do_futex 0xc0
+ futex_wait_requeue_pi 0x1b0
= 0x300
waiter 位置 = SYS_SP - 0x300 + 0x20 = SYS_SP - 0x2e0
pselect 路径:
core_sys_select 栈帧 0x1c0, stack_fds 在 sp+0x50
覆盖区间: SYS_SP - 0x1c0 + 0x50 = SYS_SP - 0x170 起
与 waiter (SYS_SP - 0x2e0) 差距 0x170 (368 字节) → 不重叠
| # | 方法 | 系统调用 | PD2229 结果 | 核心失败原因 |
|---|---|---|---|---|
| 1 | stamp_prctl | PR_SET_MM_MAP | ❌ EPERM | Android 硬拦截 |
| 2 | stamp_pselect | pselect6 (NFDS=320) | ❌ 不重叠 | waiter 在 fd_set 下方 120B |
| 3 | stamp_pselect | pselect6 (NFDS>336) | ❌ 堆分配 | kvmalloc 路径 |
| 4 | stamp_socket | MCAST_JOIN_SOURCE_GROUP | ❌ 覆盖不足 | 仅写 lock 字段 |
| 5 | stamp_sendmsg | sendmsg | ❌ 距 waiter 80B | 栈帧 0x90 深度不足 |
| 6 | stamp_sendmmsg | sendmmsg | ❌ 距 waiter 112B | 栈帧不足 |
| 7 | stamp_recvmmsg | recvmmsg | ❌ 清零 task/lock | 0x1d0 栈帧破坏关键指针 |
| 8 | stamp_process_vm | process_vm_writev | ❌ 不重叠 | 子线程栈独立分配 |
| 9 | stamp_keyctl | KEYCTL_INSTANTIATE_IOV | ❌ EOPNOTSUPP | 系统调用不支持 + 栈帧 0x40 |
| 10 | stamp_tcp | TCP_ZEROCOPY_RECEIVE | ❌ 栈帧不足 | 预估深度不够 |
| 11 | stamp_futex | FUTEX_CMP_REQUEUE_PI 递归 | ❌ 逻辑不可行 | 破坏 UAF 窗口 |
| 12 | binder ioctl | BINDER_WRITE_READ | ❌ EACCES | shell 无 /dev/binder 权限 |
| 13 | poll | poll | ❌ 堆分配 | pollfd 在堆上 |
| 14 | epoll_wait | epoll_wait | ❌ 帧太浅 | 栈帧 0xE0 |
| 15 | sched_setattr | sched_setattr | ❌ 深度不足 | 栈帧 0xb0 |
| 16 | timerfd_settime | timerfd_settime | ❌ 无栈复制 | 无大栈缓冲区 |
| 17 | io_uring_register | IORING_REGISTER_* | ❌ 双失败 | ①栈帧仅 0xF0,copy_from_user 目标固定 sp+0x8(与 waiter 的 sp+0x1D0 差 424 字节);②虽然 io_uring_setup 未被 seccomp 拦截(返回 EFAULT 而非 ENOSYS),但栈布局不匹配 |
17/17 全部失败。
PD2229 的 SM8475 5.10 GKI 编译器(PGO + LTO + BOLT)输出的栈布局,导致 core_sys_select 的 stack_fds 与 futex_wait_requeue_pi 的 rt_mutex_waiter 架构性不重叠。这是编译器决定的客观事实,而非利用技巧问题。
JoinChang 仓库明确说明:"The pselect stack overlay only works when the freed rt_mutex_waiter lands within the user-controllable region of the stack_fds buffer"——PD2229 不满足此条件。
PR_SET_MM_MAP 将 auxv 拷贝到内核栈PR_SET_MM_MAP 在 Android 上被 EPERM 拦截PSELECT_SHIFT = -2"pselect 无法操纵 waiter 结构 — NFDS >336 时 fd_set 在堆上;configfs/ashmem 不支持(ashmem SET_NAME 被截断);所有其他内核写入路径被阻塞(/proc/self/mem, /dev/mem, binder)"
"pixel10 能利用的版本的 pselect stack_fds 正好和 rt_waiter 在内核栈上重合,这个部分实际上是最麻烦的地方,OPPO findN2 的内核这两个调用的栈部分完全不重合,或者重合也不可控,得找另外的控制栈的方法,要换其他可控内核栈的系统调用来构造栈,简单适配偏移是不可能成功的,oppo 的 rt_waiter 完全与 pselect stack_fds 不重合"
| 仓库 | 设备 | SoC | 内核 | 栈回收方法 | 状态 | PD2229 可复用性 |
|---|---|---|---|---|---|---|
| NebuSec/CyberMeowfia | Pixel 10 | - | 6.x | PR_SET_MM_MAP | ✅ 97% | ❌ Android 拦截 |
| JoinChang/ghostlock-oneplus | OnePlus Ace 6T | SM8845 | 6.12.38 | pselect (SP diff=-64) | ✅ 已验证 | ❌ 内核代次不符 |
| p2p3p/GhostLock-for-OnePlus | OnePlus Ace 6T | SM8845 | 6.12.38 | pselect | ✅ 已验证 | ❌ 内核代次不符 |
| YuKongA/ghostlock-oplus | Find N5/X8 | - | 6.6.118 | pselect | ✅ | ❌ 内核代次不符 |
| OPPO Find X6 Pro 适配 | Find X6 Pro | SM8550 | 5.15.149 | perf KASLR + ? | 🟡 KASLR ✅, 后续未公开 | ❌ 平台不同 |
| pubglite55/oppo-ghostlock | Find N2 | SM8475 | 5.10.236 | 穷举失败 | ❌ 核心阻塞 | ⚠️ 同平台同代次,命运一致 |
| harry1080/oppo-ghostlock | Find N2 | SM8475 | 5.10.236 | 穷举失败 | ❌ 架构性不可行 | ⚠️ 同平台同代次,命运一致 |
| PD2229 (本报告) | PD2229 | SM8475 | 5.10.233 | 17 种候选全失败 | ❌ 架构性不可行 | — |
静态基址
0xffffffc008000000,运行时需加 KASLR slide。