From ca59e33f5a1f642d13ae0e558fdbdd9aaa9fe203 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 6 Jan 2026 05:09:56 +0200 Subject: [PATCH] drm/atomic: add max_size check to drm_property_replace_blob_from_id() The function drm_property_replace_blob_from_id() allows checking whether the blob size is equal to a predefined value. In case of variable-size properties (like the gamma / degamma LUTs) we might want to check for the blob size against the maximum, allowing properties of the size lesser than the max supported by the hardware. Extend the function in order to support such checks. Reviewed-by: Thomas Zimmermann Link: https://patch.msgid.link/20260106-drm-fix-lut-checks-v3-2-f7f979eb73c8@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- .../amd/display/amdgpu_dm/amdgpu_dm_plane.c | 18 +++++++++--------- drivers/gpu/drm/drm_atomic_uapi.c | 14 ++++++-------- drivers/gpu/drm/drm_property.c | 11 +++++++++++ include/drm/drm_property.h | 1 + 4 files changed, 27 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c index 2e3ee78999d99..8c5912b59e198 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c @@ -1676,8 +1676,8 @@ dm_atomic_plane_set_property(struct drm_plane *plane, if (property == adev->mode_info.plane_degamma_lut_property) { ret = drm_property_replace_blob_from_id(plane->dev, &dm_plane_state->degamma_lut, - val, -1, - sizeof(struct drm_color_lut), + val, + -1, -1, sizeof(struct drm_color_lut), &replaced); dm_plane_state->base.color_mgmt_changed |= replaced; return ret; @@ -1695,15 +1695,15 @@ dm_atomic_plane_set_property(struct drm_plane *plane, ret = drm_property_replace_blob_from_id(plane->dev, &dm_plane_state->ctm, val, - sizeof(struct drm_color_ctm_3x4), -1, + -1, sizeof(struct drm_color_ctm_3x4), -1, &replaced); dm_plane_state->base.color_mgmt_changed |= replaced; return ret; } else if (property == adev->mode_info.plane_shaper_lut_property) { ret = drm_property_replace_blob_from_id(plane->dev, &dm_plane_state->shaper_lut, - val, -1, - sizeof(struct drm_color_lut), + val, + -1, -1, sizeof(struct drm_color_lut), &replaced); dm_plane_state->base.color_mgmt_changed |= replaced; return ret; @@ -1715,16 +1715,16 @@ dm_atomic_plane_set_property(struct drm_plane *plane, } else if (property == adev->mode_info.plane_lut3d_property) { ret = drm_property_replace_blob_from_id(plane->dev, &dm_plane_state->lut3d, - val, -1, - sizeof(struct drm_color_lut), + val, + -1, -1, sizeof(struct drm_color_lut), &replaced); dm_plane_state->base.color_mgmt_changed |= replaced; return ret; } else if (property == adev->mode_info.plane_blend_lut_property) { ret = drm_property_replace_blob_from_id(plane->dev, &dm_plane_state->blend_lut, - val, -1, - sizeof(struct drm_color_lut), + val, + -1, -1, sizeof(struct drm_color_lut), &replaced); dm_plane_state->base.color_mgmt_changed |= replaced; return ret; diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 7320db4b8489f..dff1fdefcbeb8 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -416,7 +416,7 @@ static int drm_atomic_crtc_set_property(struct drm_crtc *crtc, ret = drm_property_replace_blob_from_id(dev, &state->degamma_lut, val, - -1, sizeof(struct drm_color_lut), + -1, -1, sizeof(struct drm_color_lut), &replaced); state->color_mgmt_changed |= replaced; return ret; @@ -424,7 +424,7 @@ static int drm_atomic_crtc_set_property(struct drm_crtc *crtc, ret = drm_property_replace_blob_from_id(dev, &state->ctm, val, - sizeof(struct drm_color_ctm), -1, + -1, sizeof(struct drm_color_ctm), -1, &replaced); state->color_mgmt_changed |= replaced; return ret; @@ -432,7 +432,7 @@ static int drm_atomic_crtc_set_property(struct drm_crtc *crtc, ret = drm_property_replace_blob_from_id(dev, &state->gamma_lut, val, - -1, sizeof(struct drm_color_lut), + -1, -1, sizeof(struct drm_color_lut), &replaced); state->color_mgmt_changed |= replaced; return ret; @@ -587,8 +587,7 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, ret = drm_property_replace_blob_from_id(dev, &state->fb_damage_clips, val, - -1, - sizeof(struct drm_mode_rect), + -1, -1, sizeof(struct drm_mode_rect), &replaced); return ret; } else if (property == plane->scaling_filter_property) { @@ -717,8 +716,7 @@ static int drm_atomic_color_set_data_property(struct drm_colorop *colorop, return drm_property_replace_blob_from_id(colorop->dev, &state->data, val, - size, - elem_size, + -1, size, elem_size, &replaced); } @@ -876,7 +874,7 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector, ret = drm_property_replace_blob_from_id(dev, &state->hdr_output_metadata, val, - sizeof(struct hdr_output_metadata), -1, + -1, sizeof(struct hdr_output_metadata), -1, &replaced); return ret; } else if (property == config->aspect_ratio_property) { diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c index 596272149a359..955fa960843b3 100644 --- a/drivers/gpu/drm/drm_property.c +++ b/drivers/gpu/drm/drm_property.c @@ -757,6 +757,7 @@ EXPORT_SYMBOL(drm_property_replace_blob); * @dev: DRM device * @blob: a pointer to the member blob to be replaced * @blob_id: the id of the new blob to replace with + * @max_size: the maximum size of the blob property for variable-size blobs * @expected_size: expected size of the blob property * @expected_elem_size: expected size of an element in the blob property * @replaced: if the blob was in fact replaced @@ -771,6 +772,7 @@ EXPORT_SYMBOL(drm_property_replace_blob); int drm_property_replace_blob_from_id(struct drm_device *dev, struct drm_property_blob **blob, uint64_t blob_id, + ssize_t max_size, ssize_t expected_size, ssize_t expected_elem_size, bool *replaced) @@ -785,6 +787,15 @@ int drm_property_replace_blob_from_id(struct drm_device *dev, return -EINVAL; } + if (max_size > 0 && + new_blob->length > max_size) { + drm_dbg_atomic(dev, + "[BLOB:%d] length %zu greater than max %zu\n", + new_blob->base.id, new_blob->length, max_size); + drm_property_blob_put(new_blob); + return -EINVAL; + } + if (expected_size > 0 && new_blob->length != expected_size) { drm_dbg_atomic(dev, diff --git a/include/drm/drm_property.h b/include/drm/drm_property.h index 082f29156b3e3..aa49b5a42bb56 100644 --- a/include/drm/drm_property.h +++ b/include/drm/drm_property.h @@ -284,6 +284,7 @@ int drm_property_replace_blob_from_id(struct drm_device *dev, uint64_t blob_id, ssize_t expected_size, ssize_t expected_elem_size, + ssize_t max_size, bool *replaced); int drm_property_replace_global_blob(struct drm_device *dev, struct drm_property_blob **replace, -- 2.47.3