Copy Fail (CVE-2026-31431): 9-year-old Linux kernel LPE via AF_ALG/splice()
Xint/Theori researchers detail CVE-2026-31431 ('Copy Fail'), a Linux kernel logic bug where the authencesn AEAD crypto template writes 4 attacker-controlled bytes past its output buffer, and AF_ALG's 2017 in-place optimization chains page-cache pages from splice() into that writable scatterlist. This lets an unprivileged local user corrupt the in-memory page cache of any readable file (e.g. /usr/bin/su) without touching disk, yielding a race-free, portable root exploit in a 732-byte Python script across Ubuntu, Amazon Linux, RHEL and SUSE. The post traces the bug's origin across 2011/2015/2017 kernel commits, walks through the exploit and the out-of-place fix, and notes the flaw was found via an AI-assisted scan (Xint Code) guided by researcher Taeyang Lee.
What it is
Copy Fail (CVE-2026-31431) is a Linux kernel local privilege escalation in the authencesn AEAD crypto template, reachable by any unprivileged user through AF_ALG sockets. It yields a deterministic (no-race, no-retry) controlled 4-byte write into the page cache of any file the user can read. Xint's team confirmed root on Ubuntu, Amazon Linux, RHEL, and SUSE across kernel lines 6.12, 6.17, and 6.18 with a single unmodified 732-byte Python script.
How it works
splice() passes page-cache pages by reference into an AF_ALG socket's scatterlist. Since 2017 (commit 72548b093ee3), algif_aead.c ran AEAD decryption in-place: AAD and ciphertext are copied into the user's RX buffer, but the tag pages are chained by reference (sg_chain) into the writable destination, with req->src = req->dst. authencesn alone among AEAD templates uses the destination as scratch space for ESN sequence-number rearrangement, writing 4 bytes at dst[assoclen + cryptlen] — past the tag — and never restoring them. In the in-place path that write lands in the chained page-cache page. HMAC then fails and recvmsg errors, but the 4-byte write persists.
The attacker controls all three variables: which file (any readable), which offset (via splice offset/length and assoclen), and which value (AAD bytes 4–7).
Preconditions / Affected
- Kernels with the 2017 in-place optimization: distributions shipped since 2017, confirmed on 6.12–6.18.
- AF_ALG available to unprivileged users (default) and
algif_aeadloadable. - Python 3.10+ on the target for
os.splice(for this specific PoC). - Bug crosses container boundaries — page cache is host-shared, making it a container-escape / Kubernetes node-compromise primitive (detailed in the vendor's Part 2, not this post).
What to do
Patch the kernel via normal distribution updates. The upstream fix (a664bf3d603d) reverts AF_ALG AEAD to out-of-place operation, removing the sg_chain of page-cache pages into the writable destination.
Immediate mitigation — block the module or AF_ALG via seccomp:
echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif-aead.conf
rmmod algif_aead 2>/dev/nullCaveats
- Stealth: the corrupted page is never marked dirty, so on-disk file integrity checks (checksum comparison) miss the modification — but the corrupted in-memory version is what
execve/read/mmapactually see, system-wide. - The default exploit targets
/usr/bin/su; the primitive is generic to any readable setuid binary. - The scan reportedly found additional high-severity kernel bugs (including another LPE) still under coordinated disclosure — expect follow-on advisories.
Organisations named here
- authencesn
- Dirty Cow
- Dirty Pipe
- Taeyang Lee
- Theori
CVEs named here
- CVE-2026-31431
- CVE-2016-5195
- CVE-2022-0847
Technologies named here
- Xint Code
- Linux kernel
- Ubuntu
- AF_ALG
- Amazon Linux
- RHEL
- SUSE
- Python
Techniques named here
- Cross-container page cache corruption
Related in Offensive Security