CVE
CVE-2026-46242
CWE
CWE-416, CWE-362
Affected Surface
Linux kernels based on the vulnerable eventpoll implementation introduced in v6.4 and publicly fixed in stable lines such as 6.18.33 and 7.0.10, with additional branch backports tracked by kernel.org and NVD, Google kernelCTF targets including lts-6.12.67 and COS 121-18867.294.100 called out in the public exploit write-up, Android devices on 6.6-based kernel lines called out by the researchers as exploitable candidates, Developer workstations, CI runners, containers, and multi-tenant Linux hosts where a malicious package, build step, or low-privilege service can first gain local code execution
Bad Epoll, tracked as CVE-2026-46242, became newly urgent this week because the public exploit repository and July 4 reporting turned a kernel bug that had existed in upstream fixes and advisory data into a widely actionable privilege-escalation path. The bug is not remote by itself. The AppSec significance is that any attacker who first lands ordinary local code execution through a malicious package, compromised build step, exposed container shell, or low-privilege service account can potentially convert that foothold into root on affected Linux hosts.
That makes Bad Epoll relevant to application-security programs even if the initial entry point is “just” npm, PyPI, Maven, or a CI task. The package compromise gets the attacker onto the host; the kernel bug can finish the privilege boundary crossing.
What is affected
Public vulnerability metadata and the researcher write-up describe the bug as introduced by Linux commit 58c9b016e128 in April 2023 inside the epoll rework that reduced ep_mutex contention. The public exploit material summarizes the broad exposure as kernels based on v6.4 or newer until the fix is backported, while public vulnerability metadata now tracks stable fixes in lines such as 6.18.33 and 7.0.10.
The practical exposure statement is:
| Environment | Publicly stated status |
|---|---|
Mainline and stable Linux branches derived from the vulnerable v6.4+ eventpoll code | potentially affected until branch-specific fix backport |
Google kernelCTF lts-6.12.67 and COS 121-18867.294.100 | public exploit targets with reported ~99% and ~98% reliability |
Android devices on newer 6.6+ kernel lines | described by the researchers as viable exploit candidates |
Older v6.1-based Android examples such as Pixel 8-class devices | described in the public repo as not affected because the bug was introduced later |
The exact safe distro version depends on backports. Kernel.org and NVD now track multiple fixed branch points, so defenders should not rely only on uname -r major/minor numbers. A vendor kernel can still be safe if the backport is present, and an apparently “older” branch may still carry the fix.
Root cause: ep_remove() kept using file after opening a free path
The bug sits in fs/eventpoll.c, specifically the cleanup path where ep_remove() clears file->f_ep under file->f_lock and then keeps using the same file object inside the critical section. The fix commit describes the core race precisely:
static void ep_remove(struct eventpoll *ep, struct epitem *epi)
{
struct file *file __free(fput) = NULL;
ep_unregister_pollwait(ep, epi);
if (unlikely(READ_ONCE(epi->dying)))
return;
file = epi_fget(epi);
if (!file)
return;
spin_lock(&file->f_lock);
ep_remove_file(ep, epi, file);
...
}
The added epi_fget() is the entire point. Before the fix, the code path could clear file->f_ep, then race with a concurrent __fput() that observed the transient NULL, skipped the slower release synchronization path, and freed objects that ep_remove() was still about to touch.
NVD’s enriched description and the upstream commit both call out two closely related failure modes:
- freed
struct eventpollreuse in the epoll-watches-epoll case, wherehlist_del_rcu()writes throughepi->fllink.pprevinto already-freedkmalloc-192memory - freed
struct filereuse becausestruct fileisSLAB_TYPESAFE_BY_RCU, so the slot can be recycled while the function still assumes it holds the right lock and object identity
The end state is not just a crash. The bug creates an attacker-steerable memory corruption primitive in a core kernel subsystem.
How the public exploit turns a narrow race into a reliable root chain
The public Bad Epoll repository is unusually important because it does not stop at root-cause analysis. It explains how to make a six-instruction race window useful at runtime.
At a high level, the exploit chain is:
create four epoll objects
-> link them into two epoll-watches-epoll pairs
-> close one pair concurrently to trigger the race
-> free a watched eventpoll while another path still writes through it
-> pivot the 8-byte write into a UAF on struct file
-> abuse /proc/self/fdinfo as an arbitrary kernel-memory read primitive
-> build a ROP chain
-> return with elevated privileges and spawn root shell
The detail that matters to defenders is not the exact exploit engineering. It is that the researchers report a nearly non-crashing retry strategy with roughly 99% reliability on one public target. That moves the bug out of the category of “theoretical local kernel memory corruption” and into “real post-compromise privilege escalation primitive.”
The README also notes that the bug can be triggered from Chrome’s renderer sandbox, which makes it more interesting than many Linux local-root flaws that depend on modules or features Android never enables.
Why AppSec teams should care
For an application-security team, Bad Epoll is best understood as a second-stage escape that pairs well with modern software supply-chain entry points.
Imagine the initial compromise looks like one of these:
npm install of a trojanized dependency
pip install of a malicious wheel
import-time Python backdoor
compromised CI job step
RCE in a local developer tool
low-privilege shell inside a build container
If that initial foothold only gets an attacker unprivileged code execution on the host, the next question becomes whether the kernel offers a fast path to root. On affected kernels, Bad Epoll is exactly that kind of path.
This is why local privilege-escalation bugs belong in application-security threat models for:
- shared CI runners
- developer workstations
- ephemeral build agents
- multitenant internal Linux shells
- Kubernetes worker nodes where application pods can reach kernel attack surface
The package compromise is the delivery mechanism. The kernel bug is the privilege amplifier.
Mitigation and version checking
There is no meaningful kill switch for epoll. The public write-up is explicit about that: you patch or you remain exposed.
The minimum practical response is:
- identify which Linux and Android fleets are running
v6.4+-derived eventpoll code - confirm whether vendor backports for
CVE-2026-46242are present - prioritize environments where untrusted application code can run locally
Start with a simple kernel inventory:
uname -r
cat /proc/version
Then verify vendor advisories or changelogs for the actual backport, not just the branch number. Where your distro exposes changelogs, search for the fix commit or CVE:
rpm -q --changelog kernel | rg "CVE-2026-46242|a6dc643c6931"
apt changelog linux-image-$(uname -r) 2>/dev/null | rg "CVE-2026-46242|eventpoll"
If you operate kernels close to upstream stable, the public metadata to anchor on is the fix family around:
a6dc643c6931
ced39b6a8062
ef4ca02e9536
Treat shared Linux environments especially aggressively. A bug with a public root exploit is much more dangerous on hosts where attackers can first land ordinary user-mode code execution through build steps, test jobs, containers, or package installation.
Detection and response after suspected exploitation
There is no single filesystem IOC that proves this kernel bug was used, because the bug is an exploit primitive, not a fixed malware family. Detection therefore has to be contextual:
- look for the initial foothold that granted local code execution
- correlate suspicious local execution with a host that still ran a vulnerable kernel
- inspect for post-root follow-on behavior such as credential access, persistence, container escape, or tampering with audit controls
In practice, if an attacker already ran arbitrary unprivileged code on a Linux host during the public exploit window and the kernel was unpatched, you should assume kernel compromise is possible even if application logs only show a user-space event.
That response should include:
- isolate the host
- collect volatile evidence if you have a mature IR process
- rotate host-reachable secrets
- rebuild or reimage high-trust systems instead of trusting in-place cleanup
The most important operational lesson from Bad Epoll is simple: local code execution is often not the end state. On affected kernels, it can be the first half of a reliable root chain. That makes this week’s public disclosure directly relevant to any team defending developer tools, package installs, CI runners, or Linux-hosted application workloads.