On 11/24/25 11:49, Johan Hovold wrote:
The reference taken to the sync provider OF node when probing the platform device is currently only dropped if the set_sync() callback fails during DAI probe.
Make sure to drop the reference on platform probe failures (e.g. probe deferral) and on driver unbind.
This also avoids a potential use-after-free in case the DAI is ever reprobed without first rebinding the platform driver.
Fixes: 5914d285f6b7 ("ASoC: stm32: sai: Add synchronization support") Fixes: d4180b4c02e7 ("ASoC: stm32: sai: fix set_sync service") Cc: Olivier Moysan olivier.moysan@st.com
Reviewed-by: olivier moysan olivier.moysan@foss.st.com
Olivier
Cc: stable@vger.kernel.org # 4.16: d4180b4c02e7 Signed-off-by: Johan Hovold johan@kernel.org
sound/soc/stm/stm32_sai.c | 12 +++--------- sound/soc/stm/stm32_sai_sub.c | 23 ++++++++++++++++------- 2 files changed, 19 insertions(+), 16 deletions(-)
diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c index 7065aeb0e524..00cf24ceca2d 100644 --- a/sound/soc/stm/stm32_sai.c +++ b/sound/soc/stm/stm32_sai.c @@ -138,7 +138,6 @@ static int stm32_sai_set_sync(struct stm32_sai_data *sai_client, if (!pdev) { dev_err(&sai_client->pdev->dev, "Device not found for node %pOFn\n", np_provider);
return -ENODEV; }of_node_put(np_provider);@@ -147,21 +146,16 @@ static int stm32_sai_set_sync(struct stm32_sai_data *sai_client, if (!sai_provider) { dev_err(&sai_client->pdev->dev, "SAI sync provider data not found\n");
ret = -EINVAL;goto error;
}return -EINVAL;/* Configure sync client */ ret = stm32_sai_sync_conf_client(sai_client, synci); if (ret < 0)
goto error;
return ret;/* Configure sync provider */
- ret = stm32_sai_sync_conf_provider(sai_provider, synco);
-error:
- of_node_put(np_provider);
- return ret;
- return stm32_sai_sync_conf_provider(sai_provider, synco); }
static int stm32_sai_get_parent_clk(struct stm32_sai_data *sai) diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index 7a005b4ad304..5ae4d2577f28 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -1586,7 +1586,8 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, dev_err(&pdev->dev, "External synchro not supported\n"); of_node_put(args.np);
return -EINVAL;
ret = -EINVAL;goto err_put_sync_provider; } sai->sync = SAI_SYNC_EXTERNAL;@@ -1595,7 +1596,8 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, (sai->synci > (SAI_GCR_SYNCIN_MAX + 1))) { dev_err(&pdev->dev, "Wrong SAI index\n"); of_node_put(args.np);
return -EINVAL;
ret = -EINVAL;goto err_put_sync_provider; }if (of_property_match_string(args.np, "compatible", @@ -1609,7 +1611,8 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, if (!sai->synco) { dev_err(&pdev->dev, "Unknown SAI sub-block\n"); of_node_put(args.np);
return -EINVAL;
ret = -EINVAL; }goto err_put_sync_provider; }@@ -1619,13 +1622,15 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, of_node_put(args.np); sai->sai_ck = devm_clk_get(&pdev->dev, "sai_ck");
- if (IS_ERR(sai->sai_ck))
return dev_err_probe(&pdev->dev, PTR_ERR(sai->sai_ck),"Missing kernel clock sai_ck\n");
- if (IS_ERR(sai->sai_ck)) {
ret = dev_err_probe(&pdev->dev, PTR_ERR(sai->sai_ck),"Missing kernel clock sai_ck\n");goto err_put_sync_provider;- }
ret = clk_prepare(sai->pdata->pclk); if (ret < 0)
return ret;
goto err_put_sync_provider;if (STM_SAI_IS_F4(sai->pdata)) return 0; @@ -1647,6 +1652,8 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, err_unprepare_pclk: clk_unprepare(sai->pdata->pclk); +err_put_sync_provider:
- of_node_put(sai->np_sync_provider);
return ret; } @@ -1720,6 +1727,7 @@ static int stm32_sai_sub_probe(struct platform_device *pdev) err_unprepare_pclk: clk_unprepare(sai->pdata->pclk);
- of_node_put(sai->np_sync_provider);
return ret; } @@ -1732,6 +1740,7 @@ static void stm32_sai_sub_remove(struct platform_device *pdev) snd_dmaengine_pcm_unregister(&pdev->dev); snd_soc_unregister_component(&pdev->dev); pm_runtime_disable(&pdev->dev);
- of_node_put(sai->np_sync_provider); }
static int stm32_sai_sub_suspend(struct device *dev)