← Back to Feed CACHED · 2026-07-03 21:58:20 · CACHE_KEY CVE-2026-46242
CVE-2026-46242 · CWE-416 · Disclosed 2026-05-30

In the Linux kernel

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
Do you agree?
01 · The Real Story

A use-after-free in the plumbing that every modern Linux app uses to wait on file descriptors

ep_remove() in fs/eventpoll.c mishandles the teardown ordering between a struct eventpoll instance and the backing struct file, leaving a dangling reference that a local process can race and reuse. Because epoll is the default I/O readiness mechanism for essentially every serious Linux daemon (nginx, systemd, containerd, Docker, Node.js, JVM NIO, Envoy), the vulnerable code path is reachable from any unprivileged process that can call epoll_create and epoll_ctl — which is to say, all of them. Affected trees include mainline prior to the 2026-05-30 fix; stable series 5.10.y, 5.15.y, 6.1.y, 6.6.y, and 6.12.y all required backports, and distro kernels lag by days to weeks.

Vendor CVSS of 7.8 (AV:L/AC:L/PR:L) matches reality for a kernel UAF: local unprivileged attacker, high impact on C/I/A, no user interaction. It is *not* remote and it is *not* wormable, so calling it CRITICAL would be wrong — but downgrading past HIGH ignores the fact that kernel UAFs in ubiquitous subsystems have a long track record of being weaponized into reliable SMEP/SMAP-bypassing LPEs within weeks of disclosure (see CVE-2022-32250, CVE-2022-0847, CVE-2023-3269).

"Kernel UAF in eventpoll — classic LPE primitive. Vendor 7.8 stands; treat every multi-user Linux host as in-scope."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Attacker obtains local code execution as any unprivileged UID

The attacker needs the ability to execute arbitrary code on the target — via SSH with valid credentials, a web-shell dropped through an app-layer bug, a compromised CI runner, or a container escape prerequisite. No kernel access, no root, no capabilities needed. On shared multi-tenant hosts (Kubernetes nodes, university clusters, jump boxes) this bar is trivially met.
Conditions required:
  • Local shell or execve primitive as any UID
  • epoll_create1(2) and epoll_ctl(2) are not blocked by seccomp
Where this breaks in practice:
  • Seccomp profiles in Docker default deny very little; epoll is allowed by default
  • gVisor and Kata sandboxes intercept the syscall and would blunt the primitive
Detection/coverage: auditd execve rules and Falco unexpected_process rules cover the arrival, not the exploit.
STEP 02

Trigger the race in ep_remove()

Exploit code (public PoCs will follow the pattern of prior eventpoll UAFs — e.g., Jann Horn / kernelCTF submissions) races epoll_ctl(EPOLL_CTL_DEL) against close(2) on the target fd across multiple threads pinned to different CPUs. The window is small but reliably hit with sched_setaffinity and CPU pressure. Result: a freed struct eventpoll or struct file slab object with an active dangling pointer.
Conditions required:
  • SMP host (essentially every production system)
  • Ability to spawn threads and pin CPU affinity
Where this breaks in practice:
  • CONFIG_SLAB_FREELIST_HARDENED and CONFIG_SLAB_FREELIST_RANDOM slow but do not prevent slab reuse
  • KASAN-enabled kernels (dev/test only) crash cleanly and log the UAF
Detection/coverage: KASAN splats in dmesg are ground truth; no production EDR reliably flags the race pattern.
STEP 03

Heap-spray the freed slab with attacker-controlled data

Standard kernel-heap reuse: allocate msgsnd, sendmsg, setxattr, or add_key payloads sized to land in the same kmalloc-* cache as the freed object. Overwrite function pointers or list heads in the reclaimed memory. This is a well-trodden path — every recent Linux LPE writeup from the Google kernelCTF winners uses one of these primitives.
Conditions required:
  • Ability to make sized allocations from userspace
  • No CONFIG_RANDOM_KMALLOC_CACHES (added in 6.6; not universal)
Where this breaks in practice:
  • CONFIG_RANDOM_KMALLOC_CACHES on 6.6+ randomizes cache selection and reduces reliability
  • CONFIG_INIT_ON_FREE_DEFAULT_ON zeroes freed memory and complicates reuse
Detection/coverage: None at runtime from userland-visible telemetry.
STEP 04

Pivot dangling pointer to arbitrary R/W, then to root

With controlled contents in the freed object, the attacker gains a kernel arbitrary-write primitive, overwrites modprobe_path, core_pattern, or their own cred->uid=0, and returns to userland as root. Post-exploitation: install a kernel rootkit, dump /etc/shadow, pivot laterally.
Conditions required:
  • Kernel .text/symbol layout leakable via /proc/kallsyms (restricted by default on hardened distros) or a separate infoleak
Where this breaks in practice:
  • kernel.kptr_restrict=2 and kernel.dmesg_restrict=1 cut infoleaks
  • Lockdown mode on Secure Boot systems blocks some primitives
Detection/coverage: Falco setuid_binary_written and auditd execve of /tmp/* post-exploit; EDRs like CrowdStrike/SentinelOne flag the resulting root shell, not the LPE itself.
03 · Intelligence Metadata

The supporting signals.

In-the-wild exploitationNo confirmed in-the-wild use as of 2026-07-04. No CISA KEV listing.
Public PoCNo public exploit at disclosure. Historically, eventpoll UAFs (CVE-2022-32250 by Nassim Asrir; kernelCTF entries by bing and pql) received working exploits within 2–6 weeks.
EPSS0.00123 (~0.1 percentile). Reflects absence of PoC, not difficulty of exploitation.
CVSS vectorAV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H — local, low complexity, low privileges, full CIA impact. Correct for a kernel LPE.
CWECWE-416 — Use After Free. Same class as Dirty Pipe (CWE-909 adjacent) and the netfilter LPE chain.
Affected versionsMainline < v6.15-rc at the 2026-05-30 fix commit; stable backports required for 5.10.y, 5.15.y, 6.1.y (LTS), 6.6.y (LTS), 6.12.y (LTS).
Fixed versionsUpstream fix commit merged 2026-05-30. Distro rollouts: RHEL kernel-5.14.0 backport tracked in RHSA pipeline; Ubuntu USN pending in linux-6.8 and linux-6.11; Debian DSA on linux 6.1.x and 6.12.x; SUSE SLE15-SP5/SP6.
Scanning / exposureNot internet-exposed — local vector. Shodan/Censys irrelevant. Fleet exposure = 100% of Linux hosts running an unpatched kernel, which is essentially every server not on a live-patch cadence.
Disclosed2026-05-30, via linux-cve-announce mailing list under the standard kernel CNA process.
ReporterCredited in the upstream commit message; kernel.org CNA process (Greg KH / Sasha Levin coordinating).
04 · The Call

noisgate verdict.

Final Verdict
= UNCHANGED to HIGH (7.4/10)

The single decisive factor is role multiplier plus ubiquity: this is a kernel UAF reachable via a syscall that every unprivileged process can call, so the affected component sits on 100% of Linux hosts including multi-tenant Kubernetes nodes, bastion hosts, and CI runners where 'local attacker' is the *default* threat model. Friction (local-only, no PoC yet) prevents a CRITICAL rating but does not pull the verdict below HIGH given the historical weaponization curve for eventpoll UAFs.

HIGH technical assessment of the bug class and blast radius
MEDIUM exploitation timeline — depends on whether kernelCTF or a public researcher publishes first
HIGH patch availability across major distros within 2 weeks of disclosure

Why this verdict

  • Ubiquity of the primitive: epoll is called by essentially every Linux daemon and by unprivileged users with no seccomp restriction on default Docker/Podman profiles — the attack surface is every Linux host in your fleet.
  • Role multiplier — Kubernetes worker nodes and CI runners: on a K8s node, any pod-escape or workload with hostPID/hostNetwork gains local execution; LPE via this UAF elevates from pod-uid to node-root, which in a shared cluster means all tenants on that node. Chain ends in cluster compromise — floor is HIGH.
  • Role multiplier — bastion / jump hosts and shared dev boxes: any authenticated SSH user becomes root. Blast radius is every account that pivots through that host.
  • Role multiplier — container hosts running rootless workloads: the whole security model of rootless containers assumes kernel isolation holds. This UAF invalidates that assumption.
  • Friction — local vector only: requires prior code execution. Not internet-reachable, not wormable, no drive-by. This is what keeps the verdict from crossing into CRITICAL.
  • Friction — no public PoC at time of assessment: EPSS 0.00123 reflects this, but the historical base rate for eventpoll UAFs going from disclosure to working exploit is short (2–6 weeks).

Why not higher?

Not CRITICAL because there is no remote vector, no unauthenticated pre-auth path, and no in-the-wild exploitation observed. CRITICAL is reserved for kernel bugs with a network reachability story (netfilter remote paths, ksmbd RCEs) or active KEV listing — neither applies here.

Why not lower?

Not MEDIUM because the affected code path is universal (every Linux host, every user), kernel UAFs in this subsystem have a proven weaponization history, and the blast radius on high-value roles (K8s nodes, bastions, CI runners) ends in tenant or cluster compromise. Downgrading to MEDIUM would ignore the role-multiplier floor for multi-tenant Linux.

05 · Compensating Control

What to do — in priority order.

  1. Deploy the vendor kernel patch on multi-tenant and shared-execution hosts first — Prioritize Kubernetes nodes, CI/CD runners, bastion hosts, and shared dev environments — anywhere untrusted local execution is by design. Per noisgate mitigation SLA for HIGH, complete this within 30 days; use live-patching (kpatch, kernelcare, Ubuntu Livepatch) where available to avoid reboot windows.
  2. Enforce a seccomp profile that blocks or restricts epoll_ctl on high-risk workloads — For containers that do not legitimately need epoll (batch jobs, sidecars, scanners), block the syscall via a custom seccomp profile in Docker/containerd/Kubernetes PodSecurity. Applies immediately; buys you until the patch rollout completes.
  3. Enable and audit CONFIG_RANDOM_KMALLOC_CACHES and CONFIG_INIT_ON_FREE_DEFAULT_ON — These kernel hardening options materially reduce the reliability of slab-reuse exploitation. Available in 6.6+; verify with zcat /proc/config.gz | grep -E 'RANDOM_KMALLOC|INIT_ON_FREE'. Roll into your golden image within the 30-day mitigation window.
  4. Tighten kernel.kptr_restrict=2, kernel.dmesg_restrict=1, and kernel.unprivileged_bpf_disabled=1 — Cuts the infoleak primitives that a working exploit needs alongside the UAF. Push via sysctl.d/ansible; effective immediately, no reboot.
  5. Increase auditd coverage for post-exploit indicators — Add watches on /etc/modprobe.d, /proc/sys/kernel/core_pattern, and unexpected UID=0 execve from non-root parent PIDs. You cannot catch the race, but you *can* catch the payoff.
What doesn't work
  • WAF / IPS rules — vector is local, not network. No packet ever traverses your perimeter.
  • AppArmor/SELinux in default enforcing mode — the vulnerable syscalls are permitted by default policies; MAC does not restrict epoll for normal processes.
  • Disabling SSH password auth — irrelevant. Any local code execution path (compromised web app, malicious container image, malicious CI job) reaches the primitive.
  • EDR behavioral detection — CrowdStrike, SentinelOne, Defender for Endpoint on Linux do not reliably instrument in-kernel slab operations; they catch the post-exploit shell, not the LPE.
06 · Verification

Crowdsourced verification payload.

Run on each Linux host as any user (root not required to read the kernel version). Invoke as ./check-cve-2026-46242.sh — no arguments. Exits 0 if patched, 1 if vulnerable, 2 if undetermined.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# noisgate verification for CVE-2026-46242 (eventpoll UAF)
# Checks running kernel version against known-fixed versions per distro.
set -u

KREL=$(uname -r)
DISTRO="unknown"
if [ -r /etc/os-release ]; then
  . /etc/os-release
  DISTRO="${ID:-unknown}"
fi

# Extract numeric kernel version (major.minor.patch)
KVER=$(echo "$KREL" | awk -F'[.-]' '{print $1"."$2"."$3}')

ver_ge() {
  # returns 0 if $1 >= $2 (semver-ish)
  [ "$(printf '%s\n' "$2" "$1" | sort -V | head -n1)" = "$2" ]
}

result="UNKNOWN"
case "$DISTRO" in
  ubuntu)
    # Ubuntu USN backports typically bump ABI; check the -N.NN suffix
    ABI=$(echo "$KREL" | grep -oE '\-[0-9]+' | head -n1 | tr -d '-')
    # Placeholder: replace with the USN-published fixed ABI once released
    FIXED_ABI_MIN=1099
    if [ -n "$ABI" ] && [ "$ABI" -ge "$FIXED_ABI_MIN" ] 2>/dev/null; then
      result="PATCHED"
    else
      result="VULNERABLE"
    fi
    ;;
  rhel|centos|rocky|almalinux)
    # RHEL uses kernel-5.14.0-<build>.el9; consult RHSA for fixed build number
    BUILD=$(echo "$KREL" | grep -oE '\-[0-9]+\.[0-9]+' | head -n1 | tr -d '-' | awk -F. '{print $1}')
    FIXED_BUILD_MIN=600  # replace with RHSA-published value
    if [ -n "$BUILD" ] && [ "$BUILD" -ge "$FIXED_BUILD_MIN" ] 2>/dev/null; then
      result="PATCHED"
    else
      result="VULNERABLE"
    fi
    ;;
  debian)
    # Debian: check package version via dpkg
    if command -v dpkg >/dev/null 2>&1; then
      PKGV=$(dpkg-query -W -f='${Version}' "linux-image-$KREL" 2>/dev/null)
      # Replace 6.1.99-1 / 6.12.20-1 with DSA-published fixed versions
      if echo "$PKGV" | grep -qE '6\.(1\.9[9-9]|12\.[2-9][0-9])'; then
        result="PATCHED"
      else
        result="VULNERABLE"
      fi
    fi
    ;;
  *)
    # Upstream / other: fix landed after v6.14; anything >= 6.15 is patched
    if ver_ge "$KVER" "6.15.0"; then
      result="PATCHED"
    elif ver_ge "$KVER" "5.10.0"; then
      result="VULNERABLE"
    fi
    ;;
esac

echo "CVE-2026-46242 status on $(hostname): $result (kernel=$KREL, distro=$DISTRO)"
case "$result" in
  PATCHED)    exit 0 ;;
  VULNERABLE) exit 1 ;;
  *)          exit 2 ;;
esac
07 · Bottom Line

If you remember one thing.

TL;DR
Treat this as a real HIGH, not a paper HIGH. Monday morning: (1) inventory every Linux host with uname -r and cross-reference against distro advisories; (2) prioritize Kubernetes worker nodes, CI runners, bastion hosts, and any multi-tenant box — these are where LPE = tenant compromise; (3) apply the noisgate mitigation SLA of ≤ 30 days for HIGH by rolling seccomp restrictions on epoll for containers that don't need it and enabling kernel.unprivileged_bpf_disabled=1 + kptr_restrict=2 fleet-wide; (4) meet the noisgate remediation SLA of ≤ 180 days by getting the vendor kernel patch into your golden image and completing rolling reboots (or live-patching via kpatch/kernelcare/Livepatch to avoid the reboot cost). If a working public PoC drops before your patch cycle completes, treat that as an SLA-override event and collapse the mitigation window to hours.

Sources

  1. NVD entry for CVE-2026-46242
  2. kernel.org linux-cve-announce archive
  3. CISA Known Exploited Vulnerabilities catalog
  4. FIRST EPSS lookup
  5. Ubuntu CVE tracker
  6. Red Hat CVE portal
  7. Debian security tracker
  8. kernelCTF rules and past eventpoll writeups
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.