DirtyClone (CVE-2026-43503): Linux Kernel LPE

By Eddy Tsalolikhin, JFrog Security Researcher and Or Peles, JFrog Senior Security Researcher | 25 Jun, 2026

What is it?
DirtyClone is a high-severity local privilege escalation flaw in the Linux kernel (CVE-2026-43503, CVSS 8.8). It lets any unprivileged local user gain root access by manipulating the page cache.

Who discovered it?
JFrog Security Research (Eddy Tsalolikhin and Or Peles) independently discovered this DirtyFrag variant and reported it to kernel maintainers on May 19, 2026. This coincided with a related broader report from the original DirtyFrag researcher, Hyunwoo Kim, on May 16, 2026. JFrog developed a private proof-of-concept and published the first public technical analysis proving that code execution is possible.

Why does it matter?
The attack is silent: it leaves no kernel logs, no audit entries, and bypasses AIDE and Tripwire. The binary on disk is unchanged — standard file-integrity monitoring will not catch it.

Who is affected?
Linux systems running vulnerable kernel versions, especially older Debian, Ubuntu, and Fedora distributions where unprivileged user namespaces are enabled by default. Highest risk in multi-tenant cloud, Kubernetes, and container environments.

What to do now
Update to Linux v7.1-rc5 or later, or apply the backported patch for CVE-2026-43503. Confirm the full 4-CVE DirtyFrag fix chain is applied — see checklist below.

What is DirtyClone (CVE-2026-43503)?
DirtyClone is a Linux kernel local privilege escalation vulnerability (CVSS 8.8) independently discovered by JFrog Security Research, coinciding with a related broader report from the original DirtyFrag researcher, Hyunwoo Kim. It exploits a flaw in how the kernel clones network packets — specifically, a dropped safety flag in __pskb_copy_fclone() — to let any unprivileged local user overwrite file-backed page cache memory and gain root access.

Which Linux distributions are affected by DirtyClone?
Any distribution running a vulnerable kernel version with unprivileged user namespaces enabled is at risk. Older versions of Debian, Ubuntu, and Fedora are all affected in their default configurations (ex. Ubuntu 22.04) and newer versions are affected in non-default configurations. RHEL 9 and 10 are affected; RHEL 6, 7, and 8 are not. A system is only fully protected once the complete 4-CVE DirtyFrag fix chain is applied (not just the DirtyClone patch by itself).

How do I fix DirtyClone?
Update your Linux kernel to v7.1-rc5 or later, or apply your distribution's backported patch for CVE-2026-43503. Check all four CVEs in the fix chain: CVE-2026-43284, CVE-2026-43500 (DirtyFrag), CVE-2026-46300 (Fragnesia), and CVE-2026-43503 (DirtyClone). If you cannot patch immediately, set kernel.unprivileged_userns_clone=0 and blacklist the esp4, esp6, and rxrpc kernel modules as a temporary workaround.

Why is DirtyClone invisible to standard security tools?
DirtyClone never writes to disk. It corrupts the kernel's in-memory copy of a file in the page cache — for example, modifying /usr/bin/su in RAM while leaving the on-disk binary unchanged. Every hash-on-disk file integrity tool (AIDE, Tripwire, and similar) monitors the on-disk version, so they have a structural blind spot for this entire attack class. DirtyClone also generates no kernel logs or audit entries.

Is DirtyClone being actively exploited in the wild?
No confirmed in-the-wild exploitation has been reported as of the publication of this research. However, JFrog has shown that arbitrary code execution is fully possible.

What is the DirtyFrag vulnerability family?
DirtyFrag is a family of Linux kernel vulnerabilities affecting how socket buffers reference shared page-cache memory. DirtyClone (CVE-2026-43503) is the fourth member of this family, following DirtyFrag (CVE-2026-43284 and CVE-2026-43500) and Fragnesia (CVE-2026-46300). All variants exploit the same underlying primitive: tricking the kernel into treating read-only, file-backed page cache memory as writable network buffers.

A system is only fully protected once the entire DirtyFrag vulnerability fix chain is applied. Confirm all four CVEs are patched:

  • CVE-2026-43284 — Original DirtyFrag (SKBFL_SHARED_FRAG flag for spliced UDP packets) — Fixed May 4, 2026
  • CVE-2026-43500 — Companion DirtyFrag patch — Fixed May 4, 2026
  • CVE-2026-46300 — Fragnesia (skb coalescing bypass) — Fixed May 13, 2026
  • CVE-2026-43503 — DirtyClone (__pskb_copy_fclone variant) — first fixed in Linux v7.1-rc5 — Fixed May 21, 2026

Block CAP_NET_ADMIN via user namespaces:

sysctl -w kernel.unprivileged_userns_clone=0   # Debian/Ubuntu
sysctl -w user.max_user_namespaces=0           # Fedora

Blacklist decryption primitives:

echo -e "blacklist esp4\nblacklist esp6\nblacklist rxrpc" | sudo tee /etc/modprobe.d/blacklist-dirtyclone.conf

Note: These workarounds break container runtimes, Chrome, and Firefox running as non-root. They are a stopgap — patch as soon as possible.

During an audit of recent Linux kernel patches, the JFrog Security Research team identified that despite fixes addressing the DirtyFrag vulnerability family, a residual issue remained unaddressed. This gap allowed the same vulnerability class to persist through a different packet processing path in the XFRM/IPsec subsystem.

We reported the issue to the Linux kernel maintainers on May 19. This coincided with a related broader report from the original DirtyFrag researcher “Hyunwoo Kim" on May 16. The variants were patched and merged into mainline on May 21 (v7.1-rc5, 9e171fc1d7d7), and assigned CVE-2026-43503.

At the time of writing, no public PoC existed for this vulnerability. JFrog researchers successfully developed a privilege escalation exploit for a newly discovered DirtyFrag variant of CVE-2026-43503, which we dubbed "DirtyClone". We are publishing this research because it demonstrates a broader exploitation pattern affecting multiple skb (socket buffer) processing paths, showing that the underlying attack primitive is not limited to a single vulnerable code path.

CVE-2026-43503 is a high-severity (8.8 CVSS) Local Privilege Escalation (LPE) flaw.
The severity of this issue is significant because it allows any unprivileged local user to gain root access (LPE) by manipulating the Linux page cache. The attack is silent, leaves no kernel logs or audit traces, and bypasses common on-disk integrity monitoring tools.

This flaw impacts a broad array of modern Linux distributions that run the necessary kernel versions and configurations.

  • Vulnerable distributions: The attack is confirmed to work on popular distributions where unprivileged user namespaces are enabled, including Debian, Ubuntu, and Fedora
  • Vulnerable kernels: Any kernel lacking the complete chain of fixes for the DirtyFrag vulnerability family is at risk. Systems entirely unpatched for the original flaws (CVE-2026-43284 and CVE-2026-43500) remain broadly exposed. Additionally, any mainline, stable, or Long Term Support (LTS) kernel branch that applied the initial mitigations but lacks the subsequent follow-up patches (CVE-2026-46300 and CVE-2026-43503) remains vulnerable to specific bypasses. A system is only fully protected against this exploitation model once the entire series of patches is applied..
  • Who is exploitable: Any local user on a server or device running a vulnerable kernel who holds or can acquire the CAP_NET_ADMIN capability (frequently obtainable via unprivileged user namespaces). This poses the highest risk to multi-tenant cloud environments, Kubernetes clusters, and containerized workloads where user namespaces are enabled or privileged containers are deployed.

The issue was patched and merged into mainline on May 21, 2026.

  • Immediate Recommendation: Users should immediately update their Linux kernel to the fixed version, v7.1-rc5, or apply the backported patch for CVE-2026-43503 to their distribution's kernel.
  • Workarounds: If immediate patching is not possible, workarounds include blocking CAP_NET_ADMIN acquisition by setting kernel.unprivileged_userns_clone=0 or blacklisting esp4, esp6, and rxrpc kernel modules block the in-place decryption primitives..
  • What This Means for JFrog Customers: As this vulnerability targets the host kernel, it emphasizes the need for a strong security posture. JFrog Artifactory and Xray are crucial in this defense; ensure all binaries and packages are sourced through a secure, curated registry (Artifactory, Repo21) and regularly scanned by Xray to block malicious or unapproved packages before they reach your machines, mitigating potential supply chain risks that could facilitate such a kernel LPE.

  • May 4: DirtyFrag patch (CVE-2026-43284 and CVE-2026-43500) lands in Linux kernel mainline. It fixes a bug where the SKBFL_SHARED_FRAG flag was missing from spliced UDP packets, ensuring subsystems performing in-place decryption trigger a safe Copy-on-Write.
  • May 13: Fragnesia (CVE-2026-46300) disclosed; patch lands in Linux kernel netdev. Flag lost during skb coalescing (skb_try_coalesce), bypassing the mitigation.
  • May 16: Upstream multi-site patch submitted, covering the remaining frag-transfer helpers (__pskb_copy_fclone, skb_shift, skb_segment, skb_gro_receive, skb_gro_receive_list, tcp_clone_payload).
  • May 19: JFrog independently rediscovers the in __pskb_copy_fclone variant, builds a PoC, and reports it.
  • May 21: Patch merged to mainline (commit 48f6a5356a33).
  • May 23: CVE-2026-43503 published.
  • May 24: Linux v7.1-rc5 released, first fixed tag.

DirtyFrag is a family of Linux kernel memory corruption vulnerabilities in the core networking stack affecting how socket buffers (skb) reference shared page-cache memory, which are subsequently weaponized through in-place cryptographic transformations in subsystems like XFRM/IPsec or RxRPC.

Despite targeting different packet cloning or forwarding paths, variants like DirtyFrag, Fragnesia, and DirtyClone all rely on a shared technique: tricking the kernel into treating read-only, file-backed page cache memory as writable network buffers.

At a high level, the kernel does not strictly separate three memory roles that can overlap in modern designs:

  1. File-backed memory (page cache used for executables and files)
  2. Networking buffers (packet data processed via zero-copy paths)
  3. In-place transformations (e.g., encryption/decryption writing back into the same buffer)

When these three contexts intersect, the kernel may modify memory that is still semantically tied to a file, leading to corruption of file-backed data in place.

The attack abuses a situation where the same physical memory page is used both as:

  • File data (page cache)
  • Network packet data (skb)

Normally, these are separate:

  • File → page cache page
  • Network → skb buffer

DirtyFrag connects them.

To exploit this overlap, the attacker follows these steps:

The attacker maps a privileged binary such as /usr/bin/su, causing it to be loaded into the page cache.

/usr/bin/su

Page-cache page (RAM)

This page becomes the target for manipulation.

The attacker crafts an IPsec packet whose payload is backed by the same page-cache page.

Using vmsplice and splice, the kernel attaches page-cache-backed memory into an skb instead of copying it.

int fd = open("/usr/bin/su", O_RDONLY);
char *p = mmap(NULL, mmap_size, PROT_READ, MAP_SHARED, fd, 0);

struct iovec iov = { .iov_base = p + patch_offset, .iov_len = 16 };
vmsplice(pipefd[1], &iov, 1, 0);
splice(pipefd[0], NULL, sockfd, NULL, 16, 0);

At this point, the packet buffer is literally backed by file memory.

The attacker uses a loopback-based IPsec tunnel so that packets remain local.

This ensures:

  1. The packet is created by the attacker
  2. The same kernel processes the packet
  3. The packet passes through the IPsec receive path

When processed, the packet reaches the ESP decryption stage (esp_input()).

IPsec decrypts packet payloads in place for performance.

That means:

  • input buffer \= output buffer
  • Decrypted bytes overwrite the same memory

Normally safe, but here the buffer is backed by a page cache page.
If the skb data resides in a page-backed buffer originating from a file mapping, in-place decryption can modify that shared page content.

IPsec decrypt
   ↓
write back into skb buffer
   ↓
same physical page as /usr/bin/su

The attacker controls cryptographic inputs (key, IV, and packet layout).
In AES-CBC, the IV influences the first decrypted block.

By combining:

  • Known original bytes
  • Chosen ciphertext structure
  • Controlled IV

The attacker can force predictable output bytes at specific offsets, which can, under constrained conditions, influence the resulting decrypted bytes in shared page-backed buffers.

The attacker uses this primitive to patch small instruction sequences inside /usr/bin/su.

Only a few bytes are needed (e.g., conditional branch logic controlling authentication).
The file on disk is unchanged, but the page-cache copy is modified.

original su page
   ↓
IPsec write primitive
   ↓
modified su page (RAM)

When /usr/bin/su is executed again:

  1. Linux reuses the cached page
  2. Modified instructions are used directly
  3. Authentication logic is bypassed

Result: privilege escalation.

modified page cache
   ↓
su executed
   ↓
modified logic runs
   ↓
root

The original DirtyFrag fix set the SKBFL_SHARED_FRAG for spliced UDP packets. This is a metadata flag marking skb packets that reference shared page-cache memory, ensuring subsystems performing in-place decryption trigger a safe Copy-on-Write.

If this flag is set, IPsec forces a copy before decryption.

shared page detected
   ↓
SKBFL_SHARED_FRAG = 1
   ↓
copy skb
   ↓
safe decrypt

This prevents direct modification of file-backed pages.

The Fragnesia and CVE-2026-43503 fixes make sure the SKBFL_SHARED_FRAG flag propagates across functions and isn’t accidentally ‘dropped’ along the way.

In order to configure the required networking and IPsec environment, CAP_NET_ADMIN is needed, as it allows control over network interfaces, routing, and XFRM/IPsec policies.

The attacker begins by creating a fresh network namespace:

unshare -Urn

This provides network administrative capabilities inside the namespace. While capabilities are namespaced, page cache is shared at the host level, so if file-backed pages are modified through shared mappings, the effects may propagate to other processes using those pages.

The attacker configures a loopback-based IPsec tunnel, so packets are processed locally by the same kernel instance.

ip link set lo up
ip addr add 10.99.0.2/24 dev lo

Then an IPsec (XFRM) state is created (creating the IPsec Interface):

ip xfrm state add \
src 127.0.0.1 dst 127.0.0.1 \
proto esp spi 0x12345678 reqid 1 mode transport \
enc 'cbc(aes)' ... \
auth 'hmac(sha1)' ...

A matching policy forces outbound traffic through IPsec:

ip xfrm policy add \
src 127.0.0.1 dst 127.0.0.1 dir out \
tmpl src 127.0.0.1 dst 127.0.0.1 proto esp reqid 1 mode transport

Finally, a netfilter rule is added (that forces our packet through the vulnerable fclone path):

iptables -t mangle -A OUTPUT -p udp --dport 4500 \
-j TEE --gateway 10.99.0.2

The TEE target is critical:
It duplicates outgoing packets inside the kernel. Internally this triggers nf_dup_ipv4 which leads to skb cloning via __pskb_copy_fclone()

When a UDP packet (similar to the described in High-level Exploitation Model - Step 2) is sent:

  1. The original skb is created.
  2. The TEE rule duplicates it.
  3. The kernel calls __pskb_copy_fclone() to create a cloned skb.

At this point, two skb objects exist:

  • Original skb → follows normal path
  • Cloned skb → enters vulnerable transformation path

During cloning, the cloned skb does not correctly preserve the SKBFL_SHARED_FRAG flag.

This flag is the kernel’s safety marker indicating that the skb references shared (potentially file-backed) page memory. As a result:

  • Original skb = safe - metadata intact
  • Cloned skb = unsafe - metadata missing

This divergence is the root of the DirtyClone bypass.

Both skb instances are routed through the local loopback-based IPsec configuration.

This ensures:

  • Packets remain local
  • Packets are processed by the same kernel instance
  • Cloned skb reaches the IPsec receive path

Eventually, the cloned skb reaches:

esp_input()

At this point, the skb payload is not ordinary network memory. Instead, it references page-cache-backed memory originating from a file mapping (for example, /usr/bin/su).

So the memory layout is:

File-backed page (page cache)
    ├─ /usr/bin/su content
    └─ skb payload reference

Importantly, the skb does not copy the data; it references the same physical page. This shared reference enables the page-cache write primitive reused across all DirtyFrag variants.

When the cloned skb reaches esp_input(), IPsec performs decryption on the packet payload.

For performance reasons, this is done in-place:

  • input buffer \== output buffer
  • Decrypted bytes overwrite existing skb memory.

Conceptually:

encrypted skb payload
        ↓
IPsec decrypt (in place)
        ↓
write output into same buffer

Because the cloned skb references page-cache memory, the kernel writes decrypted data directly into a file-backed page

The attacker does not just get arbitrary writes.

They control:

  • AES-CBC key material (via SA configuration)
  • IV per packet
  • Packet layout and offsets

In AES-CBC:

  • Each decrypted block depends on the IV
  • An attacker can compute an IV such that the output becomes predictable

So by combining known original bytes, desired target bytes, and controlled IV, the attacker transforms decryption into a controlled write primitive over page-cache memory.

The packet sent looks as follows:

Using this primitive, the attacker patches selected instruction bytes inside /usr/bin/su.

Typical targets for patching include authentication checks and conditional branch instructions. Only small localized changes are required. The result is that the disk file remains unchanged, and the page cache contains modified executable code.

original su page
      ↓
controlled IPsec write
      ↓
modified su page in RAM

When /usr/bin/su is executed, Linux loads the binary from the page cache. If the modified page is still cached:

  • No disk reload is required
  • modified instructions are executed directly

Execution flow:

modified page cache
      ↓
su executed
      ↓
modified logic runs
      ↓
privilege escalation