Overview
| Attribute | Value |
|---|---|
| CVE (ESP variant) | CVE-2026-43284 |
| CVE (RxRPC variant) | CVE-2026-43500 (reserved, no patch yet) |
| Name | Dirty Frag |
| Type | Local Privilege Escalation (LPE) |
| Affected | Ubuntu 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 Condition | None — deterministic |
| Researcher | Hyunwoo 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
| Variant | Needs 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:
- Replace the first 192 bytes of
/usr/bin/su’s page cache with a minimal root-shell ELF - The shellcode at entry point
0x400078executes:setgid(0); setuid(0); setgroups(0,NULL); execve("/bin/sh", ...) - PAM is bypassed entirely —
execve("/usr/bin/su")is enough to get root - The 192 bytes are written in 48 chunks of 4 bytes each, using the ESP variant’s arbitrary STORE
- No race conditions. No crashes. Deterministic. Page cache corruption persists until
drop_cachesor 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
| Distribution | Kernel | Result |
|---|---|---|
| Ubuntu 24.04.4 | 6.17.0-23-generic | ✅ Root |
| RHEL 10.1 | 6.12.0-124.49.1.el10_1 | ✅ Root |
| openSUSE Tumbleweed | 7.0.2-1-default | ✅ Root |
| CentOS Stream 10 | 6.12.0-224.el10 | ✅ Root |
| AlmaLinux 10 | 6.12.0-124.52.3.el10_1 | ✅ Root |
| Fedora 44 | 6.19.14-300.fc44 | ✅ Root |
Relationship to Copy Fail
Dirty Frag bypasses the Copy Fail mitigation:
| Mitigation | Copy Fail | Dirty 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:
- Mark spliced pages with
SKBFL_SHARED_FRAGflag in IPv4/IPv6 output paths - Check the flag in
esp_input()/esp6_input()skip_cow branch — if shared frags are present, route toskb_cow_data()instead - 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
| Date | Event |
|---|---|
| 2026-04-30 | Hyunwoo Kim submits exploit + patch to [email protected] |
| 2026-04-30 | Patch published to netdev mailing list |
| 2026-05-04 | Kuan-Ting Chen submits shared-frag approach patch |
| 2026-05-07 | Patch merged to netdev tree |
| 2026-05-07 | Info submitted to linux-distros; 5-day embargo set |
| 2026-05-07 | Embargo broken by unrelated third party publishing the exploit |
| 2026-05-07 | After maintainer agreement, full Dirty Frag document published |
| 2026-05-08 | Patch merged to mainline (f4c50a4034e6) |
| 2026-05-08 | CVE-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, andrxrpcsocket 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)