Corrupt EEPROM data can set tbl_size below the table header size.
Guard the RAS_NUM_RECS macros against undersized tbl_size and reset
the table during init when tbl_size is below the minimum for the table
version instead of trusting the header.

Signed-off-by: Candice Li <[email protected]>
---
 .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c    | 30 ++++++++++++++-----
 1 file changed, 23 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index c61389a079822e..159edaf2ba7576 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -145,12 +145,15 @@
 #define RAS_RI_TO_AI(_C, _I) (((_I) + (_C)->ras_fri) % \
                              (_C)->ras_max_record_count)
 
-#define RAS_NUM_RECS(_tbl_hdr)  (((_tbl_hdr)->tbl_size - \
-                                 RAS_TABLE_HEADER_SIZE) / 
RAS_TABLE_RECORD_SIZE)
+#define RAS_NUM_RECS(_tbl_hdr)                                         \
+       (((_tbl_hdr)->tbl_size < RAS_TABLE_HEADER_SIZE) ? 0u :          \
+        (((_tbl_hdr)->tbl_size - RAS_TABLE_HEADER_SIZE) / 
RAS_TABLE_RECORD_SIZE))
 
-#define RAS_NUM_RECS_V2_1(_tbl_hdr)  (((_tbl_hdr)->tbl_size - \
-                                      RAS_TABLE_HEADER_SIZE - \
-                                      RAS_TABLE_V2_1_INFO_SIZE) / 
RAS_TABLE_RECORD_SIZE)
+#define RAS_NUM_RECS_V2_1(_tbl_hdr)                                    \
+       (((_tbl_hdr)->tbl_size < RAS_TABLE_HEADER_SIZE +                        
\
+         RAS_TABLE_V2_1_INFO_SIZE) ? 0u :                              \
+        (((_tbl_hdr)->tbl_size - RAS_TABLE_HEADER_SIZE -               \
+          RAS_TABLE_V2_1_INFO_SIZE) / RAS_TABLE_RECORD_SIZE))
 
 #define to_amdgpu_device(x) ((container_of(x, struct amdgpu_ras, 
eeprom_control))->adev)
 
@@ -1610,14 +1613,27 @@ int amdgpu_ras_eeprom_init(struct 
amdgpu_ras_eeprom_control *control)
        switch (hdr->version) {
        case RAS_TABLE_VER_V2_1:
        case RAS_TABLE_VER_V3:
-               control->ras_num_recs = RAS_NUM_RECS_V2_1(hdr);
+               if (hdr->tbl_size < RAS_TABLE_HEADER_SIZE + 
RAS_TABLE_V2_1_INFO_SIZE) {
+                       dev_err(adev->dev,
+                               "RAS header invalid, tbl_size %u smaller than 
minimum %u, resetting table\n",
+                               hdr->tbl_size,
+                               RAS_TABLE_HEADER_SIZE + 
RAS_TABLE_V2_1_INFO_SIZE);
+                       return amdgpu_ras_eeprom_reset_table(control);
+               }
                control->ras_record_offset = RAS_RECORD_START_V2_1;
                control->ras_max_record_count = RAS_MAX_RECORD_COUNT_V2_1;
+               control->ras_num_recs = RAS_NUM_RECS_V2_1(hdr);
                break;
        case RAS_TABLE_VER_V1:
-               control->ras_num_recs = RAS_NUM_RECS(hdr);
+               if (hdr->tbl_size < RAS_TABLE_HEADER_SIZE) {
+                       dev_err(adev->dev,
+                               "RAS header invalid, tbl_size %u smaller than 
minimum %u, resetting table\n",
+                               hdr->tbl_size, RAS_TABLE_HEADER_SIZE);
+                       return amdgpu_ras_eeprom_reset_table(control);
+               }
                control->ras_record_offset = RAS_RECORD_START;
                control->ras_max_record_count = RAS_MAX_RECORD_COUNT;
+               control->ras_num_recs = RAS_NUM_RECS(hdr);
                break;
        default:
                dev_err(adev->dev,
-- 
2.25.1

Reply via email to