pedit COW: A Linux Kernel Bug That Hands Root to Any Local User
There is a fresh local privilege-escalation bug in the Linux kernel, and it has a nasty property: the attack leaves the file on disk completely untouched. Your integrity checks pass, your file hashes match, and a root shell is already open.
Tracked as CVE-2026-46331 and nicknamed "pedit COW," the flaw lives in the kernel's traffic-control subsystem. Red Hat rates it Important. The CVE was published on June 16, 2026, and a working public exploit followed roughly a day later. If you run any host where "local user" is not the same as "trusted user" — multi-tenant boxes, CI runners, Kubernetes nodes, build workers, shared lab machines — this is one to move on now.
What Actually Breaks
Linux's tc traffic-control framework can rewrite packet headers mid-flight using an action called pedit. The kernel routine behind it, tcf_pedit_act(), is supposed to make a private copy of the data before editing — the textbook copy-on-write move that keeps one writer from stomping on memory shared with everyone else.
The bug is in when it checks. The function calculates the writable range a single time, up front, before it loops over the individual edit operations. But some edit keys only settle on their real offset at runtime. When one of those resolves to an offset past the range that was checked, the write lands outside the privately copied region — and the kernel ends up modifying a shared page-cache page instead of a private one.
⚠️ Here's why that's so dangerous. If the shared page it corrupts happens to back a cached file — say the in-memory copy of a setuid-root binary like /bin/su — the exploit can splice a small payload into that cached image and execute the altered version as root. The file on disk never changes. This is the detail that defeats the usual detection: file-integrity monitoring (AIDE, Tripwire, hash comparisons) reads the disk, and the disk is pristine. The poison is purely in RAM. A forensic process that trusts on-disk hashes will tell you the host is clean while an attacker holds root.
A Familiar Shape
If this rings a bell, it should. pedit COW is the newest entry in a lineage of page-cache copy-on-write bugs — Dirty Pipe, Copy Fail, DirtyClone, Dirty Frag — that all share one skeleton: a kernel fast path writes into a page it doesn't exclusively own, and the page cache absorbs the damage. The week this landed, the DirtyClone variant (CVE-2026-43503) also picked up a public JFrog exploit walkthrough. The class is having a moment, and the lesson across all of them is the same: the page cache is a shared resource, and any COW path that miscalculates its writable window turns a memory bug into a root.
What's genuinely new in this one is the entry point. The classic objection to tc-based bugs was that configuring traffic-control actions needs CAP_NET_ADMIN, which an unprivileged user shouldn't have. But an unprivileged user can open a user namespace, and inside that namespace they get a namespace-local CAP_NET_ADMIN — exactly the capability needed to load a pedit rule and pull the trigger. Unprivileged user namespaces are the bridge from "ordinary user" to "can reach this bug."
Where You're Exposed
The exploit needs two conditions present together: the act_pedit module loadable, and unprivileged user namespaces open. The public PoC demonstrated unprivileged-to-root on:
- RHEL 10 and Debian 13 (trixie) — both ship with unprivileged user namespaces open by default, so they're directly exploitable.
- Ubuntu 24.04 — exploitable, but execution had to be routed through AppArmor profiles that still permit user namespaces.
- Ubuntu 26.04 — the default-deny AppArmor stance on unprivileged user namespaces blocks the demonstrated path, though the underlying kernel is still vulnerable.
Vendor patch status splits accordingly. Debian has fixed trixie through its security channel, but Debian 11 and 12 were still listed vulnerable. Ubuntu listed supported releases from 18.04 through 26.04 as vulnerable as of late June. Red Hat lists RHEL 8, 9, and 10 as affected, with RHEL 7 absent from the bulletin.
What To Do
Patch and reboot. The fix moves the writable-range check inside the per-key loop where the real offset is known, and adds overflow guards on the offset math. Install your distro's patched kernel and reboot — kernel fixes don't take hold until you do.
uname -r
Compare against the fixed version your distro published, then update and reboot. Prioritize the hosts where untrusted users can get a shell: multi-tenant servers, CI/CD runners, Kubernetes worker nodes, shared build and research machines.
If you can't patch immediately
Two mitigations each break the exploit chain on their own.
First, if the box doesn't need tc pedit rules, block the module. Check whether it's loaded:
lsmod | grep act_pedit
Then prevent it from loading:
echo 'install act_pedit /bin/true' | sudo tee /etc/modprobe.d/disable-act_pedit.conf
⚠️ Don't blanket-apply this without checking. If the host actually uses pedit for traffic shaping or header rewriting (some QoS, NAT, and SDN setups do), blocking the module breaks that. Verify with lsmod and your tc config first.
Second, disable unprivileged user namespaces, which removes the capability the exploit borrows:
sudo sysctl -w kernel.unprivileged_userns_clone=0
On RHEL the equivalent knob is user.max_user_namespaces=0. ⚠️ This one has real blast radius: it breaks rootless containers (Podman rootless, rootless Docker), some CI sandboxes, and sandboxed browsers that rely on user namespaces for isolation. Test on a non-production host before rolling it out, or you'll trade a privilege-escalation bug for a pile of broken workloads.
If you suspect a host was already hit
⚠️ Treat it as compromised, not as something you can scrub. Because the corruption lives in cached memory rather than on disk, your file-integrity tooling is blind to it — a clean AIDE or Tripwire report means nothing here. Dropping the page cache clears the poisoned in-memory image:
echo 3 | sudo tee /proc/sys/vm/drop_caches
But understand what that does and doesn't do: it flushes the corrupted cached binary, and it does nothing about the root shell the attacker already opened or any persistence they established once they had root. If you have real reason to believe a box was exploited, the honest response is full incident handling — isolate it, capture volatile state before you reboot, assume any secret on that host is burned, and rebuild rather than clean.
The Disclosure Timeline Is the Real Warning
Here's the part worth sitting with. The fix went onto the netdev kernel mailing list in late May, framed as an ordinary data-corruption patch — no CVE, no security flag. The exploitable detail sat in public, in the open, on a mailing list anyone can read, for weeks. The CVE only got assigned when the fix merged on June 16, and the weaponized proof-of-concept showed up within a day of that.
That sequence is the lesson for anyone defending Linux fleets. The window of exposure didn't start when the CVE was published — it started weeks earlier, the moment a security-relevant fix was discussed in the clear without a security label. If your patching posture is "wait for the scanner to grow a rule for the CVE," you're starting the clock late on purpose. For kernel page-cache corruption bugs in particular, where weaponization lands in hours and detection is hard by design, that lag is the difference between patched and owned.
References
- The Hacker News: New Linux pedit COW Exploit Enables Root Access by Poisoning Cached Binaries (source)
- Red Hat Security Bulletin RHSB-2026-008: CVE-2026-46331
- NVD: CVE-2026-46331
- Linux Kernel Commit: net/sched: fix pedit partial COW leading to page cache corruption
- Tenable Plugin: CVE-2026-46331
- Debian Security Tracker: CVE-2026-46331
- Ubuntu Security Notice: CVE-2026-46331