summaryrefslogtreecommitdiffstats
path: root/sound/soc/sof/topology.c
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>2020-09-17 13:56:32 +0300
committerMark Brown <broonie@kernel.org>2020-09-17 15:53:20 +0100
commit0e4ea878708be903566ad93d4972ad3dd4c1c30e (patch)
treea8e55e074d3a1d6cf468073b9b413ecfed36236e /sound/soc/sof/topology.c
parentdb69bcf915a37d7b8e54acf5f67d09d8159eb616 (diff)
downloadlinux-0e4ea878708be903566ad93d4972ad3dd4c1c30e.tar.bz2
ASoC: SOF: fix range checks
On multiple locations checks are performed of untrusted values after adding a constant to them. This is wrong, because the addition might overflow and the result can then pass the check, although the original value is invalid. Fix multiple such issues by checking the actual value and not a sum of it and a constant. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> Link: https://lore.kernel.org/r/20200917105633.2579047-8-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/sof/topology.c')
-rw-r--r--sound/soc/sof/topology.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index fa85a22b5880..eaa1122d5a68 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -1150,20 +1150,26 @@ static int sof_control_load_bytes(struct snd_soc_component *scomp,
struct snd_soc_tplg_bytes_control *control =
container_of(hdr, struct snd_soc_tplg_bytes_control, hdr);
struct soc_bytes_ext *sbe = (struct soc_bytes_ext *)kc->private_value;
- int max_size = sbe->max;
+ size_t max_size = sbe->max;
+ size_t priv_size = le32_to_cpu(control->priv.size);
int ret;
- /* init the get/put bytes data */
- scontrol->size = sizeof(struct sof_ipc_ctrl_data) +
- le32_to_cpu(control->priv.size);
+ if (max_size < sizeof(struct sof_ipc_ctrl_data) ||
+ max_size < sizeof(struct sof_abi_hdr)) {
+ ret = -EINVAL;
+ goto out;
+ }
- if (scontrol->size > max_size) {
- dev_err(scomp->dev, "err: bytes data size %d exceeds max %d.\n",
- scontrol->size, max_size);
+ /* init the get/put bytes data */
+ if (priv_size > max_size - sizeof(struct sof_ipc_ctrl_data)) {
+ dev_err(scomp->dev, "err: bytes data size %zu exceeds max %zu.\n",
+ priv_size, max_size - sizeof(struct sof_ipc_ctrl_data));
ret = -EINVAL;
goto out;
}
+ scontrol->size = sizeof(struct sof_ipc_ctrl_data) + priv_size;
+
scontrol->control_data = kzalloc(max_size, GFP_KERNEL);
cdata = scontrol->control_data;
if (!scontrol->control_data) {