技術 約7分で読めます

LinuxカーネルのCopy Fail(CVE-2026-31431)はページキャッシュを書き換えてrootを取る

いけさん目次

TL;DR

影響 2017年以降の algif_aead in-place最適化を含むLinuxカーネル。CVSS 7.8 HIGH

対応 ディストリビューションのカーネル更新(上流修正は a664bf3d603dalgif_aead をout-of-place動作に戻す)

暫定 共有サーバー・CIランナー・Kubernetesノード・サンドボックス基盤で algif_aead 無効化+AF_ALG ソケット作成のseccomp制限


TheoriのXint Codeチームが2026年4月29日、Linuxカーネルのローカル権限昇格脆弱性 Copy Fail を公開した。
CVE番号はCVE-2026-31431。
Linuxカーネルの authencesnAF_ALGsplice() が噛み合って、通常ユーザーから任意の可読ファイルのページキャッシュへ制御可能な4バイトを書き込める。

厄介なのは、ディスク上のファイルを書き換えない点だ。
ページキャッシュはLinuxがファイル内容をRAM上に保持する仕組みで、read()mmap()execve() もここを読む。
/usr/bin/su のようなsetuid-rootバイナリのキャッシュだけを汚せば、ディスク上のハッシュは正しいまま、実行時だけ改変済みの内容が使われる。

以前 Claude CodeがLinuxカーネルのNFSバグを見つけた記事 では、AI支援で見つかった23年もののリモート脆弱性を扱った。
今回もAI支援の発見だが、性質はかなり違う。
リモートから直接叩くバグではなく、ローカルユーザーやコンテナ内プロセスがホストrootへ上がるためのバグだ。

何が壊れていたか

AF_ALG は、Linuxカーネルの暗号APIをユーザー空間からソケットとして呼び出すためのインターフェースだ。
今回の経路では、ユーザーがAEAD(Authenticated Encryption with Associated Data、暗号化と改ざん検出をまとめて扱う方式)の authencesn(hmac(sha256),cbc(aes)) を開く。

そこへ splice() が絡む。
splice() はファイルとパイプなどの間でデータをコピーせずに移すシステムコールで、ファイル内容をページキャッシュの参照として渡せる。
Xintの技術解説によると、ファイルから AF_ALG ソケットへ splice() すると、暗号処理の入力scatterlistがページキャッシュの実ページを参照する。

本来、入力側にあるページキャッシュは読み取り専用扱いで終わるべきだった。
ところが2017年に入った algif_aead のin-place最適化で、入力と出力が同じscatterlistとして扱われるようになった。
その結果、ページキャッシュ由来のページが「書き込み先」としても見えてしまう。

graph TD
    A["可読ファイルをsplice"] --> B["ページキャッシュのページを<br/>AF_ALG入力へ渡す"]
    B --> C["algif_aeadのin-place処理"]
    C --> D["入力と出力のscatterlistが混ざる"]
    D --> E["authencesnが作業領域として<br/>境界外へ4バイト書く"]
    E --> F["ファイル本体ではなく<br/>ページキャッシュだけが汚れる"]

最後の引き金が authencesn だ。
これはIPsecのESN(Extended Sequence Number、64ビットの拡張シーケンス番号)を扱うAEADラッパーで、処理中に呼び出し元の出力バッファを一時作業領域として使う。
Xintの説明では、authencesndst[assoclen + cryptlen] に4バイトを書き込む。
通常ならただの出力バッファへの一時書き込みで済むが、今回のin-place経路ではその先にページキャッシュのページがつながっていた。

書き込み後に認証は失敗し、recvmsg() はエラーを返す。
ただし4バイトの書き込みは戻らない。
攻撃者は対象ファイル、オフセット、書き込む4バイトを制御できる。

ディスクに痕跡が残らない理由

Copy Failの目立つ特徴は、ファイルを永続的に改ざんしないことだ。
ディスク上の /usr/bin/su はそのままなので、パッケージマネージャーの検証やファイルハッシュ比較では異常が出ない。

一方で、実行時にカーネルが読むのはページキャッシュ上の内容だ。
キャッシュされたページに改変が残っていれば、execve() はその改変済みページを使う。
XintのPoCはこの性質を使い、setuid-rootバイナリのメモリ上コピーに小さな変更を重ねてrootシェルへ到達する。

この改変は再起動やメモリ圧迫で消える。
ページキャッシュが捨てられ、ディスクから読み直されれば元に戻る。
永続化しないから安全という話ではない。
侵害時のディスクフォレンジックで見落としやすい、という意味でむしろ面倒だ。

コンテナ境界を越える

ページキャッシュはホスト全体で共有される。
コンテナごとに完全分離されたメモリコピーを持つわけではない。
そのため、コンテナ内の非特権プロセスがこのバグを踏めると、ホスト側のsetuidバイナリのページキャッシュを汚す経路になる。

影響が重いのは、ユーザーやテナントのコードを同じカーネル上で走らせる環境だ。

環境何が起きるか
共有開発サーバー、ジャンプホスト通常ユーザーからrootへ上がれる
Kubernetesノード侵害されたPodからホストrootへ上がる経路になる
CIランナー悪意あるpull requestのジョブがランナーを奪える
ノートブック、エージェントサンドボックステナントコードが基盤ホストへ届く

この観点では、Docker EngineのAuthZバイパス と似た運用上の怖さがある。
単体サーバーのバグとして見るより、信頼できないコードをどこまで同じホストカーネルに載せているかで優先度が変わる。

修正はin-place最適化の撤回

上流修正はLinuxコミット a664bf3d603d だ。
コミットメッセージは crypto: algif_aead - Revert to operating out-of-place
2017年の 72548b093ee3 で入ったin-place動作をほぼ戻し、送信側scatterlistと受信側scatterlistを分ける。

修正前は、splice() で渡されたページキャッシュ由来のページが出力側にも連結されうる構造だった。
修正後は入力がTX scatterlist、出力がRX scatterlistに戻るため、authencesn の作業用書き込みがページキャッシュへ抜ける経路が消える。

NVDのCVEページは2026年4月30日時点で「Awaiting Enrichment」だが、kernel.org CNAによるCVSS 3.1は7.8 HIGH、ベクトルは AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H になっている。
NVDが全件エンリッチメントをやめて優先トリアージへ寄せた話は 別記事 で書いたが、今回のようなカーネルCVEでもNVD側の詳細付与は公開直後に揃わない。
判断にはベンダーアドバイザリ、kernel.org、研究者の一次情報を直接見るしかない。

更新できない間の逃げ道

最優先はディストリビューションの修正済みカーネルへ更新すること。
Theoriは、すぐパッチを当てられない場合の暫定策として algif_aead モジュールの無効化を挙げている。

echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif-aead.conf
rmmod algif_aead 2>/dev/null || true

ただし、これだけで十分とは限らない。
組み込み設定やディストリビューションの構成によっては、モジュールとして外せない場合がある。
また、信頼できないコードを走らせるホストでは、パッチ後でも AF_ALG ソケット作成をseccompで止める方が筋がいい。
通常のOpenSSL、SSH、LUKS、kTLS、IPsec/XFRMはカーネル暗号APIを直接使うかユーザー空間ライブラリを使うため、AF_ALG を使わない構成が多い。
Theoriも、一般的な環境では algif_aead 無効化による影響は限定的だとしている。

確認では、カーネルパッケージが修正コミット相当を含むか、ディストリビューションのセキュリティアドバイザリを追う。
uname -r だけで安全判定するのは危ない。
ベンダーは上流バージョン番号を上げずに修正をバックポートすることがある。

AIが見つけたという部分

Copy Failは「AIがLinuxカーネルのゼロデイを発見した」という見出しで広がっている。
Xintの説明では、人間の研究者が AF_ALG + splice() によるページキャッシュ参照という観察を与え、Xint CodeがLinux crypto/ サブシステムを約1時間スキャンして最重要の発見として上げた、という流れだ。

これは完全な自動魔法ではない。
ただし、人間が攻撃面を絞り、モデルがコードパスを広く読む形はかなり実用段階に入った。
LinuxカーネルにAIコーディングアシスタント利用ポリシーが入った件 では貢献側の透明性が焦点だったが、防御側の脆弱性発見ではもう一段先に進んだ。

公開済み情報だけでも、Copy Failは「CVE番号がついたから順番に処理する」種類のバグではない。
共有カーネル上で他人のコードを動かしているなら、通常のローカル権限昇格より優先度を上げて扱うべきだ。