Linux Dirty Frag (CVE-2026-43284) Gets Root Through ESP and RxRPC Page Cache Writes
Contents
TL;DR
Scope Linux kernel ESP and RxRPC paths. Local privilege escalation from regular user to root; on container hosts, a stepping stone to host compromise
Fix Update to a patched kernel from your distro. The ESP side is tracked as CVE-2026-43284 and already fixed in upstream mainline
Workaround Block loading of esp4, esp6, and rxrpc modules. Check for side effects if you run IPsec ESP or AFS
Dirty Frag was disclosed on May 7, 2026 as a local privilege escalation in the Linux kernel.
The ESP side got CVE-2026-43284. V4bel’s write-up mentions CVE-2026-43500 as reserved for the RxRPC side, though vendor tracking was still catching up at the time of publication.
Environments that disabled algif_aead after Copy Fail are still vulnerable to Dirty Frag through a different path.
The same page cache corruption class, but instead of AF_ALG, the attack goes through network-side struct sk_buff frags that carry page-cache-backed pages into crypto processing where they get overwritten in place.
V4bel’s Dirty Frag write-up chains xfrm-ESP Page-Cache Write and RxRPC Page-Cache Write to cover blind spots across major distributions.
It reads better as a bug class than a single-bug name: page cache references leak into network buffer frags, and the receiving side’s crypto processing STOREs into them in place.
The write target moved from AF_ALG to skb frags
Copy Fail used splice(file -> pipe -> AF_ALG) to inject page cache pages of a read-only file into the crypto API’s scatterlist.
A 4-byte STORE during authencesn processing corrupted the in-memory copy of setuid-root binaries like /usr/bin/su.
Dirty Frag aims at the same target: not the on-disk file, but the page cache copy Linux holds in RAM.
The difference is that the page cache reference enters the sk_buff frags used by UDP and RxRPC send/receive, not AF_ALG.
sk_buff is the Linux network stack’s packet representation. Beyond its linear data region, it can carry page-sized fragments.
When splice() or MSG_SPLICE_PAGES is involved, pages pass through without copying.
This zero-copy path is a performance win, but if the receiving side later modifies the contents, the kernel is supposed to copy-on-write into a private page first.
On the ESP path, that copy-on-write step was missing.
The Ubuntu CVE-2026-43284 page and NVD CVE-2026-43284 page describe how IPv4 and IPv6 datagram append paths failed to set SKBFL_SHARED_FRAG when inserting splice-originated pages into UDP skbs, unlike the TCP path.
ESP input then treated them as ordinary non-shared nonlinear skbs and took the no-COW fast path, decrypting in place.
flowchart TD
A["Readable file"] --> B["splice into pipe"]
B --> C["MSG_SPLICE_PAGES puts page<br/>into UDP skb frag"]
C --> D["ESP or RxRPC<br/>receive-side crypto"]
D --> E["No copy-on-write,<br/>in-place STORE"]
E --> F["Page cache is corrupted<br/>(not the on-disk file)"]
F --> G["setuid exec or auth reads<br/>see corrupted content"]
The last step is where it hurts.
The file’s on-disk hash stays clean, but execve() and read() see the modified page cache content, giving the attacker a path to root.
The ESP path writes 4 controlled bytes fairly directly
ESP is IPsec’s Encapsulating Security Payload, handling encrypted and authenticated communication.
On this path, ESP-in-UDP receive processing enters esp_input(), which proceeds to decrypt with authencesn(hmac(sha256), cbc(aes)).
The bug is that esp_input() considers a non-cloned, frag_list-free nonlinear skb safe and skips skb_cow_data().
Even when the frags hold splice-originated page cache pages, it passes them as both src and dst in the same scatterlist to the crypto layer.
V4bel’s write-up explains that ESN (Extended Sequence Number, a mechanism for 64-bit sequence numbers in IPsec) preprocessing produces a 4-byte STORE.
The attacker controls the 4 written bytes through seq_hi set during XFRM SA registration, and adjusts the payload length to target a specific offset.
Even when authentication fails, the STORE has already executed, so the page cache corruption persists.
Reaching this ESP path requires registering an XFRM SA, which normally needs CAP_NET_ADMIN.
Most environments reach it by creating user and network namespaces and using the capabilities inside them.
On some Ubuntu configurations, AppArmor restricts unprivileged user namespaces, which can block this route.
The RxRPC path covers Ubuntu’s gap
RxRPC is an RPC protocol used by AFS (Andrew File System) and related services.
On this path, rxkad_verify_packet_1() decrypts the first 8 bytes of received packets in place.
When the skb frags contain page-cache-backed pages, those 8 bytes of decrypted output land directly in the page cache.
Unlike ESP, the RxRPC path does not require creating user namespaces.
V4bel’s write-up describes how a regular user can register an RxRPC v1 token’s session_key via add_key("rxrpc", ...) and use that key to make fcrypt decryption output write to the page cache.
The 8 written bytes are not directly chosen.
The attacker brute-forces keys in userspace, looking for one whose decryption output is close enough to the desired plaintext.
V4bel’s PoC targets the root line in /etc/passwd, matching only the loosely constrained bytes so that PAM’s nullok setting treats it as an empty password.
This is why the two paths are chained.
The ESP path offers a strong 4-byte write but hits user namespace restrictions on some configurations.
The RxRPC path has weaker control over the written value but works on Ubuntu where rxrpc.ko is available, bypassing namespace restrictions.
Each path covers the other’s gap, making it hard to feel safe by looking at a single distro’s configuration.
Copy Fail mitigations do not block Dirty Frag
The interim fix for Copy Fail was disabling algif_aead.
Dirty Frag never touches algif_aead.
V4bel’s README explicitly states that Dirty Frag remains exploitable on Linux systems with Copy Fail mitigations applied.
The outcome is similar (page cache corruption), but the entry points are different.
Copy Fail entered through AF_ALG, Linux’s userspace crypto socket interface.
Dirty Frag enters through IPsec ESP and RxRPC receive processing.
Canonical’s Dirty Frag mitigation post lists ESP and RxRPC kernel modules as the affected components and states that both must be disabled to close the hole.
It also notes that environments running arbitrary third-party workloads in containers face not just local privilege escalation but a potential stepping stone toward container escape.
This does not mean the PoC itself implements container escape.
It means that running untrusted code on the same host kernel raises the priority.
The fix adds shared-frag awareness before COW
The ESP-side fix sets SKBFL_SHARED_FRAG on splice-originated shared frags and makes ESP input fall through to skb_cow_data() when that flag is set.
V4bel’s README, updated May 8, 2026, reports CVE-2026-43284 as fixed in upstream mainline commit f4c50a4034e6. The RxRPC side is reserved as CVE-2026-43500 but the tree-level fix was not yet landed.
NVD lists CVE-2026-43284 with a CISA-ADP CVSS 3.1 score of 7.8 HIGH and vector AV:L/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H.
NVD’s own assessment was not yet provided at the time of writing, but kernel.org descriptions and stable patch references are present.
Ubuntu listed releases from Trusty through Resolute as affected as of May 8, 2026.
The manual workaround creates /etc/modprobe.d/dirty-frag.conf to block loading esp4, esp6, and rxrpc, followed by an initramfs update and module unload (or reboot if unload fails).
echo "install esp4 /bin/false" | sudo tee /etc/modprobe.d/dirty-frag.conf
echo "install esp6 /bin/false" | sudo tee -a /etc/modprobe.d/dirty-frag.conf
echo "install rxrpc /bin/false" | sudo tee -a /etc/modprobe.d/dirty-frag.conf
sudo update-initramfs -u -k all
sudo rmmod esp4 esp6 rxrpc 2>/dev/null
This workaround has side effects.
esp4 and esp6 are used by IPsec ESP, so hosts running StrongSwan or similar IPsec VPNs will lose connectivity.
rxrpc affects AFS and RxRPC-based applications.
Most general-purpose web or dev servers don’t use these, but VPN gateways or environments with legacy distributed filesystems should check before applying.
Checking with uname -r alone is not enough.
Distributions backport fixes without bumping the upstream version number.
Debian’s security tracker, for example, shows different fixed versions per release for the same CVE.
Check the actual kernel package advisory for the release you’re running.
Corrupted page cache survives until cleared
V4bel’s README warns that page cache corruption from the PoC persists until drop_caches or a reboot.
This is also a problem for defenders testing their own systems.
Running the PoC against production to check vulnerability will dirty the in-memory copies of setuid binaries or /etc/passwd.
Checking module load state, user namespace settings, and kernel package patch status is a safer approach than running the PoC on a live host.
Page cache corruption disappears on reboot, but any persistence an attacker planted after getting root is a separate problem.
Dirty Frag itself does not write to disk, but that does not mean post-compromise files and credentials are clean.