When loading kcontrol elements make sure to first check the size of available data before accessing it.
Signed-off-by: Guennadi Liakhovetski guennadi.liakhovetski@linux.intel.com --- sound/soc/soc-topology.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index d1d3c6f..f933ad4 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1115,11 +1115,11 @@ static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg, struct snd_soc_tplg_hdr *hdr) { struct snd_soc_tplg_ctl_hdr *control_hdr; + ssize_t remainder = le32_to_cpu(hdr->payload_size); int i;
if (tplg->pass != SOC_TPLG_PASS_MIXER) { - tplg->pos += le32_to_cpu(hdr->size) + - le32_to_cpu(hdr->payload_size); + tplg->pos += le32_to_cpu(hdr->size) + remainder; return 0; }
@@ -1130,6 +1130,11 @@ static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg,
control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos;
+ if (remainder < sizeof(*control_hdr)) { + dev_err(tplg->dev, "ASoC: invalid payload size\n"); + return -EINVAL; + } + if (le32_to_cpu(control_hdr->size) != sizeof(*control_hdr)) { dev_err(tplg->dev, "ASoC: invalid control size\n"); return -EINVAL; @@ -1143,25 +1148,24 @@ static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg, case SND_SOC_TPLG_CTL_RANGE: case SND_SOC_TPLG_DAPM_CTL_VOLSW: case SND_SOC_TPLG_DAPM_CTL_PIN: - soc_tplg_dmixer_create(tplg, 1, - le32_to_cpu(hdr->payload_size)); + soc_tplg_dmixer_create(tplg, 1, remainder); break; case SND_SOC_TPLG_CTL_ENUM: case SND_SOC_TPLG_CTL_ENUM_VALUE: case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: - soc_tplg_denum_create(tplg, 1, - le32_to_cpu(hdr->payload_size)); + soc_tplg_denum_create(tplg, 1, remainder); break; case SND_SOC_TPLG_CTL_BYTES: - soc_tplg_dbytes_create(tplg, 1, - le32_to_cpu(hdr->payload_size)); + soc_tplg_dbytes_create(tplg, 1, remainder); break; default: soc_bind_err(tplg, control_hdr, i); return -EINVAL; } + + remainder -= tplg->pos - (u8 *)control_hdr; }
return 0;