v3d: Fix race condition in BO imports

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 <apinheiro@igalia.com>
Signed-off-by: Asahi Lina <lina@asahilina.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20403>
This commit is contained in:
Asahi Lina
2022-12-21 17:24:37 +09:00
committed by Marge Bot
parent 8c3c11ad33
commit 7dbb1a091a
+12 -2
View File
@@ -327,9 +327,11 @@ v3d_bo_open_handle(struct v3d_screen *screen,
{
struct v3d_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) {
@@ -381,10 +383,13 @@ v3d_bo_open_name(struct v3d_screen *screen, uint32_t name)
struct drm_gem_open o = {
.name = name
};
mtx_lock(&screen->bo_handles_mutex);
int ret = v3d_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;
}
@@ -395,10 +400,14 @@ struct v3d_bo *
v3d_bo_open_dmabuf(struct v3d_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 v3d handle for dmabuf %d\n", fd);
mtx_unlock(&screen->bo_handles_mutex);
return NULL;
}
@@ -406,6 +415,7 @@ v3d_bo_open_dmabuf(struct v3d_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;
}