Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/amdgpu: Clear cached EDID pointer after drm_edid_free()

The driver stores EDID in amdgpu_connector->edid and uses it as a cache.

amdgpu_connector_get_edid() checks this pointer. If it is not NULL, it
assumes EDID is already present and does not read it again.

In some detect paths, the driver frees the EDID using drm_edid_free(),
but does not set the pointer to NULL. Because of this, the pointer still
looks valid even though the memory is already freed.

Later, when amdgpu_connector_get_edid() is called, it returns early and
does not read a new EDID. This can lead to using a freed pointer.

Fix this by setting amdgpu_connector->edid = NULL after drm_edid_free().

This makes sure the driver reads a fresh EDID and does not use invalid
memory.

Fixes: 71036457ad85 ("drm/amdgpu/amdgpu_connectors: remove amdgpu_connector_free_edid")
Reported-by: Dan Carpenter <error27@gmail.com>
Cc: Joshua Peisach <jpeisach@ubuntu.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Christian König <christian.koenig@amd.com>
Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
Reviewed-by: Joshua Peisach <jpeisach@ubuntu.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Srinivasan Shanmugam and committed by
Alex Deucher
0f6d7ec4 b5245cbe

+6
+6
drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
··· 866 866 if (dret) { 867 867 amdgpu_connector->detected_by_load = false; 868 868 drm_edid_free(amdgpu_connector->edid); 869 + amdgpu_connector->edid = NULL; 869 870 amdgpu_connector_get_edid(connector); 870 871 871 872 if (!amdgpu_connector->edid) { ··· 883 882 */ 884 883 if (amdgpu_connector->use_digital && amdgpu_connector->shared_ddc) { 885 884 drm_edid_free(amdgpu_connector->edid); 885 + amdgpu_connector->edid = NULL; 886 886 ret = connector_status_disconnected; 887 887 } else { 888 888 ret = connector_status_connected; ··· 979 977 if (!amdgpu_display_hpd_sense(adev, 980 978 amdgpu_connector->hpd.hpd)) { 981 979 drm_edid_free(amdgpu_connector->edid); 980 + amdgpu_connector->edid = NULL; 982 981 *status = connector_status_disconnected; 983 982 } 984 983 } ··· 1049 1046 if (dret) { 1050 1047 amdgpu_connector->detected_by_load = false; 1051 1048 drm_edid_free(amdgpu_connector->edid); 1049 + amdgpu_connector->edid = NULL; 1052 1050 amdgpu_connector_get_edid(connector); 1053 1051 1054 1052 if (!amdgpu_connector->edid) { ··· 1066 1062 */ 1067 1063 if ((!amdgpu_connector->use_digital) && amdgpu_connector->shared_ddc) { 1068 1064 drm_edid_free(amdgpu_connector->edid); 1065 + amdgpu_connector->edid = NULL; 1069 1066 ret = connector_status_disconnected; 1070 1067 } else { 1071 1068 ret = connector_status_connected; ··· 1417 1412 } 1418 1413 1419 1414 drm_edid_free(amdgpu_connector->edid); 1415 + amdgpu_connector->edid = NULL; 1420 1416 1421 1417 if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) || 1422 1418 (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {