]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm: Replace old pointer to new idr
authorEdward Adam Davis <eadavis@qq.com>
Wed, 13 May 2026 04:30:50 +0000 (12:30 +0800)
committerDave Airlie <airlied@redhat.com>
Fri, 15 May 2026 23:32:43 +0000 (09:32 +1000)
Commit 5e28b7b94408 introduced a logical error by failing to replace the
newly generated IDR pointer to old id's pointer at the correct location
within the "change handle" logic; this resulted in the issue reported by
syzbot [1].

Specifically, the new IDR object pointer is intended to replace the original
id's pointer during the normal execution flow.

Additionally, an unnecessary conditional check for the ret exit path has
been removed.

[1]
!RB_EMPTY_ROOT(&prime_fpriv->dmabufs)
WARNING: drivers/gpu/drm/drm_prime.c:224 at drm_prime_destroy_file_private+0x48/0x60 drivers/gpu/drm/drm_prime.c:224, CPU#0: syz.0.17/5833
Call Trace:
 drm_file_free.part.0+0x7e6/0xcc0 drivers/gpu/drm/drm_file.c:269
 drm_file_free drivers/gpu/drm/drm_file.c:237 [inline]
 drm_close_helper.isra.0+0x186/0x200 drivers/gpu/drm/drm_file.c:290
 drm_release+0x1ab/0x360 drivers/gpu/drm/drm_file.c:438

Fixes: 5e28b7b94408 ("drm: Set old handle to NULL before prime swap in change_handle")
Reported-by: syzbot+d7c9eed171647e421013@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=d7c9eed171647e421013
Cc: stable@vger.kernel.org
Tested-by: syzbot+d7c9eed171647e421013@syzkaller.appspotmail.com
Signed-off-by: Edward Adam Davis <eadavis@qq.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Link: https://patch.msgid.link/tencent_C267296443AAA4567771176886DFF364A305@qq.com
drivers/gpu/drm/drm_gem.c

index 51a887cc7fd744c0f6269d7f3d4dbe1fa713271d..8afab57fc0554ee1a2ebff0854c5118b3e882580 100644 (file)
@@ -1067,17 +1067,12 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data,
 
        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,
                                               handle);
                if (ret < 0) {
                        spin_lock(&file_priv->table_lock);
                        idr_remove(&file_priv->object_idr, handle);
-                       idrobj = idr_replace(&file_priv->object_idr, obj, handle);
-                       WARN_ON(idrobj != NULL);
                        spin_unlock(&file_priv->table_lock);
                        goto out_unlock;
                }
@@ -1089,7 +1084,9 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data,
 
        spin_lock(&file_priv->table_lock);
        idr_remove(&file_priv->object_idr, args->handle);
+       idrobj = idr_replace(&file_priv->object_idr, obj, handle);
        spin_unlock(&file_priv->table_lock);
+       WARN_ON(idrobj != NULL);
 
 out_unlock:
        mutex_unlock(&file_priv->prime.lock);