本プロジェクトは、Linux Kernel Copy Fail(CVE-2026-31431)脆弱性の動作原理を分析し、公開PoCリポジトリの非破壊的checkerを用いてパッチ前後の状態を比較したミニプロジェクトです。
実際のsetuidバイナリ改ざんや/etc/passwd改ざんexploitは実行せず、一時testfileベースの安全な脆弱性有無確認と、検知/緩和の観点からの分析に焦点を当てています。
このプロジェクトの目的は、単にexploitを実行することではなく、Linuxカーネル脆弱性がどのような内部構造の組み合わせで発生するかを理解し、運用の観点からどのように確認し対応できるかを整理することです。
進行範囲は以下の通りです。
脆弱性原理分析
↓
PoCコード構造分析
↓
非破壊的checkerに基づく実習
↓
パッチ前後比較
↓
検知/緩和策まとめ
本実習では、copy-fail-cリポジトリのvulnerable.cのみを実行しました。
| 区分 | パッチ前 | パッチ後 |
|---|
| OS | Ubuntu 24.04.2 LTS | Ubuntu 24.04.4 LTS |
| Kernel | 6.8.0-53-generic | 6.8.0-134-generic |
| アカウント | 一般ユーザーclient | 一般ユーザーclient |
| checker | vulnerable | vulnerable |
| テスト方式 | 一時testfileベース非破壊検査 | 同一checker再実行 |
パッチ前カーネル情報:
Linux ubuntu-server 6.8.0-53-generic #55-Ubuntu SMP PREEMPT_DYNAMIC Fri Jan 17 15:37:52 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
パッチ後カーネル情報:
Linux ubuntu-server 6.8.0-134-generic #134-Ubuntu SMP PREEMPT_DYNAMIC Fri Jun 26 18:43:11 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
カーネルパッケージ変更概要:
- linux-image-6.8.0-53-generic 6.8.0-53.55
- linux-image-generic 6.8.0-53.55+1
+ linux-image-6.8.0-134-generic 6.8.0-134.134
+ linux-image-generic 6.8.0-134.134
+ linux-generic 6.8.0-134.134
+ linux-headers-generic 6.8.0-134.134
Copy Failは、LinuxカーネルのAF_ALG AEAD処理経路とsplice() zero-copy動作が結合され、読み取り専用ファイルのpage cacheが誤った書き込み対象として使用される可能性がある脆弱性です。
核心的な構成要素は以下の通りです。
| 要素 | 役割 |
|---|---|
| Linux page cache | ディスクファイルの内容をRAMにキャッシュするカーネルメカニズム |
splice() | データをユーザー空間にコピーせず、カーネル内部で参照として接続するzero-copy syscall |
AF_ALG | ユーザー空間からLinux kernel crypto APIをソケットのように使用できるインターフェース |
| AEAD in-place処理 | 入力バッファと出力バッファを別にせず、同じバッファで処理する最適化 |
authencesn | AEAD処理中に4バイトのscratch writeが発生するcrypto template |
脆弱性の核心的な流れは以下の通りです。
読み取り可能なファイル
↓
Linux page cacheに載る
↓
splice()でAF_ALG crypto経路にpage cache referenceを渡す
↓
AEAD in-place処理により入力と出力のscatterlistが絡む
↓
authencesn処理中に4バイトのscratch writeが発生
↓
別途出力バッファではなく、page cacheに書き込み発生
↓
page cache mutation発生
つまり、splice()はpage cache referenceを渡し、AEAD in-place処理は入力と出力を同じ経路に絡め、authencesnは実際の4バイト書き込みを発生させる役割を果たします。
実習に使用したリポジトリ構造は以下の通りです。
copy-fail-c/
├── exploit.c
├── exploit-passwd.c
├── vulnerable.c
├── payload.c
├── utils.c
├── utils.h
├── Makefile
└── nolibc/
| ファイル | 役割 | 本実習での使用有無 |
|---|---|---|
utils.c, utils.h | AF_ALG/spliceベースのpage cache mutation primitive実装 | 分析及びvulnerable実行に使用 |
vulnerable.c | 一時testfileベースの非破壊的脆弱性有無確認ツール | 実行 |
exploit.c | setuid rootバイナリ page cache改ざん variant | 実行しない |
exploit-passwd.c | /etc/passwd page cache改ざん variant | 実行しない |
payload.c | root権限で実行されるpayload | 実行しない |
Makefile | ビルド自動化 | vulnerable targetのみ使用 |
nolibc/ | 小規模なstatic ELF payloadビルド用軽量libc代替コード | 分析のみ |
utils.cutils.cの核心はpatch_chunk()系のpage cache mutation primitiveです。この関数はAF_ALGとsplice()を利用して対象ファイルのpage cacheをcrypto処理経路に接続し、脆弱なカーネルではAEAD処理中にpage cacheの一部が上書きされるかを確認します。
vulnerable.cvulnerable.cは実際のシステムファイルに触れません。現在のディレクトリに一時testfileを作成し、そのファイルのpage cacheが改ざんされるかを確認します。
本プロジェクトではこのファイルのみを実行しました。
カーネル更新を実行する前に、OS、カーネル、パッケージの状態を記録しました。
mkdir -p ~/copyfail-mini/{before,after,logs}
cd ~/copyfail-mini
uname -a | tee before/uname.txt
cat /etc/os-release | tee before/os-release.txt
dpkg -l | grep -E 'linux-image|linux-headers|linux-generic|linux-virtual' | tee before/kernel-package.txt
git clone https://github.com/jihwan77/copy-fail-c.git
cd copy-fail-c
make clean
make vulnerable
本実習では、デフォルトのmakeでexploitバイナリを一緒にビルドせず、vulnerable targetのみ使用しました。
./vulnerable > ../before/vulnerable-output.txt 2>&1
echo $? >> ../before/vulnerable-output.txt
cat ../before/vulnerable-output.txt
パッチ前実行結果:

判断:
exit code 100
→ page cache mutation確認
→ パッチ前カーネルでCopy Fail primitive動作確認
パッチ前結果を保存後、Ubuntuパッケージ更新を実行しました。
sudo apt update
sudo apt full-upgrade -y
sudo reboot
再起動後のカーネルは以下のように変更されました。
Before: 6.8.0-53-generic
After : 6.8.0-134-generic
cd ~/copyfail-mini/copy-fail-c
make clean
make vulnerable
./vulnerable > ../after/vulnerable-output.txt 2>&1
echo "exit_code=$?" >> ../after/vulnerable-output.txt
cat ../after/vulnerable-output.txt
パッチ後実行結果:

結果比較:
| 項目 | パッチ前 | パッチ後 |
|---|---|---|
| Kernel | 6.8.0-53-generic | 6.8.0-134-generic |
| Checker結果 | VULNERABLE | authencesn template not registered |
| Exit Code | 100 | 2 |
| Page cache mutation | 確認 | checkerがmutation段階まで進行せず |
| 解釈 | Copy Fail primitive動作 | PoCが要求するAEAD/authencesn経路への進入失敗 |
パッチ後のexit_code=2は単に「脆弱でない」ことを意味するわけではありません。正確には以下の通りです。
AF_ALGのauthencesn(hmac(sha256),cbc(aes)) templateが登録されておらず、
checkerが脆弱性有無を直接判定できない状態
追加確認の結果、Ubuntu更新後algif_aeadモジュールのロードがブロックされていました。
lsmod | grep -E 'af_alg|algif_aead'
結果:
af_alg 32768 0
algif_aeadはロードされていませんでした。
sudo modprobe algif_aead
結果:
modprobe: ERROR: ../libkmod/libkmod-module.c:1084 command_do() Error running install command '/bin/false' for module algif_aead: retcode 1
modprobe: ERROR: could not insert 'algif_aead': Invalid argument
ブロック設定確認:
grep -R "algif_aead" /etc/modprobe.d /lib/modprobe.d 2>/dev/null
結果:
/etc/modprobe.d/disable-algif_aead.conf:# Disable algif_aead module due to CVE-2026-31431 (AKA copy.fail)
/etc/modprobe.d/disable-algif_aead.conf:install algif_aead /bin/false
したがって、パッチ後の結果は以下のように解釈するのが正確です。
Ubuntuセキュリティ更新後、カーネルが6.8.0-134-genericに変更され、
kmodベースのalgif_aeadモジュールブロック緩和が適用されました。
その結果、copy-fail-cのvulnerable checkerは
PoCが要求するauthencesn(hmac(sha256),cbc(aes)) AF_ALG templateにbindできず、
page cache mutation段階まで進行しませんでした。
つまり、本実習で確認したのは「カーネルコードパッチのみの効果」ではなく、Ubuntuセキュリティ更新後、カーネル更新とalgif_aeadモジュールブロック緩和が適用され、同一PoC経路が進行しない状態です。
Copy Failはディスクファイルを直接修正せずにpage cacheを改ざんできるため、ファイルハッシュベースの検知だけでは限界があります。そのため、syscall行動ベースの検知が重要です。
本実習ではauditdを利用して以下のsyscallを観察しました。
sudo auditctl -a always,exit -F arch=b64 -S socket -F a0=38 -k copyfail_afalg
sudo auditctl -a always,exit -F arch=b64 -S bind -k copyfail_bind
sudo auditctl -a always,exit -F arch=b64 -S splice -k copyfail_splice
sudo auditctl -a always,exit -F arch=b64 -S sendmsg -k copyfail_sendmsg
socket(AF_ALG)検知ログでvulnerableプロセスがAF_ALG socketを生成したことが確認されました。
comm=vulnerable
syscall=socket
success=yes
a0=alg
key=copyfail_afalg
bind()失敗検知パッチ後/緩和後環境では、vulnerableプロセスがauthencesn templateにbindしようとしましたが失敗しました。
comm=vulnerable
syscall=bind
success=no
exit=ENOENT(No such file or directory)
saddr_fam=alg
key=copyfail_bind
これは、パッチ後環境でPoCがAF_ALG socket生成までは実行したが、authencesn(hmac(sha256),cbc(aes)) template bind段階で失敗したことを意味します。
splice() / sendmsg()ログの解釈パッチ後はbind()段階で失敗したため、checkerはsplice()とsendmsg()の段階まで進行しませんでした。したがって、該当syscallログではvulnerable実行フローが有意に観察されませんでした。
運用環境でCopy Fail系脆弱性を観察する際は、以下の行動の組み合わせが見られます。
| 検知対象 | 意味 |
|---|---|
socket(AF_ALG, ...) | カーネルcrypto API使用試行 |
bind() with authencesn | AEAD/authencesn crypto template使用試行 |
splice() | ファイルpage cache referenceをカーネル内部経路に渡す |
sendmsg() / recvmsg() | AF_ALG crypto request実行 |
| setuid binary実行 | 権限昇格cashoutの可能性 |
本実習では、socket(AF_ALG)とbind()失敗イベントをauditdで確認しました。
最も基本的な対応は、ディストリビューションのセキュリティ更新を適用することです。
sudo apt update
sudo apt full-upgrade -y
sudo reboot
本実習では更新後、Ubuntu 24.04.4 / kernel 6.8.0-134-generic環境に変更されました。
algif_aeadモジュールのブロックUbuntu更新後、以下の設定が確認されました。
/etc/modprobe.d/disable-algif_aead.conf
install algif_aead /bin/false
この設定はalgif_aeadモジュールのロードをブロックし、PoCが要求するAF_ALG AEAD経路への進入を防ぎます。
一般的なサーバーアプリケーションでAF_ALGを直接使用するケースは多くない可能性があるため、socket(AF_ALG)呼び出しは検知ポイントとして活用できます。
本実習の結果は以下のようにまとめられます。
パッチ前:
Ubuntu 24.04.2 / kernel 6.8.0-53-generic
vulnerable checker exit code 100
page cache mutation確認
→ Copy Fail primitive動作確認
パッチ後:
Ubuntu 24.04.4 / kernel 6.8.0-134-generic
vulnerable checker exit code 2
authencesn template bind失敗
algif_aeadモジュールブロック設定確認
→ 同一PoC経路がpage cache mutation段階まで進行せず
したがって、本プロジェクトの結論は以下の通りです。
パッチ前のカーネルでは、Copy Failのpage cache mutation primitiveが実際に動作した。
その後、Ubuntuセキュリティ更新を適用すると、カーネルが6.8.0-134-genericに変更され、kmodベースと思われるalgif_aeadモジュールブロック設定が適用された。
その結果、PoCが要求するauthencesn(hmac(sha256),cbc(aes))AF_ALG templateにbindできず、同一checkerがpage cache mutation段階まで進行しなかった。
つまり、本実習結果では「カーネルコードパッチ自体がpage cache mutationを直接ブロックした」とは言えませんが、現時点までのログと結果から確実に言えるのは、Ubuntuセキュリティ更新後にalgif_aeadモジュールブロック緩和が適用され、PoC経路がブロックされたという点です。
Ubuntu Security Notice - USN-8226-1: kmod update
https://ubuntu.com/security/notices/USN-8226-1
Ubuntu Blog - Fixes available for CVE-2026-31431 Copy Fail
https://ubuntu.com/blog/copy-fail-vulnerability-fixes-available
copy-fail-c PoC repository
https://github.com/jihwan77/copy-fail-c
このプロジェクトを通じて確認した核心は以下の通りです。
1. Copy Failは、AF_ALG, splice(), AEAD in-place, authencesn, page cacheが結合されたカーネル脆弱性である。
2. パッチ前のUbuntu 24.04.2 / kernel 6.8.0-53環境で非破壊checkerがpage cache mutationを確認した。
3. パッチ後のUbuntu 24.04.4 / kernel 6.8.0-134環境ではauthencesn bind段階で失敗した。
4. 追加確認の結果、algif_aeadモジュールロードが /bin/false 設定でブロックされていた。
5. auditdを通じてsocket(AF_ALG)及びbind失敗イベントを観察できた。
6. 運用対応は、カーネル/セキュリティパッケージ更新、algif_aead制限、AF_ALG syscall監視、setuidバイナリ点検としてまとめられる。