Commit c69f2713 authored by Kees Cook's avatar Kees Cook Committed by Alex Deucher
Browse files

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: 6991b8f2 ("drm/radeon/kms: fix segfault in pm rework")
Signed-off-by: default avatarKees Cook <keescook@chromium.org>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 5bbf2193
Loading
Loading
Loading
Loading
+15 −5
Original line number Diff line number Diff line
@@ -2120,11 +2120,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++) {
		/* 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 =
			kcalloc(1, sizeof(struct radeon_pm_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) {
@@ -2243,8 +2246,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;