Skip to main content

Linux Kernel EUVD-2026-25549

| CVE-2026-31656 HIGH
Integer Underflow (CWE-191)
2026-04-24 Linux GHSA-4j69-96h5-q8g9
7.8
CVSS 3.1
Share

CVSS VectorNVD

CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Attack Vector
Local
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
High

Lifecycle Timeline

8
Re-analysis Queued
Apr 27, 2026 - 20:22 vuln.today
cvss_changed
Patch released
Apr 27, 2026 - 20:16 nvd
Patch available
Analysis Generated
Apr 27, 2026 - 15:41 vuln.today
CVSS changed
Apr 27, 2026 - 15:22 NVD
7.8 (HIGH)
Patch available
Apr 24, 2026 - 16:16 EUVD
EUVD ID Assigned
Apr 24, 2026 - 15:00 euvd
EUVD-2026-25549
Analysis Generated
Apr 24, 2026 - 15:00 vuln.today
CVE Published
Apr 24, 2026 - 14:45 nvd
HIGH 7.8

DescriptionNVD

In the Linux kernel, the following vulnerability has been resolved:

drm/i915/gt: fix refcount underflow in intel_engine_park_heartbeat

A use-after-free / refcount underflow is possible when the heartbeat worker and intel_engine_park_heartbeat() race to release the same engine->heartbeat.systole request.

The heartbeat worker reads engine->heartbeat.systole and calls i915_request_put() on it when the request is complete, but clears the pointer in a separate, non-atomic step. Concurrently, a request retirement on another CPU can drop the engine wakeref to zero, triggering __engine_park() -> intel_engine_park_heartbeat(). If the heartbeat timer is pending at that point, cancel_delayed_work() returns true and intel_engine_park_heartbeat() reads the stale non-NULL systole pointer and calls i915_request_put() on it again, causing a refcount underflow:

<4> [487.221889] Workqueue: i915-unordered engine_retire [i915]
<4> [487.222640] RIP: 0010:refcount_warn_saturate+0x68/0xb0
...
<4> [487.222707] Call Trace:
<4> [487.222711]  <TASK>
<4> [487.222716]  intel_engine_park_heartbeat.part.0+0x6f/0x80 [i915]
<4> [487.223115]  intel_engine_park_heartbeat+0x25/0x40 [i915]
<4> [487.223566]  __engine_park+0xb9/0x650 [i915]
<4> [487.223973]  ____intel_wakeref_put_last+0x2e/0xb0 [i915]
<4> [487.224408]  __intel_wakeref_put_last+0x72/0x90 [i915]
<4> [487.224797]  intel_context_exit_engine+0x7c/0x80 [i915]
<4> [487.225238]  intel_context_exit+0xf1/0x1b0 [i915]
<4> [487.225695]  i915_request_retire.part.0+0x1b9/0x530 [i915]
<4> [487.226178]  i915_request_retire+0x1c/0x40 [i915]
<4> [487.226625]  engine_retire+0x122/0x180 [i915]
<4> [487.227037]  process_one_work+0x239/0x760
<4> [487.227060]  worker_thread+0x200/0x3f0
<4> [487.227068]  ? __pfx_worker_thread+0x10/0x10
<4> [487.227075]  kthread+0x10d/0x150
<4> [487.227083]  ? __pfx_kthread+0x10/0x10
<4> [487.227092]  ret_from_fork+0x3d4/0x480
<4> [487.227099]  ? __pfx_kthread+0x10/0x10
<4> [487.227107]  ret_from_fork_asm+0x1a/0x30
<4> [487.227141]  </TASK>

Fix this by replacing the non-atomic pointer read + separate clear with xchg() in both racing paths. xchg() is a single indivisible hardware instruction that atomically reads the old pointer and writes NULL. This guarantees only one of the two concurrent callers obtains the non-NULL pointer and performs the put, the other gets NULL and skips it.

(cherry picked from commit 13238dc0ee4f9ab8dafa2cca7295736191ae2f42)

AnalysisAI

Local privilege escalation in the Linux kernel's i915 graphics driver allows authenticated users to trigger a use-after-free condition via a race between the heartbeat worker and intel_engine_park_heartbeat() function when releasing engine heartbeat requests. The vulnerability stems from a non-atomic pointer read-and-clear operation that permits double-free of the same request object, causing refcount underflow and potential arbitrary code execution with elevated privileges. …

Sign in for full analysis, threat intelligence, and remediation guidance.

Vendor StatusVendor

Share

EUVD-2026-25549 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy