针对 vivo Y200i Android 14 上 CVE-2026-43499(GhostLock)内核 UAF 的研究笔记与 PoC 开发,涵盖 futex PI 链栈回收原语及帧布局限制。
设备:vivo Y200i (PD2354C),Snapdragon 4 Gen 2 (SM4450),Android 14 / OriginOS 4 内核:5.10.218-gki-g3a51ea9d5834(39 位 VA,4K 页,KASLR 开启,STACKLEAK=y,无 SVE)
目标:通过 CVE-2026-43499 (GhostLock) 实现临时 root。
目前进展:
受阻:栈回收原语无法到达 rt_mutex_waiter 的 rb_node。
关键数值(在两个独立固件包中完全一致):
__arm64_sys_futex 0xe0
do_futex 0xc0 (未内联——存在 bl do_futex)
futex_wait_requeue_pi 0x1b0 (waiter 位于 sp+0x20)
=> futex 链深度 T0-0x330
__arm64_sys_pselect6 0xa0 core_sys_select 0x1c0 (fd_set 位于 sp+0x50) => pselect 链深度 T0-0x210,可控窗口仅 120 字节 => 间隙 0x120,架构上不重叠
waiter 布局(5.10 紧凑,与 PFEM10 一致): +0x18 pi_tree_entry.__rb_parent_color <- rt_mutex_adjust_prio_chain 遍历的内容 +0x20 pi_tree_entry.rb_right +0x28 pi_tree_entry.rb_left +0x30 task +0x38 lock +0x40 prio +0x48 deadline
来自 rt_mutex_adjust_prio_chain 的证据: ldr x8, [task, #0x888] ; task->pi_waiters.rb_leftmost sub x8, x8, #0x18 ; rb_entry(node, rt_mutex_waiter, pi_tree_entry)
由于 copy_from_user 向更高地址写入,覆盖 pi_tree_entry 要求拷贝基址 <= T0-0x318。
已穷尽的路径: pselect6/core_sys_select T0-0x210 -> 差 0x120 poll/do_sys_poll 窗口结束于 T0-0x344,最大 0xf0B (N_STACK_PPS=30) -> 差 0x14 rt_sigreturn (fpsimd) T0-0x300 -> 仅到达 waiter+0x30 rt_sigreturn (SVE) T0-0x310 -> 将覆盖 waiter+0x10,但此 CPU 无 SVE;内核以 -EINVAL 拒绝 SVE sigframe 记录 compat rt_sigreturn / vfp T0-0x2c0 -> 更浅
对所有 copy_from_user 位点的全内核扫描:共 655 个,118 个可达, 最大深度 0x300(bpf_prog_get_info_by_fd,同样受 CAP_BPF 限制)。需要 0x318。
结论:此内核的栈几何结构对于基于栈的 copy_from_user 上限为 0x300;覆盖 pi_tree_entry 需要 0x318。这不是调优问题——而是 编译期栈帧布局差异。此处 do_futex 未内联,与 PFEM10(5.10.236,Clang 12.0.5)不同,很可能是不同的内联成本模型。
寻求: