DF-4927 / fix.diff
Port of upstream Linux commit 0381ac3ca2e7 ("drm/radeon: Initialize fences array entries in radeon_sa_bo_next_hole", Xiaohui Zhang 2022, amdgpu twin 6a15f3ff19a8) to DragonFly's sys/dev/drm/radeon/radeon_sa.c. Without the per-scan `fences[i] = NULL` initialization, a fence pointer borrowed (uncounted) by one radeon_sa_bo_next_hole() call can be freed by a later radeon_sa_bo_try_free()/next_hole() call on the same thread once the GPU signals it, leaving a dangling pointer that radeon_sa_bo_new() then feeds to radeon_fence_ref() (UAF write), radeon_fence_wait_any() (UAF read) and radeon_fence_unref() (double free). Validated on the line-faithful userspace port in this evidence pack: baseline reproduces the UAF/double-free sequence deterministically, --- a/sys/dev/drm/radeon/radeon_sa.c +++ b/sys/dev/drm/radeon/radeon_sa.c @@ -267,6 +267,8 @@ for (i = 0; i < RADEON_NUM_RINGS; ++i) { struct radeon_sa_bo *sa_bo; + fences[i] = NULL; + if (list_empty(&sa_manager->flist[i])) { continue; } @@ -332,10 +334,8 @@ lockmgr(&sa_manager->wq.lock, LK_EXCLUSIVE); do { - for (i = 0; i < RADEON_NUM_RINGS; ++i) { - fences[i] = NULL; + for (i = 0; i < RADEON_NUM_RINGS; ++i) tries[i] = 0; - } do { radeon_sa_bo_try_free(sa_manager); |