From bf2e9f51c58f437dcfed7a607dd7e89280d09c57 Mon Sep 17 00:00:00 2001 From: Shalini Manjunatha Date: Thu, 5 Jun 2025 18:01:42 +0530 Subject: [PATCH] asoc: lsm: thread safety issue while accessing substream data Added mutex protection while accessing substream data to avoid potential race conditions when accessing this resource from multiple threads. Change-Id: I92e368a73ec2c683c7fcbb4579a19214cc60d1d2 --- asoc/msm-lsm-client.c | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/asoc/msm-lsm-client.c b/asoc/msm-lsm-client.c index bd9b73571263..b18a558848d2 100644 --- a/asoc/msm-lsm-client.c +++ b/asoc/msm-lsm-client.c @@ -42,6 +42,11 @@ #define LSM_IS_LAST_STAGE(client, stage_idx) \ (client->num_stages == (stage_idx + 1)) +struct lsm_char_dev { + /* Protects access to LSM client sessions and shared resources */ + struct mutex lock; +}; + static struct snd_pcm_hardware msm_pcm_hardware_capture = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BLOCK_TRANSFER | @@ -3106,9 +3111,11 @@ static int msm_lsm_close(struct snd_pcm_substream *substream) { unsigned long flags; struct snd_pcm_runtime *runtime = substream->runtime; - struct lsm_priv *prtd = runtime->private_data; + struct lsm_priv *prtd = NULL; struct snd_soc_pcm_runtime *rtd; struct msm_pcm_stream_app_type_cfg cfg_data = {0}; + struct lsm_char_dev *lsm_dev; + struct snd_soc_component *component = NULL; int ret = 0; int be_id = 0; int fe_id = 0; @@ -3117,12 +3124,29 @@ static int msm_lsm_close(struct snd_pcm_substream *substream) pr_err("%s: Invalid private_data", __func__); return -EINVAL; } - if (!prtd || !prtd->lsm_client) { - pr_err("%s: No LSM session active\n", __func__); + if (!component || !component->dev) { + pr_err("%s: Invalid component\n", __func__); return -EINVAL; } rtd = substream->private_data; + lsm_dev = (struct lsm_char_dev *) dev_get_drvdata(component->dev); + if (!lsm_dev) { + pr_err("%s: platform data is NULL\n", __func__); + return -EINVAL; + } + mutex_lock(&lsm_dev->lock); + if (!runtime) { + pr_err("%s: Invalid runtime", __func__); + mutex_unlock(&lsm_dev->lock); + return -EINVAL; + } + prtd = runtime->private_data; + if (!prtd || !prtd->lsm_client) { + pr_err("%s: No LSM session active\n", __func__); + mutex_unlock(&lsm_dev->lock); + return -EINVAL; + } dev_dbg(rtd->dev, "%s\n", __func__); if (prtd->lsm_client->started) { if (prtd->lsm_client->lab_enable) { @@ -3232,6 +3256,7 @@ static int msm_lsm_close(struct snd_pcm_substream *substream) mutex_destroy(&prtd->lsm_api_lock); kfree(prtd); runtime->private_data = NULL; + mutex_unlock(&lsm_dev->lock); return 0; } @@ -3629,6 +3654,14 @@ static struct snd_soc_component_driver msm_soc_component = { static int msm_lsm_probe(struct platform_device *pdev) { + struct lsm_char_dev *lsm_dev; + + lsm_dev = devm_kzalloc(&pdev->dev, sizeof(*lsm_dev), GFP_KERNEL); + if (!lsm_dev) + return -ENOMEM; + + mutex_init(&lsm_dev->lock); + dev_set_drvdata(&pdev->dev, lsm_dev); return snd_soc_register_component(&pdev->dev, &msm_soc_component, NULL, 0); @@ -3636,6 +3669,10 @@ static int msm_lsm_probe(struct platform_device *pdev) static int msm_lsm_remove(struct platform_device *pdev) { + struct lsm_char_dev *lsm_dev; + lsm_dev = dev_get_drvdata(&pdev->dev); + mutex_destroy(&lsm_dev->lock); + snd_soc_unregister_component(&pdev->dev); return 0;