summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorXiang Liu <xiang.liu@amd.com>2026-06-23 10:59:18 +0800
committerAlex Deucher <alexander.deucher@amd.com>2026-07-01 11:47:46 -0400
commit2bf6867e5953a140fc91c3159987656e44ed29fb (patch)
tree31db2c1dbaab52f02f78620e5735edaad03e74fe /drivers
parent2d222780579fad6c46532d147c795a55d4604bfd (diff)
drm/amd/pm: Guard VBIOS AC timing table walk
Reject AC timing blocks with a stride smaller than a dword before walking VBIOS data. A zero stride can otherwise keep reg_data pinned on a nonmatching MEM_ID forever. Also bound the data-block and END marker reads by the returned VRAM_Info table size so malformed index/data sizes do not push the timing walk past the table. Signed-off-by: Xiang Liu <xiang.liu@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.c
index 1fff7567bca2..4b796d60b03d 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.c
@@ -46,16 +46,22 @@ union voltage_object_info {
static int atomctrl_retrieve_ac_timing(
uint8_t index,
ATOM_INIT_REG_BLOCK *reg_block,
+ u8 *table_end,
pp_atomctrl_mc_reg_table *table)
{
uint32_t i, j;
+ u16 stride = le16_to_cpu(reg_block->usRegDataBlkSize);
uint8_t tmem_id;
ATOM_MEMORY_SETTING_DATA_BLOCK *reg_data = (ATOM_MEMORY_SETTING_DATA_BLOCK *)
((uint8_t *)reg_block + (2 * sizeof(uint16_t)) + le16_to_cpu(reg_block->usRegIndexTblSize));
uint8_t num_ranges = 0;
- while (*(uint32_t *)reg_data != END_OF_REG_DATA_BLOCK &&
+ if (stride < sizeof(uint32_t))
+ return -EINVAL;
+
+ while ((uint8_t *)reg_data + sizeof(uint32_t) <= table_end &&
+ *(uint32_t *)reg_data != END_OF_REG_DATA_BLOCK &&
num_ranges < VBIOS_MAX_AC_TIMING_ENTRIES) {
tmem_id = (uint8_t)((*(uint32_t *)reg_data & MEM_ID_MASK) >> MEM_ID_SHIFT);
@@ -67,6 +73,10 @@ static int atomctrl_retrieve_ac_timing(
for (i = 0, j = 1; i < table->last; i++) {
if ((table->mc_reg_address[i].uc_pre_reg_data &
LOW_NIBBLE_MASK) == DATA_FROM_TABLE) {
+ if ((uint8_t *)reg_data +
+ (j + 1) * sizeof(uint32_t) > table_end)
+ return -EINVAL;
+
table->mc_reg_table_entry[num_ranges].mc_data[i] =
(uint32_t)*((uint32_t *)reg_data + j);
j++;
@@ -81,11 +91,13 @@ static int atomctrl_retrieve_ac_timing(
}
reg_data = (ATOM_MEMORY_SETTING_DATA_BLOCK *)
- ((uint8_t *)reg_data + le16_to_cpu(reg_block->usRegDataBlkSize)) ;
+ ((uint8_t *)reg_data + stride);
}
- PP_ASSERT_WITH_CODE((*(uint32_t *)reg_data == END_OF_REG_DATA_BLOCK),
- "Invalid VramInfo table.", return -1);
+ if ((uint8_t *)reg_data + sizeof(uint32_t) > table_end ||
+ *(uint32_t *)reg_data != END_OF_REG_DATA_BLOCK)
+ return -EINVAL;
+
table->num_entries = num_ranges;
return 0;
@@ -136,6 +148,7 @@ int atomctrl_initialize_mc_reg_table(
{
ATOM_VRAM_INFO_HEADER_V2_1 *vram_info;
ATOM_INIT_REG_BLOCK *reg_block;
+ u8 *table_end;
int result = 0;
u8 frev, crev;
u16 size;
@@ -157,6 +170,7 @@ int atomctrl_initialize_mc_reg_table(
}
if (0 == result) {
+ table_end = (uint8_t *)vram_info + size;
reg_block = (ATOM_INIT_REG_BLOCK *)
((uint8_t *)vram_info + le16_to_cpu(vram_info->usMemClkPatchTblOffset));
result = atomctrl_set_mc_reg_address_table(reg_block, table);
@@ -164,7 +178,7 @@ int atomctrl_initialize_mc_reg_table(
if (0 == result) {
result = atomctrl_retrieve_ac_timing(module_index,
- reg_block, table);
+ reg_block, table_end, table);
}
return result;
@@ -177,6 +191,7 @@ int atomctrl_initialize_mc_reg_table_v2_2(
{
ATOM_VRAM_INFO_HEADER_V2_2 *vram_info;
ATOM_INIT_REG_BLOCK *reg_block;
+ u8 *table_end;
int result = 0;
u8 frev, crev;
u16 size;
@@ -198,6 +213,7 @@ int atomctrl_initialize_mc_reg_table_v2_2(
}
if (0 == result) {
+ table_end = (uint8_t *)vram_info + size;
reg_block = (ATOM_INIT_REG_BLOCK *)
((uint8_t *)vram_info + le16_to_cpu(vram_info->usMemClkPatchTblOffset));
result = atomctrl_set_mc_reg_address_table(reg_block, table);
@@ -205,7 +221,7 @@ int atomctrl_initialize_mc_reg_table_v2_2(
if (0 == result) {
result = atomctrl_retrieve_ac_timing(module_index,
- reg_block, table);
+ reg_block, table_end, table);
}
return result;