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

drm/amdgpu: Fix pointer casts when reading dynamic region sizes

The function amdgpu_virt_get_dynamic_data_info() writes a 64-bit size
value. In two places (amdgpu_bios.c and amdgpu_discovery.c), the code
passed the address of a smaller variable by casting it to u64 *, which
is unsafe.

This could make the function write more bytes than the smaller variable
can hold, possibly overwriting nearby memory. Reported by static
analysis tools.

v2: Dynamic region size comes from the host (SR-IOV setup) and is always
fixed to 5 MB. (Lijo/Ellen)

5 MB easily fits inside a 32-bit value, so using a 64-bit type is not
needed. It also avoids extra type casts

Fixes: b4a8fcc7826a ("drm/amdgpu: Add logic for VF ipd and VF bios to init from dynamic crit_region offsets")
Reported by: Dan Carpenter <dan.carpenter@linaro.org>
Cc: Ellen Pan <yunru.pan@amd.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Srinivasan Shanmugam and committed by
Alex Deucher
90ef1dcb 84564d29

+5 -5
+2 -2
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
··· 103 103 { 104 104 uint8_t __iomem *bios = NULL; 105 105 resource_size_t vram_base; 106 - resource_size_t size = 256 * 1024; /* ??? */ 106 + u32 size = 256U * 1024U; /* ??? */ 107 107 108 108 if (!(adev->flags & AMD_IS_APU)) 109 109 if (amdgpu_device_need_post(adev)) ··· 126 126 */ 127 127 if (amdgpu_sriov_vf(adev) && adev->virt.is_dynamic_crit_regn_enabled) { 128 128 if (amdgpu_virt_get_dynamic_data_info(adev, 129 - AMD_SRIOV_MSG_VBIOS_IMG_TABLE_ID, adev->bios, (uint64_t *)&size)) { 129 + AMD_SRIOV_MSG_VBIOS_IMG_TABLE_ID, adev->bios, &size)) { 130 130 amdgpu_bios_release(adev); 131 131 return false; 132 132 }
+1 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
··· 311 311 */ 312 312 if (amdgpu_virt_get_dynamic_data_info(adev, 313 313 AMD_SRIOV_MSG_IPD_TABLE_ID, binary, 314 - (uint64_t *)&adev->discovery.size)) { 314 + &adev->discovery.size)) { 315 315 dev_err(adev->dev, 316 316 "failed to read discovery info from dynamic critical region."); 317 317 ret = -EINVAL;
+1 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
··· 1102 1102 } 1103 1103 1104 1104 int amdgpu_virt_get_dynamic_data_info(struct amdgpu_device *adev, 1105 - int data_id, uint8_t *binary, uint64_t *size) 1105 + int data_id, uint8_t *binary, u32 *size) 1106 1106 { 1107 1107 uint32_t data_offset = 0; 1108 1108 uint32_t data_size = 0;
+1 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
··· 443 443 444 444 int amdgpu_virt_init_critical_region(struct amdgpu_device *adev); 445 445 int amdgpu_virt_get_dynamic_data_info(struct amdgpu_device *adev, 446 - int data_id, uint8_t *binary, uint64_t *size); 446 + int data_id, uint8_t *binary, u32 *size); 447 447 448 448 bool amdgpu_virt_can_access_debugfs(struct amdgpu_device *adev); 449 449 int amdgpu_virt_enable_access_debugfs(struct amdgpu_device *adev);