Copy Fail – CVE-2026-31431
(copy.fail)- 非特権ローカルユーザーが
authencesn、AF_ALG、splice()を連結することで、読み取り可能なファイルに対する ページキャッシュへの4バイト書き込み を実現し、そこから root 権限まで昇格できる - カーネルごとのオフセットやレース条件なしに、732バイトの Python スクリプト 1本で複数の Linux ディストリビューション上でそのまま動作し、同じエクスプロイトで root shell を取得できる
- 影響範囲はパッチ適用前の 主要な Linux ディストリビューションの大半 に及び、デフォルト設定で有効な
AF_ALGにより 2017 年からパッチ時点まで広く露出している - マルチテナントホスト、Kubernetes / コンテナクラスター、CI ランナー、ユーザーコード実行型 Cloud SaaS では、一般アカウントや 1 つの pod がホスト root につながり得るため、優先的なパッチ適用が必要
- 対応としてはメインラインコミット
a664bf3d603dを含む カーネルパッチ が最優先で、パッチ前はalgif_aeadの無効化と、信頼できないワークロードに対するAF_ALGの遮断 が重要
脆弱性の概要
- 単線的なロジック欠陥 1 つを
authencesn、AF_ALG、splice()でつなぐことで、ページキャッシュへの4バイト書き込み に至るローカル権限昇格が可能になる - カーネルごとのオフセットやレースウィンドウなしに、732バイトの Python スクリプト 1本で 2017 年以降に配布された Linux ディストリビューション全般で同一に動作する
- 同じエクスプロイトバイナリが修正なしで複数のディストリビューション上で root shell を取得する
- 非特権ローカルアカウントさえあればよく、ネットワークアクセスやカーネルデバッグ機能、事前導入済みの他のプリミティブは不要
影響範囲
- パッチ適用前のカーネルを使う 主要な Linux ディストリビューションの大半 が対象となる
- デフォルト設定でカーネル暗号化 API の
AF_ALGが事実上すべてのメインストリームディストリビューションで有効になっており、2017 年からパッチ時点までそのまま露出している - 直接検証したディストリビューションは Ubuntu 24.04 LTS、Amazon Linux 2023、RHEL 14.3、SUSE 16
- Debian、Arch、Fedora、Rocky、Alma、Oracle、組み込み系も、影響を受けるカーネルを使っていれば同様に動作する
優先的にパッチが必要な環境
- マルチテナント Linux ホスト では複数ユーザーが同じカーネルを共有するため、任意のユーザーアカウントが直ちに root になり得る
- Kubernetes / コンテナクラスター ではページキャッシュがホスト全体で共有されるため、1 つの pod がノードを掌握し、テナント境界を越えられる可能性がある
- CI ランナーとビルドファーム では、一般ユーザー権限で実行された信頼できない PR コードが、ランナー上で root になり得る
- ユーザーコード実行型 Cloud SaaS では、テナントがアップロードしたコンテナやスクリプトがホスト root につながる可能性がある
- シングルテナントサーバーは内部 LPE の性格が強く、Web RCE や窃取された認証情報と結び付く可能性がある
- 単一ユーザーのノート PC やワークステーションでは緊急度はやや低いが、ローカルコード実行がそのまま root 昇格につながる可能性がある
公開された PoC と使用方法
- PoC は防御側がシステム検証やベンダーパッチ確認に活用できるよう公開されている
copy_fail_exp.pyは Python 3.10+ の標準ライブラリos、socket、zlibのみを使用する- デフォルトの対象は
/usr/bin/suで、argv[1]で別の setuid バイナリを渡せる - ページキャッシュ内の setuid バイナリを変更し、変更は再起動後に持続しないが、取得した root shell は実際に動作する
- Issue tracker
緩和策
- まず カーネルパッチ が必要であり、メインラインコミット
a664bf3d603dを含むディストリビューションのカーネルへ更新する必要がある - このパッチは、2017 年に導入された
algif_aeadの in-place 最適化を巻き戻し、ページキャッシュページが writable destination scatterlist に入らないようにする - パッチ前は
algif_aeadモジュールの無効化 が推奨されるecho "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif.confrmmod algif_aead 2>/dev/null || true
- 信頼できないワークロードを実行するコンテナ、サンドボックス、CI では、パッチ有無に関係なく seccomp による
AF_ALGソケット生成の遮断 が必要
無効化時の影響
- ほとんどのシステムでは 測定可能な影響はほぼない
dm-crypt / LUKS、kTLS、IPsec/XFRM、in-kernel TLS、OpenSSL/GnuTLS/NSS の標準ビルド、SSH、kernel keyring crypto は影響を受けない- これらはカーネル暗号化 API を直接利用しており、
AF_ALG経路を通らない
- これらはカーネル暗号化 API を直接利用しており、
- OpenSSL で
afalgエンジンを明示的に有効にしている場合、一部の組み込み暗号オフロード経路、aead/skcipher/hashソケットを直接 bind するアプリケーションは影響を受ける可能性があるlsof | grep AF_ALGまたはss -xaで確認できる
AF_ALGを無効化しても、もともとそれを呼び出していなかった対象は遅くならず、利用していた対象は一般的な userspace 暗号ライブラリへフォールバックする
一般的な Linux LPE と異なる点
- 一般的な Linux LPE と異なり、レース条件がなく、ディストリビューションごとのオフセットも不要
- 信頼性も 単発 100% とされ、狭いカーネルバージョン範囲ではなく 2017 年から 2026 年までの長期間をカバーする
- Python 標準ライブラリだけを使う 732バイトのサイズ なので、コンパイル済みペイロードや追加依存関係がない
- 書き込み経路が VFS を迂回 し、破損したページが dirty としてマークされないため、ディスクには何も書き込まれない
- ページキャッシュはホスト全体で共有されるため、単純な LPE を超えて コンテナ脱出プリミティブ としても機能する
動作原理と検知特性
- 非特権ローカルユーザーが Linux システムの 読み取り可能なファイルのページキャッシュ に制御可能な 4 バイトを書き込み、これを root 取得に利用できる
- 標的はディスク上の実ファイルではなく メモリ内のページキャッシュ であり、
/usr/bin/suのキャッシュコピーを変更すると、execveの観点ではバイナリ本体を変更したのと同等になる - ディスクに変化がないため inotify は反応せず、再起動やキャッシュ追い出し後には元のファイルが再ロードされる
sha256sum、AIDE、Tripwire のような一般的なハッシュツールはread()を通じてページキャッシュを読むため、キャッシュに破損が残っている間 は基準ハッシュと一致しない可能性がある- キャッシュが追い出されるか再起動されるとハッシュは再び元に戻り、ディスクフォレンジックイメージにも未改変のファイルしか残らない
- IMA appraisal enforcing mode で every-read measurement が有効なら、破損したバイナリは実行前の
execve時点で検出できる
他の脆弱性との違い
- Dirty Pipe と同系統であり、非特権 userspace からページキャッシュを破損させ、ディスク変更なしに setuid バイナリへ書き込んで root を得る点は共通している
- メカニズムは異なり、Dirty Pipe は pipe buffer flags を悪用し、Copy Fail は chained scatterlist 境界を越える AEAD scratch write を悪用する
- Dirty Pipe は特定のパッチが入ったカーネル 5.8 以降が必要だったが、Copy Fail は 2017 年から 2026 年までの範囲をカバーする
- Dirty Cow と異なり、TOCTOU ベースの COW レースに勝つ必要がなく、何度も試行したりシステムを不安定化させたりしない
追加の詳細
/usr/bin/suは必須ではなく、ユーザーが読み取れる setuid-root バイナリ であればpasswd、chsh、chfn、mount、sudo、pkexecも対象にできる- リモート脆弱性ではなく、まず 一般ユーザー権限でのローカルコード実行 が必要
- Web RCE が非特権サービスアカウントに落ちる場合、SSH foothold、CI ランナー上の悪意ある PR などの経路と組み合わせることで root につながる可能性がある
- パッチは
algif_aeadの in-place 最適化を巻き戻し、req->srcとreq->dstを再び分離した scatterlist にする - ページキャッシュページは読み取り専用 source にのみ残り、暗号化が書き込める対象はユーザーバッファのみになる
公開スケジュールと後続資料
- 2026-03-23 Linux カーネルセキュリティチームへ報告
- 2026-03-24 初期確認が行われた
- 2026-03-25 パッチが提案されレビューされた
- 2026-04-01 メインラインへパッチがコミットされた
- 2026-04-22 CVE-2026-31431 が割り当てられた
- 2026-04-29 https://copy.fail/ で公開
- Xint blog 技術分析
- root cause、scatterlist 図、2011→2015→2017 の沿革、エクスプロイトのウォークスルーを含む
- Kubernetes コンテナ脱出を扱う Part 2 は後日公開予定
Xint Code 関連情報
- AI-assisted な手法で発見され、出発点は
splice()がページキャッシュページを crypto subsystem に渡す点と、scatterlist のページ出所があまり探索されていないバグクラスかもしれないという人間の研究だった - その後 Xint Code が Linux
crypto/subsystem 全体の監査を約 1 時間規模に拡張し、その結果のうち 最も深刻な項目 が Copy Fail だった - Xint Code
- Xint blog write-up
- 同じスキャンで他の高リスクバグも発見されており、これらはまだ coordinated disclosure 中
1件のコメント
Hacker News の意見
Linux カーネルの crypto コードを扱う立場からすると、定期的に出てくる AF_ALG エクスプロイト には本当にうんざりする
AF_ALG は十分なレビューなしにずいぶん前にカーネルへ入ったもので、構造があまりに複雑なうえ、非特権の userspace プログラムに巨大な攻撃面を開いてしまっている
しかもほとんど不要だ。userspace にはすでに独自の暗号化コードがあり、カーネルの crypto コードはもともと dm-crypt のようなカーネル内部の用途向けのものだ
今回のエクスプロイトにある authencesn も、実質的には IPsec の内部実装の詳細であり、これを汎用的な userspace 向け暗号化/復号 API として公開したのはそもそも誤りだと思う
Linux カーネル設定を管理しているなら、すべての CONFIG_CRYPTO_USER_API_* オプションを無効化することを強く勧める
それだけでも、今回のバグだけでなく過去や将来の AF_ALG バグのかなりの部分は悪用不可能になっていたはずだ
もし userspace プログラムが壊れるなら、userspace の crypto コードへ移行するのを支援するのが正しく、実際すでにそう変わったものもある
そもそも AF_ALG は、エクスプロイト以外にはあまり使い道がなかった
以前ならこうした userspace API もそれなりに許容されたかもしれないが、syzbot や LLM 支援のバグ検出がある今では、もう持ちこたえるのは難しい
カーネルモードでしかアクセスできない ハードウェアアクセラレータ を userspace から使えるようにすること、鍵をアプリケーションメモリ内に長く残さずカーネルへ渡せること、組み込みのようにメモリが厳しい環境で userspace の crypto ライブラリよりフットプリントを減らせることが根拠として挙げられている
これが十分に妥当な正当化かは判断できないが、少なくとも理由自体はある
Linus はカーネルに何を入れるかかなり厳しいことで知られているので、こういう API が入った経緯は興味深い話になりそうだ
ハッシュと暗号化を一般的な
read(2)/write(2)呼び出しで扱えるようにする公開プロセスで何か 混乱 があったようだ
ベンダー各社がこの脆弱性を深刻に扱っておらず、そのため複数のディストリビューションでまだ未パッチのまま残っている
https://access.redhat.com/security/cve/cve-2026-31431 には "Moderate severity", "Fix deferred" とあり、Debian、Ubuntu、SUSE の追跡ページも似たような見え方だった
しかし upstream はこれを 脆弱性 として明確にコミュニケーションしておらず、Linus と Greg はカーネルでそうした分類自体を概念的にあまり重視しない傾向がある
それでもローカルで root 権限昇格が可能なのだから、通常は高優先度と見るのが妥当に思える
https://ubuntu.com/security/cves/about#priority
どの カーネルバージョン が脆弱で、どのバージョンで修正されたのかが本文にすぐ書かれていないのは残念だ
とくにこれは builtin モジュールなので
rmmodで簡単に外せないだけに、なおさらそう思うFedora 44 の kernel 6.19.14 が脆弱か確認しようとして、linux-cve-announce メーリングリストの投稿 https://lore.kernel.org/linux-cve-announce/2026042214-CVE-2026-31431-3d65@gregkh/T/#u を見つけた
そこには 6.18.22、6.19.12、7.0 でそれぞれ該当コミットによって修正されたと書かれていて、参考になった
推奨された緩和策どおりにカーネルモジュール
algif_aeadを modprobe 設定でブロックしたか確認したいなら、難読化されたシェルコードを丸ごと実行する必要はない以下のように Python を数行使うだけで、モジュールが実際にロードされるかを読みやすく確認できる
python3 -c 'import socket; s = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0); s.bind(("aead","authencesn(hmac(sha256),cbc(aes))")); print("algif_aead probably successfully loaded, mitigation not effective; remove again with: rmmod algif_aead")'緩和策が正しく適用されていれば、
modprobe algif_aeadもエラーで失敗するはずだ影響を受ける OS 上で 完全自律型 AI エージェント を一般ユーザー権限で動かしている人なんて、まさかいないよね
ゼロデイのプロンプトインジェクション と組み合わされると、かなり悲惨なことになり得る
curl | shでインストールするのを業界標準みたいにはしなかったよねLPE は local privilege escalation の意味だ
セキュリティ界隈の略語は多すぎて、文脈から推測はできたけれど、やはり最初は展開して書いてほしい
ただ、より幅広い読者に向けた文章なら明示的に定義しておく方がよいという点には同意する
しかもこの記事全体が AI 生成物 のようにも見える
これはちょっと笑える
ページには RHEL 14.3 で動くと書いてあるが、そんなバージョンは存在しない
現在の RHEL は 10.x なので、まるで TARDIS にでも乗ったのかと思った
gcc (GCC) 14.3.1 20250617 (Red Hat 14.3.1-2)のように表示されることがあり、下の例にも似た痕跡が見えるhttps://github.com/anthropics/claude-code/issues/40741
https://docs.oracle.com/en/database/oracle/tuxedo/22/otxig/software-requirements-red-hat-enterprise-linux-10-64-bit.html
6.12.0-124.45.1.el10_1とも書かれていて、それは明らかに RHEL 10 カーネルだこの手の誤字はむしろ人間がよくやる
コピペした長い数字は正確なのに、簡単な数字は手入力で打ち間違えるようなものだ
問題を説明するために情報を急いで集める過程があり、そう、マーケティング的な性格もあった
そのため細かなミスが少し入ってしまっていて、指摘に感謝している
https://access.redhat.com/articles/red-hat-enterprise-linux-release-dates
ページの一番下にある "Talk to our security experts" まで見たら、そのセキュリティ専門家の名前はもしかして Claude なのでは、という気分にさえなった
RHEL 9/10 では algif_aead がモジュールではなく builtin なので unload できなかった
そのため次善策として systemd 経由で AF_ALG をブロックする方法 を見つけ、露出している各サービスごとに drop-in が必要になる
主要な
sshdとuser@を扱う Ansible プレイブックもあるhttps://gist.github.com/m3nu/c19269ef4fd6fa53b03eb388f77464da
initcall_blacklist=algif_aead_initをカーネルのブートオプションに追加して再起動する方法も使えたそうするとエクスプロイトはもう動作しなかった
cronjobやslurmjobのような別の実行経路がどうなるのか気になるし、個別サービスごとに設定する代わりに、systemd レベルで全プロセスが継承するようにできる方法があればよいのだがこのエクスプロイトは SUID バイナリ を差し替えて PID 0 として実行させる方式のようだ
だがサイトは Kubernetes / container clusters や CI runners & build farms からの脱出まで可能だと主張している一方で、実際にコンテナ、特に user namespace 脱出 を裏づける説明は見当たらない
rootless Podman で試したところ、予想どおりコンテナから抜け出せなかった
また「2017 年以降にリリースされたすべての Linux ディストリビューションを root にする」とも主張していたが、実際にテストされたのは 4 つだけで、Alpine では動かなかった
"Next: "From Pod to Host," how Copy Fail escapes every major cloud Kubernetes platform."と予告しているhttps://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=72548b093ee3
ただし実際に悪用可能かどうかは、最新のメジャーリリースなのか、古いブランチのメンテナンスカーネルなのかによって変わるだろう
それでも PoC を 24.04 インスタンスで実際に動かしてみると、脆弱性自体は本物らしく、十分に大きな問題に見える
ただし影響を受けるディストリビューションの数は主張よりずっと少なそうで、2017 年以降のすべてのディストリビューション という表現とはかなり隔たりがある
たとえば Ubuntu は、私の解釈が正しければ 16.04 EOL にも多少影響があり、実際の主な影響は最近配布され始めた vendor カーネルである
linux-gcp、linux-oracle-6.7といった 6.17 系 にあるように見えるただし追加の手順は必要で、Alpine も根本的な脆弱性自体はあって、単にスクリプト調整が必要なだけかもしれない
結局のところ、これは完成された汎用エクスプロイトではなく PoC だ
ページ自体はかなり vibecoded っぽく広告臭もあるが、脆弱性は本物で、危険度も高そうだ
今日大きなセキュリティアップデートが来た理由が分かったので、更新の優先度を上げるべきだろう
実際にバグを見つけてパッチするという形で OSS エコシステムに意味のある貢献 をしつつ、同時に自分たちのセキュリティツールを売っている構図だからだ
ただ、今どき誰が Web ページを手作業でいちいち作るのかとも思うし、とくに カーネル開発者 ならなおさらそうだろう