A 732-byte Python script dropped today gives any unprivileged user a root shell on every mainstream Linux distribution running a kernel built after 2017. No race condition. No kernel-specific offsets. A straight logic flaw in code that has been shipping on your servers, your CI/CD runners, and your cloud instances for eight years.
The vulnerability is CVE-2026-31431. The researchers named it Copy Fail.
Here is what happened.
The AF_ALG Interface
In 2003, the Linux kernel crypto API grew a socket interface: AF_ALG. The idea was sound — expose kernel crypto primitives to userland without requiring applications to link against third-party crypto libraries. You open an AF_ALG socket, set the algorithm, feed it data, get results back. Clean separation between userland and kernel.
The attack surface that created is not theoretical. I cover AF_ALG in the cybersecurity curriculum I teach because it is the exact kind of interface where the security boundary is not obvious at first look. You are handing a socket to the kernel. The kernel is doing work on your behalf. What exactly can that socket touch?
In 2017, a developer optimized algif_aead — the authenticated encryption component — to allow page-cache pages into its writable scatter-gather lists. The intent was performance. Fewer copies. Faster throughput. It went into mainline and shipped in everything.
What That Optimization Actually Did
A scatter-gather list in this context is what the kernel uses to pass memory regions to the crypto engine. Before the optimization, those regions were kernel buffers the application had no further access to once handed off. After the optimization, page-cache pages could be included.
Page-cache pages are not isolated kernel buffers. They are the kernel’s in-memory representation of files on disk. Including them in a writable scatter-gather list means a userland process using AF_ALG could, under the right conditions, write into the page cache — the same page cache that contains your open executables.
The exploit chains AF_ALG with splice(). The splice() syscall moves data between file descriptors without copying through userland. Using both together, the PoC writes 4 bytes into the page-cache representation of /usr/bin/su. That modification changes how su behaves when executed. The result is a root shell.
The modification does not persist across reboots. The page cache clears on shutdown. No file on disk changes. Standard file integrity monitoring will not catch it.
The Scope
Every kernel built between 2017 and the patch date is affected:
- Ubuntu 24.04 LTS (kernel 6.17.0-1007-aws)
- Amazon Linux 2023 (kernel 6.18.8-9.213.amzn2023)
- RHEL 14.3 (kernel 6.12.0-124.45.1.el10_1)
- SUSE 16 (kernel 6.12.0-160000.9-default)
The attack requires only an unprivileged local account. On single-user systems that is a lower risk. On multi-tenant systems — shared servers, Kubernetes clusters, CI/CD runners, serverless platforms where different tenants run code in the same kernel — the risk is immediate and the blast radius is every workload on that host.
How I Approach Kernel CVEs
I have not run this specific PoC yet. That is not an oversight.
For kernel-level vulnerabilities, especially anything touching crypto subsystems, the first step is reading the patch diff and understanding the root cause. The patch targets mainline commit a664bf3d603d. Reading that diff tells you exactly where the optimization crossed a boundary it should not have crossed, and what the correct condition looks like. That understanding is more durable than watching a PoC produce a shell.
When I do reproduce a kernel CVE, it runs in a VM with a custom kernel — not a standard Kali install. I instrument the execution path with strace, bpftrace, and kernel debugging rather than just confirming the output. The shell at the end is validation. The path to the shell is the education.
A PoC treated as the starting point hides the thing that makes the vulnerability reusable knowledge.
Remediation
Patch to kernel mainline commit a664bf3d603d. If patching is not immediately possible, blacklist the algif_aead module:
echo "blacklist algif_aead" | sudo tee /etc/modprobe.d/no-algif-aead.conf
sudo update-initramfs -u
This disables the vulnerable component. Any application relying on algif_aead for authenticated encryption will need an alternative path — though direct algif_aead usage outside of specific crypto tooling is uncommon in most production environments.
The Pattern
This is what an eight-year-old performance shortcut looks like when someone finally checks the boundary conditions. The optimization was defensible at the time. The security implications of including page-cache pages in writable scatter-gather lists were not visible at code-review depth — they required understanding how AF_ALG could interact with splice() in ways the original designers of both did not anticipate.
Every kernel-userland bridge deserves the same adversarial scrutiny as a network-facing API. AF_ALG is not unique here. It is this week’s example.
If you are building toward a security role and want to understand how privilege escalation vulnerabilities like CVE-2026-31431 map to real-world detection and response, the Cybersecurity Career Roadmap covers that path for $47. [ku5e.com/services]
Written by Mario Martinez Jr. (ku5e / Gary7) | TryHackMe Profile | ku5e.com/blog
