dirtyfrag: Dirty Frag: How a Linux Fast Path Turned Read-Only Files into a Root Shell

A deterministic privilege-escalation framework that chains two kernel subsystems, writes through page cache pages, and shows how “dirty” bugs keep evolving.

8 to 10 min read View on GitHub More from V4bel

A split editorial scene shows a pristine file page on one side and a kernel networking path on the other. A thin write path threads through zero-copy machinery and leaves a visible scratch in the page cache, explaining how a read-only target becomes mutable.
Dirty Frag’s core trick is visual: a read-only file page is carried through fast paths that were never supposed to turn it into a write target.

Dirty Frag is a vulnerability (class) that achieves root privileges on most Linux distributions by chaining the xfrm-ESP Page-Cache Write vulnerability and the RxRPC Page-Cache Write vulnerability.

Key Takeaways

The Read-Only Lie

The unsettling part of Dirty Frag is not that it writes to memory. It is that it writes to memory that should have stayed read-only. A file like /usr/bin/su looks fixed on disk, but the kernel’s own fast paths can briefly treat a page from that file as something it can modify.

That is the whole article in one sentence. Dirty Frag is a privilege-escalation framework that chains two Linux kernel subsystems to turn page-cache data into a write primitive, then uses that primitive to alter a privileged binary and reach a root shell.

A hedcut-style portrait of Hyunwoo Kim, the creator of Dirty Frag, rendered from his verified GitHub avatar. The portrait grounds the article in a real researcher and links the exploit to its author rather than to anonymous malware mythology.

Why This Exploit Feels So Clean

A lot of kernel exploits depend on timing. Dirty Frag does not. That matters because the exploit is built around logic that the kernel follows consistently once the setup is correct, which makes the result easier to repeat and easier to reason about.

Because it is a deterministic logic bug that does not depend on a timing window, no race condition is required, the kernel does not panic when the exploit fails, and the success rate is very high.

Hyunwoo Kim, Project Creator / Security Researcher · V4bel/dirtyfrag README.md
// The exploit uses kernel primitives, not a timing race.
// setup_userns_netns();
// add_xfrm_sa();
// splice(file, pipe, socket);
// trigger page-cache write primitive;

if (success) {
    // privileged binary is now altered in place
    execve("/bin/sh", argv, envp);
}

Two Kernel Paths, One Write Primitive

Dirty Frag is broader than a single bug report. It chains two different kernel paths to reach the same outcome. One path uses xfrm-ESP and user namespaces. The other uses RxRPC and avoids that namespace dependency. The point is not that the two paths look the same. The point is that both can land on the same kind of page-cache write primitive.

The exploit is not magic. It is one pinned page moving through two different kernel routes until both land on the same write primitive.

A close-up mechanical engraving shows a single pinned page routed through two narrow kernel corridors. One corridor is marked by xfrm-ESP and user namespaces, the other by RxRPC, and both converge on the same modified page-cache page.
The article’s most important technical idea is the shared destination, not the specific route.
ExploitMechanismDependency shapeReliabilityWhat it teaches
Dirty FragPage-cache write primitive through xfrm-ESP or RxRPCTwo kernel paths, one of which can avoid namespace setupDeterministic and very highFast paths can compose into a write primitive
Copy FailPage-cache write primitive through the crypto API and spliceOften leans on AF_ALG and user namespacesDeterministic and highCrypto plumbing can expose the same class of bug
Dirty Pipesplice-based write into pipe buffersPipe-buffer manipulationDeterministic and highZero-copy plumbing can rewrite read-only data
Dirty COWCOW race against memory protectionRace condition in copy-on-writeTiming dependentA race is harder to trust than a logic flaw

How exp.c Stages the Attack

The code is deliberately compact. That compactness hides a lot of kernel knowledge. The exploit sets up namespaces when needed, configures the network state it wants, and uses splice() to keep the page pinned as it moves through kernel buffers instead of being copied in the normal way.

That detail matters because the exploit is not trying to overwrite a file through a normal write syscall. It is trying to make the kernel reuse the same physical page in a context where an in-place operation becomes a file modification. The tiny embedded payload then turns the altered file into a root shell.

// conceptually simplified flow
unshare(CLONE_NEWUSER | CLONE_NEWNET);
setup_kernel_state();
splice(fd_file, NULL, fd_pipe, NULL, len, 0);
move_page_into_socket_state();
trigger_in_place_processing();
// page cache page now contains attacker-controlled bytes

Dirty Frag Is the Next Step After Dirty Pipe

The family resemblance is real. Dirty Pipe made the page cache writable through pipe buffers. Dirty Frag keeps the same editorial tension, but moves the weak point into socket fragments and related networking machinery. That is why it feels less like a one-off exploit and more like an evolution of a bug class.

ProjectCore targetMain primitiveNature of bugWhy it matters
Dirty COWMemory protection and COWRace on copy-on-writeTiming raceShows how fragile COW assumptions can be
Dirty PipePipe bufferssplice-driven page-cache writeDeterministic logic flawTurned read-only pages into write targets
Copy FailCrypto and page-cache plumbingIn-place crypto write pathDeterministic logic flawExtended the page-cache write idea into crypto APIs
Dirty Fragxfrm-ESP and RxRPCDual path page-cache write primitiveDeterministic logic flawShows how multiple networking subsystems can converge on the same write

Why the Disclosure Mattered

The repo is also a disclosure story. The embargo broke early, which forced the researcher to publish before the clean version of the rollout existed. That created urgency for distros, defenders, and anyone responsible for hardening Linux fleets.

Copy Fail was the motivation for starting this research.

Hyunwoo Kim, Project Creator / Security Researcher · V4bel/dirtyfrag README.md

That matters because this is not just a proof-of-concept for curiosity’s sake. It is a reference point for defenders, a test case for mitigations, and a reminder that kernel attack surfaces do not stay isolated when subsystems are composed for performance.

What the Repo Says About Modern Kernel Security

Dirty Frag is really a lesson about composition. A file page, a socket fragment, in-place crypto, and zero-copy networking are all sensible optimizations on their own. Put them together, and the safety assumptions begin to leak.

That is why the repo matters beyond the headline. It shows that “read-only” is not a property you can trust if the kernel can be convinced to keep the same page alive across multiple fast paths. The code is small, but the implication is large.