Since GEM bo handles are u32 in the uapi and the internal implementation
uses idr_alloc() which uses int ranges, passing a new handle larger than
INT_MAX trivially triggers a kernel warning:
idr_alloc():
...
if (WARN_ON_ONCE(start < 0))
return -EINVAL;
...
Fix it by rejecting new handles above INT_MAX and at the same time make
the end limit calculation more obvious by moving into int domain.
Signed-off-by: Tvrtko Ursulin <[email protected]>
Reported-by: Zhi Wang <[email protected]>
Fixes: 53096728b891 ("drm: Add DRM prime interface to reassign GEM handle")
Cc: David Francis <[email protected]>
Cc: Felix Kuehling <[email protected]>
Cc: Christian König <[email protected]>
Cc: <[email protected]> # v6.18+
---
Compile tested only. Any IGTs for the new functionality?
---
drivers/gpu/drm/drm_gem.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 7ff6b7bbeb73..c5d3ecc1f8a8 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -1001,11 +1001,16 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev,
void *data,
{
struct drm_gem_change_handle *args = data;
struct drm_gem_object *obj;
- int ret;
+ int new, ret;
if (!drm_core_check_feature(dev, DRIVER_GEM))
return -EOPNOTSUPP;
+ if (args->new_handle <= INT_MAX) /* idr_alloc() limitation. */
+ new = args->new_handle;
+ else
+ return -EINVAL;
+
obj = drm_gem_object_lookup(file_priv, args->handle);
if (!obj)
return -ENOENT;
@@ -1018,8 +1023,7 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev,
void *data,
mutex_lock(&file_priv->prime.lock);
spin_lock(&file_priv->table_lock);
- ret = idr_alloc(&file_priv->object_idr, obj,
- args->new_handle, args->new_handle + 1, GFP_NOWAIT);
+ ret = idr_alloc(&file_priv->object_idr, obj, new, new + 1, GFP_NOWAIT);
spin_unlock(&file_priv->table_lock);
if (ret < 0)
--
2.52.0