Skip to content

CVE-2026-43503: Verified Repro With Script Download

CVE-2026-43503: DirtyClone Linux kernel page-cache corruption privilege escalation

CVE-2026-43503 is verified against Linux kernel · linux. Vulnerability class: Privilege Escalation. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00212.

REPRO-2026-00212 Linux kernel · linux Privilege Escalation Variant found Jul 3, 2026 CVE entry ↗ .txt
Severity
HIGH
CVSS
8.8
Confidence
HIGH
Reproduced in
70m 55s
Tool calls
218
Spend
$3.79
01 · Overview

What Is CVE-2026-43503?

CVE-2026-43503, nicknamed DirtyClone, is a critical local privilege escalation vulnerability in the Linux kernel networking stack that allows an unprivileged local attacker to gain root code execution. Pruva reproduced it (reproduction REPRO-2026-00212).

02 · Severity & CVSS

CVE-2026-43503 Severity & CVSS Score

CVE-2026-43503 is rated high severity, with a CVSS base score of 8.8 out of 10.

HIGH threat level
8.8 / 10 CVSS base
Weakness CWE-664

High — serious impact or readily exploitable. Prioritize remediation.

How to Reproduce CVE-2026-43503

$ pruva-verify REPRO-2026-00212
or curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00212/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

Proof of Reproduction for CVE-2026-43503

Privilege escalation — reproduced
  • reached the target end-to-end
  • full exploit chain demonstrated
  • on the real production code path
  • high confidence
  • the upstream fix blocks the same trigger
Trigger

unprivileged local attacker with XFRM/ESP + netfilter TEE + vmsplice/splice zero-copy data

Attack chain
  1. __pskb_copy_fclone() path via netfilter TEE; in-place ESP decryption over file-backed page cache
Variants tested

Fragnesia-style sibling variant of CVE-2026-43503 (DirtyClone) that uses ESP-in-TCP over veth and TCP receive coalescing (skb_try_coalesce) to reach the same in-place ESP-decryption sink over file-backed page-cache frags.

How the agent worked 592 events · 218 tool calls · 1h 11m
1h 11mDuration
218Tool calls
180Reasoning steps
592Events
7Dead-ends
Agent activity over 1h 11m
Support
13
Hypothesis
2
Repro
334
Judge
22
Variant
217
0:0070:55

Root Cause and Exploit Chain for CVE-2026-43503

Versions: Mainline Linux before v7.1-rc5; stable branches before 5.10.257, 5.15.208, 6.1.174, 6.6.141, 6.12.91, 6.18.33, and 7.0.10.

CVE-2026-43503, nicknamed DirtyClone, is a local privilege escalation flaw in the Linux kernel networking stack. When a socket buffer (skb) carries file-backed page-cache fragments, the SKBFL_SHARED_FRAG flag in skb_shinfo()->flags tells the XFRM/IPsec receive path that it must copy the data before decrypting in-place. Several skb fragment-transfer helpers (__pskb_copy_fclone(), skb_shift(), skb_gro_receive(), skb_gro_receive_list(), tcp_clone_payload(), and skb_segment()) fail to copy that flag to the new skb. A netfilter TEE clone therefore keeps the original page-cache reference but no longer reports itself as shared/file-backed, so esp_input() decrypts directly into the page-cache page of a root-owned setuid binary. By choosing the AES-CBC key/IV so the decrypted bytes are attacker-controlled shellcode, the attacker rewrites e.g. /usr/bin/su in RAM and obtains a root shell when the binary is executed.

  • Package/component affected: Linux kernel networking stack — specifically the skb fragment-copy helpers and the XFRM/IPsec esp_input() path.
  • Affected versions: Mainline Linux before v7.1-rc5; stable branches before 5.10.257, 5.15.208, 6.1.174, 6.6.141, 6.12.91, 6.18.33, and 7.0.10.
  • Risk level and consequences: Local privilege escalation. An unprivileged local user with the ability to create user and network namespaces can gain root code execution by corrupting the page cache of a setuid root binary. The bug is reachable from the normal networking paths used by XFRM/IPsec and netfilter, so no special hardware or third-party modules are required beyond the standard kernel configuration.

Impact Parity

  • Disclosed/claimed maximum impact: Local privilege escalation (privilege_escalation) — unprivileged attacker writes into a root-owned read-only binary's page cache and gains root.
  • Reproduced impact from this run: Full privilege escalation demonstrated. The reproducer runs as uid 1000, modifies /usr/bin/su in the page cache, and the subsequent echo id | /usr/bin/su as the same uid 1000 user prints uid=0(root) gid=0(root) groups=0(root).
  • Parity: full.
  • Not demonstrated: N/A — the claimed root shell was obtained.

Root Cause

The bug is in the skb fragment-copy routines. __pskb_copy_fclone() (and the other helpers listed above) copy the fragment array and page references from one skb to another, but they do not propagate the SKBFL_SHARED_FRAG flag from the source skb_shinfo()->flags. This flag is set by the DirtyFrag splice fix (f4c50a4034e6) whenever an skb carries file-backed page-cache fragments via vmsplice()/splice()` into a socket.

When the netfilter TEE target clones an outbound ESP-in-UDP packet, the clone goes through nf_dup_ipv4()__pskb_copy_fclone(). The clone keeps a reference to the same physical page-cache page but is no longer marked SKBFL_SHARED_FRAG. On the receive side, esp_input() calls skb_cow_data() which checks skb_has_shared_frag(). Because the flag is missing, the cow path is skipped and the in-place AES-CBC decryption writes attacker-controlled bytes into the file-backed page-cache page.

The upstream fix is commit 48f6a5356a33dd78e7144ae1faef95ffc990aae0 (first tag v7.1-rc5), which propagates the SKBFL_SHARED_FRAG flag across the fragment-transfer helpers. Ubuntu mainline v7.0.10 contains the backport, so it serves as the negative control in this reproduction.

Reproduction Steps

The reproduction is fully automated by bundle/repro/reproduction_steps.sh. In short, it:

  1. Installs QEMU, busybox-static, cpio, gcc, coreutils, and jq if they are not present.
  2. Uses the prepared project cache to obtain the Ubuntu mainline v7.0.9 (vulnerable) and v7.0.10 (fixed) kernels plus matching rootfs images.
  3. Compiles the rafaeldtinoco dirtyclone.c exploit and a small runas helper that drops to uid 1000.
  4. Builds a custom initramfs that:
    • mounts the rootfs read-only,
    • switches root into the Ubuntu rootfs,
    • loads xt_TEE, nf_dup_ipv4, esp4, and xfrm_user,
    • runs the exploit as an unprivileged uid 1000 user,
    • executes echo id | /usr/bin/su as the same uid 1000 user.
  5. Boots each kernel/rootfs pair in QEMU with the initramfs and captures the console output.
  6. Checks that the vulnerable run prints LPE_SUCCESS and uid=0(root), while the fixed run prints LPE_FAIL and su: Authentication failure.
  7. Writes bundle/repro/runtime_manifest.json and bundle/repro/validation_verdict.json.
Expected evidence
  • bundle/logs/qemu_vuln.log must contain:
    • Linux (none) 7.0.9-070009-generic ...,
    • [dc] wrote 192 bytes to /usr/bin/su starting at 0x0,
    • uid=0(root) gid=0(root) groups=0(root) from the id command,
    • LPE_SUCCESS: unprivileged user got root.
  • bundle/logs/qemu_fixed.log must contain:
    • Linux (none) 7.0.10-070010-generic ...,
    • [dc] post-write verify failed (target unchanged),
    • Password: su: Authentication failure,
    • LPE_FAIL.

Evidence

  • bundle/logs/reproduction_steps.log — high-level script progress.
  • bundle/logs/qemu_vuln.log — full console capture of the vulnerable kernel run showing the root shell.
  • bundle/logs/qemu_fixed.log — full console capture of the fixed kernel run showing the exploit is blocked.
  • bundle/repro/runtime_manifest.json — runtime evidence manifest.
  • bundle/repro/validation_verdict.json — structured verdict (claim_outcome: confirmed).

Key excerpts from the vulnerable run:

[dc] cmd: iptables -t mangle -A OUTPUT -p udp --dport 4500 -j TEE --gateway 10.99.0.2 -> 0
[dc] installed 48 xfrm SAs
[dc] wrote 192 bytes to /usr/bin/su starting at 0x0
[dc] /usr/bin/su page-cache patched (entry 0x78 = shellcode)
=== LPE check as uid 1000 ===
uid=0(root) gid=0(root) groups=0(root)
LPE_SUCCESS: unprivileged user got root

Key excerpts from the fixed run:

[dc] wrote 192 bytes to /usr/bin/su starting at 0x0
[dc] post-write verify failed (target unchanged)
=== LPE check as uid 1000 ===
Password: su: Authentication failure
LPE_FAIL

The kernel configuration required for the path is present in both Ubuntu mainline builds: CONFIG_XFRM, CONFIG_INET_ESP, CONFIG_NETFILTER_XT_TARGET_TEE, and user namespaces.

Recommendations / Next Steps

  • Upgrade: Apply the upstream fix 48f6a5356a33 (or the corresponding stable backport). Ubuntu mainline v7.0.10 and later, and mainline v7.1-rc5 and later, are patched.
  • Mitigation until patched: Disable unprivileged user namespaces (kernel.unprivileged_userns_clone=0) or prevent loading of xt_TEE / esp4 / nf_dup_ipv4 for untrusted users, since the exploit requires CAP_NET_ADMIN in a private network namespace.
  • Testing: Backport validation should verify that SKBFL_SHARED_FRAG survives __pskb_copy_fclone(), skb_shift(), skb_gro_receive(), skb_gro_receive_list(), tcp_clone_payload(), and skb_segment() by running this reproducer against the candidate kernel.

Additional Notes

  • Idempotency: The script was run twice consecutively from a clean state and produced the same confirmed verdict both times.
  • Isolation: The rootfs disk is mounted read-only inside the VM and the QEMU drive is opened with readonly=on, so the host-side image files are not modified by the exploit.
  • Limitations: The reproduction depends on the prebuilt Ubuntu mainline kernels and rootfs in the project cache. The exploit path uses udp/4500 ESP-in-UDP encapsulation and a netfilter mangle/OUTPUT TEE rule to force the __pskb_copy_fclone() clone; any kernel configuration that lacks one of these components will fail closed, which is expected behavior for an incomplete path.

Variant Analysis & Alternative Triggers for CVE-2026-43503

Versions: versions as tested: Ubuntu mainline 7.0.9-070009-generic (vulnerable to both DirtyClone and Fragnesia); Ubuntu mainline 7.0.10-070010-generic (blocked).

This variant stage investigated whether a different frag-transfer helper could bypass the CVE-2026-43503 fix. The candidate chosen was the Fragnesia path (CVE-2026-46300): instead of the original DirtyClone netfilter TEE__pskb_copy_fclone() route, Fragnesia reaches the same XFRM/ESP in-place decryption sink through ESP-in-TCP (espintcp) over a veth pair, using TCP receive coalescing (skb_try_coalesce()) to move file-backed page-cache fragments into an unmarked skb. On the vulnerable 7.0.9 kernel the variant corrupts /usr/bin/su in the page cache and would yield root. On the fixed 7.0.10 kernel the variant is blocked: the stable backport includes both the CVE-2026-43503 multi-site fix and the CVE-2026-46300 skb_try_coalesce() fix, so the shared-frag marker is preserved and skb_cow_data() forces a copy before decryption. No bypass of the fixed kernel was found.

Fix Coverage / Assumptions

The CVE-2026-43503 patch (48f6a5356a33) restores the invariant:

An skb that references externally-owned or file-backed page-cache pages must have SKBFL_SHARED_FRAG set.

It does so by OR-ing the source skb's SKBFL_SHARED_FRAG bit into the destination skb whenever one of the six audited helpers moves fragment descriptors:

  • __pskb_copy_fclone()
  • skb_shift()
  • skb_gro_receive()
  • skb_gro_receive_list()
  • tcp_clone_payload()
  • skb_segment()

The patch assumes that these are the only frag-transfer sites that can carry page-cache-backed pages to an in-place writer, and that skb_copy() / skb_copy_expand() need no change because they linearize data into freshly allocated memory.

What the patch does not cover:

  • skb_try_coalesce() (fixed separately by CVE-2026-46300).
  • skb_zerocopy() and related helpers (no known unprivileged exploit path to the ESP sink).
  • Any future kernel code that introduces a new fragment-transfer site without copying the marker.

Variant / Alternate Trigger

Candidate 1: Fragnesia / ESP-in-TCP / skb_try_coalesce() (tested)
  • Entry point: Unprivileged user+network namespace; create a veth pair, configure an XFRM transport-mode SA/SP for ESP-in-TCP, and splice a page-cache page of /usr/bin/su into a TCP socket via vmsplice()/splice().
  • Trigger path: tcp_v4_rcv() → TCP receive coalescing → skb_try_coalesce() moves shared frags into the ESP-in-TCP skb; espintcp receive path calls skb_cow_data(), which checks skb_has_shared_frag().
  • Sink: In-place AES-GCM/AES-CBC decryption over the file-backed page-cache page.
  • Files/functions involved: net/core/skbuff.c:skb_try_coalesce(), net/ipv4/espintcp.c, net/ipv4/tcp_input.c.
  • Result on v7.0.9: RESULT: VULNERABLE (page cache modified) — the write primitive works.
  • Result on v7.0.10: RESULT: NOT VULNERABLE (page cache unchanged) — the marker is preserved and skb_cow_data() makes a copy.
Candidate 2: Other CVE-2026-43503 helpers with different protocols (not tested separately)

The CVE-2026-43503 fix is applied at the function level, so any path through __pskb_copy_fclone(), skb_shift(), skb_gro_receive(), skb_gro_receive_list(), tcp_clone_payload(), or skb_segment() is covered regardless of the network protocol or driver. Additional protocol-specific triggers (IPv6 TEE, GRO on a different driver, TCP clone probes) are therefore not distinct bypasses; they reach the same now-fixed sink.

Candidate 3: skb_zerocopy() paths (ruled out by analysis)

skb_zerocopy() is used by XDP socket TX, Open vSwitch, and nfnetlink_queue. It creates fragment references without propagating SKBFL_SHARED_FRAG, but none of these consumers feed the resulting skb into the XFRM ESP input path under an unprivileged local trust boundary. No public exploit or reliable unprivileged trigger is known, so this remains a theoretical gap rather than a demonstrated bypass.

  • Package/component affected: Linux kernel networking stack (net/core/skbuff.c, net/core/gro.c, net/ipv4/tcp_output.c, net/ipv4/espintcp.c).
  • Affected versions as tested: Ubuntu mainline 7.0.9-070009-generic (vulnerable to both DirtyClone and Fragnesia); Ubuntu mainline 7.0.10-070010-generic (blocked).
  • Risk level: Local privilege escalation. An unprivileged local user with user and network namespaces can gain root by overwriting the page-cache copy of a setuid binary. The variant is at least as severe as the original DirtyClone; it is blocked only because the tested fixed kernel includes the sibling CVE-2026-46300 patch.

Impact Parity

  • Disclosed/claimed maximum impact: Local privilege escalation (privilege_escalation) — arbitrary write into read-only page-cache pages of setuid binaries, leading to root code execution.
  • Reproduced impact from this variant run: Full privilege escalation on 7.0.9 (the variant overwrites /usr/bin/su in the page cache). The impact was not reproduced on 7.0.10 because the write primitive was blocked.
  • Parity: partial — the variant is a real, distinct trigger for the same root cause on the vulnerable kernel, but it is not a bypass of the fixed kernel tested.
  • Not demonstrated: Root shell on the fixed kernel; bypass of the combined CVE-2026-43503 + CVE-2026-46300 mitigation.

Root Cause

The same root cause underlies both DirtyClone and Fragnesia: the Linux kernel has multiple fragment-transfer helpers that move page references between skbs without moving the SKBFL_SHARED_FRAG metadata flag. When the destination skb reaches an in-place writer (XFRM ESP input), skb_has_shared_frag() returns false, skb_cow_data() is skipped, and decryption writes directly into file-backed page-cache memory.

The CVE-2026-43503 patch fixes six helpers. Fragnesia uses a seventh helper, skb_try_coalesce(), which was fixed by a separate commit. The two fixes are siblings; the tested 7.0.10 stable kernel includes both, so the variant is blocked.

Reproduction Steps

  1. Run the variant reproduction script:

    bash bundle/vuln_variant/reproduction_steps.sh
    

    The script is idempotent and will exit 1 because the variant is blocked on the fixed kernel.

  2. The script performs the following:

    • Builds a minimal initramfs that mounts the Fragnesia rootfs and switch_roots into it.
    • Boots the v7.0.9 vulnerable kernel with the Fragnesia rootfs under QEMU.
    • Boots the v7.0.10 fixed kernel with the Fragnesia rootfs under QEMU.
    • Captures serial console output to bundle/logs/qemu_fragnesia_vuln.log and bundle/logs/qemu_fragnesia_fixed.log.
    • Greps for RESULT: VULNERABLE or RESULT: NOT VULNERABLE to determine whether the bypass succeeded.
  3. Expected evidence:

    • logs/qemu_fragnesia_vuln.log contains RESULT: VULNERABLE (page cache modified).
    • logs/qemu_fragnesia_fixed.log contains RESULT: NOT VULNERABLE (page cache unchanged).

Evidence

  • Vulnerable run log: bundle/logs/qemu_fragnesia_vuln.log
    Key excerpt: [+] RESULT: VULNERABLE (page cache modified)
  • Fixed run log: bundle/logs/qemu_fragnesia_fixed.log
    Key excerpt: [-] byte at index=24 unchanged after 8 attempts, kernel may be fixed followed by [*] RESULT: NOT VULNERABLE (page cache unchanged).
  • Runtime manifest: bundle/vuln_variant/runtime_manifest.json
  • Validation verdict: bundle/vuln_variant/validation_verdict.json
  • Patch analysis: bundle/vuln_variant/patch_analysis.md
  • Environment: QEMU x86_64, Ubuntu mainline kernels 7.0.9-070009-generic and 7.0.10-070010-generic, 512 MB RAM, 2 vCPUs.

Recommendations / Next Steps

  1. Do not treat CVE-2026-43503 as a standalone fix. Distribution backports must include both:

    • commit 48f6a5356a33 (CVE-2026-43503, six helpers), and
    • the CVE-2026-46300 skb_try_coalesce() commit (Fragnesia).
      A kernel with only the first commit is still vulnerable to Fragnesia.
  2. Extend static review to any remaining frag-transfer helpers such as skb_zerocopy() and future GRO/offload code. Even though no unprivileged trigger is known today, the same shape of bug could reappear.

  3. Consider a structural hardening patch that makes SKBFL_SHARED_FRAG propagation automatic when nr_frags is increased by moving descriptors, rather than relying on authors to remember each site. This would close the regression window for future variants.

  4. Regression test: Add a kernel self-test that verifies skb_has_shared_frag() is true after each of the seven known frag-transfer helpers when the source skb has the marker set.

Additional Notes

  • Idempotency: The script was run three times; each run produced identical verdicts (VULNERABLE on 7.0.9, NOT VULNERABLE on 7.0.10) and exited 1.
  • Limitations: The Fragnesia binary is a prebuilt artifact from the project cache. This run treats it as an alternate trigger to test the completeness of the fix; it does not claim to have discovered a new kernel bug. No host-side files were modified; the rootfs images are mounted read-only inside QEMU.
  • Trust boundary: The variant remains a local privilege escalation under the same trust model as the original CVE (unprivileged user/network namespace).

CVE-2026-43503 Reproduction Transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.

Full session Replay every step — scrub the timeline or play it back.

Event 1/40
0:002:03
0:00
session startedaccounts/fireworks/models/kimi-k2p7-code · CVE-2026-43503 · REPRO-20
0:05
0:07
web search
0:10
0:12
0:13
web search
0:36
0:36
extract_facts
no facts extracted
0:37
0:37
0:37
supportrepro
1:47
1:51
1:51
1:51
1:54
1:54
1:54
1:54
1:56
1:56
1:56
error

Unknown error

1:58
1:58
$ls -la /data/pruva/project-cache/6cba72b6-b104-4ebf-be7b-01f748e87ccf
{"cwd":"/data/pruva/runs/0a5d30f2-96f7-4243-8385-9ad0524e1fda","duration_ms":7,"exit_code":0,"stderr":"","stdout":"total 507388\ndrwxr-xr-x 1 vscode vscode      1370 Jul  3 10:05 .\ndrwxr-xr-x 1 vscode vscode      1894 Jul  3 04:50 ..\ndrwxr-xr-x 1 vscode vscode        22 Jul  2 21:46 .pruva\ndrwxr-xr-x 1 vscode vscode         6 Jul  3 09:21 bond-mod-stage\ndrwxr-xr-x 1 vscode vscode         6 Jul  3 09:39 bond-mod-stage-7rc2\ndrwxr-xr-x 1 vscode vscode        18 Jul  3 09:10 bond-mods\ndrwxr-xr-x 1 vscode vscode        18 Jul  3 09:29 bond-mods-7rc2\ndrwxr-xr-x 1 vscode vscode       210 Jul  3 09:11 bond-rootfs-\ndrwxr-xr-x 1 vscode vscode       210 Jul  3 09:21 bond-rootfs-base\ndrwxr-xr-x 1 vscode vscode       210 Jul  3 09:39 bond-rootfs-base-7rc2\ndrwxr-xr-x 1 vscode vscode       210 Jul  3 09:11 bond-rootfs-fixed\ndrwxr-xr-x 1 vscode vscode       210 Jul  3 09:39 bond-rootfs-fixed-7rc2\ndrwxr-xr-x 1 vscode vscode       210 Jul  3 09:29 bond-rootfs-probe-7rc2\ndrwxr-xr-x 1 vscode vscode       210 Jul  3 09:21 bond-rootfs-vuln\ndrwxr-xr-x 1 vscode vscode       210 Jul  3 09:39 bond-rootfs-vuln-7rc2\ndrwxr-xr-x 1 vscode vscode       210 Jul  3 09:39 bond-var-rootfs-fixed\ndrwxr-… [truncated]
2:01
2:01
$find /data/pruva/project-cache/6cba72b6-b104-4ebf-be7b-01f748e87ccf/.pruva -maxdepth 3 -type f -o -type l | head -50
/data/pruva/project-cache/6cba72b6-b104-4ebf-be7b-01f748e87ccf/.pruva/proof-carry/latest_attempt/proof_carry_manifest.json
/data/pruva/project-cache/6cba72b6-b104-4ebf-be7b-01f748e87ccf/.pruva/proof-carry/latest_confirmed/proof_carry_manifest.json
2:01
2:03
2:03
08 · How to Fix

How to Fix CVE-2026-43503

Coming soon

Step-by-step mitigation and hardening guidance for CVE-2026-43503 — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: CVE-2026-43503

How does the DirtyClone privilege escalation attack work?

A netfilter TEE clone keeps the original page-cache reference but no longer reports itself as shared/file-backed, which bypasses the XFRM/IPsec skb_cow_data() copy-on-write safeguard. This lets esp_input() decrypt directly into the page-cache page of a root-owned setuid binary; by choosing the AES-CBC key/IV so the decrypted bytes are attacker-controlled shellcode, an unprivileged local attacker (able to create user and network namespaces) can rewrite a binary like /usr/bin/su in RAM and obtain a root shell when it is executed.

How severe is CVE-2026-43503?

It is rated critical severity: an unprivileged local user with the ability to create user and network namespaces can achieve local root code execution by corrupting the page cache of a setuid root binary via normal networking paths.

How can I reproduce CVE-2026-43503?

Download the verified script from this page and run it in an isolated environment against an affected Linux kernel. It establishes an XFRM/IPsec session with a netfilter TEE clone that hides the shared-frag flag, forces esp_input() to decrypt attacker-controlled shellcode into a setuid root binary's page-cache page, and demonstrates a root shell when that binary is executed.
11 · References

References for CVE-2026-43503

Authoritative sources for CVE-2026-43503 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.