Root Without a Password: Testing Copy Fail 2 on Ubuntu 24.04
I tested the public Copy Fail 2 proof of concept on a fresh Ubuntu 24.04 live server VM. It worked.
No sudo password. No kernel panic. No unstable race. The exploit quietly changed what /etc/passwd looked like in memory, used that to open a root shell, and then cleaned up afterward. The file on disk was never rewritten in the normal way.
This writeup covers the Copy Fail 2 xfrm and ESP path. Dirty Frag is related context, especially the RxRPC side, but I only ran the Copy Fail 2 PoC in my VM. The full Dirty Frag chain is not covered here.

Copy Fail 2, tested on Ubuntu 24.04.
Clearing Up The Naming
There are a few names floating around, and they are worth separating before going further.
- Copy Fail is the earlier vulnerability in this family, tracked as CVE-2026-31431. Its common mitigation focused on blocking
algif_aead. - Copy Fail 2 is the public PoC I tested here. It targets CVE-2026-43284, the xfrm and ESP page cache write issue.
- Dirty Frag is the broader research from Hyunwoo Kim. It chains CVE-2026-43284 with CVE-2026-43500, the related RxRPC page cache write issue.
So this post is specifically about Copy Fail 2 and CVE-2026-43284. I mention Dirty Frag because the mitigation overlaps and because it explains why blocking only the old Copy Fail path is not enough.
The Short Version
The PoC I ran was Copy Fail 2, using the xfrm and ESP page cache write path.
Dirty Frag is related context. It chains the xfrm and ESP issue with an RxRPC issue to cover more environments. My screenshots below show the xfrm and ESP path only.
The important idea is simple. A local unprivileged user gets a way to write into the kernel page cache, then turns that into root access.
I tested the xfrm and ESP path on Ubuntu 24.04 with kernel 6.8.0-111-generic.
It worked.
My Test Environment
The target was a normal Ubuntu 24.04 live server VM.
uname -r
6.8.0-111-genericMy user was not root:
id
uid=1000(muntazir) gid=1000(muntazir) groups=1000(muntazir),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),101(lxd)The relevant /etc/passwd entry looked normal:
muntazir:x:1000:1000:muntazir:/home/muntazir:/bin/bashAfter running the PoC, I landed here:
root@dirty:/# id
uid=0(root) gid=0(root) groups=0(root)That was the point where this stopped being theoretical for me.
Why The Page Cache Matters
When Linux reads a file from disk, it usually keeps the contents in memory. That memory is the page cache.
If multiple processes read /etc/passwd, they may all read the same cached copy from memory instead of going back to disk each time. That is normal, and it is one reason Linux file IO is fast.
The cache is supposed to be protected. A normal user can read files they have permission to read, but they should not be able to write into the cached copy of a file they do not own.
That boundary matters a lot.
If an unprivileged user can write into the page cache for /etc/passwd, programs like su, PAM, and login tools may read attacker controlled data from memory while the actual file on disk still looks legitimate.
That is the class of bug Dirty Pipe made famous.
Same Bug Class, Different Path
Dirty Pipe showed that a kernel fast path could accidentally allow writes into page cache backed memory.
The earlier Copy Fail issue followed the same general pattern through a different subsystem. Copy Fail 2 does it through xfrm and ESP. Dirty Frag chains xfrm and ESP with RxRPC.
The scary part is not that one subsystem had a bug. The scary part is that the same kind of failure keeps appearing in different optimized kernel paths.
This is not about guessing passwords or abusing a bad sudo rule. It is about convincing the kernel to write where it should never write.
What xfrm And ESP Have To Do With This
xfrm is the Linux kernel framework used for IPsec transformations. ESP, short for Encapsulating Security Payload, is part of IPsec and handles encrypted packet data.
Most users never interact with this directly. It is networking plumbing.
The bug used by Copy Fail 2 abuses a zero-copy fast path in this area. Instead of copying bytes from one buffer to another, the kernel can move page references around for performance. That optimization is valid, but it becomes dangerous if page ownership and write safety are not handled correctly.
In this case, the result is a page cache write primitive.
That means a local user can influence data that later gets read as if it came from a real system file.
Why Dirty Frag Chains Two Bugs
The xfrm and ESP path is not available on every system. Understanding why explains the Dirty Frag chain.
According to the Dirty Frag README, the xfrm and ESP primitive is powerful and present on most distributions, but it requires the privilege to create a namespace. Some Ubuntu systems block unprivileged user namespace creation through AppArmor policy. In that environment, the xfrm and ESP path alone may fail.
The RxRPC primitive is different. It does not require namespace creation privileges, but the rxrpc.ko module is not included or loaded everywhere. Ubuntu is the important exception called out by the Dirty Frag research, because rxrpc.ko may be available there by default.
That is why Dirty Frag chains both issues. xfrm and ESP covers many systems where namespaces are allowed. RxRPC covers Ubuntu environments where namespace creation is blocked but RxRPC is available.
In my VM, Copy Fail 2 worked because the xfrm and ESP path was reachable. On a more locked-down Ubuntu system, the standalone Copy Fail 2 PoC may fail while the full Dirty Frag chain could still have a working path.
What The PoC Did On My VM
The exploit looked for a suitable line in /etc/passwd.
On my system, it selected the fwupd-refresh line because it was long enough to replace cleanly without changing the file size.
The injected line looked like this:
sick::0:0:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:/:/bin/bashThe important details are:
- username:
sick - UID:
0 - GID:
0 - password field: empty
- shell:
/bin/bash
A UID of 0 means root.
The empty password field matters because of how PAM is configured on many Ubuntu systems. With pam_unix.so nullok, an empty password can be accepted for an account that has no password set.
Even without nullok, the primitive would still be serious. A controlled page cache write against authentication related files could be shaped in other ways. The empty-password sick account just makes this PoC clean and easy to demonstrate.
So after the page cache mutation landed, the PoC used:
su - sickPAM read /etc/passwd, saw the injected UID 0 account, accepted the empty password path, and gave me a root shell.

The exploit verified the page cache mutation, then switched to the injected UID 0 user.
Proof That It Was Real Root
After landing in the shell, I checked the user ID:
id
uid=0(root) gid=0(root) groups=0(root)Then I checked /etc/passwd and /etc/shadow.

/etc/passwd showed the injected sick account with UID 0.
Reading /etc/shadow confirmed this was not just a fake root inside a namespace.

Reading /etc/shadow and checking the kernel version from the root shell.
Cleanup
The PoC also had a cleanup mode.
After exiting the root shell, I ran:
./run.sh --cleanIt restored the original fwupd-refresh line and removed the state file.

Cleanup restored the original line that had been used during the test.
Testing The Mitigation
For the earlier Copy Fail issue, many people focused on blocking algif_aead.
That does not stop this path.
Copy Fail 2 used xfrm and ESP in my test. Dirty Frag also discusses RxRPC, so the temporary mitigation blocks both the demonstrated xfrm and ESP path and the related RxRPC module path:
sudo sh -c "printf 'install esp4 /bin/false\ninstall esp6 /bin/false\ninstall rxrpc /bin/false\n' > /etc/modprobe.d/dirtyfrag.conf; rmmod esp4 esp6 rxrpc 2>/dev/null; echo 3 > /proc/sys/vm/drop_caches; true"The drop_caches step matters after testing because the page cache may already be polluted. Rebooting also clears it.
After applying that, the exploit no longer landed.

After blocking the modules, the xfrm setup failed and the mutation did not land.
That is the result you want to see. The xfrm and ESP path could not be used, so the page cache mutation did not happen.
Blocking rxrpc may look odd if the demo only used xfrm and ESP. The reason it is included is Dirty Frag: rxrpc is the second page cache write path tracked as CVE-2026-43500. Blocking esp4 and esp6 addresses the Copy Fail 2 path I tested. Blocking rxrpc covers the related Dirty Frag path as well.
The Tradeoff
This mitigation is not free for everyone.
Blocking esp4 and esp6 can break IPsec based VPNs. Blocking rxrpc can affect systems using AFS or other RxRPC dependent workloads.
For many desktops, lab machines, and small servers, that tradeoff may be acceptable. For environments that rely on IPsec or RxRPC, the real answer is a patched kernel and proper validation.
The main point is that blacklisting algif_aead for the earlier Copy Fail issue does not protect against the Copy Fail 2 path I tested.
Patch Status
Both CVEs now have upstream Linux fixes:
- CVE-2026-43284, the xfrm and ESP issue, was fixed upstream in
f4c50a4034e6. - CVE-2026-43500, the RxRPC issue, was fixed upstream in
aa54b1d27fe0.
That does not automatically mean your distribution kernel is fixed. Check your distro's security advisory or package changelog and update as soon as patched kernels are available.
Why This One Feels Worse
What stood out to me was how quiet the exploit was.
It did not crash the machine. It did not take dozens of tries. It did not need a visible race. When it worked, it changed what a system file looked like in memory and then let normal Linux authentication code do the rest.
That is what makes this bug class dangerous.
Security tooling often watches for noisy behavior, such as kernel crashes, repeated failed exploitation attempts, suspicious sudo activity, or obvious persistence. This did not look like that in my test. It was fast and clean.
The important part is that /etc/passwd on disk was not rewritten in the normal way. The mutation lived in the page cache, which means traditional file integrity monitoring may miss the thing the authentication stack is actually reading.
What Defenders Should Check
If you manage Linux systems, I would check three things immediately.
- Check whether your kernel includes the upstream fix for CVE-2026-43284, which covers the xfrm and ESP path I tested.
- Check whether your distribution has shipped guidance or patches for CVE-2026-43500, the related RxRPC issue covered by Dirty Frag.
- If you do not need IPsec or RxRPC, consider blocking the affected modules until your distribution ships a proper fix.
The temporary mitigation I tested was:
sudo sh -c "printf 'install esp4 /bin/false\ninstall esp6 /bin/false\ninstall rxrpc /bin/false\n' > /etc/modprobe.d/dirtyfrag.conf; rmmod esp4 esp6 rxrpc 2>/dev/null; echo 3 > /proc/sys/vm/drop_caches; true"If you depend on IPsec, do not blindly apply this in production without testing. You may break VPN connectivity.
Final Thoughts
I went into this expecting another interesting kernel PoC. After testing it, I think it deserves attention.
Copy Fail 2 is not only about one flashy demo. It is another example of the same broader problem: optimized kernel paths that accidentally bypass the safety rules normal file writes have to follow.
Dirty Pipe showed the pattern. Copy Fail showed it again. Dirty Frag shows that the class is still alive.
If your response to the earlier Copy Fail issue was only to block algif_aead, revisit that assumption. This one uses a different route.
On my Ubuntu 24.04 VM, the public Copy Fail 2 PoC turned an ordinary local user into root. That is enough reason to patch, mitigate, and take this bug class seriously.