Commit b3e3720f authored by Junhao He's avatar Junhao He Committed by Luo Gengkun
Browse files

perf: hisi: Fix use-after-free when register pmu fails

mainline inclusion
from mainline-v6.7-rc1
commit b805cafc604bfdb671fae7347a57f51154afa735
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9RKWV
CVE: CVE-2023-52859

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b805cafc604bfdb671fae7347a57f51154afa735



--------------------------------

When we fail to register the uncore pmu, the pmu context may not been
allocated. The error handing will call cpuhp_state_remove_instance()
to call uncore pmu offline callback, which migrate the pmu context.
Since that's liable to lead to some kind of use-after-free.

Use cpuhp_state_remove_instance_nocalls() instead of
cpuhp_state_remove_instance() so that the notifiers don't execute after
the PMU device has been failed to register.

Fixes: a0ab25cd ("drivers/perf: hisi: Add support for HiSilicon PA PMU driver")
FIxes: 3bf30882 ("drivers/perf: hisi: Add support for HiSilicon SLLC PMU driver")
Signed-off-by: default avatarJunhao He <hejunhao3@huawei.com>
Link: https://lore.kernel.org/r/20231024113630.13472-1-hejunhao3@huawei.com


Signed-off-by: default avatarWill Deacon <will@kernel.org>
Signed-off-by: default avatarLuo Gengkun <luogengkun2@huawei.com>
parent 5d32aa69
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -430,7 +430,7 @@ static int hisi_pa_pmu_probe(struct platform_device *pdev)
	ret = perf_pmu_register(&pa_pmu->pmu, name, -1);
	if (ret) {
		dev_err(pa_pmu->dev, "PMU register failed, ret = %d\n", ret);
		cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
		cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
						    &pa_pmu->node);
		return ret;
	}
+2 −2
Original line number Diff line number Diff line
@@ -463,7 +463,7 @@ static int hisi_sllc_pmu_probe(struct platform_device *pdev)
	ret = perf_pmu_register(&sllc_pmu->pmu, name, -1);
	if (ret) {
		dev_err(sllc_pmu->dev, "PMU register failed, ret = %d\n", ret);
		cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
		cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
						    &sllc_pmu->node);
		return ret;
	}