From f401599f79a3678dd66407cb0d112e03dd949467 Mon Sep 17 00:00:00 2001 From: Asahi Lina Date: Wed, 21 Dec 2022 17:25:09 +0900 Subject: [PATCH] vc4: Fix race condition in BO imports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When importing a BO, if it is already imported, then the handle will alias an existing BO instance. It is possible for the existing owner to free the BO after the import and leave a dangling handle before we get a chance to increase the refcount, so we need to lock the BO table mutex before importing, to make sure nobody else goes through the free path during that window. Reviewed-by: Alejandro PiƱeiro Signed-off-by: Asahi Lina Part-of: --- src/gallium/drivers/vc4/vc4_bufmgr.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/gallium/drivers/vc4/vc4_bufmgr.c b/src/gallium/drivers/vc4/vc4_bufmgr.c index 7a366caf6a1..7c1195e3ff3 100644 --- a/src/gallium/drivers/vc4/vc4_bufmgr.c +++ b/src/gallium/drivers/vc4/vc4_bufmgr.c @@ -382,9 +382,11 @@ vc4_bo_open_handle(struct vc4_screen *screen, { struct vc4_bo *bo; - assert(size); + /* Note: the caller is responsible for locking screen->bo_handles_mutex. + * This allows the lock to cover the actual BO import, avoiding a race. + */ - mtx_lock(&screen->bo_handles_mutex); + assert(size); bo = util_hash_table_get(screen->bo_handles, (void*)(uintptr_t)handle); if (bo) { @@ -418,10 +420,14 @@ vc4_bo_open_name(struct vc4_screen *screen, uint32_t name) struct drm_gem_open o = { .name = name }; + + mtx_lock(&screen->bo_handles_mutex); + int ret = vc4_ioctl(screen->fd, DRM_IOCTL_GEM_OPEN, &o); if (ret) { fprintf(stderr, "Failed to open bo %d: %s\n", name, strerror(errno)); + mtx_unlock(&screen->bo_handles_mutex); return NULL; } @@ -432,10 +438,14 @@ struct vc4_bo * vc4_bo_open_dmabuf(struct vc4_screen *screen, int fd) { uint32_t handle; + + mtx_lock(&screen->bo_handles_mutex); + int ret = drmPrimeFDToHandle(screen->fd, fd, &handle); int size; if (ret) { fprintf(stderr, "Failed to get vc4 handle for dmabuf %d\n", fd); + mtx_unlock(&screen->bo_handles_mutex); return NULL; } @@ -443,6 +453,7 @@ vc4_bo_open_dmabuf(struct vc4_screen *screen, int fd) size = lseek(fd, 0, SEEK_END); if (size == -1) { fprintf(stderr, "Couldn't get size of dmabuf fd %d.\n", fd); + mtx_unlock(&screen->bo_handles_mutex); return NULL; }