Skip to content

Commit a93d2af

Browse files
diandersbroonie
authored andcommitted
ASoC: mediatek: mt8186: Fix use-after-free in driver remove path
When devm runs function in the "remove" path for a device it runs them in the reverse order. That means that if you have parts of your driver that aren't using devm or are using "roll your own" devm w/ devm_add_action_or_reset() you need to keep that in mind. The mt8186 audio driver didn't quite get this right. Specifically, in mt8186_init_clock() it called mt8186_audsys_clk_register() and then went on to call a bunch of other devm function. The caller of mt8186_init_clock() used devm_add_action_or_reset() to call mt8186_deinit_clock() but, because of the intervening devm functions, the order was wrong. Specifically at probe time, the order was: 1. mt8186_audsys_clk_register() 2. afe_priv->clk = devm_kcalloc(...) 3. afe_priv->clk[i] = devm_clk_get(...) At remove time, the order (which should have been 3, 2, 1) was: 1. mt8186_audsys_clk_unregister() 3. Free all of afe_priv->clk[i] 2. Free afe_priv->clk The above seemed to be causing a use-after-free. Luckily, it's easy to fix this by simply using devm more correctly. Let's move the devm_add_action_or_reset() to the right place. In addition to fixing the use-after-free, code inspection shows that this fixes a leak (missing call to mt8186_audsys_clk_unregister()) that would have happened if any of the syscon_regmap_lookup_by_phandle() calls in mt8186_init_clock() had failed. Fixes: 55b423d ("ASoC: mediatek: mt8186: support audio clock control in platform driver") Signed-off-by: Douglas Anderson <[email protected] Link: https://lore.kernel.org/r/20230511092437.1.I31cceffc8c45bb1af16eb613e197b3df92cdc19e@changeid Signed-off-by: Mark Brown <[email protected]
1 parent 4708449 commit a93d2af

File tree

5 files changed

+24
-34
lines changed

5 files changed

+24
-34
lines changed

sound/soc/mediatek/mt8186/mt8186-afe-clk.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -644,9 +644,3 @@ int mt8186_init_clock(struct mtk_base_afe *afe)
644644

645645
return 0;
646646
}
647-
648-
void mt8186_deinit_clock(void *priv)
649-
{
650-
struct mtk_base_afe *afe = priv;
651-
mt8186_audsys_clk_unregister(afe);
652-
}

sound/soc/mediatek/mt8186/mt8186-afe-clk.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ enum {
8181
struct mtk_base_afe;
8282
int mt8186_set_audio_int_bus_parent(struct mtk_base_afe *afe, int clk_id);
8383
int mt8186_init_clock(struct mtk_base_afe *afe);
84-
void mt8186_deinit_clock(void *priv);
8584
int mt8186_afe_enable_cgs(struct mtk_base_afe *afe);
8685
void mt8186_afe_disable_cgs(struct mtk_base_afe *afe);
8786
int mt8186_afe_enable_clock(struct mtk_base_afe *afe);

sound/soc/mediatek/mt8186/mt8186-afe-pcm.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2848,10 +2848,6 @@ static int mt8186_afe_pcm_dev_probe(struct platform_device *pdev)
28482848
return ret;
28492849
}
28502850

2851-
ret = devm_add_action_or_reset(dev, mt8186_deinit_clock, (void *)afe);
2852-
if (ret)
2853-
return ret;
2854-
28552851
/* init memif */
28562852
afe->memif_32bit_supported = 0;
28572853
afe->memif_size = MT8186_MEMIF_NUM;

sound/soc/mediatek/mt8186/mt8186-audsys-clk.c

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,29 @@ static const struct afe_gate aud_clks[CLK_AUD_NR_CLK] = {
8484
GATE_AUD2(CLK_AUD_ETDM_OUT1_BCLK, "aud_etdm_out1_bclk", "top_audio", 24),
8585
};
8686

87+
static void mt8186_audsys_clk_unregister(void *data)
88+
{
89+
struct mtk_base_afe *afe = data;
90+
struct mt8186_afe_private *afe_priv = afe->platform_priv;
91+
struct clk *clk;
92+
struct clk_lookup *cl;
93+
int i;
94+
95+
if (!afe_priv)
96+
return;
97+
98+
for (i = 0; i < CLK_AUD_NR_CLK; i++) {
99+
cl = afe_priv->lookup[i];
100+
if (!cl)
101+
continue;
102+
103+
clk = cl->clk;
104+
clk_unregister_gate(clk);
105+
106+
clkdev_drop(cl);
107+
}
108+
}
109+
87110
int mt8186_audsys_clk_register(struct mtk_base_afe *afe)
88111
{
89112
struct mt8186_afe_private *afe_priv = afe->platform_priv;
@@ -124,27 +147,6 @@ int mt8186_audsys_clk_register(struct mtk_base_afe *afe)
124147
afe_priv->lookup[i] = cl;
125148
}
126149

127-
return 0;
150+
return devm_add_action_or_reset(afe->dev, mt8186_audsys_clk_unregister, afe);
128151
}
129152

130-
void mt8186_audsys_clk_unregister(struct mtk_base_afe *afe)
131-
{
132-
struct mt8186_afe_private *afe_priv = afe->platform_priv;
133-
struct clk *clk;
134-
struct clk_lookup *cl;
135-
int i;
136-
137-
if (!afe_priv)
138-
return;
139-
140-
for (i = 0; i < CLK_AUD_NR_CLK; i++) {
141-
cl = afe_priv->lookup[i];
142-
if (!cl)
143-
continue;
144-
145-
clk = cl->clk;
146-
clk_unregister_gate(clk);
147-
148-
clkdev_drop(cl);
149-
}
150-
}

sound/soc/mediatek/mt8186/mt8186-audsys-clk.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,5 @@
1010
#define _MT8186_AUDSYS_CLK_H_
1111

1212
int mt8186_audsys_clk_register(struct mtk_base_afe *afe);
13-
void mt8186_audsys_clk_unregister(struct mtk_base_afe *afe);
1413

1514
#endif

0 commit comments

Comments
 (0)