]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/amd/ras: validate RAS EEPROM tbl_size before record count
authorCandice Li <candice.li@amd.com>
Tue, 19 May 2026 09:31:21 +0000 (17:31 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 3 Jun 2026 17:52:55 +0000 (13:52 -0400)
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 <candice.li@amd.com>
Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/ras/rascore/ras_eeprom.c

index 34b798f45af21018cd6ec4a380e404dfdd3994ff..3a0ea036c9be980739f197cc1aa3a69d21b0dfaa 100644 (file)
 #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_ras_core_context(x) (container_of(x, struct ras_core_context, ras_eeprom))
 
@@ -1139,11 +1142,24 @@ static int __check_ras_table_status(struct ras_core_context *ras_core)
        switch (hdr->version) {
        case RAS_TABLE_VER_V2_1:
        case RAS_TABLE_VER_V3:
+               if (hdr->tbl_size < RAS_TABLE_HEADER_SIZE + RAS_TABLE_V2_1_INFO_SIZE) {
+                       RAS_DEV_ERR(ras_core->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 ras_eeprom_reset_table(ras_core);
+               }
                control->ras_num_recs = RAS_NUM_RECS_V2_1(hdr);
                control->ras_record_offset = RAS_RECORD_START_V2_1;
                control->ras_max_record_count = RAS_MAX_RECORD_COUNT_V2_1;
                break;
        case RAS_TABLE_VER_V1:
+               if (hdr->tbl_size < RAS_TABLE_HEADER_SIZE) {
+                       RAS_DEV_ERR(ras_core->dev,
+                               "RAS header invalid, tbl_size %u smaller than minimum %u, resetting table\n",
+                               hdr->tbl_size, RAS_TABLE_HEADER_SIZE);
+                       return ras_eeprom_reset_table(ras_core);
+               }
                control->ras_num_recs = RAS_NUM_RECS(hdr);
                control->ras_record_offset = RAS_RECORD_START;
                control->ras_max_record_count = RAS_MAX_RECORD_COUNT;