Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-31431 — A structured explanation of CVE-2026-31431 (Copy Fail), connecting the three kernel changes that introduced the vulnerability and enabled its exploitation. | Kitploit
Tools/GitHubGitHub/themalwareguardian/cve-2026-31431
Privilege EscalationVulnerability AnalysisExploitationPapers & ResearchLearning & EducationContainer EscapeBinary Exploitation
GitHubthemalwareguardian/cve-2026-31431

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-31431

A structured explanation of CVE-2026-31431 (Copy Fail), connecting the three kernel changes that introduced the vulnerability and enabled its exploitation.

View Repository
2144 months agoNot yet reviewed

🐞 CVE-2026-31431 - Copy Fail



A logic flaw in authencesn chained through AF_ALG and splice() into a controlled 4-byte write in the page cache of any readable file on the system. No race condition, no offsets, no compiled payload. The same 732-byte script gains root on every Linux distribution since 2017.




📑 Table of Contents

  • Overview
  • Root Cause Analysis
    📂
    • The AF_ALG + splice() primitive
    • The 2017 in-place optimization
    • The out-of-bounds write in authencesn
    • Three harmless changes → one critical bug
    • Traversing the scatterlist into page cache pages

  • Impact
  • Affected Distributions
  • Verification - Am I Affected?

  • Exploit
  • Exploit Walkthrough
    📂
    • Step 1 - Socket Setup
    • Step 2 - Construct the Write
    • Step 3 - Trigger the Page Cache Write
    • Step 4 - Execute

  • Comparison with Dirty Cow / Dirty Pipe

  • The Fix
  • Disclosure
  • References



🔍 Overview

CVE-2026-31431 - Copy Fail is a logic flaw in the Linux kernel's authencesn cryptographic template. It allows an unprivileged local user to perform a controlled 4-byte write into the page cache of any readable file on the system, without modifying the file on disk.

The bug does not exist in any of the three components individually. It emerges from their interaction:

2011 ──────────────────────────────────────────────────────────────────────
	- authencesn added to the kernel (a5079d084f8b).
	- Uses the caller's destination scatterlist as scratch space.
	- Reorder ESN bytes before HMAC computation.
	- Only caller: internal xfrm layer. Harmless.

2015 ──────────────────────────────────────────────────────────────────────
	- algif_aead.c gains AEAD support with splice() path (104880a6b470).
	- splice() can deliver page cache pages to the TX scatterlist.
	- AF_ALG uses out-of-place operation: req->src != req->dst.
	- Page cache pages remain read-only. Not exploitable.

2017 ──────────────────────────────────────────────────────────────────────
	- In-place optimization in algif_aead.c (72548b093ee3).
	- Copies AAD+CT to RX buffer but chains authentication tag pages via sg_chain().
	- Sets req->src = req->dst.
	- Page cache pages now reside in WRITABLE dst.
	- authencesn writes past boundary → page cache corruption.

2026 ──────────────────────────────────────────────────────────────────────
	- Copy Fail - CVE-2026-31431. Discovered by Theori / Xint Code.
	- Exploitable across all distros since 2017.



🧬 Root Cause Analysis

The AF_ALG + splice() primitive

AF_ALG (AF_ALG = 38) is a socket type that exposes the kernel cryptographic API to unprivileged userspace. An unprivileged process can:

  1. Open an AF_ALG / SOCK_SEQPACKET socket.
  2. bind() to any available AEAD template exposed by the kernel crypto API.
  3. Set a cryptographic key via setsockopt(SOL_ALG, ALG_SET_KEY, ...) on the configured algorithm.
  4. Call accept() to obtain a dedicated operation socket that will handle encryption and decryption requests
  5. Send crafted data using sendmsg() and receive the processed result via recvmsg(), fully interacting with the kernel crypto subsystem.

It is enabled by default in the kernel configuration of all major distributions (CONFIG_CRYPTO_USER_API_AEAD=y).

splice(2) transfers data between file descriptors without copying - it passes references to pages, not copies. The relevant flow:

open("/usr/bin/su")   ->  fd_file
pipe()                ->  pipe_rd, pipe_wr

# moves N bytes from the file into the pipe
# the pipe buffer now contains a reference to the same physical page in the page cache
splice(fd_file, pipe_wr, N)

# delivers that reference to the AF_ALG socket
# the TX scatterlist of algif_aead now points to the page cache page of /usr/bin/su
splice(pipe_rd, alg_fd, N)

The TX scatterlist of the AF_ALG socket contains direct references to the same physical pages used by the kernel for every read(), mmap(), and execve() of the file. No copy is involved.


The 2017 in-place optimization

Commit 72548b093ee3, algif_aead.c. For decryption, the implementation:

  1. Copies the AAD and ciphertext from the TX SGL (source) into the RX buffer (destination) - a real copy.
  2. Chains the authentication tag pages via sg_chain(), keeping page cache references in the RX SGL.
  3. Sets req->src = req->dst, both pointing to the combined RX SGL.
TX SGL (input from splice):
	[ page cache page: AAD || CT || Tag ]

In-place operation:
	RX SGL (req->dst):
	[ user buffer: AAD (copy) || CT (copy) ] --sg_chain--> [ Tag (page cache pages) ]
	req->src = req->dst = RX SGL

Result: page cache pages from /usr/bin/su are now part of the WRITABLE scatterlist passed to the crypto algorithm.

The out-of-bounds write in authencesn

authencesn is the kernel AEAD wrapper used by IPsec with Extended Sequence Numbers (RFC 4303). IPsec uses 64-bit sequence numbers:

  • seqno_hi - upper 32 bits (bytes 0-3 of the AAD)
  • seqno_lo - lower 32 bits (bytes 4-7 of the AAD)

Only seqno_lo is transmitted on the wire; seqno_hi is implicit context. For HMAC computation, authencesn needs to rearrange these bytes: seqno_hi at the beginning and seqno_lo at the end of the hash input.

It performs this rearrangement by using the caller's destination scatterlist as scratch space:

/* crypto/authencesn.c - crypto_authenc_esn_decrypt() */

// [1] Read bytes 0-7 of the AAD from dst
scatterwalk_map_and_copy(tmp, dst, 0, 8, 0);

// [2] Overwrite dst[4..7] with seqno_hi (temporary modification for HMAC)
scatterwalk_map_and_copy(tmp, dst, 4, 4, 1);
Download Tool