CONCEPT Cited by 1 source
Copy Fail — CVE-2026-31431¶
Copy Fail (CVE-2026-31431)
is a Linux kernel local-privilege-escalation vulnerability
disclosed publicly by Xint Code on 2026-04-29. The bug is a
4-byte out-of-bounds write in the kernel crypto API's
authencesn
wrapper (the AEAD wrapper for algorithms like authencesn(hmac(sha256),
cbc(aes))), triggered from unprivileged user-space via the
AF_ALG socket family
+ the algif_aead module. By using splice() to chain a target
file's page-cache pages into the crypto operation's scatterlist,
an attacker can taint the cached pages of a setuid-root binary
(canonically /usr/bin/su, present on essentially every Linux
distribution) and get 4-byte chunks of shellcode executed with
root privileges on the next execve().
The upstream fix (commit a664bf3d603d)
reverts a 2017 in-place-crypto optimisation in algif_aead
that chained destination and reference pages together in a
scatterlist without enforcing write-boundary constraints. The
canonical Xint write-up is at xint.io/blog/copy-fail-linux-distributions.
Exploit mechanics (summary)¶
- Cache reference. Open
/usr/bin/suasO_RDONLYandread()to populate the page cache. Usesplice()on the file descriptor to pass the page-cache references into an AF_ALG crypto scatterlist. - Setup. Create an AF_ALG socket,
bind()toauthencesn(hmac(sha256),cbc(aes)), set a key, accept a request socket — all unprivileged. - Write construction. For each 4-byte shellcode chunk,
construct the crypto request so the
authencesnwrapper's internal 4-byte write lands at the chosen offset in/usr/bin/su's cached pages. - Trigger.
recvmsg()initiates decryption; theauthencesnwrapper writes its scratch bytes past the legitimate output region into the target scatterlist page. The operation returns-EBADMSG, but the 4-byte write has already landed in the global page cache. - Execution.
execve("/usr/bin/su")loads the tainted page cache. Becausesuis setuid-root, the injected shellcode runs with root privileges.
The exact vulnerable code path (from the Linux source):
Why this bug is structurally interesting¶
- Unprivileged reachable. AF_ALG sockets +
algif_aeadare accessible to any user; no capabilities required. - Page cache is shared. Modifying a cached page of a setuid binary effectively edits that program for all users until the page is evicted — no need to write to the on-disk binary (hashes stay clean against package manifests; on-disk integrity checks don't detect the exploit).
- 4 bytes is enough. Chunk-by-chunk writes assemble full shellcode over multiple crypto operations.
- Setuid-root targets are universal.
/usr/bin/suships on essentially every distribution. - 2017 regression. The bug was introduced by an in-place-crypto optimisation that predates the disclosure by ~nine years — canonical example of a performance optimisation creating a latent security hazard.
Mitigation surface¶
Three levers, in increasing order of desirability:
- Unconditional
algif_aeadmodule removal —echo "install algif_aead /bin/false" > /etc/modprobe.d/...thenrmmod algif_aead. The researchers' recommended workaround. Coarse: breaks any software legitimately using the kernel crypto API via AF_ALG. Cloudflare attempted this in staging on 2026-04-29 evening; dependency conflicts surfaced and the attempt was rolled back (patterns/staging-caught-mitigation-failure). - Targeted bpf-lsm hook denial — eBPF program on
socket_bindhook that denies AF_ALG binds for everyone except an explicit allow-list of legitimate callers. Surgical where module removal is coarse. Canonical Cloudflare mitigation (systems/cloudflare-bpf-lsm + patterns/bpf-lsm-allowlist-hook-denial). - Patched kernel via scheduled reboot — upstream
commit
a664bf3d603dbackported to LTS 6.12 and rolled through ERR once the backport lands. Long-cycle — Cloudflare's biweekly cadence didn't close the gap before disclosure.
Detection¶
Running any variant of the exploit produces a distinctive trace in kernel logs (not publicly disclosed in detail by Cloudflare, but referenced as "the exploit leaves a distinctive trace in kernel logs when it runs" — the basis for the 48-hour retroactive threat-hunt). Independent of signature detection, behavioral detection on the process-execution chain (script interpreter → kernel crypto subsystem → setuid-root binary) flagged the exploit pattern within minutes during Cloudflare's internal validation — with "no signature update, no rule change, no human intervention".
A one-liner mitigation-verification test from the researchers:
python3 -c 'import socket; s = socket.socket(socket.AF_ALG,
socket.SOCK_SEQPACKET, 0);
s.bind(("aead","authencesn(hmac(sha256),cbc(aes))"));'
On a mitigated machine: PermissionError: [Errno 1]
Operation not permitted (or FileNotFoundError,
depending on mitigation type). On an unmitigated vulnerable
machine: successful bind.
Seen in¶
- 2026-05-07 — Cloudflare Copy Fail response. Canonical wiki first-class page for the CVE. Full exploit mechanics + mitigation surface + the structural "2017 in-place optimisation regression" framing. No Cloudflare customer impact; fleet mitigation via bpf-lsm + subsequent patched-kernel rollout via ERR. (Source: sources/2026-05-07-cloudflare-copy-fail-linux-vulnerability-response)