dri-devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/2] drm/sched: fix use-after-free of the fence timeline name
@ 2026-09-02 14:42 Jonghyuk Kim(MalHyuk)
  2026-09-02 14:42 ` [PATCH v3 1/2] " Jonghyuk Kim(MalHyuk)
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Jonghyuk Kim(MalHyuk) @ 2026-09-02 14:42 UTC (permalink / raw)
  To: tursulin, phasta, matthew.brost, dakr
  Cc: christian.koenig, dri-devel, linux-kernel, Jonghyuk Kim(MalHyuk)

drm_sched_fence_get_timeline_name() dereferences fence->sched->name. A
driver that allocates a drm_gpu_scheduler per context, queue or VM frees
that scheduler on context teardown, but the finished fence can outlive it:
unprivileged userspace holds the exported fence via a sync_file or
drm_syncobj and later queries its timeline name (e.g. SYNC_IOC_FILE_INFO),
reading the freed scheduler. Same class as CVE-2025-38703 (drm/xe) and
CVE-2025-71302 (drm/panthor); amdxdna, nouveau and msm (VM_BIND) are still
affected in mainline.

This series fixes it in the core rather than per driver.

v1 and v2 took the approach of caching the name at fence init. Review showed
that is the wrong fix:

 - Tvrtko pointed out the documented contract does not require the name
   passed to drm_sched_init() to outlive the scheduler, so caching the bare
   pointer only narrows the window; and

 - the sashiko review bot pointed out that caching does not help drivers
   whose timeline name is dynamically allocated and freed with the queue
   (drm/panthor, drm/xe) - it just moves the UAF to the string's lifetime.

Philipp suggested dropping the finished fence's ->release callback instead.
That is what this series does. dma_fence detaches a fence's ops on signalling
when it has neither .release nor .wait (dma_fence_signal_timestamp_locked()),
and dma_fence_timeline_name() returns a static string once the ops are gone.
So with the callback removed, get_timeline_name() is simply never reached on
a signalled finished fence - no ->sched dereference at all, for static and
dynamically-allocated names alike. The finished fence's only job in that
callback was to drop the scheduled fence's reference, which patch 1 moves
elsewhere.

Link to v2 (name caching):
https://lore.kernel.org/dri-devel/20260902105808.1541063-1-malhyuk97@gmail.com/

Note: detaching the finished fence's ops on signalling also makes
to_drm_sched_fence() return NULL for a signalled finished fence. Callers
already handle NULL (the normal foreign-fence result), a signalled fence is
an already-satisfied dependency so the scheduler's dependency collapsing is
unaffected, and it avoids the container_of() on a possibly-freed foreign
scheduler that amdgpu_sync_same_dev() and pvr_queue_fence_is_native() would
otherwise do. Flagging it explicitly since it touches an exported helper.

I did not add Fixes:/Cc: stable tags: the ->sched->name deref dates back to
1b1f42d8fde4 ("drm: move amd_gpu_scheduler into common location") but only
became reachable once drivers began allocating per-context schedulers, so
the right attribution is unclear to me. This is stable material as the
driver instances are live - happy to add whatever tags you prefer.

Tested with KUnit under KASAN (kunit.py --arch=x86_64), matched pair:

  - unfixed (finished fence keeps .release):
      [FAILED] drm_sched_dma_fence_uaf
      BUG: KASAN: slab-use-after-free in
          drm_sched_fence_get_timeline_name+0x9c/0xb0
      Read of size 8 ...
  - fixed (this series):
      [PASSED] drm_sched_dma_fence_uaf
      Testing complete. Ran 47 tests: passed: 47

(The whole drm_sched suite passes with the series, no regressions.)

v3:
 - Switch from caching the timeline name (v1/v2) to dropping the finished
   fence's ->release so the ops are detached on signalling (per Philipp);
   also fixes the dynamically-allocated-name drivers caching could not.
 - Rework the scheduled/finished fence lifetime: the scheduled fence now
   holds a reference on the finished fence, which is released last and freed
   from dma_fence_free(); @finished moved to offset 0. drm_sched_job_cleanup()
   drops the scheduled fence's initial reference.
 - Move the regression test to a new tests_integration.c and query via
   dma_fence_timeline_name() (per Tvrtko's review of v2).

Jonghyuk Kim(MalHyuk) (2):
  drm/sched: fix use-after-free of the fence timeline name
  drm/sched/tests: add a UAF regression test for the timeline name

 drivers/gpu/drm/scheduler/sched_fence.c       | 46 +++++-----
 drivers/gpu/drm/scheduler/sched_main.c        |  9 ++
 drivers/gpu/drm/scheduler/tests/Makefile      |  1 +
 .../drm/scheduler/tests/tests_integration.c   | 92 +++++++++++++++++++
 include/drm/gpu_scheduler.h                   | 22 +++--
 5 files changed, 139 insertions(+), 31 deletions(-)
 create mode 100644 drivers/gpu/drm/scheduler/tests/tests_integration.c

--
2.43.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2026-09-03 10:22 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-02 14:42 [PATCH v3 0/2] drm/sched: fix use-after-free of the fence timeline name Jonghyuk Kim(MalHyuk)
2026-09-02 14:42 ` [PATCH v3 1/2] " Jonghyuk Kim(MalHyuk)
2026-09-02 14:58   ` sashiko-bot
2026-09-03  8:46   ` Philipp Stanner
2026-09-03 10:02     ` Christian König
2026-09-03 10:22     ` Christian König
2026-09-02 14:42 ` [PATCH v3 2/2] drm/sched/tests: add a UAF regression test for the " Jonghyuk Kim(MalHyuk)
2026-09-02 15:04   ` sashiko-bot
2026-09-02 16:09 ` [PATCH v3 0/2] drm/sched: fix use-after-free of the fence " Philipp Stanner
2026-09-02 17:25   ` Philipp Stanner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox