mirror of
https://github.com/torvalds/linux.git
synced 2026-09-12 20:53:03 +02:00
ASoC: SOF: validate topology volume range before allocation
SOF treats the topology mixer min and max values as non-negative indices
into its volume table. It stores them in signed fields, allocates max + 1
entries through an int argument, and later indexes the table with the
stored range.
An inverted range is invalid, while a maximum at or above INT_MAX cannot
be represented safely after the increment or in the signed fields.
Validate the complete range before storing it or allocating the table.
Fixes: 311ce4fe76 ("ASoC: SOF: Add support for loading topologies")
Assisted-by: Codex:gpt-5
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Acked-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Link: https://patch.msgid.link/20260814081238.25434-1-pengpeng@iscas.ac.cn
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
ac47e22fcf
commit
a698e4a60f
|
|
@ -846,6 +846,7 @@ static int sof_control_load_volume(struct snd_soc_component *scomp,
|
|||
struct snd_soc_tplg_mixer_control *mc =
|
||||
container_of(hdr, struct snd_soc_tplg_mixer_control, hdr);
|
||||
int tlv[SOF_TLV_ITEMS];
|
||||
u32 min, max;
|
||||
unsigned int mask;
|
||||
int ret;
|
||||
|
||||
|
|
@ -853,6 +854,11 @@ static int sof_control_load_volume(struct snd_soc_component *scomp,
|
|||
if (le32_to_cpu(mc->num_channels) > SND_SOC_TPLG_MAX_CHAN)
|
||||
return -EINVAL;
|
||||
|
||||
min = le32_to_cpu(mc->min);
|
||||
max = le32_to_cpu(mc->max);
|
||||
if (min > max || max >= INT_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* If control has more than 2 channels we need to override the info. This is because even if
|
||||
* ASoC layer has defined topology's max channel count to SND_SOC_TPLG_MAX_CHAN = 8, the
|
||||
|
|
@ -863,12 +869,12 @@ static int sof_control_load_volume(struct snd_soc_component *scomp,
|
|||
kc->info = snd_sof_volume_info;
|
||||
|
||||
scontrol->comp_id = sdev->next_comp_id;
|
||||
scontrol->min_volume_step = le32_to_cpu(mc->min);
|
||||
scontrol->max_volume_step = le32_to_cpu(mc->max);
|
||||
scontrol->min_volume_step = min;
|
||||
scontrol->max_volume_step = max;
|
||||
scontrol->num_channels = le32_to_cpu(mc->num_channels);
|
||||
|
||||
scontrol->max = le32_to_cpu(mc->max);
|
||||
if (le32_to_cpu(mc->max) == 1)
|
||||
scontrol->max = max;
|
||||
if (max == 1)
|
||||
goto skip;
|
||||
|
||||
/* extract tlv data */
|
||||
|
|
@ -878,7 +884,7 @@ static int sof_control_load_volume(struct snd_soc_component *scomp,
|
|||
}
|
||||
|
||||
/* set up volume table */
|
||||
ret = set_up_volume_table(scontrol, tlv, le32_to_cpu(mc->max) + 1);
|
||||
ret = set_up_volume_table(scontrol, tlv, max + 1);
|
||||
if (ret < 0) {
|
||||
dev_err(scomp->dev, "error: setting up volume table\n");
|
||||
return ret;
|
||||
|
|
@ -911,7 +917,7 @@ static int sof_control_load_volume(struct snd_soc_component *scomp,
|
|||
return 0;
|
||||
|
||||
err:
|
||||
if (le32_to_cpu(mc->max) > 1)
|
||||
if (max > 1)
|
||||
kfree(scontrol->volume_table);
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user