diff options
| author | Asad Kamal <asad.kamal@amd.com> | 2026-06-23 00:00:00 +0000 |
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2026-07-01 11:25:52 -0400 |
| commit | f14f99fffce215f7bb4d3400193da01a43086c7b (patch) | |
| tree | 9df399b2786222029414dcb72b1907bca4b8b6b7 | |
| parent | c42871ba4833855fb3ac1cdc586b3c5345d09e5d (diff) | |
| download | linux-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.c | 80 |
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); |
