mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-12-24 06:59:27 -05:00
369 lines
11 KiB
Diff
369 lines
11 KiB
Diff
From 143ef972be1621458930ea3fc1def5ebce7b0c5d Mon Sep 17 00:00:00 2001
|
|
From: Yeleswarapu Nagaradhesh <nagaradh@codeaurora.org>
|
|
Date: Tue, 14 Feb 2017 14:27:56 +0530
|
|
Subject: ASoC: msm: acquire lock in ioctl
|
|
|
|
If two ioctls are triggered with different commands,
|
|
there is a possibility to access freed confidence level
|
|
memory. To resolve this acquire lock in ioctl.
|
|
Also release mutex lock properly in error cases.
|
|
|
|
CRs-Fixed: 1103085
|
|
Change-Id: I7d6b2eff21c8297e5f0755a0c141254be32f777d
|
|
Signed-off-by: Yeleswarapu Nagaradhesh <nagaradh@codeaurora.org>
|
|
---
|
|
sound/soc/msm/msm-cpe-lsm.c | 1 +
|
|
sound/soc/msm/qdsp6v2/msm-lsm-client.c | 93 ++++++++++++++++++++++++----------
|
|
2 files changed, 68 insertions(+), 26 deletions(-)
|
|
|
|
diff --git a/sound/soc/msm/msm-cpe-lsm.c b/sound/soc/msm/msm-cpe-lsm.c
|
|
index 7989a1e..3762e02 100644
|
|
--- a/sound/soc/msm/msm-cpe-lsm.c
|
|
+++ b/sound/soc/msm/msm-cpe-lsm.c
|
|
@@ -1621,6 +1621,7 @@ static int msm_cpe_lsm_ioctl(struct snd_pcm_substream *substream,
|
|
switch (cmd) {
|
|
case SNDRV_LSM_REG_SND_MODEL_V2: {
|
|
struct snd_lsm_sound_model_v2 snd_model;
|
|
+
|
|
if (copy_from_user(&snd_model, (void *)arg,
|
|
sizeof(struct snd_lsm_sound_model_v2))) {
|
|
dev_err(rtd->dev,
|
|
diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
|
|
index d5358e3..62a4e82 100644
|
|
--- a/sound/soc/msm/qdsp6v2/msm-lsm-client.c
|
|
+++ b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2013-2016, Linux Foundation. All rights reserved.
|
|
+ * Copyright (c) 2013-2017, Linux Foundation. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 and
|
|
@@ -84,6 +84,7 @@ struct lsm_priv {
|
|
atomic_t buf_count;
|
|
atomic_t read_abort;
|
|
wait_queue_head_t period_wait;
|
|
+ struct mutex lsm_api_lock;
|
|
int appl_cnt;
|
|
int dma_write;
|
|
};
|
|
@@ -900,10 +901,18 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
|
|
case SNDRV_LSM_EVENT_STATUS:
|
|
dev_dbg(rtd->dev, "%s: Get event status\n", __func__);
|
|
atomic_set(&prtd->event_wait_stop, 0);
|
|
+
|
|
+ /*
|
|
+ * Release the api lock before wait to allow
|
|
+ * other IOCTLs to be invoked while waiting
|
|
+ * for event
|
|
+ */
|
|
+ mutex_unlock(&prtd->lsm_api_lock);
|
|
rc = wait_event_freezable(prtd->event_wait,
|
|
(cmpxchg(&prtd->event_avail, 1, 0) ||
|
|
(xchg = atomic_cmpxchg(&prtd->event_wait_stop,
|
|
1, 0))));
|
|
+ mutex_lock(&prtd->lsm_api_lock);
|
|
dev_dbg(rtd->dev, "%s: wait_event_freezable %d event_wait_stop %d\n",
|
|
__func__, rc, xchg);
|
|
if (!rc && !xchg) {
|
|
@@ -1147,6 +1156,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
|
|
rtd = substream->private_data;
|
|
prtd = runtime->private_data;
|
|
|
|
+ mutex_lock(&prtd->lsm_api_lock);
|
|
+
|
|
switch (cmd) {
|
|
case SNDRV_LSM_EVENT_STATUS: {
|
|
struct snd_lsm_event_status *user = NULL, userarg32;
|
|
@@ -1154,7 +1165,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
|
|
if (copy_from_user(&userarg32, arg, sizeof(userarg32))) {
|
|
dev_err(rtd->dev, "%s: err copyuser ioctl %s\n",
|
|
__func__, "SNDRV_LSM_EVENT_STATUS");
|
|
- return -EFAULT;
|
|
+ err = -EFAULT;
|
|
+ goto done;
|
|
}
|
|
|
|
if (userarg32.payload_size >
|
|
@@ -1162,7 +1174,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
|
|
pr_err("%s: payload_size %d is invalid, max allowed = %d\n",
|
|
__func__, userarg32.payload_size,
|
|
LISTEN_MAX_STATUS_PAYLOAD_SIZE);
|
|
- return -EINVAL;
|
|
+ err = -EINVAL;
|
|
+ goto done;
|
|
}
|
|
|
|
size = sizeof(*user) + userarg32.payload_size;
|
|
@@ -1171,7 +1184,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
|
|
dev_err(rtd->dev,
|
|
"%s: Allocation failed event status size %d\n",
|
|
__func__, size);
|
|
- return -EFAULT;
|
|
+ err = -EFAULT;
|
|
+ goto done;
|
|
} else {
|
|
cmd = SNDRV_LSM_EVENT_STATUS;
|
|
user->payload_size = userarg32.payload_size;
|
|
@@ -1220,7 +1234,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
|
|
dev_err(rtd->dev,
|
|
"%s: %s: not supported if using topology\n",
|
|
__func__, "REG_SND_MODEL_V2");
|
|
- return -EINVAL;
|
|
+ err = -EINVAL;
|
|
+ goto done;
|
|
}
|
|
|
|
if (copy_from_user(&snd_modelv232, arg,
|
|
@@ -1261,7 +1276,7 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
|
|
dev_err(rtd->dev,
|
|
"%s: %s: not supported if using topology\n",
|
|
__func__, "SET_PARAMS_32");
|
|
- return -EINVAL;
|
|
+ err = -EINVAL;
|
|
}
|
|
|
|
if (copy_from_user(&det_params32, arg,
|
|
@@ -1304,7 +1319,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
|
|
dev_err(rtd->dev,
|
|
"%s: %s: not supported if not using topology\n",
|
|
__func__, "SET_MODULE_PARAMS_32");
|
|
- return -EINVAL;
|
|
+ err = -EINVAL;
|
|
+ goto done;
|
|
}
|
|
|
|
if (copy_from_user(&p_data_32, arg,
|
|
@@ -1313,7 +1329,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
|
|
"%s: %s: copy_from_user failed, size = %zd\n",
|
|
__func__, "SET_MODULE_PARAMS_32",
|
|
sizeof(p_data_32));
|
|
- return -EFAULT;
|
|
+ err = -EFAULT;
|
|
+ goto done;
|
|
}
|
|
|
|
p_data.params = compat_ptr(p_data_32.params);
|
|
@@ -1325,7 +1342,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
|
|
"%s: %s: Invalid num_params %d\n",
|
|
__func__, "SET_MODULE_PARAMS_32",
|
|
p_data.num_params);
|
|
- return -EINVAL;
|
|
+ err = -EINVAL;
|
|
+ goto done;
|
|
}
|
|
|
|
if (p_data.data_size !=
|
|
@@ -1334,7 +1352,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
|
|
"%s: %s: Invalid size %d\n",
|
|
__func__, "SET_MODULE_PARAMS_32",
|
|
p_data.data_size);
|
|
- return -EINVAL;
|
|
+ err = -EINVAL;
|
|
+ goto done;
|
|
}
|
|
|
|
p_size = sizeof(struct lsm_params_info_32) *
|
|
@@ -1345,7 +1364,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
|
|
dev_err(rtd->dev,
|
|
"%s: no memory for params32, size = %zd\n",
|
|
__func__, p_size);
|
|
- return -ENOMEM;
|
|
+ err = -ENOMEM;
|
|
+ goto done;
|
|
}
|
|
|
|
p_size = sizeof(struct lsm_params_info) * p_data.num_params;
|
|
@@ -1355,7 +1375,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
|
|
"%s: no memory for params, size = %zd\n",
|
|
__func__, p_size);
|
|
kfree(params32);
|
|
- return -ENOMEM;
|
|
+ err = -ENOMEM;
|
|
+ goto done;
|
|
}
|
|
|
|
if (copy_from_user(params32, p_data.params,
|
|
@@ -1365,7 +1386,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
|
|
__func__, "params32", p_data.data_size);
|
|
kfree(params32);
|
|
kfree(params);
|
|
- return -EFAULT;
|
|
+ err = -EFAULT;
|
|
+ goto done;
|
|
}
|
|
|
|
p_info_32 = (struct lsm_params_info_32 *) params32;
|
|
@@ -1408,6 +1430,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
|
|
err = msm_lsm_ioctl_shared(substream, cmd, arg);
|
|
break;
|
|
}
|
|
+done:
|
|
+ mutex_unlock(&prtd->lsm_api_lock);
|
|
return err;
|
|
}
|
|
#else
|
|
@@ -1432,6 +1456,7 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
|
|
prtd = runtime->private_data;
|
|
rtd = substream->private_data;
|
|
|
|
+ mutex_lock(&prtd->lsm_api_lock);
|
|
switch (cmd) {
|
|
case SNDRV_LSM_REG_SND_MODEL_V2: {
|
|
struct snd_lsm_sound_model_v2 snd_model_v2;
|
|
@@ -1440,7 +1465,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
|
|
dev_err(rtd->dev,
|
|
"%s: %s: not supported if using topology\n",
|
|
__func__, "REG_SND_MODEL_V2");
|
|
- return -EINVAL;
|
|
+ err = -EINVAL;
|
|
+ goto done;
|
|
}
|
|
|
|
if (copy_from_user(&snd_model_v2, arg, sizeof(snd_model_v2))) {
|
|
@@ -1467,7 +1493,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
|
|
dev_err(rtd->dev,
|
|
"%s: %s: not supported if using topology\n",
|
|
__func__, "SET_PARAMS");
|
|
- return -EINVAL;
|
|
+ err = -EINVAL;
|
|
+ goto done;
|
|
}
|
|
|
|
pr_debug("%s: SNDRV_LSM_SET_PARAMS\n", __func__);
|
|
@@ -1488,7 +1515,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
|
|
dev_err(rtd->dev,
|
|
"%s: LSM_SET_PARAMS failed, err %d\n",
|
|
__func__, err);
|
|
- return err;
|
|
+
|
|
+ goto done;
|
|
}
|
|
|
|
case SNDRV_LSM_SET_MODULE_PARAMS: {
|
|
@@ -1500,7 +1528,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
|
|
dev_err(rtd->dev,
|
|
"%s: %s: not supported if not using topology\n",
|
|
__func__, "SET_MODULE_PARAMS");
|
|
- return -EINVAL;
|
|
+ err = -EINVAL;
|
|
+ goto done;
|
|
}
|
|
|
|
if (copy_from_user(&p_data, arg,
|
|
@@ -1508,7 +1537,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
|
|
dev_err(rtd->dev,
|
|
"%s: %s: copy_from_user failed, size = %zd\n",
|
|
__func__, "p_data", sizeof(p_data));
|
|
- return -EFAULT;
|
|
+ err = -EFAULT;
|
|
+ goto done;
|
|
}
|
|
|
|
if (p_data.num_params > LSM_PARAMS_MAX) {
|
|
@@ -1516,7 +1546,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
|
|
"%s: %s: Invalid num_params %d\n",
|
|
__func__, "SET_MODULE_PARAMS",
|
|
p_data.num_params);
|
|
- return -EINVAL;
|
|
+ err = -EINVAL;
|
|
+ goto done;
|
|
}
|
|
|
|
p_size = p_data.num_params *
|
|
@@ -1527,7 +1558,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
|
|
"%s: %s: Invalid size %zd\n",
|
|
__func__, "SET_MODULE_PARAMS", p_size);
|
|
|
|
- return -EFAULT;
|
|
+ err = -EFAULT;
|
|
+ goto done;
|
|
}
|
|
|
|
params = kzalloc(p_size, GFP_KERNEL);
|
|
@@ -1535,7 +1567,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
|
|
dev_err(rtd->dev,
|
|
"%s: no memory for params\n",
|
|
__func__);
|
|
- return -ENOMEM;
|
|
+ err = -ENOMEM;
|
|
+ goto done;
|
|
}
|
|
|
|
if (copy_from_user(params, p_data.params,
|
|
@@ -1544,7 +1577,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
|
|
"%s: %s: copy_from_user failed, size = %d\n",
|
|
__func__, "params", p_data.data_size);
|
|
kfree(params);
|
|
- return -EFAULT;
|
|
+ err = -EFAULT;
|
|
+ goto done;
|
|
}
|
|
|
|
err = msm_lsm_process_params(substream, &p_data, params);
|
|
@@ -1564,7 +1598,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
|
|
dev_err(rtd->dev,
|
|
"%s: err copyuser event_status\n",
|
|
__func__);
|
|
- return -EFAULT;
|
|
+ err = -EFAULT;
|
|
+ goto done;
|
|
}
|
|
|
|
if (userarg.payload_size >
|
|
@@ -1572,7 +1607,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
|
|
pr_err("%s: payload_size %d is invalid, max allowed = %d\n",
|
|
__func__, userarg.payload_size,
|
|
LISTEN_MAX_STATUS_PAYLOAD_SIZE);
|
|
- return -EINVAL;
|
|
+ err = -EINVAL;
|
|
+ goto done;
|
|
}
|
|
|
|
size = sizeof(struct snd_lsm_event_status) +
|
|
@@ -1582,7 +1618,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
|
|
dev_err(rtd->dev,
|
|
"%s: Allocation failed event status size %d\n",
|
|
__func__, size);
|
|
- return -EFAULT;
|
|
+ err = -EFAULT;
|
|
+ goto done;
|
|
} else {
|
|
user->payload_size = userarg.payload_size;
|
|
err = msm_lsm_ioctl_shared(substream, cmd, user);
|
|
@@ -1605,12 +1642,14 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
|
|
if (err)
|
|
dev_err(rtd->dev,
|
|
"%s: lsmevent failed %d", __func__, err);
|
|
- return err;
|
|
+ goto done;
|
|
}
|
|
default:
|
|
err = msm_lsm_ioctl_shared(substream, cmd, arg);
|
|
break;
|
|
}
|
|
+done:
|
|
+ mutex_unlock(&prtd->lsm_api_lock);
|
|
return err;
|
|
}
|
|
|
|
@@ -1627,6 +1666,7 @@ static int msm_lsm_open(struct snd_pcm_substream *substream)
|
|
__func__);
|
|
return -ENOMEM;
|
|
}
|
|
+ mutex_init(&prtd->lsm_api_lock);
|
|
spin_lock_init(&prtd->event_lock);
|
|
init_waitqueue_head(&prtd->event_wait);
|
|
init_waitqueue_head(&prtd->period_wait);
|
|
@@ -1776,6 +1816,7 @@ static int msm_lsm_close(struct snd_pcm_substream *substream)
|
|
kfree(prtd->event_status);
|
|
prtd->event_status = NULL;
|
|
spin_unlock_irqrestore(&prtd->event_lock, flags);
|
|
+ mutex_destroy(&prtd->lsm_api_lock);
|
|
kfree(prtd);
|
|
runtime->private_data = NULL;
|
|
|
|
--
|
|
cgit v1.1
|
|
|