注意:这篇文章上次更新于103天前,文章内容可能已经过时。
This article was last updated103 days ago, the content may be outdated.
太炸裂了!!!
4 月 30 日下班后刷短视频,发现了这个超级劲爆的安全漏洞:CVE-2026-31431,又名 Copy Fail。
它只需 10 行 Python 代码,就能完成 Linux 本地权限提升,直接获得 root 权限。而且这个漏洞从 2017 年就存在,几乎影响所有主流 Linux 发行版。

This is absolutely insane!!!
While scrolling through short videos after work on April 30th, I discovered this absolutely explosive security vulnerability: CVE-2026-31431, also known as Copy Fail.
It only takes 10 lines of Python to achieve Linux local privilege escalation and directly obtain root privileges. What’s more, this vulnerability has existed since 2017 and affects almost all mainstream Linux distributions.

效果演示
在非 root 用户下运行 copy_fail_exp.py,即可成功获得 root 权限。
就是这么直接。
1 | wgxls@server:~$ whoami |
脚本内容
脚本的 GitHub 链接:https://github.com/theori-io/copy-fail-CVE-2026-31431
1 | #!/usr/bin/env python3 |
这个脚本故意写的非常“简洁”,让我借助 AI 把它还原成更易读的版本:
1 | #!/usr/bin/env python3 |
脚本解析
我目前还不能完全把握这个漏洞的所有细节,但从网上的资料看,2017 年的这个 commit 72548b093ee3 引入了一个 in-place 优化。这个优化使得当内核收到一个包含页缓存页的 scatterlist 时,会直接把该页缓存页作为输出 scatterlist 的一部分进行写入,结果就是页缓存被污染。
在理解这个脚本之前,我们先把几个关键的 Linux 系统调用理清楚。
socket(AF_ALG, SOCK_SEQPACKET, 0):创建 AF_ALG 加密套接字。AF_ALG 是 Linux 内核提供的特殊地址族,用于让应用程序访问内核加密算法。SOCK_SEQPACKET 表示面向连接的消息套接字,0 表示默认协议。bind(("aead", "authencesn(hmac(sha256),cbc(aes))")):绑定到 authencesn AEAD 模板。“aead” 表示使用 AEAD 模式,“authencesn(hmac(sha256),cbc(aes))” 指定了 HMAC-SHA256 认证和 CBC-AES 加密,并启用了扩展序列号(ESN)。setsockopt():配置加密密钥和相关参数。accept():接受连接,获取一个可用于收发数据的套接字。sendmsg():发送消息和控制消息,触发加密运算。os.pipe():创建管道,返回读/写两个文件描述符。后续通过写端写入,通过读端读取。os.splice():在文件描述符间进行零拷贝传输。零拷贝意味着数据不经过用户空间缓冲区,而是在内核内部直接转发。这里的offset_src=0表示从源文件开头开始读取。recv():接收数据,同时触发解密/处理操作。
了解了这些调用后,脚本的核心逻辑可以这样理解:
- 脚本先创建 AF_ALG 套接字,绑定到 authencesn AEAD 模板,并设置密钥。
- 接着 accept 连接,准备发送加密请求。
write_pagecache_chunk()是关键部分,它构造一个加密请求,AAD 中包含攻击者可控的 chunk。调用sendmsg()后,内核在 authencesn 解密过程中误触发写操作,把 chunk 写入页缓存。- 通过
os.pipe()和os.splice(),脚本把目标文件/usr/bin/su的页缓存页引入 AF_ALG 输入,使 authencesn 的写入操作可以直接改写该页缓存。 - 最后调用
os.system("su"),内核从页缓存加载/usr/bin/su,因为缓存已经被污染,所以执行的是被篡改后的内容,最终获得 root shell。
修复与缓解措施
已提交的修复补丁 a664bf3d603dc3bdcf9ae47cc21e0daec706d7a5 通过撤销 algif_aead.c 的 in-place 优化回退到 out-of-place 操作。这意味着:
req->src指向 TX SGL(可能包含 splice 带来的页缓存页)req->dst指向 RX SGL(用户 recvmsg 缓冲区)- 不再将页缓存页链接到可写目标 scatterlist
这彻底切断了 authencesn scratch write 与页缓存写入之间的桥梁。
临时缓解方式:
- 更新内核补丁并使用发行版提供的安全更新。
- 通过 seccomp 禁止 AF_ALG 套接字创建。
- 禁用
algif_aead模块:
1 | echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif-aead.conf |
实测,禁用了 algif_aead 后,攻击脚本无法成功执行。
1 | wgxls@server:~$ python3 copy_fail_exp.py |
协调披露时间线
| 日期 | 事件 |
|---|---|
| 2026-03-23 | 向 Linux 内核安全团队报告漏洞 |
| 2026-03-24 | 收到初步确认 |
| 2026-03-25 | 补丁提议与审查 |
| 2026-04-01 | 补丁合并到主线内核 |
| 2026-04-22 | 分配 CVE-2026-31431 |
| 2026-04-29 | 公开披露Blog |
| 2026-04-30 | 互联网广泛传播 |
Demo
Running copy_fail_exp.py as a non-root user successfully grants root privileges.
It’s that direct.
1 | wgxls@server:~$ whoami |
Script Contents
The script’s GitHub link: https://github.com/theori-io/copy-fail-CVE-2026-31431
1 | #!/usr/bin/env python3 |
This script is deliberately written in a very “compact” style — let me use AI to restore it to a more readable version:
1 | #!/usr/bin/env python3 |
Script Analysis
I can’t fully grasp all the details of this vulnerability yet, but from online sources, this commit 72548b093ee3 from 2017 introduced an in-place optimization. This optimization made the kernel, when receiving a scatterlist containing page cache pages, directly write to that page cache page as part of the output scatterlist — the result being that the page cache gets polluted.
Before understanding this script, let’s clarify a few key Linux system calls first.
socket(AF_ALG, SOCK_SEQPACKET, 0): Creates an AF_ALG crypto socket. AF_ALG is a special address family provided by the Linux kernel that lets applications access kernel crypto algorithms. SOCK_SEQPACKET means a connection-oriented message socket, and 0 means the default protocol.bind(("aead", "authencesn(hmac(sha256),cbc(aes))")): Binds to the authencesn AEAD template. “aead” means using AEAD mode, and “authencesn(hmac(sha256),cbc(aes))” specifies HMAC-SHA256 authentication and CBC-AES encryption with extended sequence numbers (ESN) enabled.setsockopt(): Configures the crypto key and related parameters.accept(): Accepts the connection, obtaining a socket that can be used to send and receive data.sendmsg(): Sends messages and control messages, triggering the crypto operation.os.pipe(): Creates a pipe, returning read/write file descriptors. Data is written through the write end and read from the read end.os.splice(): Performs zero-copy transfer between file descriptors. Zero-copy means data doesn’t pass through user-space buffers, but is forwarded directly inside the kernel. Hereoffset_src=0means reading from the beginning of the source file.recv(): Receives data while triggering the decryption/processing operation.
With these calls understood, the core logic of the script can be understood like this:
- The script first creates an AF_ALG socket, binds to the authencesn AEAD template, and sets the key.
- Then it accepts the connection, ready to send the crypto request.
write_pagecache_chunk()is the key part — it constructs a crypto request whose AAD contains an attacker-controlled chunk. After callingsendmsg(), the kernel mistakenly triggers a write operation during the authencesn decryption process, writing the chunk into the page cache.- Through
os.pipe()andos.splice(), the script brings the page cache page of the target file/usr/bin/suinto the AF_ALG input, allowing authencesn’s write operation to directly modify that page cache page. - Finally it calls
os.system("su"). The kernel loads/usr/bin/sufrom the page cache; since the cache has been polluted, what gets executed is the tampered content, ultimately yielding a root shell.
Fix and Mitigation
The submitted fix patch a664bf3d603dc3bdcf9ae47cc21e0daec706d7a5 reverts the in-place optimization in algif_aead.c back to out-of-place operation. This means:
req->srcpoints to the TX SGL (which may contain page cache pages brought in by splice)req->dstpoints to the RX SGL (the user’s recvmsg buffer)- Page cache pages are no longer linked into a writable destination scatterlist
This completely severs the bridge between the authencesn scratch write and page cache writes.
Temporary mitigations:
- Update the kernel patch and use the security updates provided by your distribution.
- Block AF_ALG socket creation via seccomp.
- Disable the
algif_aeadmodule:
1 | echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif-aead.conf |
In my tests, after disabling algif_aead, the exploit script fails to execute successfully.
1 | wgxls@server:~$ python3 copy_fail_exp.py |
Coordinated Disclosure Timeline
| Date | Event |
|---|---|
| 2026-03-23 | Vulnerability reported to the Linux kernel security team |
| 2026-03-24 | Initial confirmation received |
| 2026-03-25 | Patch proposed and reviewed |
| 2026-04-01 | Patch merged into mainline kernel |
| 2026-04-22 | CVE-2026-31431 assigned |
| 2026-04-29 | Public disclosure Blog |
| 2026-04-30 | Widely spread across the internet |


