Re: [syzbot] [dri?] KASAN: slab-use-after-free Read in drm_gem_object_release_handle
From: Hillf Danton
Date: Thu Apr 16 2026 - 04:27:20 EST
> Date: Mon, 13 Apr 2026 10:16:36 -0700 [thread overview]
> Hello,
>
> syzbot found the following issue on:
>
> HEAD commit: f5459048c38a Merge tag 'i2c-for-7.0-final' of git://git.ke..
> git tree: upstream
> console output: https://syzkaller.appspot.com/x/log.txt?x=1028d106580000
> kernel config: https://syzkaller.appspot.com/x/.config?x=6754c86e8d9e4c91
> dashboard link: https://syzkaller.appspot.com/bug?extid=b2e951687503f32f74ce
> compiler: Debian clang version 21.1.8 (++20251221033036+2078da43e25a-1~exp1~20251221153213.50), Debian LLD 21.1.8
> syz repro: https://syzkaller.appspot.com/x/repro.syz?x=1428d106580000
> C reproducer: https://syzkaller.appspot.com/x/repro.c?x=17509036580000
#syz test
--- x/drivers/gpu/drm/drm_gem.c
+++ y/drivers/gpu/drm/drm_gem.c
@@ -401,22 +401,20 @@ drm_gem_handle_delete(struct drm_file *f
{
struct drm_gem_object *obj;
+ mutex_lock(&filp->prime.lock);
spin_lock(&filp->table_lock);
/* Check if we currently have a reference on the object */
- obj = idr_replace(&filp->object_idr, NULL, handle);
+ obj = idr_find(&filp->object_idr, handle);
+ idr_remove(&filp->object_idr, handle);
spin_unlock(&filp->table_lock);
+ mutex_unlock(&filp->prime.lock);
+
if (IS_ERR_OR_NULL(obj))
return -EINVAL;
-
/* Release driver's reference and decrement refcount. */
drm_gem_object_release_handle(handle, obj, filp);
- /* And finally make the handle available for future allocations. */
- spin_lock(&filp->table_lock);
- idr_remove(&filp->object_idr, handle);
- spin_unlock(&filp->table_lock);
-
return 0;
}
EXPORT_SYMBOL(drm_gem_handle_delete);
@@ -1012,17 +1010,20 @@ int drm_gem_change_handle_ioctl(struct d
return -EINVAL;
handle = args->new_handle;
+ mutex_lock(&file_priv->prime.lock);
+
obj = drm_gem_object_lookup(file_priv, args->handle);
- if (!obj)
+ if (!obj) {
+ mutex_unlock(&file_priv->prime.lock);
return -ENOENT;
+ }
if (args->handle == handle) {
+ mutex_unlock(&file_priv->prime.lock);
ret = 0;
goto out;
}
- mutex_lock(&file_priv->prime.lock);
-
spin_lock(&file_priv->table_lock);
ret = idr_alloc(&file_priv->object_idr, obj, handle, handle + 1,
GFP_NOWAIT);
@@ -1085,8 +1086,22 @@ drm_gem_open(struct drm_device *dev, str
void
drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
{
- idr_for_each(&file_private->object_idr,
- &drm_gem_object_release_handle, file_private);
+ struct drm_gem_object *obj;
+ int id;
+
+ for (;;) {
+ id = 0;
+ mutex_lock(&file_private->prime.lock);
+ spin_lock(&file_private->table_lock);
+ obj = idr_get_next(&file_private->object_idr, &id);
+ if (obj)
+ idr_remove(&file_private->object_idr, id);
+ spin_unlock(&file_private->table_lock);
+ mutex_unlock(&file_private->prime.lock);
+ if (!obj)
+ break;
+ drm_gem_object_release_handle(id, obj, file_private);
+ }
idr_destroy(&file_private->object_idr);
}
--