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 トリガー → 3スレッド 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 — オリジナル悪用フレームワーク
- リポジトリ: https://github.com/NebuSec/CyberMeowfia
- ターゲット: x86_64 Linux / Pixel 10 (6.x GKI)
- スタック再利用:
PR_SET_MM_MAP で auxv をカーネルスタックにコピー
- 成功率: 97%、約 5 秒で[root shell]
- PD2229 への適用性: ❌
PR_SET_MM_MAP は Android で EPERM によりブロック
JoinChang/ghostlock-oneplus — 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 — 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 のカーネルではこれら 2 つの呼び出しのスタック部分が完全に重ならないか、重なっても制御不能であり、別のスタック制御方法を見つける必要がある。他の制御可能なカーネルスタックを持つシステムコールに切り替えてスタックを構築する必要があり、単純なオフセット適応では成功不可能である。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 トリガー — 3スレッド 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 種のスタック再利用候補の排除マトリックス
九、リファレンスリポジトリ索引