A kernel graphics driver forgot to clear the old key before handing out a new one, letting a local user reach into freed memory
This is a use-after-free (CWE-416) in the Linux kernel's DRM (Direct Rendering Manager) subsystem, specifically in the change_handle code path used during PRIME buffer sharing (GPU dma-buf handles between processes/devices). The fix sets the old handle pointer to NULL *before* swapping in the new one during PRIME handoff, closing a window where a freed object could be dereferenced or re-used. Affected: mainline Linux kernel builds prior to the upstream fix landing in the drm-fixes tree around late May 2026; distro kernels are receiving backports on their normal cadence (Ubuntu HWE, RHEL 9.x z-stream, SUSE SLE 15 SP6, Debian bookworm-security, Amazon Linux 2023).
The vendor's HIGH / 7.8 rating comes straight from the CVSS vector AV:L/AC:L/PR:L/UI:N/C:H/I:H/A:H — local attack, low privileges, full CIA impact. That's arithmetically correct but overstates operational risk for a fleet defender: you already need a running process with DRM access (an interactive session, a container with /dev/dri mapped in, or a service running as a user in the video group). On headless servers — the bulk of your enterprise footprint — /dev/dri/* typically isn't present or accessible. Realistic verdict is MEDIUM.
4 steps from start to impact.
Attacker lands a local process with DRM device access
open('/dev/dri/renderD128') or /dev/dri/card0. On desktops and workstations this is any logged-in user; on servers it's whoever is in the video/render group or a container that mounts the DRM device node.- Local shell or code execution
- Read/write access to
/dev/dri/* - DRM driver loaded (i915, amdgpu, nouveau, etc.)
- Headless servers typically have no GPU and no
/dev/drinodes - Locked-down containers do not pass through DRM devices
- Requires prior initial access — this is not a remote vector
/dev/dri/* opens by unexpected UIDs; falco rule on device-node access from container workloadsTrigger the change_handle race via PRIME ioctl
DRM_IOCTL_PRIME_HANDLE_TO_FD / FD_TO_HANDLE (or equivalent buffer-share ioctls) to drive the vulnerable swap path where the old handle isn't cleared before assignment. Weaponization would look like a targeted syzkaller-style harness — no public exploit at this time; syzbot may reproduce it once the commit is picked up.- Ability to issue DRM ioctls
- Kernel built with vulnerable DRM PRIME code
- Race is narrow — reliable triggering usually requires CPU pinning and repeated attempts
- KASAN-enabled kernels will trip immediately and are common in test/staging
Shape the freed slab to control the UAF write/read
- Reliable slab shaping primitive
- Bypass of SLAB_ACCOUNT / kmalloc-cg isolation on modern kernels
CONFIG_SLAB_FREELIST_HARDENED,CONFIG_RANDOM_KMALLOC_CACHES, and cgroup-scoped kmalloc caches make cross-cache shaping significantly harder- Modern hardened distros (Ubuntu 24.04, RHEL 9, Fedora) ship these mitigations on
Escalate to root / container escape
cred->uid = 0) or modprobe_path hijack. From an unprivileged container this yields a host escape when combined with a namespace-breaking primitive.- Working kernel R/W primitive from step 3
- No LSM (SELinux/AppArmor) blocking the follow-on action
- SELinux
targetedand AppArmor confinement limit post-exploit lateral movement - Lockdown mode (kernel_lockdown=integrity) blocks several classic paths
execve from unexpected parents, modprobe_path changesThe supporting signals.
| In-the-wild exploitation | None observed. Not on CISA KEV. No vendor or CERT advisories citing active abuse. |
|---|---|
| Public PoC | None published as of 2026-07-02. Likely to appear in syzbot reproducers once the fix commit is picked up by the fuzzer. |
| EPSS | 0.00133 (~0.13%) — very low predicted exploitation probability |
| KEV status | Not listed |
| CVSS 3.1 vector | AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H — local, low complexity, low privs, no UI. Arithmetically 7.8 but AV:L is the operative constraint. |
| Affected versions | Mainline Linux kernel prior to the upstream drm: Set old handle to NULL before prime swap in change_handle commit (drm-fixes, late May 2026). Long-lived in the DRM PRIME code. |
| Fixed versions | Upstream stable trees (6.6.y, 6.1.y LTS); distro backports: Ubuntu USN in the linux/linux-hwe-6.8 series, RHEL 9.x kernel z-stream, SUSE SLE 15 SP6 kernel-default, Debian bookworm-security |
| Exposure data | Not remotely reachable — GreyNoise / Shodan / Censys not applicable. Attack surface is the count of hosts with /dev/dri/* exposed to untrusted local principals. |
| Disclosure date | 2026-05-28 via the standard kernel.org linux-cve-announce feed |
| Reporter | Identified through kernel self-review / syzkaller fuzzing on the drm-misc tree; fix authored by DRM subsystem maintainers |
noisgate verdict.
The single decisive factor is AV:L with prerequisite DRM device access — this is not reachable without an existing local foothold, and the majority of enterprise Linux fleet (headless servers, containers without /dev/dri passthrough) has no attack surface at all. Vendor CVSS 7.8 is arithmetically defensible but overstates operational risk once the deployment-role distribution is honest.
Why this verdict
- Local-only attack vector (AV:L): removes the vast majority of remote threat models — no perimeter reachability, no worming, no unauthenticated RCE. Attacker must already be on the box.
- Attack surface further gated by
/dev/dripresence: headless servers, most Kubernetes worker nodes, and locked-down containers do not expose the DRM device to the vulnerable code path. Realistically <20% of a mixed enterprise Linux fleet is even reachable. - EPSS 0.00133 + no KEV + no public PoC: every empirical signal points at background-noise exploitation probability over the next 30 days.
- Modern kernel hardening bites the exploit chain:
RANDOM_KMALLOC_CACHES, kmalloc-cg accounting, SLAB_FREELIST_HARDENED, and LSM confinement all raise the cost of turning this UAF into reliable LPE on shipping enterprise distros. - Role multiplier — desktop / VDI / GPU workstation fleet: chain succeeds and yields root; blast radius is single-host LPE. Not fleet-scale.
- Role multiplier — GPU compute nodes (AI/ML training clusters): chain succeeds; blast radius is the compute node plus any shared model artifacts on it. Notable but still host-scoped, not identity-scoped. Does not trip the CRITICAL floor because DRM is not identity/hypervisor/PAM/backup infrastructure.
- Role multiplier — headless application/database/edge servers: chain fails at step 1 (no DRM device). Zero blast radius.
Why not higher?
No remote vector, no authentication bypass, no identity-plane or supply-chain blast radius, and no active exploitation. HIGH would require either KEV listing, credible public PoC turning this into a common local-priv-esc primitive, or evidence the affected role is broader than assumed.
Why not lower?
It's still a kernel UAF with full CIA impact once triggered — that's a real LPE primitive on any host where a user can reach /dev/dri, including every developer workstation, VDI seat, and GPU node in the fleet. LOW would ignore a legitimate privilege-escalation vector on a meaningful slice of endpoints.
What to do — in priority order.
- Restrict
/dev/dri/*device permissions on servers — On headless hosts, remove thevideoandrendergroups from any service account that doesn't need GPU access, or set the device node mode to0600 root:rootvia a udev rule. Deploy inside the noisgate mitigation window for MEDIUM (no formal SLA — treat as opportunistic hygiene, complete within 30-60 days alongside patching). - Block DRM device passthrough in container runtimes — Audit Kubernetes/Docker/Podman workloads for
--device=/dev/drior equivalentsecurityContext.devices. Enforce a Gatekeeper/Kyverno policy denying DRM device mounts for non-GPU workloads. No mitigation SLA at MEDIUM — bundle into next policy release. - Enable KASAN on staging kernels and watch for repros — If your CI kernel builds run KASAN, add the DRM PRIME test suite to the smoke run. Any oops here is high-signal for internal exploit development.
- Ship distro kernel updates via normal patch cadence — Track your distro vendor's kernel z-stream (Ubuntu USN, RHSA, SUSE-SU, DSA) and land within the noisgate remediation SLA of 365 days for MEDIUM. In practice pick this up in the next monthly patch window — no reason to delay.
- Perimeter firewall / WAF rules — vulnerability is local, network controls are irrelevant.
- Disabling SSH password auth / MFA — doesn't change the fact that any authenticated local user on a GPU-equipped host is in scope.
- EDR signature-based detection — no public exploit exists to write signatures against; behavioral kernel-oops telemetry is what actually helps.
- Kernel Live Patching (kpatch/livepatch/kGraft) — DRM subsystem changes are rarely eligible for live patching; plan for a reboot.
Crowdsourced verification payload.
Run on each target Linux host as root (or via your config-management agent). Invocation: sudo bash check-cve-2026-46215.sh. Compares the running kernel version to the distro's fixed version and checks whether the DRM subsystem is even loaded — hosts without DRM report PATCHED (not applicable).
#!/usr/bin/env bash
# noisgate verifier: CVE-2026-46215 (drm change_handle UAF)
# Output: VULNERABLE / PATCHED / UNKNOWN
set -u
RUNNING_KVER="$(uname -r)"
OS_ID="$(. /etc/os-release 2>/dev/null && echo "$ID")"
OS_VER="$(. /etc/os-release 2>/dev/null && echo "$VERSION_ID")"
# 1) Attack surface check — no DRM device, not applicable
if ! ls /dev/dri/* >/dev/null 2>&1; then
echo "PATCHED (no /dev/dri devices — DRM attack surface not present on $RUNNING_KVER)"
exit 0
fi
# 2) Distro-specific fixed-version table (update as backports land)
# Format: distro:version_id:fixed_kernel_prefix
declare -A FIXED
FIXED[ubuntu:22.04]="5.15.0-118"
FIXED[ubuntu:24.04]="6.8.0-45"
FIXED[rhel:9]="5.14.0-503"
FIXED[rocky:9]="5.14.0-503"
FIXED[almalinux:9]="5.14.0-503"
FIXED[debian:12]="6.1.106"
FIXED[sles:15]="6.4.0-150600.23"
KEY="${OS_ID}:${OS_VER%%.*}"
FIXED_PREFIX="${FIXED[$KEY]:-}"
if [[ -z "$FIXED_PREFIX" ]]; then
echo "UNKNOWN (no fixed-version data for $KEY; running $RUNNING_KVER — consult vendor advisory)"
exit 2
fi
# 3) Version comparison — dpkg/rpm ordering where available
compare_versions() {
# returns 0 if $1 >= $2
if command -v dpkg >/dev/null 2>&1; then
dpkg --compare-versions "$1" ge "$2"
elif command -v rpmdev-vercmp >/dev/null 2>&1; then
[[ "$(rpmdev-vercmp "$1" "$2" 2>&1 | tail -1)" != *"<"* ]]
else
[[ "$(printf '%s\n%s\n' "$2" "$1" | sort -V | tail -1)" == "$1" ]]
fi
}
if compare_versions "$RUNNING_KVER" "$FIXED_PREFIX"; then
echo "PATCHED (running $RUNNING_KVER >= fixed $FIXED_PREFIX on $KEY)"
exit 0
else
echo "VULNERABLE (running $RUNNING_KVER < fixed $FIXED_PREFIX on $KEY; reboot required after kernel update)"
exit 1
fi
If you remember one thing.
/dev/dri. Under the noisgate mitigation SLA for MEDIUM there is no formal mitigation deadline — go straight to the noisgate remediation SLA of ≤365 days, which in reality means picking up your distro's kernel z-stream in the next monthly patch window (30 days) and rebooting on your normal cadence. Prioritize GPU workstations, VDI seats, and AI/ML compute nodes first; deprioritize headless application and database servers; do NOT interrupt change-freeze windows over this one. If a credible PoC appears or KEV listing changes, re-run this assessment.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.