@@ -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;
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(-)