CVE-2026-98919
UnknownSummary
In the Linux kernel, a vulnerability was fixed in the drm/xe component's adjust_idledly() function, which failed to handle corner cases. When xe_gt_clock_init() fails to recognize the crystal clock, timestamp_base is 0, leading to a divide-by-zero and kernel panic. Additionally, u32 tick-to-ns conversions can overflow, and incorrect rounding can program a delay value greater than or equal to maxcnt, triggering warnings on every initialization.
Risk Assessment
The vulnerability can cause a kernel panic (denial of service) on systems with Intel graphics cards supported by the drm/xe driver, especially when the crystal clock is not recognized. This may result in system or service unavailability.
Recommendation
Update the Linux kernel to a version containing the fix (commit d864065ea25e9d12897c175de9176ce46677e176 or later). If updating is not possible, consider limiting the use of the drm/xe driver or monitoring systems for kernel panics related to this driver.
Other vulnerabilities in Linux kernel drm/xe
See all- CVE-2025-68802Unknown
A vulnerability was found in the Linux kernel drm/xe component where the exec and vm_bind ioctls do not bound the num_syncs value. Userspace can specify an arbitrarily large num_syncs, forcing an excessively large allocation and triggering kernel page allocator warnings. The fix introduces DRM_XE_MAX_SYNCS (1024) and rejects requests exceeding this limit.
- CVE-2026-98999High
In the Linux kernel's drm/xe subsystem, a stale pinned_link entry is left when framebuffer pinning performs the final unpin. This leaves a list entry pointing into freed memory, risking list corruption and a use-after-free on subsequent list walks or splices.
- CVE-2026-98310Low risk· EPSS 5%
In the Linux kernel's drm/xe/shrinker component, a bug was found where __xe_shrinker_walk() walks the SYSTEM and TT LRUs without a runtime PM reference. Shrinking a buffer object outside system memory invalidates its GPU mappings, which requires the device to be resumed — while runtime suspended this trips an assertion warning and the TLB invalidation returns -ENODEV.
- CVE-2026-97620Low risk· EPSS 9%
In the Linux kernel, the drm/xe driver's emit_render_cache_flush() did not request a flush of the LSC untyped L1 dataport cache before releasing memory for reuse. Starting with MTL, the coupling between HDC Pipeline Flush and the untyped L1 cache flush no longer holds reliably, potentially allowing stale data to leak. The fix explicitly sets PIPE_CONTROL0_UNTYPED_DATAPORT_CACHE_FLUSH on Xe2 and later platforms.
- CVE-2026-90047High
A bug in the Linux kernel's drm/xe component caused get_flat_ccs_offset() to round the end of usable VRAM upwards, exposing memory belonging to the hardware compression (flat CCS) region to the VRAM allocator as free memory. The compression hardware then overwrote data in that area without the driver's knowledge, corrupting page tables and hanging the compositor (black screen). The issue primarily affects Intel Battlemage G21 hardware.
Original NVD description (English source)
In the Linux kernel, the following vulnerability has been resolved: drm/xe: harden adjust_idledly() against divide-by-zero and overflow adjust_idledly() has several corner-case issues flagged during review: 1. If xe_gt_clock_init() failed to recognise the crystal clock, gt->info.timestamp_base is 0, which makes idledly_units_ps also 0. The subsequent DIV_ROUND_CLOSEST(..., idledly_units_ps) is then a divide-by-zero and panics the kernel. 2. The tick-to-ns conversions are done in u32: idledly * idledly_units_ps, (maxcnt - 1) * 1000 Both overflow u32 before DIV_ROUND_CLOSEST() sees them. 3. If IDLE_WAIT_TIME reads back as 0, maxcnt evaluates to 0 and the maxcnt - 1 clamp wraps to 0xFFFFFFFF in u32. 4. The register only stores whole ticks, so the clamped ns value has to be converted to ticks and back. DIV_ROUND_CLOSEST() can round that conversion up past maxcnt: maxcnt = 640 ns, one tick = 666664 ps clamp: maxcnt - 1 = 639 ns ns -> ticks: 639000 / 666664 = 0.958 -> rounds to 1 tick tick -> ns: 1 * 666664 / 1000 = 667 ns 667 ns is programmed into RING_IDLEDLY, but 667 >= maxcnt (640), so xe_gt_WARN_ON() fires again on every subsequent init. Return early if timestamp_base is 0 (the unknown-crystal path). Do the conversions in u64 via the *_ULL() helpers so they cannot wrap. Clamp with a floor (DIV_ROUND_DOWN_ULL) so the programmed delay stays strictly below maxcnt, and guard the maxcnt == 0 case with a zero delay while still writing RING_IDLEDLY so INHIBIT_SWITCH_UNTIL_PREEMPTED is cleared. v2: Drop the redundant warn on the timestamp_base == 0 path; xe_gt_clock_init() already warns on an unrecognised crystal clock. Keep the early return to avoid the divide-by-zero. - Vinay v3: Field-mask the RING_IDLEDLY write with REG_FIELD_PREP(IDLE_DELAY, ...) instead of writing the raw tick count, which could clobber INHIBIT_SWITCH_UNTIL_PREEMPTED and reserved bits. Split the inhibit-switch clear from the maxcnt clamp so a set inhibit bit no longer forces a needless delay overwrite when the delay itself is already valid. Use gt_to_xe(gt) instead of gt_to_xe(hwe->gt). (cherry picked from commit d864065ea25e9d12897c175de9176ce46677e176)
Vulnerability data from NVD (NIST) · CISA KEV · EPSS

