On 1/23/26 15:15, Tvrtko Ursulin wrote:
> 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+
Reviewed-by: Christian König <[email protected]>
> ---
> v2:
> * Rename local variable, re-position comment, drop the else block.
> (Christian)
> * Use local at more places.
> ---
> drivers/gpu/drm/drm_gem.c | 18 ++++++++++++------
> 1 file changed, 12 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
> index 7ff6b7bbeb73..ffa7852c8f6c 100644
> --- a/drivers/gpu/drm/drm_gem.c
> +++ b/drivers/gpu/drm/drm_gem.c
> @@ -1001,16 +1001,21 @@ 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 handle, ret;
>
> if (!drm_core_check_feature(dev, DRIVER_GEM))
> return -EOPNOTSUPP;
>
> + /* idr_alloc() limitation. */
> + if (args->new_handle > INT_MAX)
> + return -EINVAL;
> + handle = args->new_handle;
> +
> obj = drm_gem_object_lookup(file_priv, args->handle);
> if (!obj)
> return -ENOENT;
>
> - if (args->handle == args->new_handle) {
> + if (args->handle == handle) {
> ret = 0;
> goto out;
> }
> @@ -1018,18 +1023,19 @@ 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, handle, handle + 1,
> + GFP_NOWAIT);
> spin_unlock(&file_priv->table_lock);
>
> if (ret < 0)
> goto out_unlock;
>
> if (obj->dma_buf) {
> - ret = drm_prime_add_buf_handle(&file_priv->prime, obj->dma_buf,
> args->new_handle);
> + ret = drm_prime_add_buf_handle(&file_priv->prime, obj->dma_buf,
> + handle);
> if (ret < 0) {
> spin_lock(&file_priv->table_lock);
> - idr_remove(&file_priv->object_idr, args->new_handle);
> + idr_remove(&file_priv->object_idr, handle);
> spin_unlock(&file_priv->table_lock);
> goto out_unlock;
> }