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
1067 1067
1068 spin_unlock(&file_priv->table_lock);1068 spin_unlock(&file_priv->table_lock);
1069 1069
1070 if (ret < 0)
1071 goto out_unlock;
1072
1073 if (obj->dma_buf) {1070 if (obj->dma_buf) {
1074 ret = drm_prime_add_buf_handle(&file_priv->prime, obj->dma_buf,1071 ret = drm_prime_add_buf_handle(&file_priv->prime, obj->dma_buf,
1075 handle);1072 handle);
1076 if (ret < 0) {1073 if (ret < 0) {
1077 spin_lock(&file_priv->table_lock);1074 spin_lock(&file_priv->table_lock);
1078 idr_remove(&file_priv->object_idr, handle);1075 idr_remove(&file_priv->object_idr, handle);
1079 idrobj = idr_replace(&file_priv->object_idr, obj, handle);
1080 WARN_ON(idrobj != NULL);
1081 spin_unlock(&file_priv->table_lock);1076 spin_unlock(&file_priv->table_lock);
1082 goto out_unlock;1077 goto out_unlock;
1083 }1078 }
@@ -1089,7 +1084,9 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data, · 5 unmodified lines
1089 1084
1090 spin_lock(&file_priv->table_lock);1085 spin_lock(&file_priv->table_lock);
1091 idr_remove(&file_priv->object_idr, args->handle);1086 idr_remove(&file_priv->object_idr, args->handle);
1087 idrobj = idr_replace(&file_priv->object_idr, obj, handle);
1092 spin_unlock(&file_priv->table_lock);1088 spin_unlock(&file_priv->table_lock);
1089 WARN_ON(idrobj != NULL);
1093 1090
1094out_unlock:1091out_unlock:
1095 mutex_unlock(&file_priv->prime.lock);1092 mutex_unlock(&file_priv->prime.lock);