drm/radeon: Avoid power table parsing memory leaks

[ Upstream commit c69f27137a38d24301a6b659454a91ad85dff4aa ]

Avoid leaving a hanging pre-allocated clock_info if last mode is
invalid, and avoid heap corruption if no valid modes are found.

Bug: https://bugzilla.kernel.org/show_bug.cgi?id=211537
Fixes: 6991b8f2a3 ("drm/radeon/kms: fix segfault in pm rework")
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Kees Cook 2021-05-02 22:06:08 -07:00 committed by Greg Kroah-Hartman
parent 8e0b76725c
commit 1816d1b327
1 changed files with 15 additions and 5 deletions

View File

@ -2136,11 +2136,14 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev)
return state_index;
/* last mode is usually default, array is low to high */
for (i = 0; i < num_modes; i++) {
rdev->pm.power_state[state_index].clock_info =
kcalloc(1, sizeof(struct radeon_pm_clock_info),
GFP_KERNEL);
/* avoid memory leaks from invalid modes or unknown frev. */
if (!rdev->pm.power_state[state_index].clock_info) {
rdev->pm.power_state[state_index].clock_info =
kzalloc(sizeof(struct radeon_pm_clock_info),
GFP_KERNEL);
}
if (!rdev->pm.power_state[state_index].clock_info)
return state_index;
goto out;
rdev->pm.power_state[state_index].num_clock_modes = 1;
rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
switch (frev) {
@ -2259,8 +2262,15 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev)
break;
}
}
out:
/* free any unused clock_info allocation. */
if (state_index && state_index < num_modes) {
kfree(rdev->pm.power_state[state_index].clock_info);
rdev->pm.power_state[state_index].clock_info = NULL;
}
/* last mode is usually default */
if (rdev->pm.default_power_state_index == -1) {
if (state_index && rdev->pm.default_power_state_index == -1) {
rdev->pm.power_state[state_index - 1].type =
POWER_STATE_TYPE_DEFAULT;
rdev->pm.default_power_state_index = state_index - 1;