summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAsad Kamal <asad.kamal@amd.com>2026-06-23 00:00:00 +0000
committerAlex Deucher <alexander.deucher@amd.com>2026-07-01 11:25:52 -0400
commitf14f99fffce215f7bb4d3400193da01a43086c7b (patch)
tree9df399b2786222029414dcb72b1907bca4b8b6b7
parentc42871ba4833855fb3ac1cdc586b3c5345d09e5d (diff)
downloadlinux-stable-f14f99fffce215f7bb4d3400193da01a43086c7b.tar.gz
linux-stable-f14f99fffce215f7bb4d3400193da01a43086c7b.zip
drm/amdgpu/pm/powerplay: clamp Tonga/Polaris PP sub-table ucNumEntries
ucNumEntries in the Tonga/Polaris PowerPlay sub-tables is used as both the kzalloc count and loop bound without validation, allowing a crafted VBIOS to overflow the destination heap object and read past the VBIOS image. Clamp via pp_entries_max() in get_vddc_lookup_table(), get_mclk_voltage_dependency_table(), get_sclk_voltage_dependency_table() and get_mm_clock_voltage_table(). Fixes: c82baa281843 ("drm/amd/powerplay: add Tonga dpm support (v3)") Signed-off-by: Asad Kamal <asad.kamal@amd.com> Reviewed-by: Lijo Lazar <lijo.lazar@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/pm/powerplay/hwmgr/process_pptables_v1_0.c80
1 files changed, 61 insertions, 19 deletions
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.c
index 6fcca65bd7d4..d459ae9cf8a6 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.c
@@ -158,6 +158,7 @@ static int get_vddc_lookup_table(
)
{
uint32_t i;
+ uint32_t num_entries;
phm_ppt_v1_voltage_lookup_table *table;
phm_ppt_v1_voltage_lookup_record *record;
ATOM_Tonga_Voltage_Lookup_Record *atom_record;
@@ -165,13 +166,22 @@ static int get_vddc_lookup_table(
PP_ASSERT_WITH_CODE((0 != vddc_lookup_pp_tables->ucNumEntries),
"Invalid CAC Leakage PowerPlay Table!", return 1);
- table = kzalloc_flex(*table, entries, max_levels);
+ num_entries = min_t(uint32_t, vddc_lookup_pp_tables->ucNumEntries,
+ min_t(uint32_t, max_levels,
+ pp_entries_max(hwmgr, vddc_lookup_pp_tables,
+ sizeof(*vddc_lookup_pp_tables),
+ sizeof(ATOM_Tonga_Voltage_Lookup_Record))));
+ if (num_entries < vddc_lookup_pp_tables->ucNumEntries)
+ pr_warn("amdgpu: VddcLookup table: clamping ucNumEntries %u -> %u\n",
+ vddc_lookup_pp_tables->ucNumEntries, num_entries);
+
+ table = kzalloc_flex(*table, entries, num_entries);
if (!table)
return -ENOMEM;
- table->count = vddc_lookup_pp_tables->ucNumEntries;
+ table->count = num_entries;
- for (i = 0; i < vddc_lookup_pp_tables->ucNumEntries; i++) {
+ for (i = 0; i < num_entries; i++) {
record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
phm_ppt_v1_voltage_lookup_record,
entries, table, i);
@@ -363,6 +373,7 @@ static int get_mclk_voltage_dependency_table(
)
{
uint32_t i;
+ uint32_t num_entries;
phm_ppt_v1_clock_voltage_dependency_table *mclk_table;
phm_ppt_v1_clock_voltage_dependency_record *mclk_table_record;
ATOM_Tonga_MCLK_Dependency_Record *mclk_dep_record;
@@ -370,14 +381,21 @@ static int get_mclk_voltage_dependency_table(
PP_ASSERT_WITH_CODE((0 != mclk_dep_table->ucNumEntries),
"Invalid PowerPlay Table!", return -1);
- mclk_table = kzalloc_flex(*mclk_table, entries,
- mclk_dep_table->ucNumEntries);
+ num_entries = min_t(uint32_t, mclk_dep_table->ucNumEntries,
+ pp_entries_max(hwmgr, mclk_dep_table,
+ sizeof(*mclk_dep_table),
+ sizeof(ATOM_Tonga_MCLK_Dependency_Record)));
+ if (num_entries < mclk_dep_table->ucNumEntries)
+ pr_warn("amdgpu: MCLK dependency table: clamping ucNumEntries %u -> %u\n",
+ mclk_dep_table->ucNumEntries, num_entries);
+
+ mclk_table = kzalloc_flex(*mclk_table, entries, num_entries);
if (!mclk_table)
return -ENOMEM;
- mclk_table->count = (uint32_t)mclk_dep_table->ucNumEntries;
+ mclk_table->count = num_entries;
- for (i = 0; i < mclk_dep_table->ucNumEntries; i++) {
+ for (i = 0; i < num_entries; i++) {
mclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
phm_ppt_v1_clock_voltage_dependency_record,
entries, mclk_table, i);
@@ -403,6 +421,7 @@ static int get_sclk_voltage_dependency_table(
)
{
uint32_t i;
+ uint32_t num_entries;
phm_ppt_v1_clock_voltage_dependency_table *sclk_table;
phm_ppt_v1_clock_voltage_dependency_record *sclk_table_record;
@@ -414,14 +433,21 @@ static int get_sclk_voltage_dependency_table(
PP_ASSERT_WITH_CODE((0 != tonga_table->ucNumEntries),
"Invalid PowerPlay Table!", return -1);
- sclk_table = kzalloc_flex(*sclk_table, entries,
- tonga_table->ucNumEntries);
+ num_entries = min_t(uint32_t, tonga_table->ucNumEntries,
+ pp_entries_max(hwmgr, tonga_table,
+ sizeof(*tonga_table),
+ sizeof(ATOM_Tonga_SCLK_Dependency_Record)));
+ if (num_entries < tonga_table->ucNumEntries)
+ pr_warn("amdgpu: Tonga SCLK dependency table: clamping ucNumEntries %u -> %u\n",
+ tonga_table->ucNumEntries, num_entries);
+
+ sclk_table = kzalloc_flex(*sclk_table, entries, num_entries);
if (!sclk_table)
return -ENOMEM;
- sclk_table->count = (uint32_t)tonga_table->ucNumEntries;
+ sclk_table->count = num_entries;
- for (i = 0; i < tonga_table->ucNumEntries; i++) {
+ for (i = 0; i < num_entries; i++) {
sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
ATOM_Tonga_SCLK_Dependency_Record,
entries, tonga_table, i);
@@ -443,14 +469,21 @@ static int get_sclk_voltage_dependency_table(
PP_ASSERT_WITH_CODE((0 != polaris_table->ucNumEntries),
"Invalid PowerPlay Table!", return -1);
- sclk_table = kzalloc_flex(*sclk_table, entries,
- polaris_table->ucNumEntries);
+ num_entries = min_t(uint32_t, polaris_table->ucNumEntries,
+ pp_entries_max(hwmgr, polaris_table,
+ sizeof(*polaris_table),
+ sizeof(ATOM_Polaris_SCLK_Dependency_Record)));
+ if (num_entries < polaris_table->ucNumEntries)
+ pr_warn("amdgpu: Polaris SCLK dependency table: clamping ucNumEntries %u -> %u\n",
+ polaris_table->ucNumEntries, num_entries);
+
+ sclk_table = kzalloc_flex(*sclk_table, entries, num_entries);
if (!sclk_table)
return -ENOMEM;
- sclk_table->count = (uint32_t)polaris_table->ucNumEntries;
+ sclk_table->count = num_entries;
- for (i = 0; i < polaris_table->ucNumEntries; i++) {
+ for (i = 0; i < num_entries; i++) {
sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
ATOM_Polaris_SCLK_Dependency_Record,
entries, polaris_table, i);
@@ -715,20 +748,29 @@ static int get_mm_clock_voltage_table(
)
{
uint32_t i;
+ uint32_t num_entries;
const ATOM_Tonga_MM_Dependency_Record *mm_dependency_record;
phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table;
phm_ppt_v1_mm_clock_voltage_dependency_record *mm_table_record;
PP_ASSERT_WITH_CODE((0 != mm_dependency_table->ucNumEntries),
"Invalid PowerPlay Table!", return -1);
- mm_table = kzalloc_flex(*mm_table, entries,
- mm_dependency_table->ucNumEntries);
+
+ num_entries = min_t(uint32_t, mm_dependency_table->ucNumEntries,
+ pp_entries_max(hwmgr, mm_dependency_table,
+ sizeof(*mm_dependency_table),
+ sizeof(ATOM_Tonga_MM_Dependency_Record)));
+ if (num_entries < mm_dependency_table->ucNumEntries)
+ pr_warn("amdgpu: MM dependency table: clamping ucNumEntries %u -> %u\n",
+ mm_dependency_table->ucNumEntries, num_entries);
+
+ mm_table = kzalloc_flex(*mm_table, entries, num_entries);
if (!mm_table)
return -ENOMEM;
- mm_table->count = mm_dependency_table->ucNumEntries;
+ mm_table->count = num_entries;
- for (i = 0; i < mm_dependency_table->ucNumEntries; i++) {
+ for (i = 0; i < num_entries; i++) {
mm_dependency_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
ATOM_Tonga_MM_Dependency_Record,
entries, mm_dependency_table, i);