GhostLock 在 PD2229 (SM8475, 5.10.233 GKI) 的利用失败总结
一、漏洞与设备事实
1.1 CVE-2026-43499 (GhostLock) 基本信息
| 项目 | 值 |
|---|
| 漏洞类型 | 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 |
受影响内核范围:
- 2.6.39 ≤ Linux < 6.1.175 ✅ 受影响
- 6.2 ≤ Linux < 6.6.140 ✅ 受影响
- 6.7 ≤ Linux < 6.12.86 ✅ 受影响
- 6.13 ≤ Linux < 6.18.27 ✅ 受影响
- 6.19 ≤ Linux < 7.0.4 ✅ 受影响
- Android GKI 5.10 未在任何修复分支中 → PD2229 的 5.10.233 理论上受影响
1.2 PD2229 设备实测
二、理想利用链 vs PD2229 实际进度
2.1 NebuSec 原链(x86_64 / Pixel 10 成功)
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% 成功率)
2.2 PD2229 各环节实际进度
三、栈回收原语穷举结果(PD2229 实测)
3.1 栈帧布局关键计算
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 字节) → 不重叠
3.2 已尝试的 17 种栈写入方法
17/17 全部失败。
3.3 失败的根本原因
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 不满足此条件。
四、公开参考仓库对比分析
NebuSec/CyberMeowfia — 原始利用框架
JoinChang/ghostlock-oneplus — 一加锁 BL jailbreak
- 仓库:https://github.com/JoinChang/ghostlock-oneplus
- 已验证设备:
- OnePlus Ace 6T (PLR110, SM8845) — 6.12.38 GKI ✅
- OnePlus 15 (PLK110, SM8845) — 6.12.23 GKI ✅
- 技术要点:
- 偏移自动提取:kallsyms (28) + BTF (57) + 派生 (9) + 常量 (12) = 103/103
- pselect 栈覆盖,SP diff = -64
PSELECT_SHIFT = -2
- 利用链:futex UAF → 伪造 waiter → pselect 控制栈 → rb_erase 受限写 → selinux_state.enforcing=0 → cred 覆写为 init_cred
- 明确声明不可行:"Not Feasible (stack layout incompatible)" — 仅适用于 pselect stack_fds 与 waiter 重叠的内核
- PD2229 适用性:❌ 内核代次不符(6.12 vs 5.10),且栈布局不重叠
p2p3p/GhostLock-for-OnePlus — 一加 6.12 完整利用
YuKongA/ghostlock-oplus — OPPO Find N5/X8
OPPO Find X6 Pro (PGEM10) 适配 — 5.15.149
- 设备:SM8550, 5.15.149-android13, Android 15
- 进展:✅ KASLR 绕过(perf_event_open + callchain sampling);后续阶段未公开完整利用
- 意义:证明 5.15 GKI 上 KASLR 绕过可行,但栈回收阶段未公开验证
pubglite55/oppo-ghostlock — OPPO Find N2
- 仓库:https://github.com/pubglite55/oppo-ghostlock
- 设备:OPPO Find N2 (CPH2413, SM8475)
- 内核:5.10.236-android12-9-o-g74d132f4467a
- Android:16 (BP2A.250605.015)
- 已实现:
- ✅ Firefox CVE-2026-10702 AAW(Stage 1)
- ✅ KASLR bypass(直接计算 kaslr_base)
- ✅ GhostLock FUTEX 触发(FUTEX_CMP_REQUEUE_PI ret=0)
- ✅ KernelSnitch mm_struct 泄漏
- ✅ sk_buff 堆喷射(4/4 send 成功)
- ✅ IDA Pro 70+ 偏移验证
- 核心阻塞:
"pselect 无法操纵 waiter 结构 — NFDS >336 时 fd_set 在堆上;configfs/ashmem 不支持(ashmem SET_NAME 被截断);所有其他内核写入路径被阻塞(/proc/self/mem, /dev/mem, binder)"
- PD2229 关系:同平台同代次(SM8475, 5.10.236 vs 5.10.233),仅差 3 个小版本,面临完全相同的架构性限制
harry1080/oppo-ghostlock — OPPO Find N2
- 仓库:https://github.com/harry1080/oppo-ghostlock
- 设备:OPPO Find N2 (CPH2413, SM8475)
- 内核:5.10.236-android12-9-o-g74d132f4467a
- Android:16 (BP2A.250605.015)
- 社区公开声明:
"pixel10 能利用的版本的 pselect stack_fds 正好和 rt_waiter 在内核栈上重合,这个部分实际上是最麻烦的地方,OPPO findN2 的内核这两个调用的栈部分完全不重合,或者重合也不可控,得找另外的控制栈的方法,要换其他可控内核栈的系统调用来构造栈,简单适配偏移是不可能成功的,oppo 的 rt_waiter 完全与 pselect stack_fds 不重合"
- PD2229 关系:与 PD2229 同为 SM8475 5.10 GKI,结论完全适用
4.3 参考仓库对比总表
五、关键内核符号与偏移(PD2229 vmlinux 实测)
静态基址 0xffffffc008000000,运行时需加 KASLR slide。
rt_mutex_waiter 结构体(vivo 5.10.233 定制)
struct rt_mutex_waiter {
uint64_t private; // +0x00 (vivo 私有字段)
struct rb_node {
uint64_t rb_parent_color; // +0x08
uint64_t rb_right; // +0x10 (vivo 调换顺序)
uint64_t rb_left; // +0x18
} tree;
struct task_struct *task; // +0x20
struct rt_mutex *lock; // +0x28
};
// 总大小 0x30 (48 字节)
六、已实现 vs 需实现
✅ 已实现的基础设施
- KASLR 绕过 —
perf_event_open + callchain sampling(与 OPPO Find X6 Pro 5.15.149 方法一致)
- UAF 触发 — 三线程 PI 死锁,FUTEX_CMP_REQUEUE_PI 返回 -EDEADLK
- 完整符号表 — 103+ 符号通过 IDA 验证(参照 JoinChang 的 103/103 提取方法论)
- rt_mutex_waiter 结构体布局 — vivo 定制偏移已确认
- 栈帧布局精确分析 — futex 与 pselect/io_uring 路径深度计算完成
- 17 种栈回收候选的穷举排除 — 建立完整的"不可行"矩阵
❌ 未实现(核心阻塞)
- 栈回收原语 — SM8475 5.10 GKI 编译器栈布局导致架构性不可用
- 受限写原语 — 因栈回收失败而无法触发 rb_erase
- 后续所有阶段 — 级联阻塞
七、最终结论
⚠️ GhostLock (CVE-2026-43499) 在 PD2229 (vivo X Fold+, SM8475, 5.10.233 GKI, Android 15 OriginOS 5) 上不可利用。
根本原因是 SM8475 5.10 GKI 编译器(PGO+LTO+BOLT)输出的栈布局,导致所有已知 syscall 的栈帧与 rt_mutex_waiter 架构性不重叠。这是编译器决定的客观事实,不是利用技巧问题。
成功利用的案例均为 6.6/6.12 GKI,因为这些新内核的编译器输出使 pselect fd_set 与 waiter 完美重叠(SP diff=-64)。5.10 GKI 不具备这一条件。
已建立的基础设施
- ✅ KASLR 绕过原语(perf_event_open 侧信道)
- ✅ 103+ 内核符号与偏移
- ✅ rt_mutex_waiter 结构体布局
- ✅ UAF 触发能力
- ✅ 17 种栈回收候选的排除矩阵
九、参考仓库索引