Linux Kernel algif_aead In-Place Page-Cache Write Local Privilege Escalation (CVE-2026-31431)
Severity Assessment
- Exploitability: 9/10
- Impact: 9/10
- Weaponization Risk: 10/10
- Patch Urgency: 10/10
- Detection Coverage: 2/10
Summary
CVE-2026-31431, known as “Copy Fail,” is a logic flaw (CWE-669: Incorrect Resource Transfer Between Spheres) in the Linux kernel’s algif_aead AEAD crypto socket interface (AF_ALG). An unprivileged local attacker can exploit the flaw to write 4 bytes into the page cache of a setuid binary, then execute that binary to obtain a root shell. The exploit is straight-line — it requires no race window and no per-distribution kernel offsets — and a 732-byte Python script achieves root privileges on Linux distributions running affected kernels.
The Linux kernel’s AF_ALG (Algorithm) socket family exposes the in-kernel cryptographic subsystem to userspace over a socket interface. The algif_aead module provides the AEAD (Authenticated Encryption with Associated Data) socket front-end. In 2017, commit 72548b093ee3 introduced an in-place optimization to algif_aead: instead of maintaining separate source and destination buffers for AEAD operations, the code attempted to perform the crypto transformation directly in-place. Because AEAD operations in AF_ALG source their input from one page-cache mapping and write their output to a separate mapping, there is no valid in-place optimization — the source and destination occupy different pages in memory. The incorrect in-place operation writes crypto output into unintended page-cache entries, allowing an attacker to craft a targeted write into a file of their choice.
The flaw was present from Linux 4.14 (released November 2017) until the patch was committed to mainline on April 1, 2026. Xint Code (Theori) discovered the vulnerability and reported it to the Linux kernel security team on March 23, 2026. Public disclosure occurred on April 29, 2026, alongside publication of a 732-byte standalone Python PoC. CISA added CVE-2026-31431 to the Known Exploited Vulnerabilities catalog on May 1, 2026, with a required remediation deadline of May 15, 2026 for U.S. federal civilian agencies.
The CVSS 3.1 base score is 7.8 (HIGH; AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H). Low-complexity local exploitation requires no user interaction. The privileged outcome is root execution, and the vulnerable code path is common across affected distribution kernels. The page-cache write is not visible to on-disk file-integrity monitoring tools, crosses container boundaries on shared-kernel platforms, and does not survive a reboot (the modified page-cache entry is evicted on the next cold read of the file from disk), but root access obtained before reboot can support subsequent persistence actions.
The exploit was verified by Xint Code against Ubuntu 24.04 LTS, Amazon Linux 2023, RHEL 10.1, and SUSE 16. Any distribution running a kernel in the affected range with algif_aead loadable is in scope in its default configuration.
Exploit Chain
The vulnerability is rooted in algif_aead’s incorrect in-place AEAD operation, which allows a crafted AF_ALG socket interaction to write 4 arbitrary bytes into any page-cache entry accessible to the local user.
Stage 1: AF_ALG AEAD Socket Setup
The attacker creates an AF_ALG socket of type aead and requests the authencesn(hmac(sha1),cbc(aes)) algorithm — the authencesn (Authenticated Encryption with Sequence Numbers) composite transform. The authencesn transform is built into all affected default kernel configurations. The attacker sets valid key material and IV via setsockopt, then accept()s an operation file descriptor.
Stage 2: splice() Scatterlist Manipulation
The attacker pipes data through splice() to deliver page-cache pages as the destination scatterlist for the AEAD encrypt operation. Because algif_aead incorrectly treats the operation as in-place (source and destination sharing the same buffer), the kernel crypto engine writes its output into the source pages — which are the attacker’s target page-cache entries — rather than into separate destination pages.
Stage 3: Page-Cache Write
The AEAD encrypt operation writes 4 bytes of attacker-controlled data into a page-cache page. By opening /usr/bin/su (or another setuid-root binary) before the splice, the attacker arranges for that binary’s in-memory page-cache pages to be the destination of the write. The on-disk file is never modified; only the kernel’s in-memory representation changes. File-integrity monitoring tools that hash the on-disk copy do not detect the modification.
Stage 4: Setuid Binary Execution
The attacker executes the modified setuid binary. The kernel loads the in-memory (page-cache) version, which includes the 4-byte payload at the attacker’s chosen offset. The payload redirects execution to attacker-supplied shellcode, with the entire execution occurring in a setuid-root context (uid=0).
Stage 5: Root Shell
The injected payload spawns a Unix shell. Because execution is in a setuid-root context, the shell runs with effective uid=0. The 732-byte Python PoC (copy_fail_exp.py), published by Theori at https://github.com/theori-io/copy-fail-CVE-2026-31431, performs all five stages end-to-end in a Python process using only the standard library (os, socket, zlib). No root, no special capabilities, no additional tooling are required beyond Python 3.10 and a local user account.
Stage 6: Container Escape Primitive
The page cache is shared across the host kernel. A container with access to AF_ALG sockets can target page-cache pages belonging to setuid binaries visible on the host kernel’s page cache, making the exploit a container escape primitive in shared-kernel environments (Kubernetes worker nodes, Docker, LXC) where AF_ALG socket creation is not blocked via seccomp.
Detection Guidance
- Apply vendor kernel patches. Linux distributions are shipping backports of mainline commit
a664bf3d603d. Patched stable series cutoffs: 5.10.254, 5.15.204, 6.1.170, 6.6.137, 6.12.85, 6.18.22, 6.19.12, and the upstream merge into 7.0-rc development. Verify installed kernel version withuname -rand cross-reference against distribution security advisories. - As an interim workaround before patching, disable the
algif_aeadkernel module. This prevents the exploit without affecting dm-crypt/LUKS, kTLS, IPsec, SSH, or default OpenSSL builds:echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif.conf && rmmod algif_aead. Verify removal withlsmod | grep algif_aead. - Block
AF_ALGsocket creation via seccomp policy in container workloads and CI runner sandboxes regardless of patch state. In Kubernetes, apply a seccomp profile that deniessocket()calls with domain value 38 (AF_ALG). This eliminates the attack surface for workloads that do not use AF_ALG. - Monitor for unexpected execution of setuid binaries (particularly
/usr/bin/su,/usr/bin/newuidmap,/usr/bin/newgidmap) by processes whose effective uid was non-zero and where no corresponding PAM authentication record appears in/var/log/auth.logor the systemd journal. - Monitor for
AF_ALGsocket creation by non-root processes using auditd:auditctl -a always,exit -F arch=b64 -S socket -F a0=38 -k af_alg_socket. This captures everysocket(AF_ALG, ...)call from an unprivileged process. - Deploy runtime security tooling (Falco, Tetragon, or equivalent eBPF-based monitor) with a rule detecting the syscall sequence
socket(AF_ALG)→setsockopt→accept→splice→execveof a setuid binary within the same process lineage. - In container environments, audit all running workloads for the absence of a default seccomp profile. Pods running with
seccompProfile: UnconfinedhaveAF_ALGsocket access and are exploitable on unpatched hosts. - For environments that cannot patch or disable
algif_aeadimmediately, consider settingkernel.unprivileged_af_alg_disabled=1if the kernel build supports this sysctl, restrictingAF_ALGsocket creation to root-only.
Indicators of Compromise
Indicators consistent with CVE-2026-31431 exploitation include:
AF_ALGsocket creation (syscallsocketwith domain 38) by a non-root, non-cryptographic-service process, particularly when followed within milliseconds bysetsockopt,accept,splice, andexecveof a setuid binary.splice()activity connecting a pipe to anAF_ALGaccept file descriptor, sourced from a file descriptor pointing to a page-cache-backed file in/usr/bin/or/usr/lib/.- Execution of
/usr/bin/suor another setuid binary producing a child process withuid=0where the parent process’s effective uid was non-zero and no PAM authentication record (su: pam_unix) appears in/var/log/auth.logor the systemd journal. - Presence of
copy_fail_exp.pyor files with the SHA-256 hasha567d09b15f6e4440e70c9f2aa8edec8ed59f53301952df05c719aa3911687f9on the filesystem. - Python 3 processes spawning a shell (e.g.,
python3 → /bin/bash -i) where the resulting shell runs as uid=0 and no sudo or su interactive authentication is logged. - In Kubernetes or Docker environments: a container process obtaining root capability on the host PID namespace or accessing host filesystem paths outside its mount namespace, traceable to
AF_ALGsocket activity within the container. - Audit log entries showing repeated
type=SYSCALL syscall=socket a0=26(hex) ora0=38(decimal, AF_ALG) from unprivileged processes, particularly clustered in rapid succession as an exploit may retry.
Disclosure Timeline
2017-11-12 — Vulnerable code introduced (Linux 4.14)
Linux kernel 4.14 was released, incorporating commit 72548b093ee3 which introduced the flawed in-place AEAD operation in algif_aead. The incorrect resource transfer between page-cache spheres was present in subsequent kernel releases until patched.
2026-03-23 — Reported to Linux kernel security team
Xint Code (Theori) reported CVE-2026-31431 to the Linux kernel security team via the private security disclosure channel.
2026-03-24 — Initial acknowledgment
The Linux kernel security team acknowledged receipt and confirmed the report.
2026-03-25 — Patch proposed and reviewed
Patches reverting the flawed in-place optimization were proposed and reviewed within the kernel security response process.
2026-04-01 — Patch committed to mainline
The fix — reverting commit 72548b093ee3 while preserving the associated data copy behavior — was committed to the Linux mainline kernel. Stable backport patches were queued for all affected stable series (5.10.x, 5.15.x, 6.1.x, 6.6.x, 6.12.x, 6.18.x, 6.19.x).
2026-04-22 — CVE-2026-31431 assigned; kernel CVE announcement published
CVE-2026-31431 was assigned by the kernel CVE numbering authority. Greg Kroah-Hartman published the CVE announcement to the linux-cve-announce mailing list. NVD published the entry with CVSS 3.1 score 7.8 (HIGH) and weakness CWE-669. The fix commit was backported to all stable series by the Linux Kernel Stable Tree.
2026-04-29 — Public disclosure; PoC published
Xint Code (Theori) published the “Copy Fail” disclosure at https://copy.fail, alongside the 732-byte PoC exploit copy_fail_exp.py on GitHub (theori-io/copy-fail-CVE-2026-31431). The technical write-up was published at https://xint.io/blog/copy-fail-linux-distributions. Multiple Linux distribution security teams published advisories.
2026-05-01 — CISA adds CVE-2026-31431 to KEV
CISA added CVE-2026-31431 to the Known Exploited Vulnerabilities catalog, confirming active in-the-wild exploitation. Required remediation deadline for U.S. federal civilian agencies under BOD 22-01: 2026-05-15.
Sources & References
- National Vulnerability Database: CVE-2026-31431 — National Vulnerability Database, 2026-04-22
- CISA: Known Exploited Vulnerabilities Catalog — CVE-2026-31431 — CISA, 2026-05-01
- Linux Kernel Stable Tree: algif_aead fix commit a664bf3d — Linux Kernel Stable Tree, 2026-04-01
- Xint Code: Copy Fail CVE-2026-31431 Researcher Disclosure — Xint Code, 2026-04-29
- Xint Code: Copy Fail Technical Write-Up — Xint Code, 2026-04-29
- Theori: Copy Fail CVE-2026-31431 Proof of Concept — Theori, 2026-04-29