[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