Commit dc366607 authored by Edward Adam Davis's avatar Edward Adam Davis Committed by Dave Airlie
Browse files

drm: Replace old pointer to new idr



Commit 5e28b7b9 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: 5e28b7b9 ("drm: Set old handle to NULL before prime swap in change_handle")
Reported-by: default avatar <syzbot+d7c9eed171647e421013@syzkaller.appspotmail.com>
Closes: https://syzkaller.appspot.com/bug?extid=d7c9eed171647e421013


Cc: stable@vger.kernel.org
Tested-by: default avatar <syzbot+d7c9eed171647e421013@syzkaller.appspotmail.com>
Signed-off-by: default avatarEdward Adam Davis <eadavis@qq.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
Link: https://patch.msgid.link/tencent_C267296443AAA4567771176886DFF364A305@qq.com
parent 396db75a
Loading
Loading
Loading
Loading
+2 −5
Original line number Diff line number Diff line
@@ -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);