Contents

Pedit COW Turns a Normal Linux User Into Root While the Disk Stays Clean

 

Ethical Hacking Complete Course Zero to Expert

Hack like black hat hackers. Penetration testing, Kali Linux, WiFi and web hacking, and the hacker mindset behind it.

→ Take the full course
 
Contents

A flaw in the Linux kernel called pedit COW lets a regular, unprivileged user rewrite /bin/su in memory and become root, while the copy on disk never changes and a file integrity check comes back clean. It is tracked as CVE-2026-46331, Red Hat already rates it Important, and a working exploit is public. The flawed code has been in Linux kernels since 2022.

Linux comes with a tool for reshaping and rewriting network traffic as it flows through the machine. It is called tc, short for traffic control. One thing it can do is reach into a packet and change bytes in the header while the packet is still moving. That job is called pedit, and the kernel loads it as a small module named act_pedit. Useful for admins, and the way into this bug.

When two parts of the system share the same memory, the kernel does not let one of them write on it directly. It quietly makes a private copy first and writes to that. This habit is called copy-on-write, or COW. It keeps one program from wrecking memory another program is still using.

The mistake is in the timing. Before pedit changes anything, it measures how much memory it needs to make private, and it does that once, up front. The trouble is that some edits only work out where they land while they are running. So the up-front measurement comes out too small. Part of the change spills past the private copy and lands on a shared page the kernel never meant to expose. One number, measured a moment too early, and the protection no longer reaches far enough.

Someone already tried to fix this once. An earlier patch was meant to make these same writes safe, and it left a gap. That gap is why the hole stayed open for years and went unmarked as a security bug.

When Linux reads a file, it keeps a copy in memory so it does not have to go back to the slow disk every time. That stash is called the page cache. If one of those cached files is a program, and the kernel writes on the wrong page, the copy in memory changes while the file on disk stays the same. The version running is poisoned. The version on disk looks perfect.

So how does a packet end up sharing memory with a file? Through a shortcut called sendfile. When a program sends a file over the network, the kernel can hand the file’s cached pages straight to the network code instead of copying them first. It is faster, and it is normal. The catch is that now the packet and the file are the same piece of memory.

The public exploit, packet_edit_meme, builds on that. It takes /bin/su, the small program used to switch from one user account to another. su runs with root powers no matter who starts it. That property is called setuid, and it is what makes su a target. The exploit loads it into the page cache. Then it sends that file to itself over a local connection with sendfile, so the packet the kernel is about to edit is the cached copy of /bin/su. The pedit bug writes a few instructions into it that hand back a root shell. The file on disk never moves. The next time someone runs su, they run the tampered copy from memory.

One thing should stop an ordinary user cold. To set up tc rules at all, an account normally needs a special networking permission called CAP_NET_ADMIN, and a normal user does not have it. That sounds like the end of the story.

It is not. Linux lets an ordinary user open their own private space where they count as root inside it, while staying a plain user everywhere else. That space is called a user namespace, and on common systems like Debian and Ubuntu it is switched on by default. Inside it, the user picks up CAP_NET_ADMIN, writes the pedit rule, and sets the bug off. That same feature is what rootless containers run on, so a shared host that runs other people’s workloads is a real target.

pedit COW is part of a cluster of Linux bugs with the same ending. The idea goes back to Dirty Pipe in 2022, and a run of them landed in 2026: Copy Fail, Dirty Frag and DirtyClone. Each one rewrites the cached copy of a trusted program like /bin/su. What changes is how they get in. The others came through file shortcuts like splice and vmsplice, or through the way the kernel decrypts network packets. pedit COW comes in through traffic control, reached through user namespaces.

Red Hat lists RHEL 8, 9 and 10 as affected, along with OpenShift. Debian shipped a fix for trixie and still lists bullseye and bookworm as vulnerable. Ubuntu lists its supported releases from 18.04 through 26.04 as carrying the vulnerable kernel code as of late June. In testing during June, the exploit author reported full root on RHEL 10, Debian 13 and Ubuntu 24.04.

Ubuntu 26.04 is the odd one out. The bug is still in its kernel, but the public exploit fails there in its author’s own testing, and not because the kernel was fixed. Ubuntu tightened AppArmor, its built-in permission guard, so a normal process can no longer drop that confinement to reach the user namespace the exploit needs. The vulnerable code is still sitting there, so the machine still needs the real kernel patch. It just happens to be covered one level up for now.

The timing is part of the story. The CVE number was reserved on May 13, before there was a security label, an advisory, or a scanner rule for it. The fix itself was posted and reviewed openly on the netdev kernel mailing list from mid-May as a plain data-corruption patch, and the CVE was only assigned when it merged on June 16. A working exploit went public the day after.

A few things keep this in proportion. It is a local attack and not something that reaches in over the network, so an attacker needs an account on the machine first. Red Hat rates it Important, the NVD has not put a CVSS score on it yet, and it is not on the CISA list of bugs seen in active attacks. The part that should move it up the patch queue is the public exploit code, especially anywhere a local account does not mean a trusted person, such as shared servers, build runners, Kubernetes nodes and lab machines.

Three commands show whether a machine is exposed.

  • → See if the module is loaded:
1
lsmod | grep act_pedit
  • → See if any pedit rules are in use:
1
tc actions list action pedit
  • → Check the running kernel against the fixed version from the distribution:
1
uname -r

On Debian and Ubuntu, one more check shows whether the user-namespace door is open:

1
sysctl kernel.unprivileged_userns_clone

On Ubuntu, the AppArmor restriction that blocks the exploit path on 26.04 shows up here, where a value of 1 means that side door is closed:

1
sysctl kernel.apparmor_restrict_unprivileged_unconfined

The real fix is a patched kernel. Apply the kernel update from the distribution and reboot. Debian trixie carries the fix in linux 6.12.94-1 and later, Red Hat is shipping errata for RHEL 8, 9 and 10, and Ubuntu is rolling updates across its supported releases.

For servers that cannot take downtime, live patching applies the kernel fix without a reboot. Red Hat, Oracle and others offer it through tools like kpatch, and third-party rebootless builds were still rolling out in late June, so confirm the build being applied carries this fix.

Until that reboot can happen, two stopgaps break the exploit chain. The first blocks the act_pedit module from loading, which suits machines that do not use tc pedit rules:

1
echo "install act_pedit /bin/true" | sudo tee /etc/modprobe.d/disable-act_pedit.conf

The second switches off unprivileged user namespaces, which removes the capability the exploit needs:

1
2
3
4
5
# Debian and Ubuntu
sudo sysctl -w kernel.unprivileged_userns_clone=0

# RHEL
sudo sysctl -w user.max_user_namespaces=0

That second option comes with a cost, since it breaks rootless containers, some CI sandboxes and sandboxed browsers, so test it before rolling it out.

For detection, unexpected tc pedit rules appearing on a host, or a rise in unprivileged user namespaces being created, are the kind of signal to log and alert on.

One last point on cleanup. Because the change lives in memory and not on disk, file integrity tools can miss it. Dropping the page cache clears the poisoned copy, but it does nothing about a root shell an attacker already opened, so a confirmed hit means treating the host as compromised:

1
echo 3 | sudo tee /proc/sys/vm/drop_caches

pedit COW is a privilege escalation, the step where someone who already has a normal account on a machine turns it into root. Spotting that foothold, reading the system to find a kernel that can be pushed further, and turning a public proof-of-concept into a working exploit are the same things my ethical hacking course works through step by step, from Linux privilege escalation to real CVE hunting and post-exploitation:

Join my complete ethical hacking course

Hacking is not a hobby but a way of life.

Sources:

NVD | Red Hat | Debian

 
NEWSLETTER

Stay updated

Get the latest posts in your inbox every week. Ethical hacking, security news, tutorials, and everything that catches my attention. If that sounds useful, drop your email below.

By Bulls Eye

Jolanda de koff • emaildonate

My name is Jolanda de Koff and on the internet, I'm also known as Bulls Eye. Ethical Hacker, Penetration tester, Researcher, Programmer, Self Learner, and forever n00b. Not necessarily in that order. Like to make my own hacking tools and I sometimes share them with you. "You can create art & beauty with a computer and Hacking is not a hobby but a way of life ...

I ♥ open-source and Linux