History

drm: Replace old pointer to new idr

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

Edward Adam Davis committed 6 months ago

Commit dc366601 parent 396db751 file · +2 −5Browse files

Unified · Split

drivers/gpu/drm/drm_gem.c+2−5
@@ -1067,17 +1067,12 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data, · 1066 unmodified lines
10671067
10681068 spin_unlock(&file_priv->table_lock);
10691069
1070− if (ret < 0)
1071− goto out_unlock;
1072−
10731070 if (obj->dma_buf) {
10741071 ret = drm_prime_add_buf_handle(&file_priv->prime, obj->dma_buf,
10751072 handle);
10761073 if (ret < 0) {
10771074 spin_lock(&file_priv->table_lock);
10781075 idr_remove(&file_priv->object_idr, handle);
1079− idrobj = idr_replace(&file_priv->object_idr, obj, handle);
1080− WARN_ON(idrobj != NULL);
10811076 spin_unlock(&file_priv->table_lock);
10821077 goto out_unlock;
10831078 }
@@ -1089,7 +1084,9 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data, · 5 unmodified lines
10891084
10901085 spin_lock(&file_priv->table_lock);
10911086 idr_remove(&file_priv->object_idr, args->handle);
1087+ idrobj = idr_replace(&file_priv->object_idr, obj, handle);
10921088 spin_unlock(&file_priv->table_lock);
1089+ WARN_ON(idrobj != NULL);
10931090
10941091 out_unlock:
10951092 mutex_unlock(&file_priv->prime.lock);