Overview

AttributeValue
CVE (ESP variant)CVE-2026-43284
CVE (RxRPC variant)CVE-2026-43500 (reserved, no patch yet)
NameDirty Frag
TypeLocal Privilege Escalation (LPE)
AffectedUbuntu 24.04, RHEL 10.1, CentOS Stream 10, AlmaLinux 10, Fedora 44, openSUSE Tumbleweed — effectively all major distros
Effective Lifetime~9 years (xfrm-ESP since 2017, RxRPC since 2023)
Race ConditionNone — deterministic
ResearcherHyunwoo Kim (@v4bel)
PoC✅ Public (github.com/V4bel/dirtyfrag)
ESP Patch✅ Merged to mainline (f4c50a4034e6)
RxRPC Patch❌ No patch in any tree yet

What Is Dirty Frag?

Dirty Frag is a vulnerability class — not a single bug — that extends the same lineage as Dirty Pipe (CVE-2022-0847) and Copy Fail (CVE-2026-31431). Where Dirty Pipe overwrites struct pipe_buffer and Copy Fail overwrites the AF_ALG scatterlist, Dirty Frag overwrites the frag member of struct sk_buff.

The key insight: by chaining two variants that cover each other’s blind spots, Dirty Frag achieves root on every major Linux distribution, including systems where the publicly known Copy Fail mitigation (blacklisting algif_aead) is already applied.

The Two Variants

1. xfrm-ESP Page-Cache Write (CVE-2026-43284)

Mechanism: When esp_input() processes a non-linear skb that arrived via splice(), it skips skb_cow_data() and performs in-place AEAD decryption directly on the frag. An attacker pins a page cache page (e.g., from /usr/bin/su) into the frag via splice(), then the kernel’s crypto_authenc_esn_decrypt() writes 4 controlled bytes at a controlled offset.

Critical detail: The 4-byte STORE happens before AEAD authentication is verified. Even though authentication fails (fabricated ciphertext), the write persists in page cache permanently.

Requirement: CAP_NET_ADMIN — needs user namespace creation (unshare(CLONE_NEWUSER | CLONE_NEWNET)). On Ubuntu, this works by default. On distros where AppArmor blocks unprivileged user namespaces, this variant is blocked.

Scope: Kernels from cac2661c53f3 (January 2017) to current upstream.

2. RxRPC Page-Cache Write (CVE-2026-43500)

Mechanism: rxkad_verify_packet_1() performs in-place pcbc(fcrypt) decryption on 8 bytes of the skb’s frag. The attacker controls the cipher key (registered via add_key("rxrpc", ...) — no privilege required) and brute-forces the desired plaintext by iterating through key space in userspace.

Advantage: Does not require user namespace creation. On Ubuntu, the rxrpc.ko module is loaded by default.

Limitation: The STORE value is fcrypt_decrypt(C, K) — not directly controllable. Brute-force is required, and cost grows exponentially with constrained bytes (feasible for partial overwrites, impractical for full 8-byte control).

Scope: Kernels from 2dc334f1a63a (June 2023) to current upstream.

The Chain: Why Both Matter

VariantNeeds unshare?Module Present?Direct Control?
xfrm-ESP✅ Yes✅ Built-in (most distros)✅ 4 arbitrary bytes
RxRPC❌ No⚠️ Ubuntu only by default❌ Brute-force required

On Ubuntu: Both variants work. xfrm-ESP is cleaner (arbitrary bytes). On RHEL/SUSE/etc: AppArmor blocks unshare → xfrm-ESP fails. But rxrpc.ko isn’t loaded → RxRPC fails too. The chain: On Ubuntu, xfrm-ESP works directly. On locked-down systems, if rxrpc.ko happens to be loaded (e.g., AFS/Kerberos use cases), RxRPC provides the fallback.

The Exploit

The PoC targets /usr/bin/su — a setuid-root binary present on all Linux systems:

  1. Replace the first 192 bytes of /usr/bin/su’s page cache with a minimal root-shell ELF
  2. The shellcode at entry point 0x400078 executes: setgid(0); setuid(0); setgroups(0,NULL); execve("/bin/sh", ...)
  3. PAM is bypassed entirely — execve("/usr/bin/su") is enough to get root
  4. The 192 bytes are written in 48 chunks of 4 bytes each, using the ESP variant’s arbitrary STORE
  5. No race conditions. No crashes. Deterministic. Page cache corruption persists until drop_caches or reboot.
# Build and run the PoC (on authorized systems only!)
git clone https://github.com/V4bel/dirtyfrag.git
cd dirtyfrag && gcc -O0 -Wall -o exp exp.c -lutil && ./exp

After testing, clear the contaminated page cache:

echo 3 > /proc/sys/vm/drop_caches
# Or reboot

Tested Distributions

DistributionKernelResult
Ubuntu 24.04.46.17.0-23-generic✅ Root
RHEL 10.16.12.0-124.49.1.el10_1✅ Root
openSUSE Tumbleweed7.0.2-1-default✅ Root
CentOS Stream 106.12.0-224.el10✅ Root
AlmaLinux 106.12.0-124.52.3.el10_1✅ Root
Fedora 446.19.14-300.fc44✅ Root

Relationship to Copy Fail

Dirty Frag bypasses the Copy Fail mitigation:

MitigationCopy FailDirty Frag
Blacklist algif_aead✅ Blocks exploit❌ Uses xfrm-ESP / rxrpc instead
Kernel patch (out-of-place AEAD)✅ Fixed❌ Different code path entirely

Copy Fail’s root cause was AF_ALG’s in-place AEAD operation. Dirty Frag exploits the same underlying pattern (page cache corruption via in-place crypto on splice-delivered frags) but in completely different kernel subsystems — IPsec and RxRPC — that were never patched for this bug class.

The Patch (ESP Variant)

The merged patch (f4c50a4034e6) takes a shared-frag approach:

  1. Mark spliced pages with SKBFL_SHARED_FRAG flag in IPv4/IPv6 output paths
  2. Check the flag in esp_input() / esp6_input() skip_cow branch — if shared frags are present, route to skb_cow_data() instead
  3. This ensures attacker-pinned page cache pages can no longer enter the in-place AEAD dst SGL
// esp4.c — the critical check
- } else if (!skb_has_frag_list(skb)) {
+ } else if (!skb_has_frag_list(skb) &&
+            !skb_has_shared_frag(skb)) {

The RxRPC variant (CVE-2026-43500) has no patch in any tree yet.

Immediate Mitigation

Until your distribution ships a patched kernel:

# Block the vulnerable modules from loading
sudo sh -c "printf 'install esp4 /bin/false\ninstall esp6 /bin/false\ninstall rxrpc /bin/false\n' > /etc/modprobe.d/dirtyfrag.conf"
sudo rmmod esp4 esp6 rxrpc 2>/dev/null
# Clear contaminated page cache
sudo sh -c "echo 3 > /proc/sys/vm/drop_caches"

Caveat: Blocking esp4/esp6 will break IPsec/VPN connections. Blocking rxrpc will break AFS and RxRPC-based services. Assess your environment before applying.

Disclosure Timeline

DateEvent
2026-04-30Hyunwoo Kim submits exploit + patch to [email protected]
2026-04-30Patch published to netdev mailing list
2026-05-04Kuan-Ting Chen submits shared-frag approach patch
2026-05-07Patch merged to netdev tree
2026-05-07Info submitted to linux-distros; 5-day embargo set
2026-05-07Embargo broken by unrelated third party publishing the exploit
2026-05-07After maintainer agreement, full Dirty Frag document published
2026-05-08Patch merged to mainline (f4c50a4034e6)
2026-05-08CVE-2026-43284 assigned

Impact Assessment

For Red Team Operators

  • Extremely valuable — deterministic LPE on all tested distros, no crash risk
  • Bypasses Copy Fail mitigation (algif_aead blacklist)
  • Chaining covers blind spots between variants
  • Page cache corruption leaves no on-disk forensic traces

For Defenders

  • Patch immediately — kernel update required for CVE-2026-43284
  • CVE-2026-43500 (RxRPC) remains unpatched — apply modprobe mitigation
  • Monitor for AF_ALG, xfrm, and rxrpc socket usage by unprivileged users
  • Detection difficulty: page cache modifications are invisible to file integrity monitors
  • Cross-container impact: page cache is shared across containers

The Bug Class Continues

Dirty Frag proves that the pattern behind Dirty Pipe and Copy Fail — splice delivering page cache references into kernel crypto paths that perform in-place writes — is still producing exploitable variants. The bug class isn’t limited to pipe_buffer or AF_ALG; it extends to any kernel path where zero-copy frags meet in-place transformations.

Expect more discoveries in this space. The mitigation isn’t patching individual paths — it’s ensuring that spliced/shared page cache pages are never used as both source and destination for in-place operations.


Source: github.com/V4bel/dirtyfrag · Write-up Researcher: Hyunwoo Kim (@v4bel) CVEs: CVE-2026-43284 (xfrm-ESP) · CVE-2026-43500 (RxRPC)