Blog / Threat Analysis · CVE

CVE-2026-46300 ("Fragnesia") — TLCTC Analysis

A second Linux kernel page-cache write primitive lands in under two weeks. Different subsystem (XFRM ESP-in-TCP instead of AF_ALG), different write width (192 bytes instead of 4), different canonical target (/usr/bin/su instead of /etc/passwd) — and the same TLCTC classification as Copy Fail: #2.2 Exploiting Server. The cause-oriented view collapses two subsystem stories into one threat.

BK
Bernhard Kreinz
Loading read time...

1. Chronology — how Fragnesia followed Copy Fail and Dirty Frag

Three Linux kernel privilege-escalation primitives, all yielding root from an unprivileged local user, all landing inside three weeks. The compressed timing matters: defenders working off the original Copy Fail analysis are still mid-patch when Fragnesia drops.

Date (2026) Event
Late April Coordinated public disclosure of CVE-2026-31431 ("Copy Fail"). Theori publishes the write-up. AF_ALG / algif_aead path. CVSS 7.8. PoCs on GitHub within hours.
2026-05-01 CISA alert on Copy Fail. (See our earlier analysis.)
2026-05-04 In-the-wild exploitation of Copy Fail confirmed. Kroah-Hartman ships 6.18.22 / 6.19.12 / 7.0.
2026-05-07 Dirty Frag disclosed by Red Hat (RHSB-2026-003): CVE-2026-43284 (esp4/esp6 / XFRM-ESP) and CVE-2026-43500 (rxrpc). Same shape as Copy Fail at the cluster level — different subsystem.
2026-05-08 Microsoft Security Blog reports active attack against Dirty Frag. Detections Trojan:Linux/DirtyFrag.Z!MTB and Trojan:Linux/DirtyFrag.DA!MTB.
2026-05-13 William Bowling (Zellic) posts the Fragnesia patch to netdev. Two-line fix. PoC and write-up on Bowling's GitHub. The bug was introduced by the patch for CVE-2026-43284 — the Dirty Frag fix activated a latent path in skb_try_coalesce() that drops SKBFL_SHARED_FRAG.
2026-05-14 heise.de: "Microsoft warns of further privilege-escalation vulnerability in Linux." AlmaLinux and CloudLinux ship patched kernels. Ubuntu, Debian, RHEL, openSUSE, CentOS Stream, Gentoo still pending at time of writing.
2026-05-15 (today) No in-the-wild exploitation of Fragnesia observed yet. Window between patch publication and weaponisation likely measured in days, given Dirty Frag and Copy Fail set the operator playbook two weeks ago.
A patch introduced the next CVE

Fragnesia was spawned by the Dirty Frag patch. The fix for CVE-2026-43284 changed how skb fragments are coalesced and inadvertently dropped the SKBFL_SHARED_FRAG flag along the espintcp ULP-transition path. This is not a missed variant — it is a regression introduced by the remediation. The cause-side fix loop is itself a source of #2.2.

2. What the bug does, technically

Stripped to mechanics:

  1. Setup. An unprivileged process creates a new user namespace + network namespace. Both are enabled by default on most distributions; the new netns hands the process CAP_NET_ADMIN inside that namespace without any host privilege.
  2. Page injection. The process opens a TCP socket and splice()s data from a target file (e.g. /usr/bin/su) into the socket's receive queue. The pages enqueued are shared with the page cache — the kernel marks the corresponding skb frags with SKBFL_SHARED_FRAG so downstream code knows not to modify them in place.
  3. ULP flip. The process then attaches the espintcp ULP to that socket (XFRM ESP-in-TCP mode). The kernel now treats the bytes already sitting in the receive queue as ESP ciphertext.
  4. Coalesce loses the flag. When the kernel coalesces queued fragments via skb_try_coalesce(), the post-Dirty-Frag code path fails to propagate SKBFL_SHARED_FRAG. The coalesced skb now looks like a private buffer to the rest of the pipeline.
  5. In-place decryption hits the page cache. The ESP receive path decrypts AES-GCM in place. XOR of an attacker-controlled keystream lands directly on the shared page-cache page. By controlling the IV nonce, the attacker controls the bytes written. 192 bytes per trigger.
  6. Privesc. The public PoC rewrites /usr/bin/su in the page cache so the next invocation drops to root. /etc/passwd, /etc/shadow, sudoers fragments, setuid binaries — any file readable by the attacker is a target. The on-disk file is untouched; a reboot or echo 3 > /proc/sys/vm/drop_caches restores the original.

The two-line upstream fix re-propagates the SKBFL_SHARED_FRAG marker through skb_try_coalesce(), restoring the invariant the rest of the receive path depends on.

No race window

Like Copy Fail, Fragnesia is deterministic — no race condition, no infoleak prerequisite, no kernel offset disclosure. Single syscall sequence, one shot, root. This is a property of the underlying flaw class (#2.2 internal processing logic), not of the specific subsystem.

3. TLCTC classification — identical to Copy Fail

Cluster #2 Exploiting Server, sub-cluster #2.2 (core function vector — internal processing/parsing flaws in a server-role component). Same reasoning chain, different subsystem.

  • R-ROLE. The Linux kernel, exposed via the TCP socket + espintcp ULP attachment, receives and processes inbound data from the attacker's unprivileged userspace process. The kernel is in server role for this interaction → #2, not #3.
  • #1 vs #2. The exploit path requires a logic flaw in skb_try_coalesce(): a marker bit (SKBFL_SHARED_FRAG) is dropped where it must be preserved. The intended design assumes the marker survives coalescing; the implementation no longer enforces that assumption. Implementation flaw → #2 / #3, not #1. There is no abuse of an intended feature within its documented contract.
  • #2 sub-clustering. Not socket-protocol parsing (#2.1) — the TCP and ESP packet parsing themselves are not the bug. Not delegated external processing (#2.3) — no third-party component is in the trust path. The locus is the kernel's own internal skb-management and AEAD-decryption logic; the upstream fix changes how skb_try_coalesce() handles a flag in its own code, confirming core-function-logic placement → #2.2.
  • R-CRED does not apply. The attacker does not present a credential to anyone. The identity-store / setuid-binary is rewritten in the page cache. The subsequent su call simply runs the corrupted binary — there is no #4 Identity Theft follow-up step. The follow-up is a Loss-of-Integrity DRE on the page-cache file, exactly as with Copy Fail.
  • Axiom IV (actor identity does not determine cluster). Whether the operator is a CI runner, a tenant container, or a phishing victim, the kernel step remains #2.2.

Generic vulnerability: code imperfection in server-side software (internal kernel processing path).

4. Side-by-side — Fragnesia vs. Copy Fail

Dimension Copy Fail (CVE-2026-31431) Fragnesia (CVE-2026-46300)
Disclosure Late April 2026 2026-05-13
Subsystem AF_ALG / algif_aead (in-place AEAD scatterlist) XFRM ESP-in-TCP / espintcp ULP + skb_try_coalesce()
Trigger surface AF_ALG socket from unprivileged user (no namespace required) TCP socket + ULP attach inside user+net namespace (CAP_NET_ADMIN from netns)
Write width per trigger 4 bytes 192 bytes (AES-GCM keystream XOR)
Race condition None None
Canonical PoC target /etc/passwd page cache /usr/bin/su page cache
Target flexibility Any user-readable file Any user-readable file
On-disk artefact None (page cache only) None (page cache only)
Discovered by Theori William Bowling (Zellic) — AI-assisted audit
Origin of the bug Long-standing logic flaw in in-place AEAD path (~2017) Regression introduced by the Dirty Frag patch (CVE-2026-43284)
Patch Revert in-place AEAD to out-of-place Two lines: re-propagate SKBFL_SHARED_FRAG in skb_try_coalesce()
Containment without patch seccomp / runtime opt to block AF_ALG Blacklist esp4, esp6 (and rxrpc for Dirty Frag)
CVSS 7.8 7.8
In-the-wild Yes (as of 2026-05-04) Not yet observed
TLCTC cluster #2.2 Exploiting Server #2.2 Exploiting Server
Bow-Tie SRE Loss of Control — kernel writes outside intended buffer Loss of Control — kernel writes outside intended buffer
Primary DRE Loss of Integrity — page cache of readable file Loss of Integrity — page cache of readable file
Velocity VC-4 at the kernel step VC-4 at the kernel step
Container-escape implication Yes — shared host page cache crosses namespaces Yes — same mechanism
ATT&CK mapping T1068 (conflates cause and effect) T1068 (conflates cause and effect)

Read the right-hand column of "same"-flagged rows top to bottom: it is a definition. Two CVEs published three weeks apart, in completely different kernel subsystems, with completely different mechanics, produce identical Bow-Tie placements and identical attack-path skeletons. This is what a cause-oriented taxonomy is supposed to do — collapse outcome-driven noise into one threat-cluster signal.

5. Attack paths — same four shapes

The Fragnesia kernel step is, like Copy Fail, a terminal local privilege-escalation primitive. It needs prior local code execution as an unprivileged user and yields root (or host-kernel control from a container). The four chains we enumerated for Copy Fail apply unchanged; only the kernel-step label moves from "algif_aead" to "espintcp coalesce". The intra-system boundary annotation is identical: |[kernel][@user→@kernel]|.

Path A — Local foothold from a server-side compromise

Path A — Server-side compromise → Fragnesia privesc
#2 ||[api][@External→@Org]||                    (initial RCE: web app, edge appliance, etc.)
   →[Δt=minutes–hours]
#7                                              (webshell/implant as service user)
   →[Δt=minutes]
#2.2 |[kernel][@user→@kernel]|                 (espintcp ULP + skb coalesce primitive)
   →[Δt<1s]
   + [DRE: I — /usr/bin/su page cache]
   → SRE: Loss of Control (root)
   + [DRE: C, I, A — host]
#2 initial RCE
Δt = minutes–hours
#7 webshell/implant
Δt = minutes
#2.2 espintcp primitive
Δt < 1s
[DRE: C, I, A — host]

Path B — Container escape in multi-tenant infrastructure

The page cache is shared across containers on the same host kernel. As with Copy Fail, this elevates the CVE from "local privesc" to "cloud incident." Containers remain a non-boundary against #2 in the host kernel. The extra wrinkle for Fragnesia: user+netns availability is the default on most distributions, which lowers the prerequisites inside the container compared to other LPE classes.

Path B — Container escape via host kernel
[any path delivering code execution into tenant container]
   
#2.2 |[kernel][@container→@host-kernel]|       (same primitive, escapes namespace by design)
   →[Δt<1s]
   + [DRE: I — host page cache, shared across tenants]
   → SRE: Cross-tenant compromise
   + [DRE: C, I, A — host and sibling containers]

Path C — Endpoint chain via phishing / malware

Targeted Linux workstations and developer machines. The required user+netns capability is already present on stock Ubuntu/Fedora/Debian desktops — no setup required.

Path C — Phishing / malware → Fragnesia privesc
#9 ||[human][@External→@Org]||                 (lure → user runs attacker code)
   →[Δt=hours]
#7                                              (stage-1 loader / dropper as user)
   →[Δt<1m]
#2.2 |[kernel][@user→@kernel]|
   →[Δt<1s]
   + [DRE: I — /usr/bin/su]
   → SRE: Loss of Control
   + [DRE: C, I, A — host]

Path D — Supply-chain delivery to a build / dev / CI host

CI runners and build farms are particularly exposed: short-lived, namespace-rich, often running untrusted package code by design. A poisoned postinstall hook that needs ~200 bytes of write into /usr/bin/su is well within a single CI step.

Path D — Supply-chain → build host privesc
#10 ||[update][@Vendor→@Org]||                (poisoned package, TAE = install)
   →[Δt=seconds]
#7                                              (post-install hook executes)
   →[Δt<1m]
#2.2 |[kernel][@user→@kernel]|
   →[Δt<1s]
   + [DRE: I — /usr/bin/su]
   → SRE: Loss of Control on the build host
   + [DRE: C, I, A — host, with onward supply-chain blast radius]

Notes on the chains

  • No #4 follow-up. Same logic as Copy Fail. The attacker rewrites the setuid binary or identity store in cache; the subsequent su invocation runs the corrupted code and the kernel resolves UID=0. No credential is presented and none is acquired. The "privilege escalation" is the Loss-of-Integrity DRE flowing from #2.2, not a new step.
  • Privilege escalation is an outcome, not a cluster (SG4). TLCTC keeps cause separate from effect.
  • Same shape, twice. The four chains for Copy Fail and the four chains for Fragnesia are structurally identical. Only the cause-side kernel-step label differs, and that label is the same cluster.

6. Bow-Tie placement

Position Element
Cause #2.2 Exploiting Serverskb_try_coalesce() drops SKBFL_SHARED_FRAG on the espintcp ULP path
Generic vulnerability Code imperfection in server-side software (kernel internal processing) — introduced by the Dirty Frag patch
SRE / Central event Loss of Control — kernel decrypts AES-GCM in place onto a page that should have been treated as shared
DRE (primary) Loss of Integrity — page cache of arbitrary readable file (canonical: /usr/bin/su)
DRE (containerised) Loss of Integrity — host page cache, propagating to all co-tenant namespaces
Consequence Full Loss of C-I-A on the host; cross-tenant compromise in shared-kernel multi-tenancy

7. Velocity & containment

  • Exploit primitive: Δt<1s. End-to-end privesc: <1 minute once local code execution exists.
  • Velocity class VC-4 for the kernel step itself; surrounding chain velocity bounded by the initial-access cluster (typically VC-2 / VC-3).
  • Detection-only controls remain structurally weak. Detection has the same problem as Copy Fail: the operation completes in one syscall sequence, leaves no on-disk artefact, and finishes faster than any inline EDR can react. The CDE_max ceiling for behavioural detection is set by syscall-level visibility into TCP_ULP=espintcp, splice() from a regular file into a TCP receive queue, and unexpected user-namespace+CAP_NET_ADMIN patterns from non-net workloads.
  • Cause-side prevention dominates the ECR ceiling — identically to Copy Fail.

8. Controls grouped by Bow-Tie position

Cause-side (against #2.2)

  • Apply the upstream kernel patch as your distro ships it (AlmaLinux and CloudLinux first; others in flight). The two-line SKBFL_SHARED_FRAG-propagation fix is the only control that closes the generic vulnerability.
  • Mitigation while patching lags: modprobe -r esp4 esp6 (and rxrpc for Dirty Frag coverage). Add to /etc/modprobe.d/∗.conf blacklist. After mitigation, echo 3 > /proc/sys/vm/drop_caches drops any speculatively-corrupted cache pages from a prior probe.
  • Restrict user-namespace creation for non-trusted workloads (kernel.unprivileged_userns_clone=0 on distros that expose it, or seccomp/NoNewPrivileges at the runtime level). Removes the CAP_NET_ADMIN-from-netns prerequisite.
  • For multi-tenant: same conclusion as Copy Fail — if the workload runs untrusted code, the boundary must be VM/hardware, not container/namespace. The host kernel is in #2 role for every tenant simultaneously.

Cause-side (against the chains delivering local exec)

  • Path A: edge-service patching, WAF, server hardening (against #2).
  • Path B: image provenance, runtime admission control, drop ambient capabilities, deny new user namespaces to tenant containers (against the #2/#7/#10 paths into the container).
  • Path C: anti-phishing, mail gateway, user education (against #9); EDR/AV (against #7).
  • Path D: dependency pinning, signed packages, sandboxed builds with userns disabled, isolation of CI runners from production trust (against #10 at the TAE).

Consequence-side (after SRE)

  • File integrity monitoring that compares on-disk state to served page cache — catches the /usr/bin/su divergence that the exploit produces and never flushes. Same control as for Copy Fail.
  • auditd rules on UID changes, setuid binary modifications, unexpected TCP_ULP attachment, and splice() from regular files into TCP sockets.
  • Egress controls and process-tree anomaly detection to bound blast radius once root is achieved.

9. Cross-framework note

In MITRE ATT&CK both Copy Fail and Fragnesia map to T1068 (Exploitation for Privilege Escalation), a technique that conflates the cause (server-side coding flaw) and the effect (privilege escalation). The two CVEs are indistinguishable under T1068. They are also indistinguishable under TLCTC — but TLCTC stops at the cause: #2.2 in both cases, with the effect (Loss-of-Integrity DRE leading to root SRE) recorded separately. The CWE picture is equally messy: Copy Fail tracks against an in-place buffer mishandling weakness (CWE-787 family); Fragnesia against an information-flow / flag-not-propagated weakness (CWE-908 / CWE-704 family). Both feed the same cluster.

Dirty Pipe (CVE-2022-0847), Copy Fail (CVE-2026-31431), Dirty Frag (CVE-2026-43284), and Fragnesia (CVE-2026-46300) form a family at the cluster level: all four are #2.2 kernel page-cache write primitives, all four bypass #4 by rewriting the integrity-store rather than presenting a credential, all four end the same way. That is the actionable picture for defenders — not a sequence of subsystem stories.

10. The patch-introduces-the-CVE pattern

One detail in this case deserves its own note: Fragnesia exists because of the Dirty Frag fix. The patch for CVE-2026-43284 reshaped the code path through skb_try_coalesce() and silently dropped the SKBFL_SHARED_FRAG invariant on the espintcp transition. The mitigation introduced the next vulnerability.

In TLCTC terms, this is not a new cluster — it is still #2.2, and the chain shape is unchanged. What changes is the defender's mental model: a kernel patch is not in itself a containment event for a cluster. The patched code path can host a new #2.2, and frequently does. Your control inventory needs to treat upstream patches as changes to the cause-side attack surface, not as control activations — especially in subsystems (XFRM, AF_ALG, io_uring, BPF, rxrpc) where the rate of #2.2 discovery is high.

11. Summary

CVE-2026-46300 ("Fragnesia") is a Linux kernel page-cache write primitive in the XFRM ESP-in-TCP path, introduced by the Dirty Frag patch. At the level of generic vulnerability it is a single #2.2 step — identical to Copy Fail at the cluster level, despite a different subsystem, different mechanics, and a different write width. The Bow-Tie position is the same, the SRE is the same, the primary DRE is the same, the attack-path skeletons are the same, and the controls map to the same Bow-Tie positions. The cause-oriented taxonomy makes the two CVEs analytically interchangeable for planning purposes — you patch them with the same workflow, you contain them with the same compensating controls, you detect their downstream behaviour with the same syscall-pattern and page-cache-vs-disk visibility, and you prioritise them with the same logic.

The operational implication for defenders: do not budget for "Linux kernel privesc CVEs" as a moving target measured in patches. Budget for #2.2 in the kernel as a persistent cause-side exposure, set the controls accordingly (timely patching, AF_ALG/XFRM module hygiene, unprivileged-userns lockdown, VM boundaries for untrusted workloads), and expect another instance within the next few weeks.

The TLCTC lesson

The kernel flaw is one cluster, one sub-cluster: #2.2 Exploiting Server — identical to Copy Fail and Dirty Frag.

The chain shape is determined by the operator's initial-access cluster (#2, #9, or #10) plus #7, then a single #2.2 step at the userspace→kernel boundary — the same four chains as Copy Fail.

Privilege escalation is the SRE outcome, not a separate cluster. R-CRED excludes a follow-up #4 because no credential is presented — the setuid binary itself is rewritten in the page cache.

The Dirty Frag patch introduced this CVE. A fix is a change to the cause-side attack surface, not a control activation. Your model should expect new #2.2 in subsystems with high churn.

ATT&CK T1068 and most CWE mappings collapse to one label across all four kernel CVEs in this family. TLCTC also collapses them — cleanly, at the cause — and gives you a single playbook to plan against.

Final classification

CVE focus#2.2 Exploiting Server — Linux kernel skb_try_coalesce() drops SKBFL_SHARED_FRAG on espintcp ULP path
SRELoss of Control — kernel decrypts AES-GCM in place onto a shared page-cache page
DRELoss of Integrity — page cache of arbitrary readable file (canonical: /usr/bin/su)
VelocityVC-4 at the kernel step (Δt < 1s); end-to-end privesc < 1 min
Path A#2#7#2.2 + [DRE: C, I, A — host]
Path B[any code-exec into container] → #2.2 + [DRE: C, I, A — host and siblings]
Path C#9#7#2.2 + [DRE: C, I, A — host]
Path D#10#7#2.2 + [DRE: C, I, A — build host + onward blast radius]
ATT&CK refT1068 (Exploitation for Privilege Escalation) — conflates cause and effect; TLCTC keeps them separate
Sibling casesCVE-2026-31431 (Copy Fail), CVE-2026-43284 / 43500 (Dirty Frag), CVE-2022-0847 (Dirty Pipe) — all #2.2

Sources

About the methodology

This analysis applies the TLCTC v2.1 framework: ten cause-oriented threat clusters, the Bow-Tie SRE/DRE separation, attack path notation with Δt velocity classes and v2.1 boundary operators (||...|| for system-edge crossings, |...| for intra-system crossings such as userspace→kernel). For framework definitions: tlctc.net.

Licensed under CC BY 4.0. Framework: tlctc.net · Source: github.com/Barnes70/TLCTC