DirtyDecrypt-Go — RxRPC rxgk Page-Cache Overwrite LPE (Go Port) — CVE-2026-31635
by Koshmare-Blossom (Go port); original vulnerability discovery and PoC by Aaron Esau / V12 Security · 2026-07-05
- Severity
- High
- CVE
- CVE-2026-31635
- Category
- binary
- Affected product
- Linux kernel — net/rxrpc/rxgk_common.h (rxgk_decrypt_skb())
- Affected versions
- Kernels with RxRPC + rxgk support prior to the upstream fix (same range as the wider "Dirty Frag" vulnerability class)
- Disclosed
- 2026-07-05
- Patch status
- unpatched
References
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-05 |
| Last Updated | 2026-05 |
| Author / Researcher | Koshmare-Blossom (Go port); original vulnerability discovery and PoC by Aaron Esau / V12 Security |
| CVE / Advisory | CVE-2026-31635 |
| Category | binary |
| Severity | High |
| CVSS Score | Not specified in source |
| Status | Weaponized |
| Tags | linux-kernel, lpe, rxrpc, rxgk, page-cache, dirty-pipe-variant, splice, golang, unprivileged |
| Related | pocs/binary/2026-05-18_dirtydecrypt/ |
Affected Target
| Field | Value |
|---|---|
| Software / System | Linux kernel — net/rxrpc/rxgk_common.h (rxgk_decrypt_skb()) |
| Versions Affected | Kernels with RxRPC + rxgk support prior to the upstream fix (same range as the wider “Dirty Frag” vulnerability class) |
| Language / Platform | Go (single static binary PoC), Linux x86-64 |
| Authentication Required | No |
| Network Access Required | No (local; uses an AF_RXRPC loopback connection) |
Summary
This is a Go re-implementation (“port”) of the original C dirtydecrypt PoC, now tracked as its own CVE (CVE-2026-31635). The bug is a missing skb_cow_data() call in rxgk_decrypt_skb(): the krb5enc AEAD used by RxRPC’s rxgk security class decrypts skb payload data in-place, directly into whatever physical page backs the skb — including page-cache pages pinned there via vmsplice/splice. Because RxRPC’s rxgk AES-128-CTS decryption is keyed per-call (unlike the deterministic keystream-table technique used by the related fragnesia bug), each corrupting write is probabilistic (~1/256 per byte), but a sliding-window technique allows forward-only, byte-by-byte recovery of the target value without ever needing to win a race. The PoC uses this to rewrite /usr/bin/su’s in-page-cache bytes and obtain a root shell via a PTY, leaving the on-disk binary untouched.
Vulnerability Details
Root Cause
rxgk_decrypt_skb() passes skb fragment pages directly into crypto_krb5_decrypt() for in-place AEAD decryption without first calling skb_cow_data() to ensure the kernel owns a private copy of the backing page. When the backing page is a page-cache page (pinned via vmsplice + splice), the in-place decryption directly corrupts that file’s page-cache contents.
Attack Vector
add_key("rxrpc", ...)installs a randomly generated AES-128rxgksession key.- An
AF_RXRPCclient socket connects to a fake UDP server bound to loopback. - The fake server sends a CHALLENGE packet (SecuIdx=6,
rxgk); the client responds, establishing the security context. - The fake server builds a malicious DATA packet combining a
vmsplice-supplied wire header with asplice-supplied file page (the target file, e.g./usr/bin/su, at a chosen offseti). rxgk_decrypt_skb()runs client-side and decrypts in-place, so byteiof the target file’s page-cache becomes a uniformly random byte (1/256 chance of matching the desired value).- A sliding-window technique advances to offset
i+1once byteimatches, so each subsequent fire (corrupting bytesi+1..i+16) never disturbs the already-correct bytei— giving forward-only, race-free convergence at ~256 fires per byte on average. - After ~49,152 total fires (192 target bytes), the target binary’s in-page-cache bytes are fully attacker-controlled, e.g. clearing
su’s privilege-check logic, and the PoC drops into a root shell via a PTY — the on-disk file itself is never modified.
Impact
Arbitrary page-cache write primitive usable by an unprivileged local user to achieve local privilege escalation to root, without leaving any modification to the on-disk binary.
Environment / Lab Setup
Target: Unpatched Linux kernel with the rxrpc module available (autoloaded on socket(AF_RXRPC, ...))
Attacker: Go toolchain (no external tools required — pure Go, single static binary)
Proof of Concept
PoC Script
See
main.go,lpe.go,rxgk.go, andpty.goin this folder.
| |
The binary establishes the rxgk session key, runs the fake-server/loopback DATA-packet exchange described above, and applies the sliding-window byte-recovery technique to progressively corrupt the target binary’s page-cache image until root access is obtained via a PTY.
Detection & Indicators of Compromise
Signs of compromise:
- Unexpected root shells spawned from processes with no corresponding sudo/authentication event
vmsplice/splicesyscall activity involving setuid binaries from an unprivileged user contextrxrpcmodule loaded/active on systems where it is not legitimately used
Remediation
| Action | Detail |
|---|---|
| Primary fix | Apply the upstream kernel fix adding skb_cow_data() to rxgk_decrypt_skb() (and the related rxkad_verify_packet_2 path) — same range as the “Dirty Frag” family fixes |
| Interim mitigation | rmmod rxrpc and blacklist it: printf 'install rxrpc /bin/false\n' > /etc/modprobe.d/dirtydecrypt.conf |
References
Notes
Mirrored from https://github.com/Koshmare-Blossom/Dirtydecrypt-go on 2026-07-05. This is a Go port of the same underlying rxgk page-cache-overwrite technique already archived in this repository as pocs/binary/2026-05-18_dirtydecrypt/ (the original C PoC by Aaron Esau / V12 Security); this entry is mirrored separately because it corresponds to its own assigned CVE (CVE-2026-31635).
| |