CVE-2026-46242 “Bad Epoll” Anatomy: Linux Kernel Use-After-Free from Unprivileged User to Root, and Why Anthropic’s Mythos AI Missed the Bug It Neighbors
A PhD student in Seoul found a six-instruction-wide race window in the Linux kernel’s epoll subsystem that gives any unprivileged user a root shell. The bug sat in mainline for three years. Anthropic’s Mythos, the most capable AI vulnerability research model ever built, audited the same 2,500 lines of code, found a different race bug right next to this one, and walked past it. That combination of facts tells you something important about where kernel security stands in mid-2026, and where the real gaps in AI-assisted auditing still hide.
The epoll Subsystem: More Complex Than You Think
Most Linux developers interact with epoll through three syscalls: epoll_create1, epoll_ctl, and epoll_wait. The API looks simple. Underneath, the kernel maintains a surprisingly intricate web of objects and cross-references that makes lifetime management genuinely hard to get right.
The key structures live in fs/eventpoll.c, roughly 2,500 lines of C:
| Structure | Purpose | Key Fields |
|---|---|---|
struct eventpoll | One per epoll instance. The “watcher” object. | refs (hlist_head), mtx (mutex), wait queue |
struct epitem (epi) | One per monitored fd within an epoll instance. | fllink (hlist_node linking into file->f_ep), fllink.pprev (pointer-to-pointer for hlist_del_rcu) |
struct file | VFS file object for any open fd, including epoll fds. | f_ep (hlist_head *, the per-file list of epitems), f_lock (spinlock), f_count (refcount) |
The detail that makes this bug possible: epoll can watch other epoll instances. You can epoll_ctl(epfd_outer, EPOLL_CTL_ADD, epfd_inner, &ev) and now an epoll fd is both a watcher (through its struct eventpoll) and a watched file (through its struct file). When you tear that relationship down, two different kernel paths need to coordinate: the epoll removal path (ep_remove) and the VFS file teardown path (__fput). If they don’t coordinate perfectly, objects get freed while pointers to them are still live.
That is exactly what happened.
The 2023 Commit That Broke It
Commit 58c9b016e128, merged on April 8, 2023, changed the teardown ordering in the epoll subsystem. The commit itself wasn’t malicious or obviously wrong. It reorganized how ep_remove() and eventpoll_release_file() interact with the file’s f_ep list, presumably to fix a different correctness issue or reduce lock contention.
What the commit actually introduced were two separate race conditions in the same code region. Two bugs, sitting side by side in the same ~2,500 lines, both involving concurrent teardown paths, both exploitable. One would be found by an AI. The other by a human. Neither found both.
The affected kernel versions start at v6.4 (where 58c9b016e128 first shipped) and extend through every subsequent release until the fix landed in mainline on April 24, 2026 as commit a6dc643c6931. That is a three-year window of vulnerability in every kernel from v6.4 through v6.12+.
Root Cause: The Race Between ep_remove() and __fput()
Here is the race, step by step. Understanding it requires following two threads of execution simultaneously, which is exactly why both humans and AI models find these bugs so difficult to reason about.
Thread A calls epoll_ctl(epfd, EPOLL_CTL_DEL, watched_fd, NULL), which enters ep_remove(). Inside ep_remove(), the helper ep_remove_file() is called. This function:
- Acquires
file->f_lock - Clears
file->f_ep(sets it to NULL) - Releases
file->f_lock - Calls
is_file_epoll(file)(dereferences@file) - Calls
hlist_del_rcu(&epi->fllink)(dereferencesepi->fllink.pprev, which points into the watchedstruct eventpoll) - Calls
spin_unlock(&file->f_lock)in the trailing cleanup
Steps 4 through 6 are the problem. The function has already cleared f_ep and released the lock, but it continues to dereference @file and objects reachable through the epitem.
Thread B concurrently calls close(watched_fd), which eventually reaches __fput(). Here is the critical check inside __fput():
// Simplified from fs/file_table.c
static void __fput(struct file *file)
{
// ...
if (file->f_ep) // <-- reads f_ep
eventpoll_release_file(file); // slow path: acquires ep->mtx, waits
// ...
file->f_op->release(inode, file); // fast path if f_ep was NULL
}
If Thread B reads f_ep after Thread A has cleared it (step 2) but before Thread A finishes using the objects (steps 4-6), Thread B takes the fast path. It skips eventpoll_release_file() entirely. For an epoll-watches-epoll scenario, the fast path calls ep_eventpoll_release(), which chains into ep_clear_and_put() and ultimately ep_free(). That ep_free() call runs kfree() on the watched struct eventpoll.
Now Thread A is still executing step 5: hlist_del_rcu(&epi->fllink). The hlist_del_rcu macro performs *pprev = next, an 8-byte write. But pprev points into the refs field of the struct eventpoll that Thread B just freed. Thread A writes 8 bytes into freed kmalloc-192 memory.
That is CWE-416, use-after-free. The race window is approximately six instructions wide.
Thread A (ep_remove_file) Thread B (__fput)
───────────────────────── ──────────────────
spin_lock(&file->f_lock)
file->f_ep = NULL
spin_unlock(&file->f_lock)
reads file->f_ep → NULL
skips eventpoll_release_file()
calls f_op->release → ep_free()
kfree(struct eventpoll) ← FREED
is_file_epoll(file) ← ok, file still alive (refcounted separately)
hlist_del_rcu(...) ← WRITES INTO FREED MEMORY
The root cause is simple once you see it: ep_remove() did not pin the lifetime of @file for the duration of its critical section. Without that pin, the file’s refcount can reach zero while ep_remove() still holds a bare pointer to the file and, more critically, to the struct eventpoll reachable through the epitem.

The Exploitation Primitive: 8-Byte UAF Write to Cross-Cache Attack
An 8-byte write into freed slab memory sounds like a constrained primitive. It is. But the way Jaeyoung Chung’s exploit widens it is elegant.
The exploit uses four epoll objects arranged in two pairs:
int epA = epoll_create1(0); // watcher (pair 1)
int epB = epoll_create1(0); // watched / victim (pair 1)
int epC = epoll_create1(0); // watcher (pair 2)
int epD = epoll_create1(0); // watched (pair 2)
epoll_ctl(epA, EPOLL_CTL_ADD, epB, &ev);
epoll_ctl(epC, EPOLL_CTL_ADD, epD, &ev);
Closing pair 1 triggers the race. Pair 2 becomes the victim: after the race corrupts the kmalloc-192 slab where struct eventpoll objects live, the attacker sprays the freed slot with controlled data.
Here is where SLAB_TYPESAFE_BY_RCU becomes critical. The struct file slab cache uses this flag, which means freed struct file slots can be immediately recycled by alloc_empty_file() without waiting for an RCU grace period. This is a deliberate performance optimization in the kernel, but it gives the attacker a cross-cache primitive: the corrupted 8-byte write in kmalloc-192 can be aimed at a recycled struct file object. If the attacker controls what gets allocated into that slot, the corrupted pointer overwrites a field in a live struct file.
The heap spray strategy to reclaim the freed slot:
// After triggering the race and freeing the struct eventpoll:
int spray_fds[512];
for (int i = 0; i < 512; i++) {
spray_fds[i] = open("/dev/null", O_RDONLY);
// Each open() allocates a struct file in the same kmalloc-192 cache
}
By spraying roughly 512 file allocations, the attacker places a controlled struct file into the freed kmalloc-192 slot with high probability. The dangling hlist_del_rcu write then corrupts a field in that struct file.

Achieving 99% Reliability: Why the Exploit Self-Heals
Race condition exploits are notoriously unreliable. A six-instruction window sounds like it would require thousands of attempts and crash the kernel on failures. Bad Epoll’s exploit achieves roughly 99% reliability, and the reason is structural.
The key insight: if the race is lost (Thread B completes __fput either before or after the critical window), no corruption occurs. The epoll objects are simply cleaned up normally. There is no kernel crash, no oops, no partial corruption. The attacker can loop the attempt indefinitely.
while (!got_root) {
// Set up four epoll objects
// Attempt race between EPOLL_CTL_DEL and close()
// Check if heap corruption occurred
// If not, tear down cleanly and retry
}
The exploit widens the race window using CPU affinity pinning, binding Thread A and Thread B to specific cores and using scheduling tricks to create consistent interleaving. On modern multicore systems, the race hits within a handful of iterations. The self-healing property means the attacker can attempt it hundreds of times per second without any system instability.
Combined with the heap spray, this produces a highly deterministic exploit. The write primitive lands in the target slab, the info leak works on the first read, and the ROP chain executes cleanly.
KASLR Bypass and Root Shell
With a corrupted struct file, the attacker needs two more primitives: an information leak to defeat KASLR, and a code execution primitive to escalate privileges.
The info leak comes from /proc/self/fdinfo. When you read /proc/self/fdinfo/<fd>, the kernel formats information about that file descriptor, including internal pointers. With a corrupted struct file whose fields the attacker partially controls, reading fdinfo for that fd leaks kernel pointers.
cat /proc/self/fdinfo/42
# Output includes kernel addresses that reveal the KASLR base
From the leaked pointer, the attacker computes kaslr_base = leaked_ptr - known_symbol_offset using symbol offsets extracted from the kernel image.
The final step is a ROP chain targeting the standard Linux kernel privilege escalation sequence:
// Pseudocode for the ROP payload
prepare_kernel_cred(0) // create a root credential
commit_creds(cred) // apply it to the current task
swapgs // restore user GS base
iretq // return to userspace
// Back in userspace:
execve("/bin/sh", NULL, NULL); // root shell
id prints uid=0(root). From unprivileged user to root, without any special capabilities, namespaces, or modules.
Android and Chrome Renderer Sandbox Reachability
Most Linux kernel LPEs don’t translate to Android because they depend on kernel modules, config options, or filesystem features that Android strips out. Bad Epoll is different. epoll is fundamental infrastructure on Android. Every Android process uses it. The epoll_create1, epoll_ctl, and close syscalls are all available inside Chrome’s renderer sandbox on Android.
This means Bad Epoll is reachable as the second stage of a two-bug exploit chain: a Chrome renderer RCE (the first bug) followed by Bad Epoll (the second bug) to escape the sandbox and gain root on the device.
Affected Android devices are those running kernel v6.4 or newer. In practice:
- Pixel 10 (kernel v6.6+): affected. The PoC triggers the UAF; a full root exploit is reported to be in progress.
- Pixel 8 (kernel v6.1): not affected, because v6.1 predates the introducing commit.
- Samsung, OnePlus, and other vendors shipping kernels v6.4+ are potentially affected depending on their backport status.
You cannot simply disable epoll with a seccomp filter. Every event-loop-based application on Android (which is basically every application) depends on it. This is not a niche subsystem you can restrict away.
What Mythos Found, What It Missed, and Why
Here is the part that matters for the future of vulnerability research.
Anthropic’s Mythos Preview, announced April 7, 2026, autonomously discovered thousands of previously unknown vulnerabilities across major operating systems and browsers. Among them was CVE-2026-43074, a race condition in the Linux kernel’s epoll subsystem. Same file. Same ~2,500 lines of code. Same 2023 commit that introduced Bad Epoll. Mythos found a real, exploitable race bug in fs/eventpoll.c, which is genuinely impressive given how notoriously difficult concurrency bugs are to identify through static analysis.
But Mythos missed CVE-2026-46242. The bug was sitting right next to the one it found.
Jaeyoung Chung, the discoverer, has proposed two hypotheses for why.
Hypothesis 1: The race window is too narrow for static reasoning. Six instructions. To identify this as a vulnerability, you need to reason about a specific interleaving where Thread A clears f_ep under the spinlock, releases the lock, and then Thread B reads f_ep as NULL and takes the fast path through __fput, all before Thread A reaches hlist_del_rcu. This is not a pattern you can match syntactically. It requires building a mental model of two concurrent execution paths, tracking the state of shared variables at each interleaving point, and understanding the semantic consequences of each ordering. Current AI models, even frontier ones, struggle with this kind of reasoning because it requires holding multiple parallel execution states in working memory simultaneously.
Hypothesis 2: Weak runtime evidence after the first patch. After CVE-2026-43074 was fixed, Bad Epoll’s use-after-free typically does not trigger KASAN. Without that runtime signal, there’s nothing in the fuzzing output or sanitizer logs to point at this code region as suspicious. Mythos likely relied partly on KASAN crash reports as a signal for where to focus its analysis. No KASAN hit, no signal, no investigation.
The second hypothesis is particularly revealing. It suggests that Mythos, like many human auditors, may be using a workflow that starts with runtime signals (crashes, sanitizer reports, fuzzer outputs) and then reasons backward to root causes. That workflow is powerful for bugs that produce observable symptoms. It is blind to bugs that fail silently.
Bad Epoll fails silently on most attempts. When the race is lost, nothing happens. When the race is won, the corrupted write lands in freed memory that may already be reallocated, producing no immediate crash. You need to be running KASAN with specific heap configurations to catch it, and even then it’s intermittent. A human auditor reading the code with fresh eyes after the CVE-2026-43074 patch, asking “did we fix the entire class of lifetime issues, or just one instance?” would catch it. And one did.

A Hybrid Human+AI Kernel Audit Workflow
The Bad Epoll story doesn’t prove AI is useless for kernel auditing. Mythos found CVE-2026-43074, a real race condition in the same code, which most human auditors also missed for three years. What it proves is that AI and humans have complementary blind spots, and the optimal workflow uses both.
Here is what I’d recommend based on what Bad Epoll reveals:
AI-suited tasks:
- Wide-coverage static pattern matching across entire subsystems. Scanning 2,500 lines of
eventpoll.cfor lifecycle inconsistencies is exactly the kind of tedious, systematic work AI handles well. - Triaging Syzkaller crash reports at scale. A busy fuzzing farm generates thousands of reports. AI can deduplicate, classify, and prioritize them faster than any human team.
- Drafting initial fix proposals. Once a bug is identified, AI can propose the fix pattern (add a refcount pin, extend a lock scope, etc.) and flag whether it might introduce new issues.
- Ranking code regions by suspiciousness based on complexity metrics, recent churn, and known bug patterns.
Human-suited tasks:
- Reasoning about narrow concurrent execution paths where no runtime signal exists. This is the gap Mythos fell into. Humans can construct abstract interleaving scenarios and reason about them, especially when prompted by a nearby fix.
- Post-patch “is the class closed?” analysis. After CVE-2026-43074 was fixed, someone should have asked: “The fix addressed one lifetime issue. Are there other lifetime issues in the same teardown paths?” That question requires semantic understanding of what the fix actually changed and what it left unchanged. This is the single most important lesson from Bad Epoll.
- Semantic lifetime analysis across lock boundaries. Understanding that releasing a spinlock before finishing use of the protected object creates a window, even when the code “looks” correct, requires the kind of deep systems reasoning that humans still do better.
- Evaluating whether a UAF is exploitable in practice, including cross-cache attack feasibility and slab allocator behavior.
The integration point: Syzkaller + AI triage + human review loop. Run Syzkaller continuously, including after patches land. Use AI to triage the output and flag anomalies. Have human reviewers focus on the cases where the AI is uncertain, where the KASAN signal is absent or intermittent, and where a recent patch may have only partially addressed a bug class. This loop catches both the bugs that produce clear signals (AI’s strength) and the bugs that hide in narrow timing windows with weak evidence (human strength).

Syzkaller Reproducer Anatomy
The public repository at github.com/J-jaeyoung/bad-epoll includes a Syzkaller reproducer. Here is the structural anatomy.
The reproducer uses two threads sharing a file descriptor table. Thread A calls epoll_ctl(EPOLL_CTL_DEL) on the watched epoll fd. Thread B calls close() on the same fd simultaneously. The key is getting the interleaving right.
// Simplified reproducer structure (not the full PoC)
void *thread_a(void *arg) {
// Triggers ep_remove() → ep_remove_file()
epoll_ctl(epfd_watcher, EPOLL_CTL_DEL, epfd_watched, NULL);
return NULL;
}
void *thread_b(void *arg) {
// Triggers __fput() on the watched epoll fd
close(epfd_watched);
return NULL;
}
int main() {
for (int attempt = 0; attempt < 10000; attempt++) {
int epfd_watcher = epoll_create1(0);
int epfd_watched = epoll_create1(0);
struct epoll_event ev = { .events = EPOLLIN };
epoll_ctl(epfd_watcher, EPOLL_CTL_ADD, epfd_watched, &ev);
pthread_t t1, t2;
pthread_create(&t1, NULL, thread_a, NULL);
pthread_create(&t2, NULL, thread_b, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
close(epfd_watcher);
}
}
Required kernel config flags for catching the bug in a lab:
CONFIG_KASAN=y # Catches the UAF write
CONFIG_KCSAN=y # Detects the data race on f_ep
CONFIG_DEBUG_ATOMIC_SLEEP=y # Catches lock inversions
CONFIG_PROVE_LOCKING=y # Lockdep for ordering violations
In Syzkaller’s configuration, set "collide": true to enable concurrent syscall execution. Without this, Syzkaller serializes syscalls and will never hit the race window.
Expected KASAN output when the race is won:
BUG: KASAN: use-after-free in hlist_del_rcu+0x.../0x...
Write of size 8 at addr ffff888012345678 by task poc/1234
Allocated by task 1233:
ep_alloc+0x...
do_epoll_create+0x...
Freed by task 1235:
ep_free+0x...
ep_clear_and_put+0x...
ep_eventpoll_release+0x...
The stack trace in the “Freed by” section confirms the race: ep_free was called through the f_op->release fast path while hlist_del_rcu was still running in the removal path.
eBPF-Based Runtime Detection
For production systems where you cannot run KASAN (the performance overhead is 2-3x), an eBPF-based detection approach can flag potential exploitation attempts.
The strategy: attach fentry/kprobe programs to the four key functions and detect the fastpath skip pattern, specifically the case where __fput() reads f_ep == NULL for an epoll file while ep_remove_file() is concurrently active on another CPU.
// BPF program sketch (attach to __fput via fentry)
SEC("fentry/__fput")
int BPF_PROG(trace_fput, struct file *file) {
if (!file->f_ep) {
// f_ep is NULL at __fput entry
// Check if this is an epoll file
// Record timestamp for correlation
__u64 ts = bpf_ktime_get_ns();
__u64 file_addr = (__u64)file;
bpf_map_update_elem(&fput_events, &file_addr, &ts, BPF_ANY);
}
return 0;
}
SEC("kprobe/ep_remove_file")
int kprobe_ep_remove_file(struct pt_regs *ctx) {
struct file *file = (struct file *)PT_REGS_PARM2(ctx);
__u64 file_addr = (__u64)file;
__u64 *fput_ts = bpf_map_lookup_elem(&fput_events, &file_addr);
if (fput_ts) {
__u64 now = bpf_ktime_get_ns();
__u64 delta = now - *fput_ts;
if (delta < 1000000) { // within 1ms
// Potential Bad Epoll race detected
bpf_printk("BAD_EPOLL_RACE: file=%llx delta=%llu ns\n",
file_addr, delta);
// Emit perf event for SIEM integration
}
}
return 0;
}
Practical limitations are significant. The race window is ~6 instructions wide. On a busy server running nginx, Node.js, or any event-loop application, nested epoll usage is common and the temporal correlation between __fput and ep_remove_file will produce false positives. This detection is best deployed as a canary on CI runners, container hosts, and development systems, not as a blocking control on production servers.
Complement the eBPF approach with auditd rules that catch the post-exploitation indicators:
-a always,exit -F arch=b64 -S setuid,setreuid,setresuid -k priv_change
-a always,exit -F arch=b64 -S execve -F euid=0 -F auid!=0 -k root_exec_unexp
Distro Patch Status and Hardening
The fix landed in mainline on April 24, 2026. The public writeup dropped July 3. That is a 70-day window where the fix was in the kernel git tree but most people didn’t know why it mattered.
| Distribution | Kernel Base | Affected? | Patch Status (July 2026) |
|---|---|---|---|
| Ubuntu 22.04 LTS (GA kernel 5.15) | v5.15 | No | N/A |
| Ubuntu 22.04 LTS (HWE kernel 6.5+) | v6.5+ | Yes | Backport expected |
| Ubuntu 24.04 LTS | v6.8 | Yes | Backport in progress |
| Debian 12 Bookworm | v6.1 | No | N/A |
| Debian 13 Trixie | v6.12 | Yes | Track security-tracker.debian.org |
| RHEL 9 / Rocky / Alma (base) | v5.14 | No | Verify HWE/EUS kernels |
| Fedora 40/41 | v6.8/6.11 | Yes | Updates typically fast |
| SUSE / openSUSE Leap 15.6 | v6.4 | Yes | Check suse.com/security |
| Android Pixel 10 | v6.6 | Yes | July 2026 security patch |
| Android Pixel 8 | v6.1 | No | N/A |
Hardening options that reduce (but do not eliminate) exploit reliability:
| Config Option | Effect |
|---|---|
CONFIG_SLAB_FREELIST_HARDENED=y | Obfuscates freelist pointers; reduces cross-cache precision |
CONFIG_RANDOM_KMALLOC_CACHES=y | Randomizes per-type slab caches; makes heap spray less predictable |
kernel.unprivileged_userns_clone=0 | Raises the bar for sandbox-context exploitation |
None of these are substitutes for applying the actual fix commits: a6dc643c6931, ced39b6a8062, and ef4ca02e9536. If your kernel is v6.4 or newer and you haven’t backported these, patch now.
MITRE ATT&CK Mapping
| Technique | Name | Application |
|---|---|---|
| T1068 | Exploitation for Privilege Escalation | Primary: unprivileged user to root via kernel UAF |
| T1611 | Escape to Host | Android Chrome renderer sandbox escape chain |
| T1203 | Exploitation for Client Execution | Chrome RCE as the first bug in a two-bug chain |
| T1005 | Data from Local System | /proc/self/fdinfo info-leak primitive |
| T1082 | System Information Discovery | uname -r, /proc/kallsyms for KASLR recon |
ATT&CK does not have a sub-technique specifically covering kernel UAF race conditions. T1068 is the correct primary mapping. The Chrome sandbox escape aligns most closely with T1611, though ATT&CK frames that technique around containers rather than mobile app sandboxes.
What Bad Epoll Actually Teaches Us
The technical root cause of Bad Epoll is straightforward: a missing refcount pin on a struct file pointer during a critical section. The fix is six lines of code. The bug existed for three years in one of the most reviewed codebases on Earth.
The deeper lesson is about what happens at the boundary between a fix and a bug class. CVE-2026-43074 got patched. The person (or AI) who patched it addressed one lifetime issue. They did not ask: “Is this the only lifetime issue in this teardown path?” If they had, they would have found Bad Epoll. The struct file use-after-free remained until the separate CVE-2026-46242 fix. Fixing one visible symptom did not fix the entire lifetime design problem.
This is the gap where human auditors still outperform AI. Not in raw coverage, not in speed, not in pattern matching, but in asking the second question: “What else could be wrong here, even if I can’t see it crashing?” Mythos found the bug that crashed. A human found the bug that didn’t.
The right response is not to distrust AI tools. Mythos finding CVE-2026-43074 is a genuine achievement. Race conditions in kernel code have historically been found almost exclusively through either manual auditing by top-tier researchers or through brute-force fuzzing with specialized harnesses. Having an AI find one through static analysis is a step change. But it’s not the whole picture, and Bad Epoll is the proof.
Build your kernel audit workflow around the complementary strengths. Let AI scan wide and flag the obvious lifecycle issues. Let humans focus on the narrow timing windows, the missing KASAN signals, the “is the class actually closed?” analysis that requires understanding what a patch meant, not just what it changed. Run Syzkaller continuously, including after patches land, with collide: true and full sanitizer coverage. And when AI finds a bug in a subsystem, treat that as a signal to have a human spend a week in the same code asking what the AI missed.
Six instructions. Three years. One refcount pin. That is the distance between unprivileged and root.
Key Takeaways
- Bad Epoll (CVE-2026-46242) is a race between
ep_remove_file()and__fput()where a clearedf_eppointer causes the file teardown fast path tokfree()astruct eventpollwhilehlist_del_rcu()is still writing into it. - The exploit achieves ~99% reliability because failed race attempts cause no kernel instability, allowing indefinite retries combined with precise heap spraying against
kmalloc-192. - Android devices on kernel v6.4+ are affected, and the bug is reachable from Chrome’s renderer sandbox, making it viable as the second stage of a two-bug chain.
- Mythos found a sibling bug (CVE-2026-43074) in the same code and missed this one, most likely because the six-instruction race window produces no KASAN signal under normal conditions.
- The real gap in AI-assisted vulnerability research is post-patch class analysis: asking whether a fix closes an entire category of issues or just one instance. That remains a human skill.
- Patch immediately. Apply commits
a6dc643c6931,ced39b6a8062,ef4ca02e9536. Slab hardening options reduce exploit reliability but do not eliminate the primitive. There is no viable seccomp workaround for epoll.
Related Tutorials
- System Calls and SSDT: How User Mode Reaches the Kernel
- User Mode vs Kernel Mode: Privilege Rings and the Boundary
- Access Tokens and Privileges: The Kernel’s Security Context
- Shellcode Encoders: XOR Encoding, Custom Decoders, and Avoiding Bad Chars
- Fibers: User-Mode Cooperative Threads
References
- Bad Epoll (CVE-2026-46242) – Official Researcher GitHub Repository & Technical Writeup (Jaeyoung Chung, Seoul National University CompSec Lab)
- New “Bad Epoll” Linux Kernel Flaw Lets Unprivileged Users Gain Root, Hits Android – The Hacker News
- New “Bad Epoll” 0-Day Vulnerability Allows Root Access on Linux Servers and Android Devices – CyberSecurityNews
- CVE-2026-46242: Linux Kernel Use-After-Free Vulnerability – SentinelOne Vulnerability Database
- Bad Epoll, Linux CVE-2026-46242 and the Race to Root – Penligent AI HackingLabs
- Anthropic: Mythos Detected 23,000 Potential Vulnerabilities Across 1,000 OSS Projects – SecurityWeek