From 7164d78559b0ff29931a366a840a9e5dd53d4b7c Mon Sep 17 00:00:00 2001 From: Zhenghang Xiao Date: Tue, 26 May 2026 16:53:13 +0800 Subject: [PATCH] drm/gem: fix race between change_handle and handle_delete drm_gem_change_handle_ioctl leaves the old handle live in the IDR during the window between spin_unlock(table_lock) and the final spin_lock(table_lock). A concurrent drm_gem_handle_delete on the old handle succeeds in this window, decrements handle_count to 0, and frees the GEM object while the new handle's IDR entry still references it. NULL the old handle's IDR entry before dropping table_lock so that any concurrent GEM_CLOSE on the old handle sees NULL and returns -EINVAL. Restore the old entry on the prime-bookkeeping error path. Fixes: 5e28b7b94408 ("drm: Set old handle to NULL before prime swap in change_handle") Signed-off-by: Zhenghang Xiao Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie Link: https://patch.msgid.link/20260526085313.26791-1-kipreyyy@gmail.com --- drivers/gpu/drm/drm_gem.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index e3b8a1f353cb..e12cdf91f4dc 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -1065,6 +1065,7 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data, goto out_unlock; } + idr_replace(&file_priv->object_idr, NULL, args->handle); spin_unlock(&file_priv->table_lock); if (obj->dma_buf) { @@ -1073,6 +1074,7 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data, if (ret < 0) { spin_lock(&file_priv->table_lock); idr_remove(&file_priv->object_idr, handle); + idr_replace(&file_priv->object_idr, obj, args->handle); spin_unlock(&file_priv->table_lock); goto out_unlock; }