GhostLock(CVE-2026-43499)徹底解説 — 15年間全Linuxに潜んだfutex UAFがrootを奪う仕組み

はじめに

2026年7月7日、セキュリティ研究組織 Nebula Security が GhostLock(CVE-2026-43499) を公開しました。Linuxカーネルの futex 優先度継承(PI)コードに潜むスタック Use-After-Free(UAF)で、なんと 2011年の Linux 2.6.39 から15年間、ほぼすべての主要ディストリに存在し続けた 代物です。特別な権限もネットワークも不要で、ログインできる一般ユーザーなら誰でも root を奪取し、コンテナからも脱出できます。しかも実証コード(PoC)が公開済みです。本記事では「なぜ15年も見つからなかったのか」「どうやってrootを取るのか」「今すぐ何をすべきか」を、カーネルの仕組みまで掘り下げて解説します。

何が起きたか — 15年もの、97%の信頼性で動く実物のroot exploit

GhostLock を発見したのは Nebula Security の研究者 VEGA 氏。同社はこの脆弱性を テスト環境で97%の成功率で動作する実用的な root exploit に仕立て上げ、Google の kernelCTF バグバウンティで $92,337(約1,400万円相当) の報奨を獲得しました。

影響範囲が異常に広いのがこの脆弱性の怖さです。

  • 導入時期: Linux 2.6.39-rc1(2011年5月)
  • 影響バージョン: 2.6.39 〜 7.1-rc1 直前(2026年4月の修正以前)
  • 必要な設定: カーネルビルドで CONFIG_FUTEX_PI=y になっていること(=ほぼすべてのディストリのデフォルト)
  • 必要な権限: なし。user namespace も特別な capability も不要

つまり「パッチ未適用の一般的なLinuxマシンで、ローカルシェルさえ取れれば root」という、共有サーバー・クラウド・コンテナ・CIランナーにとって最悪クラスの前提条件です。攻撃者がまず狙うのはこうした マルチテナント環境 だと各アドバイザリは警告しています。

技術的な仕組み — 「後始末する人」を取り違えるバグ

根本原因は、kernel/locking/rtmutex.c の remove_waiter() というクリーンアップ関数の設計前提が、ある特殊なfutex操作で崩れることにあります。

rtmutex(リアルタイムmutex)は、優先度継承(Priority Inheritance)を実現するためのロック機構です。remove_waiter() は本来 「あるスレッドが自分自身の後始末をする」 という単一シナリオ向けに書かれていました。ここで前提になっているのは「後始末をしている current(現在のスレッド)=掃除される対象の持ち主」という等式です。

ところが Requeue-PI(FUTEX_WAIT_REQUEUE_PI / FUTEX_CMP_REQUEUE_PI)は、この前提を破ります。rt_mutex_start_proxy_lock() は 別の眠っているスレッドの代理で ロックを操作するからです。__rt_mutex_start_proxy_lock() が -EDEADLK(デッドロック検出)を返してロールバックする際、remove_waiter() は本来クリアすべき waiter->task->pi_blocked_on ではなく、誤って current->pi_blocked_on(=間違ったタスク)をクリアしてしまいます。

結果、代理された waiter タスク側には すでに解放された自分のスタックフレームを指すダングリングポインタ が残ります。これがスタックUAFの正体です。修正コミット 3bfdc63936dd は、waiter->task->pi_lock を取って waiter->task->pi_blocked_on を正しくクリアするだけの、いわば「掃除する相手を正す」1点修正でした。

15年見つからなかった理由もここにあります。トリガーには 3つのfutexで意図的にデッドロック閉路を作る という不自然な操作が必要で、通常のアプリはまずこんな使い方をしません。正常系では決して踏まないコードパスだったのです。

エンジニアへの影響 — ダングリングポインタからrootまでの一本道

UAF一つがなぜ完全なroot奪取に繋がるのか。Nebula の exploit チェーンは、カーネルエクスプロイトの教科書のような多段構成でした。

  1. ASLRリーク(Prefetch): メモリアクセス時間の差を測る side-channel でカーネルイメージ/physmap のベースアドレスを漏洩
  2. スタックUAFの再取得: PR_SET_MM_MAP prctl を使って解放済み waiter のスタックフレームを奪い、auxv バッファ経由で偽の rt_mutex_waiter 構造体を仕込む
  3. 任意書き込み: rtmutex の rb-tree 削除処理を悪用し、CPU entry area(CEA)内の inet6_protos[IPPROTO_UDP] に制御可能なポインタを書き込む
  4. 制御フロー乗っ取り: inet6 プロトコルハンドラの関数ポインタを上書き
  5. 昇格(DirtyMode): /proc/sys/kernel/core_pattern のパーミッションビットを書き換え、一般ユーザーが root として任意コード実行

実務への含意はシンプルかつ重大です。信頼できないユーザーにシェルを渡している環境はすべて危険 ということ。具体的には共有ホスティング、Kubernetes などのコンテナ基盤(コンテナ脱出が成立する)、マルチテナントSaaS基盤、そして外部PRを実行するCIランナーが最優先の防御対象です。エージェント実行環境を使い捨てVMに隔離する動き(Clawk など)が支持を集める背景とも符合します。

対策 — 「最初のパッチ」では不十分な点に注意

まず優先すべきはパッチ適用です。 ただし注意点があります。

  • 初回修正には別のクラッシュバグ(CVE-2026-53166)が混入 したため、「最初にパッチされたビルド」ではなく ディストリの最新カーネルを入れること。
  • Ubuntu は要確認: 新しめのリリースや一部クラウドカーネルは修正済みだが、公開初期時点で 24.04 / 22.04 / 20.04 LTS が「脆弱 or 対応中」のままだった。必ず自分のディストリのアドバイザリで、修正済みパッケージのバージョンを確認すること。
  • AlmaLinux は7月9日にパッチ済み を告知するなど、主要ディストリは順次対応中。

すぐにパッチを当てられない場合の緩和策(あくまで一時しのぎ):

  • RANDOMIZE_KSTACK_OFFSET: スタック再利用の成功率を約1/32に下げ、悪用信頼性を低下させる
  • STATIC_USERMODE_HELPER: DirtyMode 経路を特異的にブロック

なお各アドバイザリは IOC(侵害の痕跡)や検知シグネチャを提供していない 点も要注意です。事後検知に頼れないため、「先に塞ぐ」以外の選択肢は実質ありません。

まとめ

  • GhostLock(CVE-2026-43499)は Linux の futex PI コードの15年もののスタックUAF。2.6.39〜7.1直前が対象。
  • 原因は remove_waiter() が Requeue-PI で「後始末する対象のタスク」を取り違えること。修正コミットは 3bfdc63936dd。
  • 無権限のローカルユーザーが root 昇格+コンテナ脱出可能。PoC公開済みで、97%の信頼性で動く実物が存在。
  • 共有・マルチテナント・コンテナ・CI環境を最優先に、ディストリ最新カーネルへ更新。初回パッチにはクラッシュバグ(CVE-2026-53166)があるため注意。

15年間「正常系では踏まないコードパス」に潜んでいた事実は、カーネルのような枯れたコードにも未知の危険が眠っていることを改めて示しました。マルチテナント基盤を運用しているなら、この週末のうちにカーネルバージョンを棚卸しする価値は十分にあります。

ソース


今日のその他のニュース

  • GPT-5.6ファミリーGA / Claude Sonnet 5: OpenAIが7/9にGPT-5.6(Luna=高速安価/Terra=バランス/Sol=フラッグシップ)をGA。AnthropicもClaude Sonnet 5をリリース済みで、モデル選定の基準が再び動いています。
  • Cursorに曖昧な指示でDドライブ消失: AIエージェントに「不要なブランチを整理して」と頼んだらDドライブが消えた実体験談。破壊的操作リスクとサンドボックス化の重要性を示す教訓として話題(Zenn・67 likes)。
  • Grok Buildが認証情報を無加工で送信: Grok Build がセンシティブな認証情報をマスクせずサーバー送信していたとの分析。AI開発ツールのデータ取り扱いへの警戒が続きます(GIGAZINE)。