Skip to content

Commit 69bbe3a

Browse files
matt-auldlucasdemarchi
authored andcommitted
drm/xe/client: add missing bo locking in show_meminfo()
bo_meminfo() wants to inspect bo state like tt and the ttm resource, however this state can change at any point leading to stuff like NPD and UAF, if the bo lock is not held. Grab the bo lock when calling bo_meminfo(), ensuring we drop any spinlocks first. In the case of object_idr we now also need to hold a ref. v2 (MattB) - Also add xe_bo_assert_held() Fixes: 0845233 ("drm/xe: Implement fdinfo memory stats printing") Signed-off-by: Matthew Auld <[email protected]> Cc: Himal Prasad Ghimiray <[email protected]> Cc: Tejas Upadhyay <[email protected]> Cc: "Thomas Hellström" <[email protected]> Cc: <[email protected]> # v6.8+ Reviewed-by: Matthew Brost <[email protected]> Reviewed-by: Tejas Upadhyay <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] (cherry picked from commit 4f63d71) Signed-off-by: Lucas De Marchi <[email protected]>
1 parent 99b1f74 commit 69bbe3a

File tree

1 file changed

+36
-3
lines changed

1 file changed

+36
-3
lines changed

drivers/gpu/drm/xe/xe_drm_client.c

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/slab.h>
1111
#include <linux/types.h>
1212

13+
#include "xe_assert.h"
1314
#include "xe_bo.h"
1415
#include "xe_bo_types.h"
1516
#include "xe_device_types.h"
@@ -151,10 +152,13 @@ void xe_drm_client_add_bo(struct xe_drm_client *client,
151152
*/
152153
void xe_drm_client_remove_bo(struct xe_bo *bo)
153154
{
155+
struct xe_device *xe = ttm_to_xe_device(bo->ttm.bdev);
154156
struct xe_drm_client *client = bo->client;
155157

158+
xe_assert(xe, !kref_read(&bo->ttm.base.refcount));
159+
156160
spin_lock(&client->bos_lock);
157-
list_del(&bo->client_link);
161+
list_del_init(&bo->client_link);
158162
spin_unlock(&client->bos_lock);
159163

160164
xe_drm_client_put(client);
@@ -166,6 +170,8 @@ static void bo_meminfo(struct xe_bo *bo,
166170
u64 sz = bo->size;
167171
u32 mem_type;
168172

173+
xe_bo_assert_held(bo);
174+
169175
if (bo->placement.placement)
170176
mem_type = bo->placement.placement->mem_type;
171177
else
@@ -207,7 +213,20 @@ static void show_meminfo(struct drm_printer *p, struct drm_file *file)
207213
idr_for_each_entry(&file->object_idr, obj, id) {
208214
struct xe_bo *bo = gem_to_xe_bo(obj);
209215

210-
bo_meminfo(bo, stats);
216+
if (dma_resv_trylock(bo->ttm.base.resv)) {
217+
bo_meminfo(bo, stats);
218+
xe_bo_unlock(bo);
219+
} else {
220+
xe_bo_get(bo);
221+
spin_unlock(&file->table_lock);
222+
223+
xe_bo_lock(bo, false);
224+
bo_meminfo(bo, stats);
225+
xe_bo_unlock(bo);
226+
227+
xe_bo_put(bo);
228+
spin_lock(&file->table_lock);
229+
}
211230
}
212231
spin_unlock(&file->table_lock);
213232

@@ -217,7 +236,21 @@ static void show_meminfo(struct drm_printer *p, struct drm_file *file)
217236
if (!kref_get_unless_zero(&bo->ttm.base.refcount))
218237
continue;
219238

220-
bo_meminfo(bo, stats);
239+
if (dma_resv_trylock(bo->ttm.base.resv)) {
240+
bo_meminfo(bo, stats);
241+
xe_bo_unlock(bo);
242+
} else {
243+
spin_unlock(&client->bos_lock);
244+
245+
xe_bo_lock(bo, false);
246+
bo_meminfo(bo, stats);
247+
xe_bo_unlock(bo);
248+
249+
spin_lock(&client->bos_lock);
250+
/* The bo ref will prevent this bo from being removed from the list */
251+
xe_assert(xef->xe, !list_empty(&bo->client_link));
252+
}
253+
221254
xe_bo_put_deferred(bo, &deferred);
222255
}
223256
spin_unlock(&client->bos_lock);

0 commit comments

Comments
 (0)