Dirty Frag — Linux kernel local privilege escalation
Universal Linux kernel local privilege escalation disclosed
publicly on 2026-05-07 (confirmed by both
Canonical's advisory
and Red Hat's CVE record), with broader public discussion
across oss-security and r/hetzner on 2026-05-08 after the
coordinated-disclosure embargo broke. Also referred to as
Copy Fail 2 by a separate disclosing entity.
The bug class — externally-owned paged skb fragments
(SKBFL_SHARED_FRAG, set by
MSG_SPLICE_PAGES / splice() into UDP
sockets) being processed in place by crypto code that assumes
the skb owns its pages — affects two kernel subsystems. Per
Red Hat's record, the practical exploitation primitive is
corrupting page-cache contents of readable system
files such as /etc/passwd to gain root —
the same broad pattern as Dirty COW. Tracked as two CVEs:
CVE-2026-43284
in the xfrm ESP-in-UDP input path (CVSS 8.8 HIGH) and
CVE-2026-43500
in the rxrpc DATA / RESPONSE handlers (CVSS 7.8 HIGH).
Local attack vector (no remote exploitation), but a
public proof-of-concept
has been released. Patch via your distro's normal kernel update
channel and reboot — the fix landed across every maintained
stable branch.
TL;DR
- Local attack only (CVSS
AV:L). Attacker needs an existing low-privilege user account on the host. Not remotely exploitable. - Affects: stable Linux kernels from 4.11
through 7.0.x across both subsystems. The
xfrm-side bug (43284) covers the broader range; therxrpc-side bug (43500) starts at 5.3. Fixed in kernel.org stable releases 5.10.255, 5.15.205, 6.1.171, 6.6.138, 6.12.87, 6.18.29, and 7.0.6 (and newer). - Public PoC exists at github.com/V4bel/dirtyfrag — NVD has tagged this URL "Exploit, Third Party Advisory" on the 43284 record.
- Risk to a single-operator homelab where only you have shell access: moderate, not low. With a public PoC available, any service-account foothold (Apache, Plex, *arr, etc.) becomes a kernel root foothold in one step.
- Risk to multi-user / VPS-style hosts where guest accounts, container users, or shared admin paths exist: high — patch this cycle.
- Fix: apply your distro's latest kernel security update and reboot. The patched kernel must actually be running; a package upgrade alone does not apply the fix.
How the two CVEs relate
Both CVEs are different code-path manifestations of the
same bug class: an skb (socket buffer) can carry paged
fragments that are externally owned — typically because
userspace called splice() or sent with
MSG_SPLICE_PAGES into a UDP socket, attaching pipe
pages directly to the skb. The kernel marks these with the
SKBFL_SHARED_FRAG flag so later paths know to copy
before modifying. The bug is downstream code paths that took the
"uncloned, no frag_list, fast path" branch without
checking that flag, and then performed an in-place crypto
operation on pages they did not actually own privately.
- CVE-2026-43284 lives in the
xfrmESP-in-UDP input path (IPsec NAT-traversal). The fix marks IPv4/IPv6 datagram splice frags withSKBFL_SHARED_FRAG(matching TCP) and makes ESP input fall back toskb_cow_data()when the flag is set. CVSS 8.8 HIGH (kernel.org CNA) — theS:CScope-Changed vector reflects user-to-kernel boundary crossing. CISA-ADP independently scores it 7.8 withAC:H. CWE-123 (Write-what-where Condition). - CVE-2026-43500 lives in
rxrpc's DATA and RESPONSE packet handlers. The existing gate only unshared the skb whenskb_cloned()was true; an uncloned skb carrying externally-owned paged fragments still fell through to in-place decryption that bound the frag pages directly into the AEAD SGL viaskb_to_sgvec(). The fix extends the gate to also unshare onskb_has_frag_list()orskb_has_shared_frag(). CVSS 7.8 HIGH, CWE-787 (Out-of-bounds Write).
If you're scoring patch priority by CVE: fix both
together — they're patched in the same stable releases.
The xfrm one matters to anyone running IPsec with NAT-T; the
rxrpc one matters to anyone running AFS (uncommon outside
universities / large enterprises) or any host where userspace
can open AF_RXRPC sockets.
At a glance
| Field | CVE-2026-43284 | CVE-2026-43500 |
|---|---|---|
| Also known as | Copy Fail 2 — per a separate disclosing entity, referenced by Canonical's CVE-tracker note. (Canonical's CVE-tracker note also contains a one-letter typo "Dirty Flag"; the canonical name is "Dirty Frag" per Red Hat's Bugzilla titles #2467771 + #2468273, the upstream PoC repo, and Canonical's own blog URL.) | |
| Subsystem | xfrm ESP-in-UDP input (IPsec NAT-T) |
rxrpc DATA / RESPONSE handlers |
| CVSS 3.1 base | 8.8 HIGH (kernel.org CNA); 7.8 HIGH (CISA-ADP / Red Hat / Canonical) | 7.8 HIGH (NVD; Red Hat scoring: Draft, base 7.8) |
| CVSS vector | AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H (kernel.org)AV:L/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H (CISA-ADP)AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H (Red Hat) |
AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H (NVD + Red Hat) |
| CWE | CWE-123 (Write-what-where Condition) — CISA-ADP, Red Hat | CWE-787 (Out-of-bounds Write) — NVD; CWE-123 — Red Hat |
| Red Hat threat severity | Important (not Critical — local-only exploitation) | Not Affected on RHEL / RHCOS (RxRPC module not shipped) |
| Live patching (kpatch) | Available for RHEL 8.8 E4S, 9.2 E4S, 9.4 EUS, 9.6 EUS (RHSA-2026:19572 / 19573 / 19577 / 18025) | N/A (not affected) |
| Attack vector | Local — requires existing local account | |
| Privileges required | Low (any local user) | |
| User interaction | None | |
| Affected kernel range | 4.11 → 7.0.5 (multiple stable branches) | 5.3 → 7.0.6 |
| CNA | kernel.org | |
| NVD analysis status | Analyzed (enriched) | Analyzed (enriched) |
| Published / last modified | 2026-05-08 / 2026-05-14 | 2026-05-11 / 2026-05-17 |
| Public PoC | github.com/V4bel/dirtyfrag — tagged "Exploit, Third Party Advisory" by NVD on CVE-2026-43284 | |
| CISA KEV listed | Not at time of writing (2026-05-20) | |
| Disclosure timeline |
2026-05-07: public disclosure per Canonical's advisory. 2026-05-08: oss-security mailing list thread, r/hetzner discussion, kernel-stable patches land, NVD publishes CVE-2026-43284. 2026-05-11: NVD publishes CVE-2026-43500. |
|
| Embargo status | Broken ahead of coordinated disclosure date | |
What the kernel actually changed
Both fixes are documented in the kernel-stable commit messages. Quoted verbatim:
CVE-2026-43284 —
xfrm: esp: avoid in-place decrypt on shared skb frags
MSG_SPLICE_PAGEScan attach pages from a pipe directly to an skb. TCP marks such skbs withSKBFL_SHARED_FRAGafterskb_splice_from_iter(), so later paths that may modify packet data can first make a private copy. The IPv4/IPv6 datagram append paths did not set this flag when splicing pages into UDP skbs. That leaves an ESP-in-UDP packet made from shared pipe pages looking like an ordinary uncloned nonlinear skb. ESP input then takes the no-COW fast path for uncloned skbs without afrag_listand decrypts in place over data that is not owned privately by the skb. Mark IPv4/IPv6 datagram splice frags withSKBFL_SHARED_FRAG, matching TCP. Also make ESP input fall back toskb_cow_data()when the flag is present, so ESP does not decrypt externally backed frags in place.
CVE-2026-43500 —
rxrpc: Also unshare DATA/RESPONSE packets when paged frags are presentThe DATA-packet handler in
rxrpc_input_call_event()and the RESPONSE handler inrxrpc_verify_response()copy the skb to a linear one before calling into the security ops only whenskb_cloned()is true. An skb that is not cloned but still carries externally-owned paged fragments (e.g.SKBFL_SHARED_FRAGset bysplice()into a UDP socket via__ip_append_data, or a chainedskb_has_frag_list()) falls through to the in-place decryption path, which binds the frag pages directly into the AEAD/skcipher SGL viaskb_to_sgvec(). Extend the gate to also unshare whenskb_has_frag_list()orskb_has_shared_frag()is true. This catches the splice-loopback vector and other externally-shared frag sources while preserving the zero-copy fast path for skbs whose frags are kernel-private (e.g. NICpage_poolRX, GRO).
Plain-English read: when userspace splices pipe pages into a UDP
socket, the resulting skb carries pages it does not own
privately. Two crypto-touching code paths (xfrm ESP
input and rxrpc packet handlers) failed to detect
this and decrypted in place over those externally-owned pages,
giving a local attacker a write primitive into pages the kernel
assumed were exclusively held. CWE-123 (Write-what-where) on the
ESP side reflects the severity of that primitive.
Why "Dirty Frag" matters even if you're not multi-user
The "Dirty" naming convention (Dirty COW in 2016, Dirty Pipe in
2022, Dirty Cred in 2022) marks kernel bugs that turn an existing
low-privilege foothold into full root. The reason these matter
even on single-operator boxes is that they collapse the gap
between "an attacker got code execution as the
www-data service account" and "the attacker
owns the kernel".
If you run any service that has been targeted by a public exploit in the past 12 months — Apache, nginx with a vulnerable module, Plex, an internet-exposed admin panel, a sandboxed container that can reach the host's kernel — a kernel LPE is the step that converts a service-account compromise into a permanent backdoor. That's why the "single-user homelab, low immediate risk" framing undersells it. Patch on the next kernel cycle, not the one after.
Per-distro fix status
Distro security teams are publishing backports to their stable kernel packages now. Cross-reference the running kernel against your distro's tracker — both CVE IDs:
| Distro | Tracker (both CVEs) | Update path |
|---|---|---|
| Ubuntu 24.04 / 22.04 / 20.04 (+ 18.04 / 16.04 ESM) |
ubuntu.com/security/CVE-2026-43284 ubuntu.com/security/CVE-2026-43500 Status: "Needs evaluation" on every release as of 2026-05-20 — Canonical's tracker notes "Fix currently in netdev tree only", so backports are pending the next netdev → mainline-stable cycle. Canonical's "Dirty Frag" blog has the official mitigation guidance. Ubuntu Priority: High. Ubuntu CVSS: 7.8. |
sudo apt update && sudo apt full-upgrade -y && sudo reboot |
| Debian 13 (Trixie) | DSA-6253-1 — linux fixed in 6.12.86-1 (CVE-2026-43284), 6.12.88-1 (CVE-2026-43500) | sudo apt update && sudo apt full-upgrade -y && sudo reboot |
| Debian 12 (Bookworm) | DSA-6258-1 — linux fixed in 6.1.170-3 (CVE-2026-43284), 6.1.172-1 (CVE-2026-43500) | sudo apt update && sudo apt full-upgrade -y && sudo reboot |
| Debian 11 (Bullseye LTS) | DLA-4572-1 (linux 5.10.251-5) + DLA-4574-1 (linux-6.1 6.1.172-1~deb11u1) — see the security tracker for the announcement links. | sudo apt update && sudo apt full-upgrade -y && sudo reboot |
| RHEL / Rocky / AlmaLinux 8, 9, 10 (+ OpenShift) |
CVE-2026-43284: patched across all supported majors via 37 RHSAs (kernel + kernel-rt + RHCOS) — 32 at first publication, +5 additional advisories landed 2026-05-21 (RHSA-2026:19564 / 19568 / 19569 / 19574 / 19575). Headline advisories: RHSA-2026:16195 (RHEL 8), RHSA-2026:16206 / 16312 (RHEL 9.x), RHSA-2026:16062 / 19074 (RHEL 10.x). Live-patching via kpatch on E4S/EUS streams (RHSA-2026:19572 / 19573 / 19577 / 18025) — no reboot required. RHEL 6/7: Not affected. Full RHSA matrix on Red Hat's CVE page. CVE-2026-43500: Not affected on RHEL / RHCOS — the RxRPC module is not shipped, supported, or installed by default. Confirmed by Red Hat's CVE page. |
sudo dnf upgrade -y kernel && sudo rebootor kpatch (E4S/EUS): sudo dnf install kpatch-patch-<ver> && sudo systemctl enable --now kpatch |
| Alpine |
security.alpinelinux.org/CVE-2026-43284 security.alpinelinux.org/CVE-2026-43500 |
sudo apk update && sudo apk upgrade && sudo reboot |
| Mainline / custom-built kernels | kernel.org stable: fixed in 5.10.255, 5.15.205, 6.1.171, 6.6.138, 6.12.87, 6.18.29, 7.0.6 (see Authoritative sources for individual commit hashes) | Rebuild and redeploy via your kernel-build pipeline |
Quick check on a host
Determine the running kernel version and whether the system has a newer one installed but not yet booted:
# Running kernel:
uname -r
# Installed but not yet running:
# Debian / Ubuntu
ls /boot/vmlinuz-* | sort -V | tail -1
# RHEL / Rocky / AlmaLinux
rpm -q --last kernel | head -2
# Reboot required indicator on Debian/Ubuntu:
[ -f /var/run/reboot-required ] && echo "REBOOT REQUIRED" || echo "No pending reboot"
# Across multiple hosts via SSH:
for h in host-a host-b host-c; do
echo -n "$h: "
ssh "$h" 'uname -r'
done
Mitigations short of patching
If you can't reboot immediately, the attack surface for each CVE
is shaped by which kernel modules and code paths are actually
reachable on the host. Canonical published an official
pre-patch mitigation in their
"Dirty Frag" advisory:
drop a /etc/modprobe.d/dirty-frag.conf file
blacklisting the affected modules, regenerate
initramfs, unload the modules, verify, and reboot
if necessary. Follow Canonical's blog for the exact commands;
the items below add context for which lines you actually need
based on what's loaded on your host.
-
CVE-2026-43500 (rxrpc) — disable if unused.
rxrpcis the RX RPC protocol used almost exclusively by AFS. Most homelab and VPS hosts do not use it. Check withlsmod | grep -E '^(rxrpc|kafs)\b'; if not loaded and not needed, blacklist both: addblacklist rxrpcandblacklist kafsto/etc/modprobe.d/dirty-frag.conf(matching Canonical's filename for consistency across hosts). This removes the 43500 surface entirely on hosts that don't need AFS. -
CVE-2026-43284 (xfrm ESP-in-UDP) — depends on IPsec
use. If the host does not run IPsec / xfrm (most
homelab routers using WireGuard, OpenVPN, or Tailscale do
not), the path is not reachable: check
ip xfrm policyandlsmod | grep -E '^(esp|xfrm)'. If IPsec is in use and you specifically need NAT-traversal (ESP-in-UDP on port 4500), there is no clean disable-the-feature workaround — patch and reboot is the only fix. -
Restrict local access: the attack requires a
local account that can open the relevant sockets. Tighten
which users / containers have shell access. Service accounts
for
www-data-style processes are the realistic first foothold an attacker chains to this LPE. -
Tighten container isolation: ensure
unprivileged containers drop
CAP_NET_RAW/CAP_NET_ADMINand that user-namespace remapping is in place. Thesplice()+ UDP trigger doesn't need elevated capabilities, but constrained namespaces reduce availability of the trigger conditions inside containers. -
Live-patch via kpatch (RHEL E4S / EUS only).
Red Hat ships kpatch live-patches for RHEL 8.8 E4S
(RHSA-2026:19572), 9.2 E4S (19573), 9.4 EUS (19577), and
9.6 EUS (18025). Install
kpatch-patch-<version>via dnf and enable kpatch; the fix applies to the running kernel without a reboot. Covers only CVE-2026-43284 — the static patch (next reboot) is still the recommended end state. Useful when reboot windows are constrained.
All workarounds are temporary. With a public PoC published, patch and reboot as soon as the kernel update window opens.
What Noxen does about this
Once a CVE ID is assigned and Noxen's daily-rebuilt feed picks it
up, every host whose installed kernel package is older than the
per-distro fix version is flagged automatically. The package name
varies by distro (linux-image-* on Debian/Ubuntu,
kernel on RHEL-family), but Noxen's distro-aware
matcher normalises both to the same CVE record.
Hosts that have the fix installed but haven't rebooted are flagged separately as "kernel updated but not yet running" — a kernel-LPE fix that isn't booted is effectively no fix at all.
Authoritative sources
- NVD entries:
- CVE-2026-43284 (Analyzed; kernel.org CNA + CISA-ADP scoring)
- CVE-2026-43500 (Analyzed)
- cve.org records:
- FIRST EPSS (exploit-probability scoring):
- kernel.org stable backport commits for CVE-2026-43284 (xfrm ESP):
- kernel.org stable backport commits for CVE-2026-43500 (rxrpc):
- oss-security mailing list (disclosure thread):
- Red Hat references:
- Red Hat CVE-2026-43284 (Important, 32 RHSAs)
- Red Hat CVE-2026-43500 (Not affected — RxRPC not shipped)
- Red Hat Security Data API — CVE-2026-43284 (JSON)
- Red Hat Security Data API — CVE-2026-43500 (JSON)
- Bugzilla #2467771 — "Dirty Frag" ESP XFRM variant
- Bugzilla #2468273 — "Dirty Frag" RxRPC variant
- Distro security blog coverage: Canonical: "Dirty Frag" Linux vulnerability fixes available (Ubuntu's primary advisory blog post)
- Public proof-of-concept: github.com/V4bel/dirtyfrag (NVD-tagged "Exploit, Third Party Advisory" on CVE-2026-43284)
- CISA KEV catalogue — not listed at time of writing (2026-05-20)
- r/hetzner discussion (early embargo-break thread)
Related on Noxen
- CVE-2026-31431 — earlier kernel LPE (algif_aead) with the same patch-and-reboot pattern
- Ubuntu 24.04 CVE tracker
- Debian 12 CVE tracker
- Rocky 9 CVE tracker
- How to triage CVE findings
- The patching gap
See what Noxen does about CVEs like this → Back to the CVE feed →