All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] drm/gem: Fix and enable CHANGE_HANDLE
@ 2026-08-07 18:37 David Francis
  2026-08-07 18:46 ` sashiko-bot
  0 siblings, 1 reply; 3+ messages in thread
From: David Francis @ 2026-08-07 18:37 UTC (permalink / raw)
  To: dri-devel; +Cc: David Francis, Tvrtko Ursulin, Christian Koenig, Simona Vetter

Make the following changes to CHANGE_HANDLE
- Changing a non-existent handle to itself is ENOENT
- idr_preload before idr_alloc
- reject new_handle = 0 with EINVAL

This patch will not be merged until the relevant igt-tests
(https://gitlab.freedesktop.org/fdavid-amd/igt-gpu-tools)
are reviewed, merged, and run to the satisfaction of everyone
involved.

cc: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
cc: Christian Koenig <christian.koenig@amd.com>
cc: Simona Vetter <simona.vetter@ffwll.ch>
Signed-off-by: David Francis <David.Francis@amd.com>
---
 drivers/gpu/drm/drm_gem.c   | 29 +++++++++++++----------------
 drivers/gpu/drm/drm_ioctl.c |  3 +--
 2 files changed, 14 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index e3ed684ddcf2..9a9b91256b8a 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -1015,19 +1015,6 @@ drm_gem_open_ioctl(struct drm_device *dev, void *data,
 	return ret;
 }
 
-/*
- * This ioctl is disabled for security reasons but also it failed
- * to follow process in terms of adding testing in igt and verifying
- * all the corner cases which made fixing security bugs in it even
- * harder than necessary.
- *
- * To re-enable this ioctl
- * 1. land working IGT tests in igt-gpu-tools that cover
- *    all corner cases and race conditions.
- * 2. handle idr_preload
- * 3. handle == 0
- * 4. handle == new_handle semantics definition.
- */
 int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data,
 				struct drm_file *file_priv)
 {
@@ -1039,14 +1026,22 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data,
 		return -EOPNOTSUPP;
 
 	/* idr_alloc() limitation. */
-	if (args->new_handle > INT_MAX)
+	if (args->new_handle == 0 || args->new_handle > INT_MAX)
 		return -EINVAL;
 	new_handle = args->new_handle;
 
-	if (args->handle == new_handle)
-		return 0;
+	if (args->handle == new_handle) {
+		spin_lock(&file_priv->table_lock);
+		if (idr_find(&file_priv->object_idr, args->handle))
+			ret = 0;
+		else
+			ret = -ENOENT;
+		spin_unlock(&file_priv->table_lock);
+		return ret;
+	}
 
 	mutex_lock(&file_priv->prime.lock);
+	idr_preload(GFP_KERNEL);
 	spin_lock(&file_priv->table_lock);
 	ret = idr_alloc(&file_priv->object_idr, NULL, new_handle, new_handle + 1,
 			GFP_NOWAIT);
@@ -1060,10 +1055,12 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data,
 	if (IS_ERR_OR_NULL(obj)) {
 		idr_remove(&file_priv->object_idr, new_handle);
 		spin_unlock(&file_priv->table_lock);
+		idr_preload_end();
 		ret = -ENOENT;
 		goto out_unlock;
 	}
 	spin_unlock(&file_priv->table_lock);
+	idr_preload_end();
 
 	if (obj->dma_buf) {
 		ret = drm_prime_add_buf_handle(&file_priv->prime, obj->dma_buf,
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index e2df4becce62..ff193155129e 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -660,8 +660,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
 	DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH),
 	DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH),
-	/* see drm_gem.c:drm_gem_change_handle_ioctl for why this is invalid */
-	DRM_IOCTL_DEF(DRM_IOCTL_GEM_CHANGE_HANDLE, drm_invalid_op, DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF(DRM_IOCTL_GEM_CHANGE_HANDLE, drm_gem_change_handle_ioctl, DRM_RENDER_ALLOW),
 
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, 0),
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] drm/gem: Fix and enable CHANGE_HANDLE
  2026-08-07 18:37 [PATCH] drm/gem: Fix and enable CHANGE_HANDLE David Francis
@ 2026-08-07 18:46 ` sashiko-bot
  2026-08-10 13:06   ` Francis, David
  0 siblings, 1 reply; 3+ messages in thread
From: sashiko-bot @ 2026-08-07 18:46 UTC (permalink / raw)
  To: David Francis; +Cc: dri-devel

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Critical] Missing idr_preload_end() in the idr_alloc error path leaves preemption permanently disabled.
--

--- Patch [1]: [PATCH] drm/gem: Fix and enable CHANGE_HANDLE ---
commit 4926fe37208872dd7c9115003f10226cea7a200a
Author: David Francis <David.Francis@amd.com>
drm/gem: Fix and enable CHANGE_HANDLE

This patch enables the CHANGE_HANDLE ioctl for GEM and adds validation
for the handle inputs. It also adds idr_preload before idr_alloc to
ensure memory allocation can be fulfilled without sleeping while holding
a spinlock.

> diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
> index 018df97d590dc..00693626d7683 100644
> --- a/drivers/gpu/drm/drm_gem.c
> +++ b/drivers/gpu/drm/drm_gem.c
[ ... ]
> @@ -1038,14 +1025,22 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data,
[ ... ]
>  	mutex_lock(&file_priv->prime.lock);
> +	idr_preload(GFP_KERNEL);
>  	spin_lock(&file_priv->table_lock);
>  	ret = idr_alloc(&file_priv->object_idr, NULL, new_handle, new_handle + 1,
>  			GFP_NOWAIT);
> @@ -1059,10 +1054,12 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data,

[Severity: Critical]
Does this error path leave preemption permanently disabled?

Looking at the code just after idr_alloc() in drm_gem_change_handle_ioctl(),
there is an error path that skips idr_preload_end():

	ret = idr_alloc(&file_priv->object_idr, NULL, new_handle, new_handle + 1,
			GFP_NOWAIT);

	if (ret < 0) {
		spin_unlock(&file_priv->table_lock);
		goto out_unlock;
	}

If idr_alloc() fails (for example, returning -ENOSPC when new_handle is
already in use), the code jumps to out_unlock which only releases prime.lock
and returns. Since idr_preload() disables preemption, wouldn't we need an
idr_preload_end() call before returning to avoid a scheduling while atomic
system panic?

>  	if (IS_ERR_OR_NULL(obj)) {
>  		idr_remove(&file_priv->object_idr, new_handle);
>  		spin_unlock(&file_priv->table_lock);
> +		idr_preload_end();
>  		ret = -ENOENT;
>  		goto out_unlock;
>  	}
>  	spin_unlock(&file_priv->table_lock);
> +	idr_preload_end();
>  
>  	if (obj->dma_buf) {
>  		ret = drm_prime_add_buf_handle(&file_priv->prime, obj->dma_buf,

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260807183735.1019040-1-David.Francis@amd.com?part=1

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] drm/gem: Fix and enable CHANGE_HANDLE
  2026-08-07 18:46 ` sashiko-bot
@ 2026-08-10 13:06   ` Francis, David
  0 siblings, 0 replies; 3+ messages in thread
From: Francis, David @ 2026-08-10 13:06 UTC (permalink / raw)
  To: sashiko-reviews@lists.linux.dev; +Cc: dri-devel@lists.freedesktop.org


Whoops, good catch. Fix is simple; add an idr_preload_end() on that path. Will be in v2.

David Francis

________________________________________
From: sashiko-bot@kernel.org <sashiko-bot@kernel.org>
Sent: Friday, August 7, 2026 2:46 PM
To: Francis, David
Cc: dri-devel@lists.freedesktop.org
Subject: Re: [PATCH] drm/gem: Fix and enable CHANGE_HANDLE

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Critical] Missing idr_preload_end() in the idr_alloc error path leaves preemption permanently disabled.
--

--- Patch [1]: [PATCH] drm/gem: Fix and enable CHANGE_HANDLE ---
commit 4926fe37208872dd7c9115003f10226cea7a200a
Author: David Francis <David.Francis@amd.com>
drm/gem: Fix and enable CHANGE_HANDLE

This patch enables the CHANGE_HANDLE ioctl for GEM and adds validation
for the handle inputs. It also adds idr_preload before idr_alloc to
ensure memory allocation can be fulfilled without sleeping while holding
a spinlock.

> diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
> index 018df97d590dc..00693626d7683 100644
> --- a/drivers/gpu/drm/drm_gem.c
> +++ b/drivers/gpu/drm/drm_gem.c
[ ... ]
> @@ -1038,14 +1025,22 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data,
[ ... ]
>       mutex_lock(&file_priv->prime.lock);
> +     idr_preload(GFP_KERNEL);
>       spin_lock(&file_priv->table_lock);
>       ret = idr_alloc(&file_priv->object_idr, NULL, new_handle, new_handle + 1,
>                       GFP_NOWAIT);
> @@ -1059,10 +1054,12 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data,

[Severity: Critical]
Does this error path leave preemption permanently disabled?

Looking at the code just after idr_alloc() in drm_gem_change_handle_ioctl(),
there is an error path that skips idr_preload_end():

        ret = idr_alloc(&file_priv->object_idr, NULL, new_handle, new_handle + 1,
                        GFP_NOWAIT);

        if (ret < 0) {
                spin_unlock(&file_priv->table_lock);
                goto out_unlock;
        }

If idr_alloc() fails (for example, returning -ENOSPC when new_handle is
already in use), the code jumps to out_unlock which only releases prime.lock
and returns. Since idr_preload() disables preemption, wouldn't we need an
idr_preload_end() call before returning to avoid a scheduling while atomic
system panic?

>       if (IS_ERR_OR_NULL(obj)) {
>               idr_remove(&file_priv->object_idr, new_handle);
>               spin_unlock(&file_priv->table_lock);
> +             idr_preload_end();
>               ret = -ENOENT;
>               goto out_unlock;
>       }
>       spin_unlock(&file_priv->table_lock);
> +     idr_preload_end();
>
>       if (obj->dma_buf) {
>               ret = drm_prime_add_buf_handle(&file_priv->prime, obj->dma_buf,

--
Sashiko AI review · https://sashiko.dev/#/patchset/20260807183735.1019040-1-David.Francis@amd.com?part=1

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-08-10 13:06 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-07 18:37 [PATCH] drm/gem: Fix and enable CHANGE_HANDLE David Francis
2026-08-07 18:46 ` sashiko-bot
2026-08-10 13:06   ` Francis, David

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.