Executive Summary
"Dirty Frag" is a two-CVE local privilege escalation (LPE) exploit chain in the Linux kernel that allows any unprivileged local user to gain full root access in a single command on nearly every major Linux distribution. CVE-2026-43284 (xfrm-ESP, CVSS 7.8) received a kernel patch on May 8, 2026, but CVE-2026-43500 (RxRPC) remains unpatched as of this writing. A public proof-of-concept is already circulating, and Microsoft's security team has documented active in-the-wild exploitation. Immediate action — either kernel patching or module blacklisting — is required.
1. What Is This Vulnerability?
Dirty Frag is a chained exploit built on two separate page-cache write primitives discovered in the Linux kernel's networking subsystem:
-
CVE-2026-43284 — A flaw in the
xfrm-ESP(IPsec Encapsulating Security Payload) subsystem introduced in January 2017 (commitcac2661c53f3). When the ESP receive path decrypts data over paged buffers not privately owned by the kernel — such as pipe pages forwarded to a socket viasplice(2)orsendfile(2)— an unprivileged process can retain references to the resulting plaintext. This yields a 4-byte write primitive directly into arbitrary kernel page cache memory. -
CVE-2026-43500 — A nearly identical flaw in the
RxRPCsubsystem (introduced June 2023), the protocol underlying the AFS distributed filesystem. RxRPC provides the namespace creation primitive that, combined with the ESP write primitive, completes the privilege escalation chain.
Together, these two weaknesses enable corruption of sensitive page-cached files (e.g., /etc/passwd, setuid binaries, or kernel module paths) without any special permissions, sandbox escapes, or kernel configuration changes.
The name "Dirty Frag" is a nod to the earlier Dirty Pipe (CVE-2022-0847) and Copy Fail (CVE-2026-31431) vulnerabilities — both of which abused similar page-cache mechanics. Importantly, systems that applied the algif_aead module blacklist as a Copy Fail mitigation remain fully vulnerable to Dirty Frag via the ESP/RxRPC attack path.
Attack Vector
The exploit leverages only standard Linux syscalls that any unprivileged user can invoke:
socket() → opens an AF_KEY or AF_INET raw socket
setsockopt() → configures ESP or RxRPC parameters
bind() → prepares the transport endpoint
vmsplice() → splices pipe pages into the socket's receive buffer
splice() → routes the pipe-backed buffer through the ESP decrypt path
sendmsg() → triggers the decrypt-over-shared-page condition
A publicly released exploit script (nicknamed "Copy Fail 2: Electric Boogaloo") compiles and executes in seconds, requiring no root privileges, no special kernel modules pre-loaded by the attacker, and no interaction from another user.
Real-World Impact
- May 8, 2026: Wiz Research publicly disclosed both CVEs and released technical write-ups.
- May 8, 2026: Microsoft Security Blog documented active in-the-wild exploitation, describing threat actors using Dirty Frag as a post-compromise escalation step after initial foothold via other vulnerabilities.
- May 8, 2026: The Linux Kernel Organization released patches for CVE-2026-43284. CVE-2026-43500 (RxRPC) remains unpatched upstream.
- CloudLinux, TuxCare, and other live-patching vendors began rolling out KernelCare livepatches the same day.
2. Who Is Affected?
Any Linux system running a kernel version between 4.11 (when the ESP/xfrm code path was introduced) and the latest unpatched release is vulnerable. This includes:
| Distribution | Status |
|---|---|
| Ubuntu 20.04 / 22.04 / 24.04 | Vulnerable — awaiting official kernel update |
| Debian 11 / 12 | Vulnerable — awaiting official kernel update |
| RHEL / CentOS 8 / 9 | Vulnerable — awaiting official kernel update |
| Fedora 39 / 40 | Vulnerable — awaiting official kernel update |
| SUSE Linux Enterprise 15 | Vulnerable — awaiting official kernel update |
| Amazon Linux 2 / 2023 | Vulnerable — awaiting official kernel update |
| CloudLinux 7 / 8 | Patch available via KernelCare |
| Arch Linux | Patch available (kernel 6.x updated May 8) |
| Alpine Linux | Vulnerable — awaiting official kernel update |
Key scope conditions:
- Requires local access (shell session, container escape landing on host, SSH, or code execution via another vulnerability)
- No special privileges, capabilities, or configuration required
- The modules
esp4,esp6, andrxrpcmust be loadable — they are enabled by default in all major enterprise distributions - Containers using the host kernel (non-gVisor, non-VM-isolated) are affected if the attacker can load these modules
Not affected:
- Systems running gVisor, Kata Containers, or other VM-level container isolation
- Environments with strict
CAP_SYS_MODULErestrictions preventing module loading - Systems that have already blacklisted all three modules (
esp4,esp6,rxrpc)
3. How to Detect It (Testing)
Manual Testing Steps
Step 1: Check your running kernel version
uname -r
Compare against your distribution's security advisories. Any kernel below the patched version is vulnerable.
Step 2: Verify whether the vulnerable modules are loadable
# Check if modules are currently loaded
lsmod | grep -E "esp4|esp6|rxrpc"
# Check if modules are blacklisted
cat /etc/modprobe.d/*.conf | grep -E "blacklist.*(esp4|esp6|rxrpc)"
If the modules appear in lsmod output and are not blacklisted, the system is at risk.
Step 3: Check for exploitation indicators in kernel logs
# Look for suspicious splice/sendmsg patterns involving AF_KEY or XFRM
dmesg | grep -iE "xfrm|esp[46]|rxrpc|splice.*sock|af_key"
# Look for unexpected privilege escalation markers
journalctl -k --since "2026-05-08" | grep -iE "uid.*0|euid.*root|capability"
Step 4: Check for the public PoC binary or script on disk
find / -name "dirty_frag*" -o -name "copy_fail2*" -o -name "electric_boogaloo*" 2>/dev/null
Automated Scanning
Tenable Nessus / Tenable.io
- Plugin ID: Search for "Dirty Frag" or CVE-2026-43284 in the plugin feed
- Run a credentialed local scan against Linux hosts
- Expected output: Flags kernel version below patched threshold and module blacklist absence
Wazuh / OSSEC
Add a custom rule to alert on unexpected loading of esp4, esp6, or rxrpc by non-root users:
<rule id="100500" level="12">
<if_sid>5104</if_sid>
<match>modprobe|insmod</match>
<regex>esp4|esp6|rxrpc</regex>
<description>Possible Dirty Frag module load attempt (CVE-2026-43284)</description>
</rule>
Sysdig / Falco Sysdig has published a detection rule for Dirty Frag exploitation patterns:
- rule: Dirty Frag LPE Exploit Attempt
desc: Detects potential Dirty Frag exploitation via splice+sendmsg over ESP/RxRPC
condition: >
syscall.type in (splice, vmsplice, sendmsg) and
fd.type = sock and
fd.sock_family in (AF_KEY, AF_INET) and
proc.uid != 0
output: >
Possible Dirty Frag exploit attempt (user=%proc.loginname pid=%proc.pid
syscall=%syscall.type fd.name=%fd.name)
priority: CRITICAL
Code Review Checklist
When auditing kernel modules or eBPF programs that interact with the xfrm or RxRPC subsystems:
- Verify all
skb(socket buffer) pages passed to crypto decrypt paths are private kernel copies, not user-shared pipe pages - Confirm
splice()/sendfile()paths into IPsec sockets enforce page-ownership checks - Review any custom
AF_KEYorAF_RXRPCsocket usage for unexpected plaintext retention - Check whether live-patching infrastructure is current on all nodes
4. How to Fix It (Mitigation)
Step-by-Step Remediation
Option A: Apply the Kernel Patch (Preferred)
-
Check for available updates via your distribution's package manager:
# Debian / Ubuntu sudo apt update && sudo apt list --upgradable | grep linux-image # RHEL / CentOS / Fedora sudo dnf check-update | grep kernel # SUSE sudo zypper list-updates | grep kernel -
Install the patched kernel:
# Debian / Ubuntu sudo apt upgrade linux-image-generic linux-headers-generic # RHEL / CentOS / Fedora sudo dnf upgrade kernel # SUSE sudo zypper update -t patch -
Reboot to activate the new kernel:
sudo reboot -
Verify the new kernel is running:
uname -r -
For CVE-2026-43500 (RxRPC — no upstream patch yet): proceed to Option B (blacklist) even after applying kernel patches, until the RxRPC fix ships.
Option B: Blacklist Vulnerable Modules (Immediate Compensating Control)
This applies while waiting for kernel updates, or as a permanent control if RxRPC/ESP are not needed:
# Create a blacklist configuration file
sudo tee /etc/modprobe.d/dirty-frag-blacklist.conf << 'EOF'
# Dirty Frag (CVE-2026-43284 / CVE-2026-43500) mitigations
# Disable ESP/IPsec and RxRPC kernel modules
blacklist esp4
blacklist esp6
blacklist rxrpc
install esp4 /bin/false
install esp6 /bin/false
install rxrpc /bin/false
EOF
# Rebuild the initramfs to enforce the blacklist at boot
# Debian / Ubuntu:
sudo update-initramfs -u -k all
# RHEL / CentOS / Fedora:
sudo dracut --force
# Verify modules cannot be loaded after reboot:
sudo modprobe esp4 && echo "FAILED: module loaded" || echo "OK: module blocked"
⚠️ Warning: Blacklisting
esp4/esp6will break IPsec VPN connections that rely on ESP transport mode. Evaluate the operational impact before applying in production.rxrpcis rarely used in enterprise environments and can almost always be safely blacklisted.
Option C: Live Patching (Zero-Downtime)
If rebooting is not acceptable, use a live-patching solution:
- KernelCare (CloudLinux, TuxCare): Already released a livepatch for CVE-2026-43284 as of May 8, 2026
- RHEL Live Patching: Check
dnf updateinfo list | grep kernel-livepatch - Canonical Livepatch:
canonical-livepatch statusto verify coverage
Code Fix Example
The upstream kernel fix for CVE-2026-43284 adds an ownership check before allowing decryption over paged buffers in the ESP receive path:
Before (vulnerable):
/* net/xfrm/xfrm_input.c — simplified */
static int xfrm_input_esp_decrypt(struct sk_buff *skb)
{
struct page *page = skb_frag_page(&skb->frags[0]);
/* BUG: no check whether page is kernel-private */
crypto_aead_decrypt(req, page_address(page));
return 0;
}
After (patched):
static int xfrm_input_esp_decrypt(struct sk_buff *skb)
{
struct page *page = skb_frag_page(&skb->frags[0]);
/* Ensure page is not shared with userspace before decrypting in-place */
if (!PagePrivate(page) || page_count(page) > 1) {
skb = skb_unshare(skb, GFP_ATOMIC);
if (!skb)
return -ENOMEM;
page = skb_frag_page(&skb->frags[0]);
}
crypto_aead_decrypt(req, page_address(page));
return 0;
}
The key fix is the page_count(page) > 1 check: if the page has more than one reference (meaning it is shared with a user pipe), the kernel makes a private copy before decrypting in-place.
Configuration Hardening
# Restrict unprivileged user namespace creation (limits attacker's namespace setup)
sudo sysctl -w kernel.unprivileged_userns_clone=0
echo "kernel.unprivileged_userns_clone=0" | sudo tee -a /etc/sysctl.d/99-dirty-frag.conf
# Load sysctl changes persistently
sudo sysctl --system
# Enable kernel module signing enforcement (prevents unsigned module loads)
# Check if Secure Boot is enforcing module signing:
mokutil --sb-state
5. How to Test the Fix (Validation)
Regression Test Scenarios
- Scenario A: Confirm the patched kernel is active and the exploit no longer gains root
- Scenario B: Confirm that legitimate IPsec/ESP VPN traffic is unaffected (if ESP modules were not blacklisted)
- Scenario C: Confirm that splicing data through pipes into normal sockets functions correctly for unaffected applications
Security Test Cases
Test Case 1: Verify the LPE exploit no longer works
# Run as an unprivileged user on the patched system:
id # Should show uid=1000 (non-root)
# Attempt the exploit (safe on patched kernels — it simply fails):
git clone https://github.com/security-research/dirty-frag-poc /tmp/dirty-frag 2>/dev/null
cd /tmp/dirty-frag && make && ./dirty_frag
# Expected result on patched kernel:
# [*] Setting up ESP socket... OK
# [*] Attempting page-cache write via splice... FAILED (EPERM or EINVAL)
# [-] Exploit failed — target kernel is patched.
id # Must still show uid=1000, NOT root
Test Case 2: Confirm module blacklist enforcement
# Run as root or with sudo:
modprobe esp4 2>&1
# Expected: "modprobe: ERROR: could not insert 'esp4': Operation not permitted"
modprobe rxrpc 2>&1
# Expected: "modprobe: ERROR: could not insert 'rxrpc': Operation not permitted"
Test Case 3: Verify kernel version
uname -r
# Compare against your distro's security bulletin for the patched kernel version
# E.g., Ubuntu expects kernel 6.8.0-xxx or later per USN advisory
Automated Tests
#!/usr/bin/env python3
"""
Dirty Frag (CVE-2026-43284/43500) remediation validation script.
Run as root on the target host after patching.
"""
import subprocess, re, sys
PATCHED_KERNEL_PREFIXES = ["6.8.1", "6.9", "6.10"] # Update per distro advisory
BLACKLISTED_MODULES = ["esp4", "esp6", "rxrpc"]
def check_kernel_version():
version = subprocess.check_output(["uname", "-r"]).decode().strip()
patched = any(version.startswith(p) for p in PATCHED_KERNEL_PREFIXES)
print(f"[{'PASS' if patched else 'WARN'}] Kernel version: {version}")
return patched
def check_modules_blocked():
all_blocked = True
for mod in BLACKLISTED_MODULES:
result = subprocess.run(
["modprobe", "--dry-run", mod],
capture_output=True
)
blocked = result.returncode != 0
print(f"[{'PASS' if blocked else 'FAIL'}] Module {mod}: {'blocked' if blocked else 'LOADABLE — RISK!'}")
all_blocked = all_blocked and blocked
return all_blocked
def check_livepatches():
result = subprocess.run(["kpatch", "list"], capture_output=True)
if result.returncode == 0:
patches = result.stdout.decode()
has_patch = "CVE-2026-43284" in patches or "dirty_frag" in patches.lower()
print(f"[{'PASS' if has_patch else 'WARN'}] Livepatch for CVE-2026-43284: {'present' if has_patch else 'not detected'}")
else:
print("[INFO] kpatch not installed — skipping livepatch check")
print("=== Dirty Frag (CVE-2026-43284 / CVE-2026-43500) Remediation Check ===")
kernel_ok = check_kernel_version()
modules_ok = check_modules_blocked()
check_livepatches()
print("\n=== Result ===")
if kernel_ok or modules_ok:
print("[OK] System appears mitigated against Dirty Frag.")
else:
print("[CRITICAL] System may be VULNERABLE. Apply kernel patch or module blacklist immediately.")
sys.exit(1)
6. Prevention & Hardening
Best Practices
-
Keep kernel update cadence tight. Linux kernel LPEs like Dirty Frag, Dirty Pipe, Copy Fail, and Dirty COW all share a common thread: page-cache manipulation. Plan for patching within 24–48 hours of any kernel LPE disclosure.
-
Apply the principle of minimal module surface. Audit which kernel modules are actually required in each environment. Modules like
rxrpc(AFS protocol) are loaded by default but used by almost no enterprise workloads. Preemptively blacklisting unused networking modules dramatically reduces the attack surface. -
Use live-patching in production. KernelCare, RHEL Live Patching, and Canonical Livepatch allow you to apply kernel security fixes without rebooting — eliminating the gap between disclosure and remediation in high-availability environments.
-
Enforce namespace restrictions. Setting
kernel.unprivileged_userns_clone=0prevents unprivileged users from creating user namespaces, which is a prerequisite for the namespace-based portion of the Dirty Frag exploit chain. -
Isolate sensitive workloads with strong kernel isolation. For multi-tenant environments, prefer gVisor or Kata Containers over traditional cgroup-based container isolation — they run workloads on separate kernel instances, making host-kernel LPEs irrelevant.
Monitoring & Detection
Deploy the following monitoring controls to detect active exploitation attempts:
Auditd rules — detect suspicious splice/sendmsg to ESP sockets:
sudo tee /etc/audit/rules.d/dirty-frag.rules << 'EOF'
# Detect potential Dirty Frag exploit activity
-a always,exit -F arch=b64 -S vmsplice -k dirty_frag_attempt
-a always,exit -F arch=b64 -S splice -F uid!=0 -k dirty_frag_attempt
-a always,exit -F arch=b64 -S socket -F a0=15 -F uid!=0 -k af_key_socket
EOF
sudo augenrules --load
Monitor for unexpected privilege escalation events:
# Alert on any process that transitions from non-root to root UID unexpectedly
ausearch -k dirty_frag_attempt -ts recent | aureport --interpret
Integrate with SIEM: Forward kernel audit logs and module load events to your SIEM (Splunk, Elastic SIEM, Chronicle). Create an alert for:
modprobe esp4/esp6/rxrpcby non-administrative accounts- Any process with
euid=0whose parent haduid>0without asu/sudoevent - Falco alerts tagged
CRITICALfor Dirty Frag rules (see Section 3)
References
- CVE-2026-43284 NVD Entry: https://nvd.nist.gov/vuln/detail/CVE-2026-43284
- Wiz Blog — Dirty Frag Technical Analysis: https://www.wiz.io/blog/dirty-frag-linux-kernel-local-privilege-escalation-via-esp-and-rxrpc
- Microsoft Security Blog — Active Exploitation: https://www.microsoft.com/en-us/security/blog/2026/05/08/active-attack-dirty-frag-linux-vulnerability-expands-post-compromise-risk/
- Tenable FAQ: https://www.tenable.com/blog/dirty-frag-cve-2026-43284-cve-2026-43500-frequently-asked-questions-linux-kernel-lpe
- Sysdig Detection Guide: https://www.sysdig.com/blog/dirty-frag-cve-2026-43284-and-cve-2026-43500-detecting-unpatched-local-privilege-escalation-via-linux-kernel-esp-and-rxrpc
- CloudLinux Mitigation & KernelCare Patch: https://blog.cloudlinux.com/dirty-frag-mitigation-and-kernel-update
- TuxCare Explainer: https://tuxcare.com/blog/dirty-frag-explained-linux-root-exploit-mitigation-patching-guide/
- Help Net Security: https://www.helpnetsecurity.com/2026/05/08/dirty-frag-linux-vulnerability-cve-2026-43284-cve-2026-43500/
- Upwind Analysis: https://www.upwind.io/feed/dirty-frag-linux-root-exploit-esp-rxrpc
- The Hacker News Coverage: https://thehackernews.com/2026/05/linux-kernel-dirty-frag-lpe-exploit.html