Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

radeon: avoid double free in ci_dpm_init()

Several calls to ci_dpm_fini() will attempt to free resources that
either have been freed before or haven't been allocated yet. This
may lead to undefined or dangerous behaviour.

For instance, if r600_parse_extended_power_table() fails, it might
call r600_free_extended_power_table() as will ci_dpm_fini() later
during error handling.

Fix this by only freeing pointers to objects previously allocated.

Found by Linux Verification Center (linuxtesting.org) with static
analysis tool SVACE.

Fixes: cc8dbbb4f62a ("drm/radeon: add dpm support for CI dGPUs (v2)")
Co-developed-by: Natalia Petrova <n.petrova@fintech.ru>
Signed-off-by: Nikita Zhandarovich <n.zhandarovich@fintech.ru>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Nikita Zhandarovich and committed by
Alex Deucher
20c3dffd 94344e62

+20 -8
+20 -8
drivers/gpu/drm/radeon/ci_dpm.c
··· 5517 5517 u8 frev, crev; 5518 5518 u8 *power_state_offset; 5519 5519 struct ci_ps *ps; 5520 + int ret; 5520 5521 5521 5522 if (!atom_parse_data_header(mode_info->atom_context, index, NULL, 5522 5523 &frev, &crev, &data_offset)) ··· 5547 5546 non_clock_array_index = power_state->v2.nonClockInfoIndex; 5548 5547 non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) 5549 5548 &non_clock_info_array->nonClockInfo[non_clock_array_index]; 5550 - if (!rdev->pm.power_state[i].clock_info) 5551 - return -EINVAL; 5549 + if (!rdev->pm.power_state[i].clock_info) { 5550 + ret = -EINVAL; 5551 + goto err_free_ps; 5552 + } 5552 5553 ps = kzalloc(sizeof(struct ci_ps), GFP_KERNEL); 5553 - if (ps == NULL) 5554 - return -ENOMEM; 5554 + if (ps == NULL) { 5555 + ret = -ENOMEM; 5556 + goto err_free_ps; 5557 + } 5555 5558 rdev->pm.dpm.ps[i].ps_priv = ps; 5556 5559 ci_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i], 5557 5560 non_clock_info, ··· 5595 5590 } 5596 5591 5597 5592 return 0; 5593 + 5594 + err_free_ps: 5595 + for (i = 0; i < rdev->pm.dpm.num_ps; i++) 5596 + kfree(rdev->pm.dpm.ps[i].ps_priv); 5597 + kfree(rdev->pm.dpm.ps); 5598 + return ret; 5598 5599 } 5599 5600 5600 5601 static int ci_get_vbios_boot_values(struct radeon_device *rdev, ··· 5689 5678 5690 5679 ret = ci_get_vbios_boot_values(rdev, &pi->vbios_boot_state); 5691 5680 if (ret) { 5692 - ci_dpm_fini(rdev); 5681 + kfree(rdev->pm.dpm.priv); 5693 5682 return ret; 5694 5683 } 5695 5684 5696 5685 ret = r600_get_platform_caps(rdev); 5697 5686 if (ret) { 5698 - ci_dpm_fini(rdev); 5687 + kfree(rdev->pm.dpm.priv); 5699 5688 return ret; 5700 5689 } 5701 5690 5702 5691 ret = r600_parse_extended_power_table(rdev); 5703 5692 if (ret) { 5704 - ci_dpm_fini(rdev); 5693 + kfree(rdev->pm.dpm.priv); 5705 5694 return ret; 5706 5695 } 5707 5696 5708 5697 ret = ci_parse_power_table(rdev); 5709 5698 if (ret) { 5710 - ci_dpm_fini(rdev); 5699 + kfree(rdev->pm.dpm.priv); 5700 + r600_free_extended_power_table(rdev); 5711 5701 return ret; 5712 5702 } 5713 5703