Skip to content

Commit a658270

Browse files
AlexiousLualexdeucher
authored andcommitted
drm/amd/pm: fix a double-free in amdgpu_parse_extended_power_table
The amdgpu_free_extended_power_table is called in every error-handling paths of amdgpu_parse_extended_power_table. However, after the following call chain of returning: amdgpu_parse_extended_power_table |-> kv_dpm_init / si_dpm_init (the only two caller of amdgpu_parse_extended_power_table) |-> kv_dpm_sw_init / si_dpm_sw_init (the only caller of kv_dpm_init / si_dpm_init, accordingly) |-> kv_dpm_fini / si_dpm_fini (goto dpm_failed in xx_dpm_sw_init) |-> amdgpu_free_extended_power_table As above, the amdgpu_free_extended_power_table is called twice in this returning chain and thus a double-free is triggered. Similarily, the last kfree in amdgpu_parse_extended_power_table also cause a double free with amdgpu_free_extended_power_table in kv_dpm_fini. Fixes: 8417666 ("drm/amd/pm: create a new holder for those APIs used only by legacy ASICs(si/kv)") Signed-off-by: Zhipeng Lu <alexious@zju.edu.cn> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
1 parent c2709b2 commit a658270

1 file changed

Lines changed: 13 additions & 39 deletions

File tree

drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c

Lines changed: 13 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -272,43 +272,35 @@ int amdgpu_parse_extended_power_table(struct amdgpu_device *adev)
272272
le16_to_cpu(power_info->pplib4.usVddcDependencyOnSCLKOffset));
273273
ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
274274
dep_table);
275-
if (ret) {
276-
amdgpu_free_extended_power_table(adev);
275+
if (ret)
277276
return ret;
278-
}
279277
}
280278
if (power_info->pplib4.usVddciDependencyOnMCLKOffset) {
281279
dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
282280
(mode_info->atom_context->bios + data_offset +
283281
le16_to_cpu(power_info->pplib4.usVddciDependencyOnMCLKOffset));
284282
ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
285283
dep_table);
286-
if (ret) {
287-
amdgpu_free_extended_power_table(adev);
284+
if (ret)
288285
return ret;
289-
}
290286
}
291287
if (power_info->pplib4.usVddcDependencyOnMCLKOffset) {
292288
dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
293289
(mode_info->atom_context->bios + data_offset +
294290
le16_to_cpu(power_info->pplib4.usVddcDependencyOnMCLKOffset));
295291
ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
296292
dep_table);
297-
if (ret) {
298-
amdgpu_free_extended_power_table(adev);
293+
if (ret)
299294
return ret;
300-
}
301295
}
302296
if (power_info->pplib4.usMvddDependencyOnMCLKOffset) {
303297
dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
304298
(mode_info->atom_context->bios + data_offset +
305299
le16_to_cpu(power_info->pplib4.usMvddDependencyOnMCLKOffset));
306300
ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.mvdd_dependency_on_mclk,
307301
dep_table);
308-
if (ret) {
309-
amdgpu_free_extended_power_table(adev);
302+
if (ret)
310303
return ret;
311-
}
312304
}
313305
if (power_info->pplib4.usMaxClockVoltageOnDCOffset) {
314306
ATOM_PPLIB_Clock_Voltage_Limit_Table *clk_v =
@@ -339,10 +331,8 @@ int amdgpu_parse_extended_power_table(struct amdgpu_device *adev)
339331
kcalloc(psl->ucNumEntries,
340332
sizeof(struct amdgpu_phase_shedding_limits_entry),
341333
GFP_KERNEL);
342-
if (!adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) {
343-
amdgpu_free_extended_power_table(adev);
334+
if (!adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries)
344335
return -ENOMEM;
345-
}
346336

347337
entry = &psl->entries[0];
348338
for (i = 0; i < psl->ucNumEntries; i++) {
@@ -383,10 +373,8 @@ int amdgpu_parse_extended_power_table(struct amdgpu_device *adev)
383373
ATOM_PPLIB_CAC_Leakage_Record *entry;
384374
u32 size = cac_table->ucNumEntries * sizeof(struct amdgpu_cac_leakage_table);
385375
adev->pm.dpm.dyn_state.cac_leakage_table.entries = kzalloc(size, GFP_KERNEL);
386-
if (!adev->pm.dpm.dyn_state.cac_leakage_table.entries) {
387-
amdgpu_free_extended_power_table(adev);
376+
if (!adev->pm.dpm.dyn_state.cac_leakage_table.entries)
388377
return -ENOMEM;
389-
}
390378
entry = &cac_table->entries[0];
391379
for (i = 0; i < cac_table->ucNumEntries; i++) {
392380
if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) {
@@ -438,10 +426,8 @@ int amdgpu_parse_extended_power_table(struct amdgpu_device *adev)
438426
sizeof(struct amdgpu_vce_clock_voltage_dependency_entry);
439427
adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries =
440428
kzalloc(size, GFP_KERNEL);
441-
if (!adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries) {
442-
amdgpu_free_extended_power_table(adev);
429+
if (!adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries)
443430
return -ENOMEM;
444-
}
445431
adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count =
446432
limits->numEntries;
447433
entry = &limits->entries[0];
@@ -493,10 +479,8 @@ int amdgpu_parse_extended_power_table(struct amdgpu_device *adev)
493479
sizeof(struct amdgpu_uvd_clock_voltage_dependency_entry);
494480
adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries =
495481
kzalloc(size, GFP_KERNEL);
496-
if (!adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) {
497-
amdgpu_free_extended_power_table(adev);
482+
if (!adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries)
498483
return -ENOMEM;
499-
}
500484
adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count =
501485
limits->numEntries;
502486
entry = &limits->entries[0];
@@ -525,10 +509,8 @@ int amdgpu_parse_extended_power_table(struct amdgpu_device *adev)
525509
sizeof(struct amdgpu_clock_voltage_dependency_entry);
526510
adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries =
527511
kzalloc(size, GFP_KERNEL);
528-
if (!adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) {
529-
amdgpu_free_extended_power_table(adev);
512+
if (!adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries)
530513
return -ENOMEM;
531-
}
532514
adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.count =
533515
limits->numEntries;
534516
entry = &limits->entries[0];
@@ -548,10 +530,8 @@ int amdgpu_parse_extended_power_table(struct amdgpu_device *adev)
548530
le16_to_cpu(ext_hdr->usPPMTableOffset));
549531
adev->pm.dpm.dyn_state.ppm_table =
550532
kzalloc(sizeof(struct amdgpu_ppm_table), GFP_KERNEL);
551-
if (!adev->pm.dpm.dyn_state.ppm_table) {
552-
amdgpu_free_extended_power_table(adev);
533+
if (!adev->pm.dpm.dyn_state.ppm_table)
553534
return -ENOMEM;
554-
}
555535
adev->pm.dpm.dyn_state.ppm_table->ppm_design = ppm->ucPpmDesign;
556536
adev->pm.dpm.dyn_state.ppm_table->cpu_core_number =
557537
le16_to_cpu(ppm->usCpuCoreNumber);
@@ -583,10 +563,8 @@ int amdgpu_parse_extended_power_table(struct amdgpu_device *adev)
583563
sizeof(struct amdgpu_clock_voltage_dependency_entry);
584564
adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries =
585565
kzalloc(size, GFP_KERNEL);
586-
if (!adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries) {
587-
amdgpu_free_extended_power_table(adev);
566+
if (!adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries)
588567
return -ENOMEM;
589-
}
590568
adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.count =
591569
limits->numEntries;
592570
entry = &limits->entries[0];
@@ -606,10 +584,8 @@ int amdgpu_parse_extended_power_table(struct amdgpu_device *adev)
606584
ATOM_PowerTune_Table *pt;
607585
adev->pm.dpm.dyn_state.cac_tdp_table =
608586
kzalloc(sizeof(struct amdgpu_cac_tdp_table), GFP_KERNEL);
609-
if (!adev->pm.dpm.dyn_state.cac_tdp_table) {
610-
amdgpu_free_extended_power_table(adev);
587+
if (!adev->pm.dpm.dyn_state.cac_tdp_table)
611588
return -ENOMEM;
612-
}
613589
if (rev > 0) {
614590
ATOM_PPLIB_POWERTUNE_Table_V1 *ppt = (ATOM_PPLIB_POWERTUNE_Table_V1 *)
615591
(mode_info->atom_context->bios + data_offset +
@@ -645,10 +621,8 @@ int amdgpu_parse_extended_power_table(struct amdgpu_device *adev)
645621
ret = amdgpu_parse_clk_voltage_dep_table(
646622
&adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk,
647623
dep_table);
648-
if (ret) {
649-
kfree(adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk.entries);
624+
if (ret)
650625
return ret;
651-
}
652626
}
653627
}
654628

0 commit comments

Comments
 (0)