Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm: Do not allow userspace to trigger kernel warnings in drm_gem_change_handle_ioctl()

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 <tvrtko.ursulin@igalia.com>
Reported-by: Zhi Wang <wangzhi@stu.xidian.edu.cn>
Fixes: 53096728b891 ("drm: Add DRM prime interface to reassign GEM handle")
Cc: David Francis <David.Francis@amd.com>
Cc: Felix Kuehling <felix.kuehling@amd.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: <stable@vger.kernel.org> # v6.18+
Tested-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Tvrtko Ursulin <tursulin@ursulin.net>
Link: https://lore.kernel.org/r/20260123141540.76540-1-tvrtko.ursulin@igalia.com

authored by

Tvrtko Ursulin and committed by
Tvrtko Ursulin
12f15d52 0a095b64

+12 -6
+12 -6
drivers/gpu/drm/drm_gem.c
··· 960 960 { 961 961 struct drm_gem_change_handle *args = data; 962 962 struct drm_gem_object *obj; 963 - int ret; 963 + int handle, ret; 964 964 965 965 if (!drm_core_check_feature(dev, DRIVER_GEM)) 966 966 return -EOPNOTSUPP; 967 + 968 + /* idr_alloc() limitation. */ 969 + if (args->new_handle > INT_MAX) 970 + return -EINVAL; 971 + handle = args->new_handle; 967 972 968 973 obj = drm_gem_object_lookup(file_priv, args->handle); 969 974 if (!obj) 970 975 return -ENOENT; 971 976 972 - if (args->handle == args->new_handle) { 977 + if (args->handle == handle) { 973 978 ret = 0; 974 979 goto out; 975 980 } ··· 982 977 mutex_lock(&file_priv->prime.lock); 983 978 984 979 spin_lock(&file_priv->table_lock); 985 - ret = idr_alloc(&file_priv->object_idr, obj, 986 - args->new_handle, args->new_handle + 1, GFP_NOWAIT); 980 + ret = idr_alloc(&file_priv->object_idr, obj, handle, handle + 1, 981 + GFP_NOWAIT); 987 982 spin_unlock(&file_priv->table_lock); 988 983 989 984 if (ret < 0) 990 985 goto out_unlock; 991 986 992 987 if (obj->dma_buf) { 993 - ret = drm_prime_add_buf_handle(&file_priv->prime, obj->dma_buf, args->new_handle); 988 + ret = drm_prime_add_buf_handle(&file_priv->prime, obj->dma_buf, 989 + handle); 994 990 if (ret < 0) { 995 991 spin_lock(&file_priv->table_lock); 996 - idr_remove(&file_priv->object_idr, args->new_handle); 992 + idr_remove(&file_priv->object_idr, handle); 997 993 spin_unlock(&file_priv->table_lock); 998 994 goto out_unlock; 999 995 }