Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/V4bel/dirtyfrag/llms.txt

Use this file to discover all available pages before exploring further.

Dirty Frag is a local privilege escalation vulnerability class discovered by Hyunwoo Kim (@v4bel) that achieves root on most major Linux distributions by chaining two independent page-cache write primitives: the xfrm-ESP Page-Cache Write (CVE-2026-43284) and the RxRPC Page-Cache Write (CVE-2026-43500). Because neither variant depends on a timing window, you do not need to win a race condition, the kernel does not panic on failure, and the exploit succeeds at a very high rate.
This documentation is provided for security research and authorized testing only. Do not use the exploit or any technique described here on systems you do not have permission to test.

Bug class: Dirty Pipe lineage

Dirty Frag belongs to the same vulnerability class as Dirty Pipe and Copy Fail. The defining trait of this class is that a kernel code path performs an in-place write into a page-cache page that the calling process only has read access to, permanently modifying the cached copy in RAM.
VulnerabilitySink overwritten
Dirty Pipestruct pipe_buffer
Copy FailTX SGL via algif_aead
Dirty Fragfrag of struct sk_buff
Dirty Frag reproduces the Copy Fail pattern on the frag slot of a nonlinear skb that originates from splice(). Notably, Dirty Frag can be triggered regardless of whether the algif_aead module is available — systems where the publicly known Copy Fail mitigation (blacklisting algif_aead) has been applied are still vulnerable to Dirty Frag.

Core mechanism

The shared root cause of both variants is the zero-copy send path. When you call splice() to send a file into a socket, the kernel plants a reference to the underlying page-cache page directly into the frag slot of the sender-side skb — no copy is made. The page is read-only from the attacker’s perspective. On the receiver side, kernel code in both the xfrm-ESP and RxRPC paths performs in-place cryptographic operations directly on top of that frag, writing back the result without first allocating a private buffer. Because the frag still points at the original page-cache page, the write lands in the page cache itself. The result: an unprivileged attacker can modify read-only files such as /etc/passwd or /usr/bin/su in RAM, and every subsequent read from any process sees the modified copy — until drop_caches or a reboot clears the cache.

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

In esp_input(), when an skb has frags but no frag list and is not cloned, the function skips the skb_cow_data() call that would normally allocate a private buffer and jumps directly to in-place AEAD decryption. During the crypto_authenc_esn_decrypt() preprocessing step, the kernel performs a 4-byte store at a position calculated from assoclen + cryptlen in the destination SGL. If the attacker has spliced the target page into the frag at that position, the store hits the page cache directly. The value written is the high-order 32 bits of the ESP sequence number (seq_hi), which the attacker freely sets at SA registration time via the XFRMA_REPLAY_ESN_VAL netlink attribute. This gives the attacker full control of both the target offset and the 4-byte value. AEAD authentication runs after the store, so even when verification fails the modification has already persisted. This variant requires CAP_NET_ADMIN, which you obtain by creating a user namespace via unshare(CLONE_NEWUSER | CLONE_NEWNET).

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

In rxkad_verify_packet_1(), the kernel verifies an RXRPC_SECURITY_AUTH-level data packet by performing an in-place single-block pcbc(fcrypt) decryption on the first 8 bytes of the RxRPC payload of the skb. Because skb_to_sgvec() converts the frag directly into the SGL without copying, a page-cache page spliced into the frag becomes both the source and destination of the decrypt, resulting in an 8-byte store into the page cache. The written value is fcrypt_decrypt(C, K), where C is the existing ciphertext at that file offset and K is the session key in an RxRPC v1 token that the attacker registers with add_key("rxrpc", ...). Since fcrypt has a 56-bit key and is a deterministic function, the attacker brute-forces K in user space until the decrypt produces the desired plaintext bytes. This variant does not require a user namespace, making it available to unprivileged users on any system.

Chaining to cover all major distributions

Neither variant alone covers every distribution, so the exploit chains them:
  • xfrm-ESP ships on almost all distributions but requires user namespace creation. Ubuntu sometimes blocks unprivileged namespace creation via AppArmor policy.
  • RxRPC does not require namespace privileges but rxrpc.ko is absent from most distributions. On Ubuntu, rxrpc.ko is loaded by default.
Chaining the two variants makes each one’s blind spot the other’s strength. A single exploit binary first attempts the ESP variant; if that fails (for example, unshare(CLONE_NEWUSER) returns -EPERM), it falls back to the RxRPC variant. This provides reliable root across Ubuntu, RHEL, Fedora, openSUSE, CentOS, and AlmaLinux.

Key properties

  • Deterministic logic bug — no race condition or timing window required
  • No kernel panic — exploit failures are silent; the kernel returns an error code and continues normally
  • Very high success rate — each store is unconditional and persists in the page cache until cleared
  • Persistent modification — every subsequent read of the affected file returns the modified bytes until drop_caches or reboot
  • Two CVEs — CVE-2026-43284 (xfrm-ESP, patched in mainline at f4c50a4034e6) and CVE-2026-43500 (RxRPC, patch submitted but not yet upstream)

Explore further

xfrm-ESP Page-Cache Write

Root cause, exploit flow, and patch details for CVE-2026-43284.

RxRPC Page-Cache Write

Root cause, brute-force key search, and patch details for CVE-2026-43500.

Chaining the two variants

How the exploit combines both primitives to achieve universal coverage across distributions.

Running the exploit

Build instructions, one-line invocation, and post-exploit cleanup.

Build docs developers (and LLMs) love