[lvc-project] [PATCH v2] drm/amd/display: Fix dangling pointers in state reset functions on allocation failure

Mario Limonciello mario.limonciello at amd.com
Fri Jun 26 20:24:34 MSK 2026



On 6/26/26 08:38, Evgenii Burenchev wrote:
> Multiple reset functions in amdgpu_dm free the old state before allocating
> a new one. If kzalloc_obj() fails, the function returns without updating
> the state pointer, leaving a dangling pointer to already freed memory.
> 
> Fix this by allocating the new state first. If allocation fails, warn and
> return without touching the old state, as it remains valid and the caller
> will handle the error appropriately.
> 
> This affects three functions:
> - amdgpu_dm_plane_drm_plane_reset()
> - amdgpu_dm_crtc_reset_state()
> - amdgpu_dm_connector_funcs_reset()
> 
> Found by Linux Verification Center (linuxtesting.org) with SVACE.
> 
> Fixes: 5d945cbcd4b1 ("drm/amd/display: Create a file dedicated to planes")
> Fixes: 473683a03495 ("drm/amd/display: Create a file dedicated for CRTC")
> Fixes: e7b07ceef2a6 ("drm/amd/display: Merge amdgpu_dm_types and amdgpu_dm")
> Signed-off-by: Evgenii Burenchev <evg28bur at yandex.ru>
> ---
> Changes in v2:
> - Also fix amdgpu_dm_crtc_reset_state() and amdgpu_dm_connector_funcs_reset()
> ---
>   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 48 ++++++++++---------
>   .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c    |  8 ++--
>   .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 14 +++---
>   3 files changed, 37 insertions(+), 33 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index 97ab1e83b318..6ef1b07ec251 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -8151,33 +8151,35 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector)
>   
>   void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector)
>   {
> -	struct dm_connector_state *state =
> -		to_dm_connector_state(connector->state);
> -
> -	if (connector->state)
> -		__drm_atomic_helper_connector_destroy_state(connector->state);
> -
> -	kfree(state);

You seem to have lost this kfree() in your refactor.

> +	struct dm_connector_state *state;
>   
> +	/* Allocate new state first */
>   	state = kzalloc_obj(*state);
> +	if (WARN_ON(!state))
> +		return;
>   
> -	if (state) {
> -		state->scaling = RMX_OFF;
> -		state->underscan_enable = false;
> -		state->underscan_hborder = 0;
> -		state->underscan_vborder = 0;
> -		state->base.max_requested_bpc = 8;
> -		state->vcpi_slots = 0;
> -		state->pbn = 0;
> -
> -		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
> -			if (amdgpu_dm_abm_level <= 0)
> -				state->abm_level = ABM_LEVEL_IMMEDIATE_DISABLE;
> -			else
> -				state->abm_level = amdgpu_dm_abm_level;
> -		}
> +	/* Destroy old state only after successful allocation */
> +	if (connector->state)
> +		__drm_atomic_helper_connector_destroy_state(connector->state);
>   
> -		__drm_atomic_helper_connector_reset(connector, &state->base);
> +	/* Let DRM core install the new state */
> +	__drm_atomic_helper_connector_reset(connector, &state->base);
> +
> +	/* Initialize driver-specific fields */
> +	state->scaling = RMX_OFF;
> +	state->underscan_enable = false;
> +	state->underscan_hborder = 0;
> +	state->underscan_vborder = 0;
> +	state->base.max_requested_bpc = 8;
> +	state->vcpi_slots = 0;
> +	state->pbn = 0;
> +
> +	/* eDP-specific initialization */
> +	if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
> +		if (amdgpu_dm_abm_level <= 0)
> +			state->abm_level = ABM_LEVEL_IMMEDIATE_DISABLE;
> +		else
> +			state->abm_level = amdgpu_dm_abm_level;
>   	}
>   }
>   
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
> index 3dcedaa67ed8..6146fbc528c3 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
> @@ -437,13 +437,15 @@ static void amdgpu_dm_crtc_reset_state(struct drm_crtc *crtc)
>   {
>   	struct dm_crtc_state *state;
>   
> -	if (crtc->state)
> -		amdgpu_dm_crtc_destroy_state(crtc, crtc->state);
> -
> +	/* Allocate new state first */
>   	state = kzalloc_obj(*state);
>   	if (WARN_ON(!state))
>   		return;
>   
> +	/* Destroy old state only after successful allocation */
> +	if (crtc->state)
> +		amdgpu_dm_crtc_destroy_state(crtc, crtc->state);
> +
>   	__drm_atomic_helper_crtc_reset(crtc, &state->base);
>   }
>   
> 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 e957657b06c7..eb1c0a26f20d 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
> @@ -1488,17 +1488,17 @@ static const struct drm_plane_helper_funcs dm_primary_plane_helper_funcs = {
>   
>   static void amdgpu_dm_plane_drm_plane_reset(struct drm_plane *plane)
>   {
> -	struct dm_plane_state *amdgpu_state = NULL;
> -
> -	if (plane->state)
> -		plane->funcs->atomic_destroy_state(plane, plane->state);
> +	struct dm_plane_state *amdgpu_state;
>   
> +	/* Allocate new state first */
>   	amdgpu_state = kzalloc_obj(*amdgpu_state);
> -	WARN_ON(amdgpu_state == NULL);
> -
> -	if (!amdgpu_state)
> +	if (WARN_ON(!amdgpu_state))
>   		return;
>   
> +	/* Destroy old state only after successful allocation */
> +	if (plane->state)
> +		plane->funcs->atomic_destroy_state(plane, plane->state);
> +
>   	__drm_atomic_helper_plane_reset(plane, &amdgpu_state->base);
>   	amdgpu_state->degamma_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
>   	amdgpu_state->hdr_mult = AMDGPU_HDR_MULT_DEFAULT;




More information about the lvc-project mailing list