From: Andi Shyti <andi.shyti@linux.intel.com>
To: intel-gfx <intel-gfx@lists.freedesktop.org>,
dri-devel <dri-devel@lists.freedesktop.org>
Cc: Chris Wilson <chris.p.wilson@linux.intel.com>,
Sebastian Brzezinka <sebastian.brzezinka@intel.com>,
Andi Shyti <andi.shyti@kernel.org>,
Shuangpeng Bai <shuangpeng.kernel@gmail.com>,
stable@vger.kernel.org, Andi Shyti <andi.shyti@linux.intel.com>
Subject: [PATCH v2] drm/i915/gt: Fix request use-after-free in heartbeat()
Date: Mon, 31 Aug 2026 00:57:08 +0200 [thread overview]
Message-ID: <20260830225708.3959691-1-andi.shyti@linux.intel.com> (raw)
From: Shuangpeng Bai <shuangpeng.kernel@gmail.com>
heartbeat() detaches engine->heartbeat.systole with xchg() before
checking whether the request has completed. If the request is complete,
dropping the detached systole reference may free it. Concurrently,
idle_pulse() can observe the empty slot and publish a newer request.
The worker then sees a non-NULL engine->heartbeat.systole, but continues
to dereference its stale local rq. The newer request can therefore make
the shared-slot check succeed after the old request has been freed,
causing use-after-free accesses to emitted_jiffies, submit, and sched.
If the detached request is incomplete, heartbeat() can also overwrite a
newer request published by idle_pulse() when it unconditionally restores
the old pointer.
Use cmpxchg() both when idle_pulse() publishes a request and when
heartbeat() restores the detached request. Drop the detached reference
when restoration loses the race, and reload rq from the shared slot
before dereferencing it.
A KASAN-enabled i915 mock selftest reproduces the use-after-free before
this change and completes without a report after the fix.
Fixes: 4c71fd099513 ("drm/i915/gt: fix refcount underflow in intel_engine_park_heartbeat")
Signed-off-by: Shuangpeng Bai <shuangpeng.kernel@gmail.com>
Cc: <stable@vger.kernel.org> # v7.0+
Reviewed-by: Andi Shyti <andi.shyti@linux.intel.com>
Signed-off-by: Andi Shyti <andi.shyti@linux.intel.com>
Link: https://patch.msgid.link/20260808184302.1509585-1-shuangpeng.kernel@gmail.com
---
Hi,
I'm resending Shuangpeng's patch[*] so that it's tested by CI
Andi
https://patchwork.freedesktop.org/patch/745366/?series=171942&rev=1
- Changelog:
v2: Use the correct fix tag
.../gpu/drm/i915/gt/intel_engine_heartbeat.c | 22 ++++++++++++++-----
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c
index 6424ecce8bcb..fc6c53c93cf5 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c
@@ -81,10 +81,18 @@ heartbeat_create(struct intel_context *ce, gfp_t gfp)
static void idle_pulse(struct intel_engine_cs *engine, struct i915_request *rq)
{
+ struct i915_request *systole;
+
engine->wakeref_serial = READ_ONCE(engine->serial) + 1;
i915_request_add_active_barriers(rq);
- if (!engine->heartbeat.systole && intel_engine_has_heartbeat(engine))
- engine->heartbeat.systole = i915_request_get(rq);
+ if (READ_ONCE(engine->heartbeat.systole) ||
+ !intel_engine_has_heartbeat(engine))
+ return;
+
+ systole = i915_request_get(rq);
+ /* The worker may have restored its detached systole in the meantime. */
+ if (cmpxchg(&engine->heartbeat.systole, NULL, systole))
+ i915_request_put(systole);
}
static void heartbeat_commit(struct i915_request *rq,
@@ -152,9 +160,11 @@ static void heartbeat(struct work_struct *wrk)
if (rq) {
if (i915_request_completed(rq))
i915_request_put(rq);
- else
- engine->heartbeat.systole = rq;
+ /* Keep a newer pulse that raced with the detached systole. */
+ else if (cmpxchg(&engine->heartbeat.systole, NULL, rq))
+ i915_request_put(rq);
}
+ rq = READ_ONCE(engine->heartbeat.systole);
if (!intel_engine_pm_get_if_awake(engine))
return;
@@ -163,11 +173,11 @@ static void heartbeat(struct work_struct *wrk)
goto out;
if (i915_sched_engine_disabled(engine->sched_engine)) {
- reset_engine(engine, engine->heartbeat.systole);
+ reset_engine(engine, rq);
goto out;
}
- if (engine->heartbeat.systole) {
+ if (rq) {
long delay = READ_ONCE(engine->props.heartbeat_interval_ms);
/* Safeguard against too-fast worker invocations */
--
2.55.0
next reply other threads:[~2026-08-30 22:57 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-30 22:57 Andi Shyti [this message]
2026-08-30 23:08 ` [PATCH v2] drm/i915/gt: Fix request use-after-free in heartbeat() sashiko-bot
2026-08-30 23:37 ` ✓ i915.CI.BAT: success for drm/i915/gt: Fix request use-after-free in heartbeat() (rev2) Patchwork
2026-08-31 1:36 ` ✗ i915.CI.Full: failure " Patchwork
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260830225708.3959691-1-andi.shyti@linux.intel.com \
--to=andi.shyti@linux.intel.com \
--cc=andi.shyti@kernel.org \
--cc=chris.p.wilson@linux.intel.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=intel-gfx@lists.freedesktop.org \
--cc=sebastian.brzezinka@intel.com \
--cc=shuangpeng.kernel@gmail.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.