[PATCH v1 2/3] cpufreq: mediatek: fix KP caused by handler usage after regulator_put/clk_put

jia-wei.chang jia-wei.chang at mediatek.com
Thu Mar 9 21:17:49 PST 2023


From: "Jia-Wei Chang" <jia-wei.chang at mediatek.com>

Any kind of failure in mtk_cpu_dvfs_info_init() will lead to calling
regulator_put() or clk_put() and the KP will occur since the regulator/clk
handlers are used after released in mtk_cpu_dvfs_info_release().

To prevent the usage after regulator_put()/clk_put(), the regulator/clk
handlers are reassigned to NULL value for validation check afterwards.

Signed-off-by: Jia-Wei Chang <jia-wei.chang at mediatek.com>
Fixes: 4b9ceb757bbb ("cpufreq: mediatek: Enable clocks and regulators")
Reported-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
Link: https://lore.kernel.org/linux-arm-kernel/20220921071913.p7kwsjnnuad2jgvk@vireshk-i7/T/
---
 drivers/cpufreq/mediatek-cpufreq.c | 28 ++++++++++++++++++++--------
 1 file changed, 20 insertions(+), 8 deletions(-)

diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
index 01d949707c37..cb8b76f9c2c3 100644
--- a/drivers/cpufreq/mediatek-cpufreq.c
+++ b/drivers/cpufreq/mediatek-cpufreq.c
@@ -539,35 +539,47 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
 	if (info->sram_reg && regulator_is_enabled(info->sram_reg))
 		regulator_disable(info->sram_reg);
 
-	if (!IS_ERR(info->proc_reg))
+	if (!IS_ERR(info->proc_reg)) {
 		regulator_put(info->proc_reg);
-	if (!IS_ERR(info->sram_reg))
+		info->proc_reg = NULL;
+	}
+	if (!IS_ERR(info->sram_reg)) {
 		regulator_put(info->sram_reg);
-	if (!IS_ERR(info->cpu_clk))
+		info->sram_reg = NULL;
+	}
+	if (!IS_ERR(info->cpu_clk)) {
 		clk_put(info->cpu_clk);
-	if (!IS_ERR(info->inter_clk))
+		info->cpu_clk = NULL;
+	}
+	if (!IS_ERR(info->inter_clk)) {
 		clk_put(info->inter_clk);
+		info->inter_clk = NULL;
+	}
 
 	return ret;
 }
 
 static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info)
 {
-	if (!IS_ERR(info->proc_reg)) {
+	if (!IS_ERR_OR_NULL(info->proc_reg)) {
 		regulator_disable(info->proc_reg);
 		regulator_put(info->proc_reg);
+		info->proc_reg = NULL;
 	}
-	if (!IS_ERR(info->sram_reg)) {
+	if (!IS_ERR_OR_NULL(info->sram_reg)) {
 		regulator_disable(info->sram_reg);
 		regulator_put(info->sram_reg);
+		info->sram_reg = NULL;
 	}
-	if (!IS_ERR(info->cpu_clk)) {
+	if (!IS_ERR_OR_NULL(info->cpu_clk)) {
 		clk_disable_unprepare(info->cpu_clk);
 		clk_put(info->cpu_clk);
+		info->cpu_clk = NULL;
 	}
-	if (!IS_ERR(info->inter_clk)) {
+	if (!IS_ERR_OR_NULL(info->inter_clk)) {
 		clk_disable_unprepare(info->inter_clk);
 		clk_put(info->inter_clk);
+		info->inter_clk = NULL;
 	}
 
 	dev_pm_opp_of_cpumask_remove_table(&info->cpus);
-- 
2.18.0




More information about the linux-arm-kernel mailing list