Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: mediatek: fix use-after-free in driver remove

Merge series from Trevor Wu <trevor.wu@mediatek.com>:

These patches concern modifications made in mt8186[1]. The clock
unregistration mechanism used in mt8188 and mt8195 is similar with
mt8186, resulting in the same problem existing within the driver.
Therefore, the solution has also been applied to these two platforms.

[1] https://lore.kernel.org/all/20230511092437.1.I31cceffc8c45bb1af16eb613e197b3df92cdc19e@changeid/

+48 -70
-7
sound/soc/mediatek/mt8188/mt8188-afe-clk.c
··· 418 418 return 0; 419 419 } 420 420 421 - void mt8188_afe_deinit_clock(void *priv) 422 - { 423 - struct mtk_base_afe *afe = priv; 424 - 425 - mt8188_audsys_clk_unregister(afe); 426 - } 427 - 428 421 int mt8188_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk) 429 422 { 430 423 int ret;
-1
sound/soc/mediatek/mt8188/mt8188-afe-clk.h
··· 100 100 int mt8188_afe_get_mclk_source_rate(struct mtk_base_afe *afe, int apll); 101 101 int mt8188_afe_get_default_mclk_source_by_rate(int rate); 102 102 int mt8188_afe_init_clock(struct mtk_base_afe *afe); 103 - void mt8188_afe_deinit_clock(void *priv); 104 103 int mt8188_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk); 105 104 void mt8188_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk); 106 105 int mt8188_afe_set_clk_rate(struct mtk_base_afe *afe, struct clk *clk,
-4
sound/soc/mediatek/mt8188/mt8188-afe-pcm.c
··· 3185 3185 if (ret) 3186 3186 return dev_err_probe(dev, ret, "init clock error"); 3187 3187 3188 - ret = devm_add_action_or_reset(dev, mt8188_afe_deinit_clock, (void *)afe); 3189 - if (ret) 3190 - return ret; 3191 - 3192 3188 spin_lock_init(&afe_priv->afe_ctrl_lock); 3193 3189 3194 3190 mutex_init(&afe->irq_alloc_lock);
+24 -23
sound/soc/mediatek/mt8188/mt8188-audsys-clk.c
··· 138 138 GATE_AUD6(CLK_AUD_GASRC11, "aud_gasrc11", "top_asm_h", 11), 139 139 }; 140 140 141 + static void mt8188_audsys_clk_unregister(void *data) 142 + { 143 + struct mtk_base_afe *afe = data; 144 + struct mt8188_afe_private *afe_priv = afe->platform_priv; 145 + struct clk *clk; 146 + struct clk_lookup *cl; 147 + int i; 148 + 149 + if (!afe_priv) 150 + return; 151 + 152 + for (i = 0; i < CLK_AUD_NR_CLK; i++) { 153 + cl = afe_priv->lookup[i]; 154 + if (!cl) 155 + continue; 156 + 157 + clk = cl->clk; 158 + clk_unregister_gate(clk); 159 + 160 + clkdev_drop(cl); 161 + } 162 + } 163 + 141 164 int mt8188_audsys_clk_register(struct mtk_base_afe *afe) 142 165 { 143 166 struct mt8188_afe_private *afe_priv = afe->platform_priv; ··· 202 179 afe_priv->lookup[i] = cl; 203 180 } 204 181 205 - return 0; 206 - } 207 - 208 - void mt8188_audsys_clk_unregister(struct mtk_base_afe *afe) 209 - { 210 - struct mt8188_afe_private *afe_priv = afe->platform_priv; 211 - struct clk *clk; 212 - struct clk_lookup *cl; 213 - int i; 214 - 215 - if (!afe_priv) 216 - return; 217 - 218 - for (i = 0; i < CLK_AUD_NR_CLK; i++) { 219 - cl = afe_priv->lookup[i]; 220 - if (!cl) 221 - continue; 222 - 223 - clk = cl->clk; 224 - clk_unregister_gate(clk); 225 - 226 - clkdev_drop(cl); 227 - } 182 + return devm_add_action_or_reset(afe->dev, mt8188_audsys_clk_unregister, afe); 228 183 }
-1
sound/soc/mediatek/mt8188/mt8188-audsys-clk.h
··· 10 10 #define _MT8188_AUDSYS_CLK_H_ 11 11 12 12 int mt8188_audsys_clk_register(struct mtk_base_afe *afe); 13 - void mt8188_audsys_clk_unregister(struct mtk_base_afe *afe); 14 13 15 14 #endif
-5
sound/soc/mediatek/mt8195/mt8195-afe-clk.c
··· 410 410 return 0; 411 411 } 412 412 413 - void mt8195_afe_deinit_clock(struct mtk_base_afe *afe) 414 - { 415 - mt8195_audsys_clk_unregister(afe); 416 - } 417 - 418 413 int mt8195_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk) 419 414 { 420 415 int ret;
-1
sound/soc/mediatek/mt8195/mt8195-afe-clk.h
··· 101 101 int mt8195_afe_get_mclk_source_rate(struct mtk_base_afe *afe, int apll); 102 102 int mt8195_afe_get_default_mclk_source_by_rate(int rate); 103 103 int mt8195_afe_init_clock(struct mtk_base_afe *afe); 104 - void mt8195_afe_deinit_clock(struct mtk_base_afe *afe); 105 104 int mt8195_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk); 106 105 void mt8195_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk); 107 106 int mt8195_afe_prepare_clk(struct mtk_base_afe *afe, struct clk *clk);
-4
sound/soc/mediatek/mt8195/mt8195-afe-pcm.c
··· 3255 3255 3256 3256 static void mt8195_afe_pcm_dev_remove(struct platform_device *pdev) 3257 3257 { 3258 - struct mtk_base_afe *afe = platform_get_drvdata(pdev); 3259 - 3260 3258 snd_soc_unregister_component(&pdev->dev); 3261 3259 3262 3260 pm_runtime_disable(&pdev->dev); 3263 3261 if (!pm_runtime_status_suspended(&pdev->dev)) 3264 3262 mt8195_afe_runtime_suspend(&pdev->dev); 3265 - 3266 - mt8195_afe_deinit_clock(afe); 3267 3263 } 3268 3264 3269 3265 static const struct of_device_id mt8195_afe_pcm_dt_match[] = {
+24 -23
sound/soc/mediatek/mt8195/mt8195-audsys-clk.c
··· 148 148 GATE_AUD6(CLK_AUD_GASRC19, "aud_gasrc19", "top_asm_h", 19), 149 149 }; 150 150 151 + static void mt8195_audsys_clk_unregister(void *data) 152 + { 153 + struct mtk_base_afe *afe = data; 154 + struct mt8195_afe_private *afe_priv = afe->platform_priv; 155 + struct clk *clk; 156 + struct clk_lookup *cl; 157 + int i; 158 + 159 + if (!afe_priv) 160 + return; 161 + 162 + for (i = 0; i < CLK_AUD_NR_CLK; i++) { 163 + cl = afe_priv->lookup[i]; 164 + if (!cl) 165 + continue; 166 + 167 + clk = cl->clk; 168 + clk_unregister_gate(clk); 169 + 170 + clkdev_drop(cl); 171 + } 172 + } 173 + 151 174 int mt8195_audsys_clk_register(struct mtk_base_afe *afe) 152 175 { 153 176 struct mt8195_afe_private *afe_priv = afe->platform_priv; ··· 211 188 afe_priv->lookup[i] = cl; 212 189 } 213 190 214 - return 0; 215 - } 216 - 217 - void mt8195_audsys_clk_unregister(struct mtk_base_afe *afe) 218 - { 219 - struct mt8195_afe_private *afe_priv = afe->platform_priv; 220 - struct clk *clk; 221 - struct clk_lookup *cl; 222 - int i; 223 - 224 - if (!afe_priv) 225 - return; 226 - 227 - for (i = 0; i < CLK_AUD_NR_CLK; i++) { 228 - cl = afe_priv->lookup[i]; 229 - if (!cl) 230 - continue; 231 - 232 - clk = cl->clk; 233 - clk_unregister_gate(clk); 234 - 235 - clkdev_drop(cl); 236 - } 191 + return devm_add_action_or_reset(afe->dev, mt8195_audsys_clk_unregister, afe); 237 192 }
-1
sound/soc/mediatek/mt8195/mt8195-audsys-clk.h
··· 10 10 #define _MT8195_AUDSYS_CLK_H_ 11 11 12 12 int mt8195_audsys_clk_register(struct mtk_base_afe *afe); 13 - void mt8195_audsys_clk_unregister(struct mtk_base_afe *afe); 14 13 15 14 #endif