drm/radeon: Avoid power table parsing memory leaks
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>
This commit is contained in:
@@ -2120,11 +2120,14 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev)
|
|||||||
return state_index;
|
return state_index;
|
||||||
/* last mode is usually default, array is low to high */
|
/* last mode is usually default, array is low to high */
|
||||||
for (i = 0; i < num_modes; i++) {
|
for (i = 0; i < num_modes; i++) {
|
||||||
|
/* 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 =
|
rdev->pm.power_state[state_index].clock_info =
|
||||||
kcalloc(1, sizeof(struct radeon_pm_clock_info),
|
kzalloc(sizeof(struct radeon_pm_clock_info),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
|
}
|
||||||
if (!rdev->pm.power_state[state_index].clock_info)
|
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].num_clock_modes = 1;
|
||||||
rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
|
rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
|
||||||
switch (frev) {
|
switch (frev) {
|
||||||
@@ -2243,8 +2246,15 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev)
|
|||||||
break;
|
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 */
|
/* 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 =
|
rdev->pm.power_state[state_index - 1].type =
|
||||||
POWER_STATE_TYPE_DEFAULT;
|
POWER_STATE_TYPE_DEFAULT;
|
||||||
rdev->pm.default_power_state_index = state_index - 1;
|
rdev->pm.default_power_state_index = state_index - 1;
|
||||||
|
Reference in New Issue
Block a user