summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCandice Li <candice.li@amd.com>2026-05-19 17:31:21 +0800
committerAlex Deucher <alexander.deucher@amd.com>2026-06-03 13:52:55 -0400
commite5565e7c3fada97f8b95c9704df80db85feafea4 (patch)
tree31bbfbee7440a305bdfb3555d49cdfe713e55fb7
parenta4b0c3f5d2287997876d8f711a40d3c0418458d8 (diff)
drm/amd/ras: validate RAS EEPROM tbl_size before record count
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>
-rw-r--r--drivers/gpu/drm/amd/ras/rascore/ras_eeprom.c26
1 files changed, 21 insertions, 5 deletions
diff --git a/drivers/gpu/drm/amd/ras/rascore/ras_eeprom.c b/drivers/gpu/drm/amd/ras/rascore/ras_eeprom.c
index 34b798f45af2..3a0ea036c9be 100644
--- a/drivers/gpu/drm/amd/ras/rascore/ras_eeprom.c
+++ b/drivers/gpu/drm/amd/ras/rascore/ras_eeprom.c
@@ -141,12 +141,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_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;