radeon_sa_bo_manager_fini manipulates SA lists without holding wq.lock (race condition / potential UAF)
- File:
sys/dev/drm/radeon/radeon_sa.c - Lines: 82β91 (manager_fini without lock); cf. locked paths at 333, 386, 405
- Severity: Low
- CVSS 3.1:
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U:C:N/I:N/A:H - CWE: CWE-362 Concurrent Execution using Shared Resource with Improper Synchronization (Race Condition)
- Confidence: likely
- Status: new
Summary
radeon_sa_bo_manager_fini calls radeon_sa_bo_try_free and iterates
sa_manager->olist calling radeon_sa_bo_remove_locked without acquiring
sa_manager->wq.lock.
Every other function in this file that touches the olist/flist/hole
(radeon_sa_bo_new at line 333, radeon_sa_bo_free at line 386,
radeon_sa_bo_dump_debug_info at line 405) properly acquires the lock first.
If manager_fini races with a concurrent allocator operation, the lockless
list traversal and node removal can corrupt the list, leading to use-after-free
or double-free.
Root cause
At radeon_sa.c:82-91, radeon_sa_bo_manager_fini does:
(void) line 84: calls radeon_sa_bo_try_free(sa_manager)
-- which reads/modifies sa_manager->hole, iterates olist,
calls radeon_sa_bo_remove_locked
lines 89-91: list_for_each_entry_safe over sa_manager->olist calling
radeon_sa_bo_remove_locked
-- which does list_del_init on both olist and flist,
reads/modifies sa_manager->hole, and calls radeon_fence_unref
None of these operations are protected by
lockmgr(&sa_manager->wq.lock, LK_EXCLUSIVE).
Contrast with radeon_sa_bo_new:333, radeon_sa_bo_free:386, and
radeon_sa_bo_dump_debug_info:405 which all acquire the lock before touching
the same data structures.
Threat model
Attacker position: local user who can trigger a GPU reset (e.g., by submitting a malicious command stream that causes a GPU lockup) while concurrent CS submissions are in flight.
radeon_ib_pool_fini (radeon_ib.c:238-245) calls
radeon_sa_bo_manager_fini from ASIC hw_fini/suspend functions during GPU
reset or device teardown.
If a CS submission thread is simultaneously inside radeon_sa_bo_new or
radeon_sa_bo_free (holding wq.lock and manipulating the lists), the
lockless traversal in manager_fini can dereference a freed sa_bo node or
corrupt list pointers.
This is a narrow race requiring precise timing during GPU reset, hence Low severity.
Proof of concept
Difficult to reliably exploit due to narrow timing window during GPU reset. The attack would involve:
- Thread A: submit a continuous stream of
DRM_IOCTL_RADEON_CScalls to keep the SA allocator busy. - Thread B: submit a malicious IB that triggers a GPU lockup, causing
radeon_gpu_resetto callhw_fini β radeon_ib_pool_fini β radeon_sa_bo_manager_fini. - If
manager_fini's lockless list traversal overlaps with Thread A's locked list manipulation inradeon_sa_bo_new, list corruption occurs.
Success: kernel panic from corrupted list pointers (e.g., page fault
dereferencing a poisoned list_head). This is a reliability/DoS issue rather
than a controlled exploitation primitive.
Recommended fix
Acquire sa_manager->wq.lock before performing list operations in
radeon_sa_bo_manager_fini, consistent with every other function in the file.
--- a/sys/dev/drm/radeon/radeon_sa.c
+++ b/sys/dev/drm/radeon/radeon_sa.c
@@ -77,11 +77,14 @@ void radeon_sa_bo_manager_fini(struct radeon_device *rdev,
struct radeon_sa_bo *sa_bo, *tmp;
+ lockmgr(&sa_manager->wq.lock, LK_EXCLUSIVE);
if (!list_empty(&sa_manager->olist)) {
sa_manager->hole = &sa_manager->olist,
radeon_sa_bo_try_free(sa_manager);
if (!list_empty(&sa_manager->olist)) {
dev_err(rdev->dev, "sa_manager is not empty, clearing anyway\n");
}
}
list_for_each_entry_safe(sa_bo, tmp, &sa_manager->olist, olist) {
radeon_sa_bo_remove_locked(sa_bo);
}
+ lockmgr(&sa_manager->wq.lock, LK_RELEASE);
radeon_bo_unref(&sa_manager->bo);
sa_manager->size = 0;
References
sys/dev/drm/radeon/radeon_sa.c:77-91βradeon_sa_bo_manager_finiwithout locksys/dev/drm/radeon/radeon_sa.c:333,386,405β sibling functions that correctly acquire locksys/dev/drm/radeon/radeon_ib.c:238-245β caller during GPU reset / device teardown
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1988 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| VERDICT.md | verdict | Source verification narrative | 1.2 KB | β raw |
| fix.diff | suggested-fix | Fix: Acquire sa_manager->wq.lock before list operations; release at end. | 570 B | view raw |
| build.sh | build-script | Build/validation instructions | 366 B | view raw |
| run.sh | run-script | Run instructions (HW-gated, source-only) | 184 B | view raw |
| env.txt | environment | Guest environment | 404 B | view raw |
DF-1988 - Source Verification
Verdict: REPRODUCED (source-only confirmation)
Finding: sys/dev/drm/radeon/radeon_sa.c:82-91
Mechanism: radeon_sa_bo_manager_fini manipulates sa_manager->olist and calls radeon_sa_bo_try_free/list_for_each_entry_safe WITHOUT acquiring sa_manager->wq.lock. Race with concurrent allocator β UAF/list corruption.
Hardware dependency: Requires radeon GPU with SA bo manager.
Fix: Acquire sa_manager->wq.lock before list operations; release at end.
Verification method
Source-only confirmation. The cited code path was traced line-by-line in the audited sys/ tree. The bug exists exactly as described. This is a HW-gated driver finding β the vulnerable code path requires specific hardware (GPU, controller, PHY, TPM, etc.) not present in the QEMU audit guest. Runtime reproduction on this guest is not possible without the hardware.
Fix validation
fix.diff authored and applied to guest source. All 40 fixes in this batch
compile cleanly in a single combined kernel build: make -j6 nativekernel
KERNCONF=X86_64_GENERIC β rc=0, zero -Werror violations.
Kernel: DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026
Fix verification
not_testablenot_testable: HW-gated. fix.diff applies + compiles in batch build (rc=0 -Werror). Source trace confirms fix closes the path.
Batch build: 40 fix.diffs applied, make nativekernel β rc=0 -Werror. Bug at sys/dev/drm/radeon/radeon_sa.c:82-91 source-confirmed.
Confirmed kernel references
- s
- y
- s
- /
- d
- e
- v
- /
- d
- r
- m
- /
- r
- a
- d
- e
- o
- n
- /
- r
- a
- d
- e
- o
- n
- _
- s
- a
- .
- c
- :
- 8
- 2
- -
- 9
- 1
Detail
Exploit chain
none
Evidence (decisive lines)
Source trace sys/dev/drm/radeon/radeon_sa.c:82-91. HW-gated (no HW in QEMU). Fix compiles in batch build rc=0.
PoC changes
Evidence pack: VERDICT.md, fix.diff, manifest.json. Fix: manager_fini without wq.lock β race UAF. Acquire lock.
Verified recommended fix
See fix.diff. manager_fini without wq.lock β race UAF. Acquire lock.
Verdict
REPRODUCED (source-only). sys/dev/drm/radeon/radeon_sa.c:82-91: manager_fini without wq.lock β race UAF. Acquire lock.
No comments yet.