Dirty Frag:Linux カーネルゼロコピー権限昇格脆弱性の深層解析
Dirty Frag:Linux カーネルのゼロコピーパス上でのページキャッシュ書き込み脆弱性チェーン。xfrm-ESP と RxRPC の2つの独立した脆弱性を連結し、2017年以降のほぼすべての主流ディストリビューションに影響を与え、パスワードなしで root 権限に昇格可能。
またかよ?静かにさせてくれないのか
正直なところ、こんなに早くまたカーネル権限昇格の記事を書くことになるとは思っていなかった。
前回の Copy Fail の記事からわずか 8日 だ。8日だぞ!Copy Fail の algif_aead ブラックリストをターミナルに打ち込んだばかりで、パッチもまだ温かいうちに、また降ってきた — Dirty Frag だ。
さらに馬鹿げているのは、Copy Fail の緩和策が Dirty Frag に対して 完全に無効 という点だ。今回はまったく異なるカーネルサブシステム — xfrm-ESP と RxRPC の暗号化パス — を攻撃しているので、algif_aead を無効にしようがしまいが関係ない。
Dirty Pipe(2022)、Copy Fail(2026.04)、Dirty Frag(2026.05)……毎回「2017年以降のほぼすべてのディストリビューションに影響」と言っている。これが何を意味するかわかるか?過去10年近く、システム内の任意の非特権アカウントにログインした者が、こっそり root になれるチャンスがあったということだ。
だがよく考えると、これは全部カーネル開発者の責任なのか?必ずしもそうではない。
ここ数年の AI 支援コード監査ツールの爆発的な成長により、セキュリティ研究者は 数時間で 10年近く潜んでいた脆弱性を発見できるようになった。以前は人力で一行一行レビューしなければ見つからなかったバグが、今では AI が一括スキャンして次々と発見される。Copy Fail は AI ツール Xint Code が1時間で特定した。Dirty Frag は韓国の研究者 Hyunwoo Kim による人工監査だが、影響を与えるコードパスは Copy Fail と同じファミリー — ゼロコピーパス上のページキャッシュ書き込み — に属しており、この種の設計欠陥が一握りの孤立したケースにとどまらないことを示している。ツールが強くなり、効率が上がり、自然と脆弱性が「増える」。
さらに不安なのは今回の開示方法だ。研究者は当初、カーネルセキュリティチームに脆弱性の詳細を提出し、ディストリビューションにパッチ適用の時間を与えるために 5日間のエンバーゴ を約定していた。ところが 当日、無関係な第三者が ESP(xfrm) 脆弱性の完全な詳細とエクスプロイトを 直接公開 してしまった。CVE もなく、パッチもないのに、PoC は誰でも実行できる状態になった。これは責任ある開示ではなく、すべての Linux ユーザーに背中からナイフを突き刺す行為だ — パッチ適用の窓が完全に破壊され、全員が裸のまま走らされることになった。
よし、文句はこれくらいにして。今回の脆弱性がどういうものか、真面目に見ていこう。
タイムライン
| 日付 | 出来事 |
|---|---|
| 2017-01 | xfrm-ESP 脆弱性がコミット cac2661c53f3 でカーネルに導入(9年間 潜伏) |
| 2023-06 | RxRPC 脆弱性がコミット 2dc334f1a63a で導入 |
| 2026-04-29 | 韓国の研究者 Hyunwoo Kim (@v4bel) が RxRPC 脆弱性と完全なエクスプロイトを security@kernel.org に報告 |
| 2026-05-07 | 脆弱性詳細が linux-distros メーリングリストに提出され、5日間のエンバーゴ を約定 |
| 2026-05-07 | 同日、第三者が ESP(xfrm) 脆弱性の詳細情報とエクスプロイトを公開し、エンバーゴは即座に破棄 |
| 2026-05-07 | 各ディストリビューションのメンテナーと協議の上、完全な Dirty Frag 文書が公開。この時点で CVE なし、公式パッチなし |
| 2026-05-08 | 本文執筆時点で、主要ディストリビューションはまだアップストリームのパッチ統合を待っている |
影響性分析
| 指標 | 詳細 |
|---|---|
| CVE | 未割り当て(エンバーゴ破棄時に NVD が割り当てる暇がなかった) |
| 脆弱性タイプ | 決定論的論理欠陥、競合状態ではない |
| 悪用成功率 | 100%、一度実行すれば必ず成功 |
| 影響範囲 | 2017年以降のほぼすべての主流 Linux ディストリビューション(2026年5月時点で、最新カーネル 7.0.3 も影響を受ける) |
| 悪用方法 | 192バイトのペイロードを、48回の4バイト書き込みで root-shell ELF を組み立てる |
| ディスク痕跡 | 永続的変更なし — メモリ内のページキャッシュのみを汚染し、inotify を回避;再起動で復元 |
| Copy Fail 緩和策の回避 | Copy Fail の algif_aead 無効化は 完全に無効、異なるサブシステムを攻撃するため |
過去のカーネル LPE 脆弱性との比較:
| 特性 | Dirty Cow (2016) | Dirty Pipe (2022) | Copy Fail (2026) | Dirty Frag (2026) |
|---|---|---|---|---|
| 競合状態 | 必要 | 不要 | 不要 | 不要 |
| 影響範囲 | 特定バージョン | 5.8+ | 2017年以降の全主流ディストリビューション | 2017年以降の全主流ディストリビューション |
| 悪用コード量 | 複雑 | 複雑 | Python 10行 | 単一ファイル C プログラム |
| ディスク痕跡 | 有り | 有り | 無し | 無し |
| パッチ状況 | 修正済み | 修正済み | 修正済み | 公式パッチなし |
影響が確認されたディストリビューション:
| ディストリビューション | テストしたカーネルバージョン |
|---|---|
| Ubuntu 24.04.4 | 6.17.0-23-generic |
| RHEL 10.1 | 6.12.0-124.49.1 |
| CentOS Stream 10 | 6.12.0-224 |
| AlmaLinux 10 | 6.12.0-124.52.3 |
| Fedora 44 | 6.19.14-300 |
| openSUSE Tumbleweed | 7.0.2-1 |
| Arch Linux | 7.0.3 |
6.12 から 7.0 まで、Ubuntu から Arch まで、全プラットフォームを通殺。そう、インストールしているほぼすべての主流ディストリビューションが影響を受けるだろう。
技術原理:なぜ Dirty Frag なのか?
一言で言えば
splice() が読み取り専用ファイルの ページキャッシュ参照 をネットワーク送信バッファ(skb)の frag スロットに埋め込む → 受信側カーネルが frag に対して インプレース暗号操作(in-place crypto、src == dst が同じメモリを指す)を実行する → 暗号文に対する復号操作が、読み取り専用ページキャッシュへの直接書き込み STORE プリミティブ に変わる → su の機械語を root-shell ELF に置き換える。
「Dirty」はページキャッシュの汚染を、「Frag」は skb(socket buffer)のフラグメント機構の悪用を指す。合わせて — Dirty Frag。
ゼロコピーパス上の skb frag 汚染
これは脆弱性全体を理解する上で鍵となる部分なので、詳しく説明する。
通常、ソケットにデータを書き込むと、カーネルはユーザ空間のデータを コピー してカーネルの skb に入れる。しかし splice() は ゼロコピー パスを通る — データそのものをコピーせず、ファイルページキャッシュページへのポインタ(page 構造体 + オフセット)を skb の frag 配列に直接詰め込む:
struct skb_shared_info {
struct sk_buff *frag_list; // frag リンクリスト
skb_frag_t frags[MAX_SKB_FRAGS]; // frag 配列、各要素は {page, offset, size}
// ...
};
ここで重要な点:splice() に渡される page は、ファイル(例えば /usr/bin/su)の メモリ内ページキャッシュページ だ — 読み取り権限しかないが、このページへの参照は既にネットワークプロトコルスタックの skb に詰め込まれている。
次は、受信側のネットワークプロトコルスタックがこのページに「余計なことをして」書き込むかどうかだ。
脆弱性その1:xfrm-ESP ページキャッシュ書き込み
最初の脆弱性は IPsec ESP(Encapsulating Security Payload)の復号パスにある。
esp_input() 関数は暗号文データを復号するために使われる。通常、skb のデータ領域が frag と共有される場合、カーネルは先に skb_cow_data()(Copy-on-Write)を呼んで共有ページをコピーしてから操作すべきだ。しかし、esp_input() には cow を迂回するコードパスが存在する:
static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
{
if (!skb_cloned(skb)) {
if (!skb_is_nonlinear(skb)) {
// [1] 線形 skb:head データのみ、frag なし、安全
nfrags = 1;
goto skip_cow;
} else if (!skb_has_frag_list(skb)) {
// [2] frag があるが frag_list がない → cow を直接スキップ!
nfrags = skb_shinfo(skb)->nr_frags;
nfrags++;
goto skip_cow; // 爆弾はここ
}
}
// 通常パス:データをコピー、安全
err = skb_cow_data(skb, 0, &trailer);
}
skb が非線形(splice で渡されたページキャッシュを保存した frag がある)だが frag_list が空の場合、コードは直接 skip_cow にジャンプする。その後、crypto_authenc_esn_decrypt() がインプレースで AEAD 復号を行う — src と dst は 同じ scatterlist を指し、つまり攻撃者が埋め込んだページキャッシュページだ。
復号プロセス中に、特に重要なコード行がある:
// シーケンス番号の上位4バイトを dst SGL の末尾に移動
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);
このコード行は dst(つまり su のページキャッシュページ)の assoclen + cryptlen オフセットに 4バイト を書き込む。そして tmp + 1 の値は ESP ヘッダのシーケンス番号上位32ビットから来る — 攻撃者は XFRM SA(Security Association)を登録する際に、XFRMA_REPLAY_ESN_VAL.seq_hi を通じてこの値を完全に制御できる。
つまり、攻撃者は同時に以下を制御する:
- どこに書くか(ファイルオフセット、ペイロード長を調整して位置決め)
- 何の値を書くか(4バイト、
seq_hiで指定)
48個の異なる XFRM SA を登録し、各 SA の seq_hi に ELF の4バイト断片を格納し、48回ループすれば、完全な root-shell ELF が su のページキャッシュに組み立てられる。
ただしこの脆弱性には制限がある:XFRM SA の登録には CAP_NET_ADMIN 権限が必要だ。攻撃者はユーザー名前空間を作成することで(unshare(CLONE_NEWUSER | CLONE_NEWNET))この権限を得られるが、Ubuntu の AppArmor は非特権ユーザーがネットワーク名前空間を作成するのを阻止している。
だから2つ目の脆弱性が必要なのだ。
脆弱性その2:RxRPC ページキャッシュ書き込み
2つ目の脆弱性は RxRPC プロトコルの Kerberos 認証復号パスにある。
rxkad_verify_packet_1() 関数は、受信したデータパケットの先頭8バイトに対してインプレース pcbc(fcrypt) 復号を実行する:
skcipher_request_set_crypt(req, sg, sg, 8, iv.x);
// ^^ ^^
// src==dst → インプレース操作!
ret = crypto_skcipher_decrypt(req); // 8バイト書き込みがここで発生
skb_to_sgvec() は skb の frag(攻撃者が splice で入れたページキャッシュページを含む)を直接 scatterlist に変換し、src と dst は 同じ sg だ。したがって復号操作は、8バイトの「復号結果」をその読み取り専用ページキャッシュページに直接書き戻す。
xfrm-ESP と比較すると:
| 特性 | xfrm-ESP | RxRPC |
|---|---|---|
| 書き込みサイズ | 4バイト | 8バイト |
| 値の制御 | 直接制御(seq_hi) | 間接的(fcrypt 鍵のブルートフォースが必要) |
| 必要な特権 | ユーザー名前空間 | 特権不要 |
| 導入時期 | 2017-01 | 2023-06 |
RxRPC 経由で書き込まれる値は直接制御できない — それは fcrypt_decrypt(C, K) の結果だ。攻撃者は先に add_key("rxrpc", ...) で鍵 K を登録し、ユーザ空間でブルートフォースして、目標の8バイト平文を生成する K を見つける必要がある。幸い、fcrypt は56ビット鍵、8バイトブロックの Andrew File System 専用暗号なので、ブルートフォースは大した問題ではない。
最も重要な点:RxRPC パスは 完全に特権を必要としない。ユーザー名前空間の作成も、ネットワーク名前空間も、CAP_NET_ADMIN も不要だ。しかも Ubuntu はデフォルトで rxrpc.ko モジュールをロードする。
連結ロジック
2つの脆弱性は互いを補完し、完全なカバレッジを形成する:
| シナリオ | 使用する脆弱性 | 理由 |
|---|---|---|
| Ubuntu(AppArmor が名前空間を阻止) | RxRPC | rxrpc.ko がデフォルトでロードされ、特権不要 |
| RHEL / Fedora / openSUSE | xfrm-ESP | 名前空間が利用可能、ESP 書き込みが精密に制御可能 |
| その他のディストリビューション | xfrm-ESP または RxRPC | モジュールのロード状況に応じて選択、少なくとも1つのパスが利用可能 |
これが Dirty Frag の恐ろしいところだ — どう設定しようが、root への道は必ずある。
PoC 分析
完全なエクスプロイトは github.com/V4bel/dirtyfrag でオープンソース化されている。コンパイルして実行するのに必要なのは1行だけだ:
git clone https://github.com/V4bel/dirtyfrag.git
cd dirtyfrag && gcc -O0 -Wall -o exp exp.c -lutil && ./exp
核心のアイデアはそれほど複雑ではない:
- 192バイトの最小限 ELF を準備する — 実行すると権限昇格する root-shell
- この192バイトを48個の4バイトチャンクに分割する(xfrm-ESP パスを使う場合)
- 各4バイトチャンクに対して1つの XFRM SA を登録し、その
seq_hiをそのチャンクの値に設定する - 毎回
splice()でsuのページキャッシュを skb に送り、インプレース書き込みをトリガーする - 48回ループし、
suのページキャッシュ領域(先頭192バイト)を完全に root-shell ELF に置き換える execve("/usr/bin/su")→ root shell
一切ディスクファイルには触れない。ディスク上の /usr/bin/su は微動だにせず、md5 は元のままだ。しかしカーネルのページキャッシュ内では、すでにすり替えられている。
任意のプロセスが su に対して execve を発行すると、カーネルはページキャッシュから読み取る — おっと、あなたが仕込んだバイナリが実行される。root 獲得。
応急処置:脆弱性モジュールの一時的無効化
現時点(2026年5月8日)では、公式カーネルパッチはまだリリースされていない。パッチが出るまでの一時的な緩和策は、3つの脆弱性モジュールをアンロードしてブラックリストに入れることだけだ。
まず、自分のシステムが影響を受けているか確認する:
lsmod | grep -E 'esp4|esp6|rxrpc'
何か出力があれば、影響を受けている。
直ちに以下のコマンドを実行する(再起動不要):
sudo sh -c "printf 'install esp4 /bin/false\ninstall esp6 /bin/false\ninstall rxrpc /bin/false\n' > /etc/modprobe.d/dirtyfrag.conf"
sudo rmmod esp4 esp6 rxrpc 2>/dev/null
確認:
lsmod | grep -E 'esp4|esp6|rxrpc'
重要:PoC が既に実行された可能性がある場合は、ページキャッシュをクリアしなければならない:
echo 3 | sudo tee /proc/sys/vm/drop_caches
これを実行しないと、モジュールを無効にしても、汚染されたページキャッシュがメモリに残ったままだ — su を実行すれば root shell になってしまう。
副作用:
esp4/esp6を無効化すると IPsec VPN トンネルが中断される。デスクトップユーザーとほとんどのサーバーには影響しないが、IPsec VPN(strongSwan、Libreswan など)に依存している場合は、先に影響を評価すること。rxrpcを無効化する影響は極めて小さい。AFS(Andrew File System)を使用していない限り問題ない。
AI 加速下の脆弱性軍拡競争
Dirty Frag の暴露は、もっと深い問題を考えさせられる:なぜ最近、カーネル LPE 脆弱性が次々と出てくるのか?
| 脆弱性 | 発見時期 | 主要ツール | 報告から公開まで |
|---|---|---|---|
| Dirty Pipe | 2022 | 人工監査 | 標準プロセス |
| Copy Fail | 2026-04 | Xint Code (AI) | 約1ヶ月 |
| Dirty Frag | 2026-05 | 人工監査 | 8日(エンバーゴ当日破棄) |
カーネル LPE 脆弱性は1年に1個から1ヶ月に1個になり、そして1ヶ月に1個から……1週間に1個になろうとしているのか?
その背景には、AI 支援コード監査ツールの爆発的な成長がある。以前は人力で一行一行レビューし、10年間誰にも発見されない脆弱性が普通だった。今や AI は数時間でサブシステム全体をスキャンし、すべての潜在的なゼロコピーパス、インプレース操作、共有参照を引き出す。ツールが強くなり、効率が上がり、自然と脆弱性が「増える」 — カーネルが突然悪くなったわけではなく、隅に隠された旧債が AI によって一つずつ暴かれているのだ。
さらに警戒すべきは開示エコシステムの変化だ。Dirty Frag のエンバーゴは第三者によって意図的に破棄され、脆弱性詳細と PoC が 同日 に公開された。これが何を意味するか?研究者が security@kernel.org に脆弱性を報告してから、世界中のハッカーが武器を手に入れるまで、8日 しかなかったということだ。パッチ適用の窓 — 消えた。
エンバーゴを破棄した人を非難できる。しかし現実には、こういうことは今後ますます増えるだけだ。AI は脆弱性発見を速くし、武器化も速くする。永遠にすべての人がエンバーゴの約束を守ることを期待することはできない。
そして忘れてはならない、同じ脆弱性ファミリーがまだ掘り出され続けている:
| 脆弱性 | サブシステム | 状態 |
|---|---|---|
| Copy Fail | AF_ALG + authencesn | 修正済み |
| Dirty Frag | xfrm-ESP + RxRPC | パッチなし |
| Copy Fail 2 | ESP-in-UDP | 公開済み |
| ZCRX Freelist | io_uring ZCRX | 公開済み |
この4つの脆弱性の核心原理は驚くほど似ている — splice() が読み取り専用ページキャッシュ参照をカーネルサブシステムに詰め込み、サブシステムが frag 上でインプレース書き込みを行う。これらが暴露しているのは、実は 同じクラスの設計問題 だ:
| コンポーネント | 導入理由 | 副作用 |
|---|---|---|
splice() | ゼロコピー、性能最適化 | 読み取り専用ページキャッシュ参照がカーネルサブシステムに送られる |
AF_ALG | カーネル暗号能力の公開 | 非特権ユーザーが直接暗号セッションを開始できる |
| xfrm-ESP | IPsec 加速 | インプレース復号、読み取り専用ページを出力バッファとして使う |
| RxRPC | AFS ネットワークプロトコルサポート | 同上、名前空間特権すら不要 |
各設計を個別に見れば、どれも合理的な性能最適化または機能要件だ。しかし組み合わせると、任意のローカルユーザーがパスワードなしで root になれる 脆弱性チェーンになる。
アップストリームカーネルが「ゼロコピーパス上のインプレース操作」というパラダイムそのものを徹底的に見直さない限り、保証する — これが最後ではない。
一般ユーザーへの私のアドバイスは単純だ:
- 今すぐ上記のブラックリストコマンドを実行する。 公式パッチが来たら元に戻せばいい。
- パッケージマネージャーのカーネル更新を密切に監視する。 修正版が出たら、直ちにアップグレードして再起動する。
- 定期的に
lsmod | grepで、これらのモジュールが誤ってロードされていないか確認する。
参考リンク
- GitHub PoC リポジトリ:https://github.com/V4bel/dirtyfrag
- LWN 報道:https://lwn.net/Articles/1071719/
- Phoronix 報道:https://www.phoronix.com/news/Dirty-Frag-Linux
- 韓国語技術分析 (GeekNews):https://news.hada.io/topic?id=29275
- Copy Fail 開示サイト:https://copy.fail/
- Copy Fail 2 (Electric Boogaloo):https://github.com/0xdeadbeefnetwork/Copy_Fail2-Electric_Boogaloo
インフォグラフィック

図1:Dirty Frag 脆弱性の概要 — ゼロコピーページキャッシュ参照が skb frags を通じてどのように悪用されるか