Neither the xfrm-ESP variant nor the RxRPC variant works universally on its own. The ESP variant needs an unprivileged user namespace, which Ubuntu can block via AppArmor policy. The RxRPC variant needsDocumentation 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.
rxrpc.ko, which is absent from most non-Ubuntu distributions. By running the two variants in sequence and falling back from one to the other, a single binary achieves root on all major Linux distributions: whichever blind spot blocks the first attempt is filled in by the second.
The problem: each variant has a blind spot
ESP variant
Requires
unshare(CLONE_NEWUSER | CLONE_NEWNET) to gain CAP_NET_ADMIN for XFRM SA registration.Blind spot: Ubuntu applies an AppArmor policy (kernel.apparmor_restrict_unprivileged_userns = 1) that returns -EPERM from unshare(CLONE_NEWUSER) in some configurations, preventing the ESP variant from running at all. In addition, esp4.ko must be loaded or loadable.RxRPC variant
Requires
rxrpc.ko to be present (loaded automatically by socket(AF_RXRPC, ...)).Blind spot: RHEL 10.1 and most non-Ubuntu distributions do not ship rxrpc.ko in their default kernel build. However, Ubuntu ships and loads rxrpc.ko by default.The blind spots are complementary: the environment that blocks the ESP variant (Ubuntu with AppArmor namespace restriction) is exactly the environment where the RxRPC variant works. The environments that lack
rxrpc.ko (RHEL, CentOS, most non-Ubuntu distributions) are exactly the environments where user namespace creation is allowed and the ESP variant works.The solution: chain them
Run the ESP variant first. If it succeeds, you are done. If it fails for any reason —unshare returns -EPERM, esp4.ko is not loaded, or SA registration fails — fall back to the RxRPC variant. Because the two blind spots do not overlap on any major distribution, one of the two variants will always succeed.
The chain logic
Fork child, attempt ESP exploit
The parent forks a child. The child calls
unshare(CLONE_NEWUSER | CLONE_NEWNET), writes identity uid/gid maps, brings lo up, and registers 48 XFRM SAs — one per 4-byte chunk of the root-shell ELF. It then runs 48 vmsplice + splice triggers to overwrite the first 192 bytes of /usr/bin/su in the page cache and exits with status 0 on success or 2 on failure.Parent checks the result
The parent
waitpids for the child. If the child exited 0, the parent opens /usr/bin/su and verifies that bytes at file offset 0x78–0x79 are 0x31 0xff (the xor edi, edi at the shellcode entry). A successful verify means the page cache is patched.Execute /usr/bin/su for a root shell (ESP path)
The parent calls
forkpty + execve("/usr/bin/su", ...). The kernel maps the patched page cache page. The setuid-root bit elevates the process to euid=0. The shellcode at 0x400078 calls setgid(0), setuid(0), setgroups(0, NULL), and execve("/bin/sh", NULL, envp), dropping into a root shell.Fall back to the RxRPC variant (if ESP failed)
If the child exited non-zero or the verify failed, the parent moves on to the RxRPC variant. It opens
/etc/passwd read-only, reads the ciphertexts at offsets 4, 6, and 8, and brute-forces K_A, K_B, K_C in user space using a port of the kernel’s crypto/fcrypt.c. Then it runs three add_key + socket + handshake + splice + recvmsg sequences to write ::0:0:GGGGGG: over characters 4–15 of line 1.Execute /usr/bin/su for a root shell (RxRPC path)
With the root entry’s password field now empty,
forkpty + execve("/usr/bin/su", ...) triggers PAM authentication. pam_unix.so with the nullok option accepts the empty password and returns PAM_SUCCESS. su calls setresuid(0,0,0) and execs /bin/bash, producing a root shell.Coverage table
| Environment | ESP variant works | RxRPC variant works | Combined result |
|---|---|---|---|
| Ubuntu (AppArmor userns blocked, rxrpc.ko loaded) | No — unshare returns -EPERM | Yes — rxrpc.ko is present | Root via RxRPC |
| Ubuntu (AppArmor userns allowed, rxrpc.ko loaded) | Yes | Yes | Root via ESP (first attempt succeeds) |
| Debian / generic systemd distro | Yes — userns allowed | Likely yes if rxrpc.ko is built | Root via ESP |
| RHEL 10.1 / CentOS (no rxrpc.ko) | Yes — userns allowed | No — rxrpc.ko absent | Root via ESP |
| Arch / Fedora (default config) | Yes — userns allowed | Depends on kernel config | Root via ESP |
| Environment with both vectors blocked | No | No | Not covered |
Why a single binary handles all distributions
The binary embeds both exploit variants and the brute-force engine forfcrypt key search. At runtime it probes its environment by attempting the namespace creation and checking the return value, then selects the appropriate variant. Neither variant is attempted if it cannot succeed: the ESP path exits cleanly if unshare fails, and the RxRPC path is only reached after the ESP path reports failure. No distribution-specific compile flags or separate binaries are needed.
Related pages
xfrm-ESP Page-Cache Write
Root cause, 4-byte STORE primitive, 48-SA exploit flow, and the
SKBFL_SHARED_FRAG patch for CVE-2026-43284.RxRPC Page-Cache Write
Root cause, fcrypt brute force, three-splice chain for
/etc/passwd, and the skb->data_len gate patch for CVE-2026-43500.