ArticlesSecurity Advisories

CVE-2026-46215 (DRM GEM change_handle Use-After-Free) on Rocky Linux and RLC Pro Kernels

cvecve-2026-46215cve-2026-52966cve-2026-53145cve-2026-23149securitykerneldrmgpurender nodeprivilege escalationrocky linuxmitigationtroubleshooting

Stephen Simpson
Customer Support Engineer

Jul 27, 2026

Introduction

CVE-2026-46215 is a local privilege escalation vulnerability in the Linux kernel's DRM (Direct Rendering Manager) subsystem. The DRM_IOCTL_GEM_CHANGE_HANDLE ioctl moves a GEM (Graphics Execution Manager) buffer object to a caller-chosen handle number, and its handler does not reconcile the handle-to-object mapping atomically. The handler allocates the new handle in the IDR (idr_alloc) and removes the old one (idr_remove) in separate steps. In the window between them the object holds two live IDR entries, the old handle and the new one, while its handle_count still reads 1. A DRM_IOCTL_GEM_CLOSE racing on the old handle drops what looks like the last handle reference, decrements handle_count to 0, and frees the object while the surviving new handle still points at it. Any subsequent use of that handle thus is a use-after-free exploit.

A public proof-of-concept and technical writeup are available. The exploit turns the use-after-free into a passwordless root account with a data-only technique that needs no memory-corruption gadgets. It reclaims the freed object into a kmalloc slab sprayed with pipe buffers, leaks a kernel pointer to defeat KASLR, bypasses the Dirty Pipe fix, and overwrites the page cache for /etc/passwd to add a passwordless UID 0 entry.

The scoping detail that matters for CIQ customers is where the vulnerable change_handle ioctl came from. It was introduced upstream in kernel 6.18, and it was also backported into the RHEL 9 and RHEL 10 kernel trees. That produces two exposure routes. The el9_8 and el10_2 backport exposes both the RLC Pro (9 and 10) and the Rocky Linux (9.8 and 10.2) kernels, and CIQ Linux Kernel 6.18 carries the feature natively until it is updated to a build that disables it. Most other CIQ kernels never carried the feature and are not affected. On every affected CIQ kernel the fix disables the ioctl outright (see Status).

This article describes what is affected, the current patch status, how to confirm exposure on a given host, how to install the patched kernel or apply an interim mitigation, and how to verify the result.

Problem

The flaw is reachable through the DRM render node. Both DRM_IOCTL_GEM_CHANGE_HANDLE and DRM_IOCTL_GEM_CLOSE are flagged DRM_RENDER_ALLOW, and drm_ioctl_permit() gates them on nothing else: no DRM master, no DRM_AUTH, no capability. Any process that can open /dev/dri/renderD* can call them. Two consequences are worth calling out during triage.

No graphical session is required. Render-node access is usually granted by systemd-logind on desktops, which is the source of most confusion around this CVE, but the bug is triggered by a plain ioctl() on a render node with no X11, Wayland, compositor, or logged-in graphical session running. The public proof-of-concept runs headless in a QEMU guest with virtio-gpu.

The render node is world-accessible by default. On stock Rocky Linux and RHEL 9/10, 50-udev-default.rules ships /dev/dri/renderD* as GROUP=render MODE=0666, so any local UID can open it. The card* nodes are seat- and uaccess-gated and do need a graphical login, which is why the render node, not card0, is the headless attack path.

The exploitable drivers are those that register GEM plus a render node (DRIVER_GEM | DRIVER_RENDER): virtio_gpu (common in cloud and virtualized guests), and bare-metal GPU drivers such as amdgpu, i915, nouveau, radeon, vmwgfx, and xe. NVIDIA's proprietary stack is a partial carve-out, since the GEM-create path at default modeset=0 is unproven and default CUDA containers expose only /dev/nvidia*.

Because the exposure depends on both an affected kernel and an openable render node, the highest real-world risk is on multi-tenant or shared hosts where untrusted local users can run code: virtualized guests using virtio-gpu, and GPU or AI compute servers where users legitimately hold render-node access.

Treat the following as affected unless running a patched kernel (see Status):

  • RLC Pro 9 and Rocky Linux 9.8, via the RHEL 9 backport
  • RLC Pro 10 and Rocky Linux 10.2, via the RHEL 10 backport
  • CIQ Linux Kernel 6.18, which carries the feature natively (builds older than 6.18.36-1 are affected)

The following CIQ kernels are not affected, because the change_handle feature was never present in them:

  • RLC Pro 8 and RLC Pro LTS 8.6
  • RLC Pro LTS 9.2 and RLC Pro LTS 9.6 (5.14-based, but before the RHEL backport)
  • CIQ Bridge 7.9
  • CIQ Linux Kernel 6.12 (the feature was introduced upstream in 6.18)

Confirming exposure on a specific host

First confirm the running kernel is on an affected line and older than the patched build:

uname -r

An el9_8 build older than 5.14.0-687.29.1, or an el10_2 build older than 6.12.0-211.37.1, is affected, on both RLC Pro (which adds a +2.1...el9_8_ciq or +2.1...el10_2_ciq suffix) and Rocky Linux. A CIQ Linux Kernel 6.18 build older than 6.18.36-1 is also affected. Any other CIQ kernel (LTS 8.6/9.2/9.6, RLC Pro 8, Bridge 7.9, CIQ Linux Kernel 6.12) is not affected by this CVE.

Then check whether a render node exists and which driver backs it, since exposure requires an openable render node bound to an affected driver:

ls -l /dev/dri/
lsmod | grep -E 'virtio_gpu|amdgpu|i915|nouveau|radeon|vmwgfx|^xe'

If there is no renderD* node under /dev/dri/ (common on stock cloud VMs with no GPU, for example default AWS Nitro or Azure hyperv_drm, and on GCP instances with no /dev/dri), the attack path is not present regardless of kernel version. If a renderD* node exists, check its permissions:

stat -c '%n %a %G' /dev/dri/renderD* 2>/dev/null

On a default install this reports mode 666 and group render, meaning any local user can open it. That is the exposed configuration.

Status

  • Patched kernels are available for every affected line: RLC Pro 9 and 10, Rocky Linux 9.8 and 10.2, and CIQ Linux Kernel 6.18. See the Patched Kernels table below for exact versions. On all of them the fix disables the change_handle ioctl by pointing it at drm_invalid_op, so the ioctl now returns -EINVAL instead of running the vulnerable handle swap. Every affected CIQ kernel ships the full five-commit change_handle fix chain that ends in that disable, and there is no variant that keeps the ioctl live behind a narrower race fix.
  • One update clears the whole chain. The change_handle fix chain's RPM changelog names four CVEs: CVE-2026-46215 (the use-after-free), CVE-2026-52966, CVE-2026-53145, and CVE-2026-23149 (a warning-hardening change). The same patched kernel resolves all four, so a scanner citing any of them on an affected line is cleared by the same update.
  • All other CIQ kernels are not affected (the feature is absent), and no action is required on them for this CVE.
  • Recommended action: on any affected host, install the patched kernel and reboot (see Installing the Update). RLC Pro 9/10 and Rocky Linux 9.8/10.2 update via dnf update kernel*, and CIQ Linux Kernel 6.18 hosts update to 6.18.36-1 or newer. If you cannot update immediately, see Mitigation for interim steps.
  • Open a support case if you need help confirming exposure on a specific host or validating a patched kernel against your workload.

Patched Kernels

Variant Patched Kernel Version Released
RLC Pro 9 kernel-5.14.0-687.29.1+2.1.el9_8_ciq 2026-07-24
RLC Pro 10 kernel-6.12.0-211.37.1+2.1.el10_2_ciq 2026-07-25
CIQ Linux Kernel 6.18 6.18.39-1 2026-07-20

For Rocky Linux 9.8 and 10.2, the fixed kernels ship through the Rocky Linux errata. Refer to the Rocky Linux errata for the exact published build.

Confirm what is running on a given system with:

uname -r

If your system reports one of the patched versions above (or newer), the fix is in place and any interim mitigation can be reverted. See Resolution.

Installing the Update

RLC Pro 9 and 10

The patched kernel comes from the CIQ repositories your variant already uses, with no additional setup:

sudo dnf update kernel*
sudo reboot

If your RLC Pro variant draws the kernel from the Core Repo through depot channels, refresh metadata and enable the channel that matches your product before updating:

sudo dnf clean all && sudo dnf makecache
sudo depot enable rlc-pro-9   # use rlc-pro-10 on RLC Pro 10
sudo dnf update kernel*
sudo reboot

CIQ Linux Kernel 6.18

Update to 6.18.36-1 or newer through your configured CLK repository, then reboot. Any 6.18 build from 6.18.36-1 onward carries the fix:

sudo dnf update kernel*
sudo reboot

Rocky Linux (Community)

On Rocky Linux 9.8 and 10.2, the fixed kernel ships through the Rocky Linux errata in the standard BaseOS repository, with no additional configuration:

sudo dnf update kernel*
sudo reboot

Mitigation

Warning: The steps below are interim measures for hosts that cannot be patched immediately. Each one trades off GPU or display functionality. The fix is the patched kernel in Installing the Update. Test in a non-production environment before applying fleet-wide, and revert once the patched kernel is installed.

The exposure requires an unprivileged user to open a render node bound to an affected driver. The two options below each remove one side of that condition. Pick based on whether the host actually needs GPU or display functionality.

Option 1: Restrict access to the render node

By default /dev/dri/renderD* is world read/write (0666). Restricting it to the render group removes access from arbitrary local UIDs while leaving GPU access intact for accounts you place in that group. This does not fix the kernel bug; it narrows who can reach it. Use this on hosts that use the GPU only through specific accounts.

Step 1: install the udev rule.

cat <<'EOF' | sudo tee /etc/udev/rules.d/99-cve-2026-46215.rules
# Interim CVE-2026-46215 mitigation: remove world access to DRM render nodes
SUBSYSTEM=="drm", KERNEL=="renderD*", GROUP="render", MODE="0660"
EOF
sudo udevadm control --reload-rules
sudo udevadm trigger --subsystem-match=drm

Step 2: confirm the new mode and grant access to the accounts that need it.

stat -c '%n %a %G' /dev/dri/renderD*
# e.g. usermod -aG render <account>   # for a service account that runs GPU/compute work

This leaves the flaw reachable by members of the render group, so it only helps where those members are trusted. On a host where every local user must have render access, this option provides no protection; use Option 2 or patch instead.

Option 2: Block the affected driver module

On a headless VM or server that does not need a display or GPU compute, preventing the affected driver from loading removes the render node entirely. The most common case is virtio_gpu on a virtualized guest with no graphical workload.

Warning: Blocking the driver removes the GPU/DRM device. On a guest that uses virtio-gpu for its console this can affect the graphical console. Only apply where the host is genuinely headless and does not need the device. Do not use this option on GPU or AI compute nodes, since it removes the functionality they exist to provide.

Step 1: install the modprobe override.

# Replace virtio_gpu with the driver reported by the lsmod check above if different
echo "install virtio_gpu /bin/false" | sudo tee /etc/modprobe.d/cve-2026-46215.conf

Step 2: clear any resident copy of the module.

If the module is already loaded and not in use, unload it so the override takes effect immediately:

sudo rmmod virtio_gpu

If rmmod reports the module is in use, something is actively using the GPU or console framebuffer. Do not force the unload on a production host; schedule the change for a maintenance window, or install the patched kernel instead.

Verification

Use these checks to confirm an interim mitigation is active. For confirming the patched kernel is running, see Resolution.

After applying Option 1 (render node permissions)

stat -c '%n %a %G' /dev/dri/renderD*

The mode should read 660, not 666. Any local user outside the render group can no longer open the node.

After applying Option 2 (driver block)

Confirm the module is not loaded:

lsmod | grep virtio_gpu

No output means the module is not currently loaded. Confirm the modprobe override is in place:

sudo modprobe -n -v virtio_gpu

This should print install /bin/false. If it resolves to a .ko path, re-check /etc/modprobe.d/cve-2026-46215.conf and confirm it is present and readable. If the module still appears in lsmod after a reboot, the override is not catching the early boot load path; confirm the conf file is present and readable, rebuild the initramfs to include the modprobe config, and reboot again.

Resolution

After installing the patched kernel and rebooting, confirm the running kernel matches a patched version from the Patched Kernels table:

uname -r

If your system reports one of the patched versions (or newer), the fix is in place.

The one behavior change the fix introduces is that DRM_IOCTL_GEM_CHANGE_HANDLE now returns -EINVAL instead of running. The ioctl was added for a niche checkpoint/restore path and has no real userspace consumers, so the impact is negligible. Normal GPU, compute, and display workloads are unaffected.

If you applied either mitigation, revert it once the patched kernel is running:

# Revert Option 1 (render node permissions)
sudo rm /etc/udev/rules.d/99-cve-2026-46215.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --subsystem-match=drm

# Revert Option 2 (driver block)
sudo rm /etc/modprobe.d/cve-2026-46215.conf
sudo modprobe virtio_gpu   # or the driver you blocked

Notes

  • Scanner hits. A vulnerability scanner flagging the kernel on an affected line (RLC Pro 9/10, Rocky Linux 9.8/10.2, or CIQ Linux Kernel 6.18 older than 6.18.36-1) is accurate. A scanner may cite any of the four CVEs the fix chain carries, CVE-2026-46215, CVE-2026-52966, CVE-2026-53145, or CVE-2026-23149, and the same patched kernel resolves all four. Real-world risk is highest where untrusted local users can run code and a render node is present and openable: virtio-gpu guests, shared GPU/AI compute nodes, CI runners. A host with no /dev/dri/renderD* node has no attack path here even on an affected kernel.
  • Backport versus native. The affected 5.14 (el9_8) and 6.12 (el10_2) kernels are vulnerable because the change_handle feature was backported into them, not because of their base version. That is why RLC Pro LTS 9.2 and 9.6 (also 5.14-based) and CIQ Linux Kernel 6.12 are not affected; they never received the backport. CIQ Linux Kernel 6.18 is the exception, since it carries the feature natively because change_handle was introduced upstream in 6.18.
  • Not a display-only issue. The exploit does not need a desktop, compositor, or graphical login. Assume any affected host with an openable render node and local users is reachable.
  • The mitigations are interim. Install the patched kernel and revert the workaround as soon as the build is applied.