Skip to content

Commit

Permalink
drm/amdgpu: Prevent random memory access in FRU code
Browse files Browse the repository at this point in the history
Prevent random memory access in the FRU EEPROM code by passing the size of
the destination buffer to the reading routine, and reading no more than the
size of the buffer.

Cc: Kent Russell <[email protected]>
Cc: Alex Deucher <[email protected]>
Signed-off-by: Luben Tuikov <[email protected]>
Acked-by: Harish Kasiviswanathan <[email protected]>
Reviewed-by: Kent Russell <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
  • Loading branch information
Luben Tuikov authored and alexdeucher committed Feb 7, 2022
1 parent 3f3a24a commit 00b14ce
Showing 1 changed file with 12 additions and 10 deletions.
22 changes: 12 additions & 10 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
#include "amdgpu_eeprom.h"

#define FRU_EEPROM_MADDR 0x60000
#define I2C_PRODUCT_INFO_OFFSET 0xC0

static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
{
Expand Down Expand Up @@ -77,9 +76,10 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
}

static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
unsigned char *buf)
unsigned char *buf, size_t buf_size)
{
int ret, size;
int ret;
u8 size;

ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr, buf, 1);
if (ret < 1) {
Expand All @@ -90,9 +90,11 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
/* The size returned by the i2c requires subtraction of 0xC0 since the
* size apparently always reports as 0xC0+actual size.
*/
size = buf[0] - I2C_PRODUCT_INFO_OFFSET;
size = buf[0] & 0x3F;
size = min_t(size_t, size, buf_size);

ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr + 1, buf, size);
ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr + 1,
buf, size);
if (ret < 1) {
DRM_WARN("FRU: Failed to get data field");
return ret;
Expand Down Expand Up @@ -129,7 +131,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
* and the language field, so just start from 0xb, manufacturer size
*/
addrptr = FRU_EEPROM_MADDR + 0xb;
size = amdgpu_fru_read_eeprom(adev, addrptr, buf);
size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf));
if (size < 1) {
DRM_ERROR("Failed to read FRU Manufacturer, ret:%d", size);
return -EINVAL;
Expand All @@ -139,7 +141,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
* size field being 1 byte. This pattern continues below.
*/
addrptr += size + 1;
size = amdgpu_fru_read_eeprom(adev, addrptr, buf);
size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf));
if (size < 1) {
DRM_ERROR("Failed to read FRU product name, ret:%d", size);
return -EINVAL;
Expand All @@ -155,7 +157,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
adev->product_name[len] = '\0';

addrptr += size + 1;
size = amdgpu_fru_read_eeprom(adev, addrptr, buf);
size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf));
if (size < 1) {
DRM_ERROR("Failed to read FRU product number, ret:%d", size);
return -EINVAL;
Expand All @@ -173,15 +175,15 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
adev->product_number[len] = '\0';

addrptr += size + 1;
size = amdgpu_fru_read_eeprom(adev, addrptr, buf);
size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf));

if (size < 1) {
DRM_ERROR("Failed to read FRU product version, ret:%d", size);
return -EINVAL;
}

addrptr += size + 1;
size = amdgpu_fru_read_eeprom(adev, addrptr, buf);
size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf));

if (size < 1) {
DRM_ERROR("Failed to read FRU serial number, ret:%d", size);
Expand Down

0 comments on commit 00b14ce

Please sign in to comment.