Linux Kernel Security Research: Page Cache Vulnerability Class

The Vulnerability Class

Every "dirty" Linux kernel privilege escalation shares a single anti-pattern:

  1. User-controlled splice() or sendfile() plants a page cache page reference into a kernel buffer (pipe_buffer, sk_buff frag, scatterlist, etc.)

  2. A kernel subsystem performs in-place modification on that buffer (crypto transform, checksum, compression)

  3. No check verifies page exclusivity before writing

  4. Result: a read-only page cache page is silently corrupted in RAM

The page cache is the recurring battleground because it backs both file I/O and memory-mapped files. Corrupt it and you can modify /etc/passwd, /usr/bin/su, or any SUID binary in RAM without touching disk.

Known Exploits

Vulnerability Year Target Structure Mechanism

Dirty COW

2016

Page table entries

Race condition in COW fault handler (CVE-2016-5195)

Dirty Pipe

2022

struct pipe_buffer

PIPE_BUF_FLAG_CAN_MERGE flag not cleared after splice() (CVE-2022-0847)

CopyFail

2026

Page cache via algif_aead

In-place AEAD crypto on shared page cache page (CVE-2026-31431)

Dirty Frag

2026

Page cache via sk_buff frags

In-place crypto on `splice()’d page cache ref in ESP/RxRPC (CVE-2026-43284, CVE-2026-43500)

CopyFail — CVE-2026-31431

Disclosed April 29, 2026. A logic flaw in algif_aead.c — the kernel’s AF_ALG socket interface for AEAD cryptography. An unprivileged local user can write 4 controlled bytes into the page cache of any readable file.

Root cause: Three independently reasonable kernel changes created a dangerous combination:

  1. authencesn AEAD wrapper added (2011)

  2. AF_ALG AEAD socket support added (2015)

  3. An in-place optimization in algif_aead.c (2017) — this commit made it exploitable

Severity:

  • Deterministic — no race condition. A 732-byte Python script gets root. Every time.

  • No disk trace — corruption happens in the page cache (RAM-resident file data), not on disk

  • 9 years of exposure — kernel 4.14 through 6.18.21 / 6.19.11 / pre-7.0

  • CISA confirmed active exploitation May 5, 2026; federal patch deadline May 15

Fix: One-line revert of the 2017 optimization (commit a664bf3d603d).

The modprobe blacklist workaround for algif_aead does nothing on RHEL-family distros because the module is compiled into the kernel (CONFIG_CRYPTO_USER_API_AEAD=y). The commands succeed silently, giving a false sense of security.

Dirty Frag — CVE-2026-43284 + CVE-2026-43500

Disclosed May 7, 2026. Two page-cache write primitives chained together — one in ESP (IPsec, esp4/esp6) and one in RxRPC. Both exploit splice() zero-copy send paths where the kernel performs in-place crypto operations on frag members of struct sk_buff that reference read-only page cache pages.

Why two CVEs: Each variant covers the other’s blind spots:

  • ESP variant needs CAP_NET_ADMIN (obtainable via unprivileged user namespaces)

  • RxRPC variant works without user namespaces but requires rxrpc.ko

  • Ubuntu blocks user namespace creation — RxRPC path works

  • RHEL allows user namespaces — ESP path works

Relationship to CopyFail: Same vulnerability class. Dirty Frag explicitly bypasses CopyFail’s mitigation — the algif_aead blacklist is irrelevant here.

Patch status (as of 2026-05-08):

  • ESP half patched in mainline (commit f4c50a4034e6)

  • RxRPC half (CVE-2026-43500) — no patch yet. PoC is public. This is a live zero-day.

What Makes This Class Exploitable

The common thread across all four vulnerabilities:

kernel receives page reference via splice()/sendfile()
    → page belongs to the page cache (shared, read-only)
    → subsystem treats it as a private buffer
    → writes through the reference
    → page cache is corrupted for all consumers

The correct kernel behavior is to copy before modifying — call skb_cow_data(), alloc_page() + memcpy, or equivalent. The vulnerability exists wherever this guard is absent.