DRM_IOCTL_MODE_CREATEPROPBLOB allows userspace to create property blobs whose lifetime is scoped to a drm_file.
Currently, a single drm_file may create an unbounded number of blobs. Repeated ioctl calls can trigger unbounded kernel memory allocation and lead to OOM, resulting in a denial-of-service. Introduce a per-drm_file limit on the number of user-created property blobs. The limit is enforced at the point where a blob becomes associated with a drm_file, matching the existing ownership and lifetime model. This bounds per-file allocations while the total number of DRM file descriptors remains constrained by existing kernel limits. Signed-off-by: Xiao Kan <[email protected]> Signed-off-by: Xiao Kan <[email protected]> --- drivers/gpu/drm/drm_file.c | 1 + drivers/gpu/drm/drm_property.c | 8 ++++++++ include/drm/drm_file.h | 6 ++++++ 3 files changed, 15 insertions(+) diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index eebd1a05e..873bf6248 100755 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -152,6 +152,7 @@ struct drm_file *drm_file_alloc(struct drm_minor *minor) INIT_LIST_HEAD(&file->fbs); mutex_init(&file->fbs_lock); INIT_LIST_HEAD(&file->blobs); + file->blob_count = 0; INIT_LIST_HEAD(&file->pending_event_list); INIT_LIST_HEAD(&file->event_list); init_waitqueue_head(&file->event_wait); diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c index 596272149..00eac336a 100755 --- a/drivers/gpu/drm/drm_property.c +++ b/drivers/gpu/drm/drm_property.c @@ -618,6 +618,7 @@ void drm_property_destroy_user_blobs(struct drm_device *dev, */ list_for_each_entry_safe(blob, bt, &file_priv->blobs, head_file) { list_del_init(&blob->head_file); + file_priv->blob_count--; drm_property_blob_put(blob); } } @@ -864,8 +865,14 @@ int drm_mode_createblob_ioctl(struct drm_device *dev, * as only the same file_priv can remove the blob; at this point, it is * not associated with any file_priv. */ mutex_lock(&dev->mode_config.blob_lock); + if (file_priv->blob_count >= DRM_FILE_MAX_PROPBLOBS) { + mutex_unlock(&dev->mode_config.blob_lock); + drm_property_blob_put(blob); + return -ENOSPC; + } out_resp->blob_id = blob->base.id; list_add_tail(&blob->head_file, &file_priv->blobs); + file_priv->blob_count++; mutex_unlock(&dev->mode_config.blob_lock); return 0; @@ -907,6 +914,7 @@ int drm_mode_destroyblob_ioctl(struct drm_device *dev, /* We must drop head_file here, because we may not be the last * reference on the blob. */ list_del_init(&blob->head_file); + file_priv->blob_count--; mutex_unlock(&dev->mode_config.blob_lock); /* One reference from lookup, and one from the filp. */ diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h index 115763799..211c4284f 100755 --- a/include/drm/drm_file.h +++ b/include/drm/drm_file.h @@ -38,6 +38,9 @@ #include <drm/drm_prime.h> +/* Maximum number of user-created property blobs per drm_file */ +#define DRM_FILE_MAX_PROPBLOBS 256 + struct dma_fence; struct drm_file; struct drm_device; @@ -349,6 +352,9 @@ struct drm_file { */ struct list_head blobs; + /* Number of property blobs owned by this file */ + unsigned int blob_count; + /** @event_wait: Waitqueue for new events added to @event_list. */ wait_queue_head_t event_wait; -- 2.51.0
