By falco365 · Published April 29, 2026

CVE-2026-31431: Copy Fail — four bytes into the Linux page cache for root

A 2017 algif_aead in-place optimization lets an unprivileged user write four controlled bytes into the page cache of any readable file. 732-byte exploit, no race condition, every Linux distribution since 2017 — including across containers.

CVE-2026-31431: Copy Fail — four bytes into the Linux page cache for root
Analysis

CVE-2026-31431, codenamed Copy Fail by Xint.io and Theori, is a Linux kernel local privilege escalation rooted in a 2017 in-place optimization in the algif_aead module. An unprivileged local user can drive a four-byte write into the page cache of any file they have read access to, using a 732-byte Python exploit that requires no kernel offsets, no race condition, and works across every Linux distribution shipped since the bad commit landed. The page cache is shared across containers on the same host, so a low-privilege user inside one container can corrupt a setuid binary visible to processes on the host or in sibling containers.

What the bug actually is

The kernel's algif_aead module exposes Authenticated Encryption with Associated Data (AEAD) operations to userspace through the AF_ALG socket family. In August 2017, commit 72548b093ee3 changed AEAD operations to run in-place: the destination scatterlist for the cipher's output was allowed to point at the same memory as the source. The intent was a small performance win for kernel crypto consumers.

The flaw: when userspace submits an AEAD operation over AF_ALG and feeds it data via splice() from a pipe, the kernel can end up with a page-cache page in the writable destination scatterlist — a page belonging to a file the calling process does not own. The cipher then writes its output back into that page-cache page. The output is small (a few bytes of AEAD ciphertext), but it lands in the page cache of an arbitrary readable file, and from the kernel's perspective it is the most recent version of the file's contents.

The patch is, almost literally, a revert: crypto: algif_aead — Revert to operating out-of-place. The 2017 optimization is removed; only the small benefit of copying associated data is preserved.

The exploit, in four steps
  • 1. Open an AF_ALG socket and bind to the cipher authencesn(hmac(sha256),cbc(aes)).
  • 2. Construct a payload whose AEAD output, when written into a target page, lands a controlled four-byte value at a controlled offset.
  • 3. Drive a write into the kernel's cached copy of /usr/bin/su (or any other readable file the attacker chooses) by routing the AEAD operation through splice() against a pipe whose pages overlap with the target file's page cache.
  • 4. Call execve("/usr/bin/su") — the kernel loads the corrupted page from cache, executes the injected shellcode in the suid context, and the calling user gets a root shell.

Four bytes is enough. With careful selection of the target instruction in the setuid binary, the attacker doesn't need to write a full payload — they just need to flip a check or rewire a control-flow edge. The published research notes that the same primitive can be used against any setuid binary on the system, not just su.

Why this is dangerous in 2026 specifically

Three properties together make Copy Fail a near-worst-case Linux LPE:

  • Reliability — no race condition, no kernel offset leak required. The exploit works deterministically on first run.
  • Portability — the bug is in upstream code. Every distribution that backported the 2017 optimization is affected, which is essentially all of them. Amazon Linux, Debian, RHEL, SUSE, and Ubuntu have shipped advisories.
  • Cross-container blast radius — the page cache is a host-wide resource shared across all processes regardless of namespace. A user inside an unprivileged container can corrupt a binary visible to processes on the host. Container boundaries do not contain this primitive.
The page cache is not a per-container resource. Container isolation does not bound which files an in-container attacker can corrupt with this primitive.

Researchers compare it directly to Dirty Pipe (CVE-2022-0847). The classification is fair — both are page-cache write primitives that bypass file-system permissions. Copy Fail's path is different: Dirty Pipe abused the splice/pipe-buffer flag handling; Copy Fail abuses the in-place AEAD destination scatterlist. The exploitation pattern is similar enough that the same response playbook applies.

The bug also crossed onto a criminal-market exploit forum within a week of disclosure — a fast crossing for a Linux LPE, and one that should shift patch prioritization from "high CVSS" to "actively commoditizing." See the time-to-criminalization analysis for the dark-web evidence and what it implies for fleet patch ordering.

Who is exposed
  • Every Linux host shipped with a kernel containing the 2017-08 algif_aead in-place optimization — that is, essentially all production Linux distributions in active use today, on all architectures the upstream kernel supports.
  • Multi-tenant container hosts — Kubernetes nodes with mixed-trust workloads, shared CI runners, container-as-a-service platforms. The cross-container property converts a low-privilege workload compromise into host compromise.
  • Shared developer hosts — bastion hosts, jump boxes, classroom and lab servers, anywhere multiple users share a kernel.
  • Cloud workstations and devcontainers running with AF_ALG reachable to the developer's user account, which is most default configurations.

The bar to exploitation is low: an attacker who has any unprivileged code-execution foothold inside a container or on a shared host. That includes a compromised CI job, a malicious devcontainer, a webshell on an application server, a lateral-movement landing pad inside a Kubernetes pod.

Mitigation

Patch the kernel. The fix is upstream and the distribution advisories are out — Amazon Linux, Debian, RHEL, SUSE, Ubuntu have shipped updates as of 2026-04-22. There is no workaround that doesn't touch the kernel; the bug is structural to the in-place AEAD path.

  • Reboot after patching. The kernel module path is exercised at runtime. Live-patching solutions that handle algif_aead are an option for fleets that cannot reboot, but verify your live-patch vendor explicitly covers this CVE before relying on it.
  • Block AF_ALG at the seccomp layer for workloads that don't need it — most application workloads do not touch the kernel cryptographic socket interface. A seccomp filter denying socket(AF_ALG, ...) closes the exploit surface for that workload without touching the kernel. This is the right defense-in-depth layer for any container runtime that doesn't strictly require AF_ALG.
  • Audit setuid binary inventories. Reduce the count where you can. Fewer setuid targets means fewer easy exploitation endpoints for any future page-cache write primitive.
  • Hunt for post-exploitation on hosts you cannot patch immediately: page-cache corruption leaves no on-disk trace, but the resulting root shell does — look for unexpected execve of setuid binaries followed by elevated activity that doesn't match a user's normal session pattern.
The broader pattern

Page-cache write primitives have become a recurring Linux LPE shape. Dirty Pipe in 2022 made the primitive concrete. Copy Fail in 2026 is the second high-quality entry in the same class, in a different subsystem, from a completely unrelated 2017 optimization commit. The lesson is that any code path that produces a writable scatterlist from userspace input is a candidate for the same bug class. Future audits of splice(), vmsplice(), AF_ALG, and any other userspace → kernel-buffer interface should specifically look for in-place destination paths that can intersect the page cache. Copy Fail is unlikely to be the last entry.

The Linux LPE backlog continues to grow alongside this. CVE-2026-2091 (io_uring race LPE) earlier this year was a different primitive — a race in IORING_REGISTER_FILES_UPDATE — but the same defensive lesson holds: if a userspace-reachable kernel surface isn't load-bearing for your workload, lock it down at the seccomp boundary. Copy Fail makes the case for AF_ALG; the io_uring CVE made the same case for io_uring. Production Linux fleets should default to a deny-list-by-default posture for every kernel surface that isn't explicitly load-bearing.