* [PATCH] ASoC: SOF: control: Reject out of range volume and switch values
@ 2026-11-14 2:17 HyeongJun An
0 siblings, 0 replies; only message in thread
From: HyeongJun An @ 2026-11-14 2:17 UTC (permalink / raw)
To: Mark Brown
Cc: Liam Girdwood, Peter Ujfalusi, Bard Liao, Daniel Baluta,
Kai Vehmanen, Pierre-Louis Bossart, Jaroslav Kysela,
Takashi Iwai, sound-open-firmware, linux-sound, linux-kernel,
HyeongJun An
The snd_sof_volume_put() and snd_sof_switch_put() pass the user values
to the IPC put handlers without a range check. The switch handlers
store any value and send it to the firmware, so on IPC3 writing 2 or -1
to a switch reads back as 2 or 4294967295. The volume handlers convert
the value to u32 and clamp it to the end of the volume table. Writing -1
sets the maximum volume, and on 64-bit writing LONG_MIN sets the
minimum, both without an error.
Return -EINVAL for values outside the range reported by the info
callback, as snd_soc_put_volsw() does. This fixes the write_invalid
failures in mixer-test, and the event_spurious failures caused by the
events those writes generated.
Fixes: c3078f539704 ("ASoC: SOF: Add Sound Open Firmware KControl support")
Signed-off-by: HyeongJun An <sammiee5311@gmail.com>
---
Tested on a Dell Latitude 9420 (Tiger Lake, SOF IPC3): the out of range
writes now fail with -EINVAL, in range writes still work, and the 9
mixer-test failures on the SOF controls are gone. IPC4 was not tested.
Its put handlers store the value the same way and now go through the
same check.
Prepared with Claude Code (Claude Opus 5.5). Tested on x86_64.
sound/soc/sof/control.c | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c
index 74d997a4f620..b6497e50505b 100644
--- a/sound/soc/sof/control.c
+++ b/sound/soc/sof/control.c
@@ -30,6 +30,30 @@ int snd_sof_volume_get(struct snd_kcontrol *kcontrol,
return 0;
}
+/*
+ * Reject values outside the range the info callback reports, as
+ * snd_soc_put_volsw() does. The IPC put handlers do not check the range.
+ */
+static int sof_mixer_check_values(struct soc_mixer_control *sm,
+ struct snd_sof_control *scontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ long max = sm->max - sm->min;
+ unsigned int i;
+
+ if (sm->platform_max && sm->platform_max < max)
+ max = sm->platform_max;
+
+ for (i = 0; i < scontrol->num_channels; i++) {
+ long val = ucontrol->value.integer.value[i];
+
+ if (val < 0 || val > max)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
int snd_sof_volume_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -38,6 +62,11 @@ int snd_sof_volume_put(struct snd_kcontrol *kcontrol,
struct snd_soc_component *scomp = scontrol->scomp;
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
+ int ret;
+
+ ret = sof_mixer_check_values(sm, scontrol, ucontrol);
+ if (ret)
+ return ret;
if (tplg_ops && tplg_ops->control && tplg_ops->control->volume_put)
return tplg_ops->control->volume_put(scontrol, ucontrol);
@@ -90,6 +119,11 @@ int snd_sof_switch_put(struct snd_kcontrol *kcontrol,
struct snd_soc_component *scomp = scontrol->scomp;
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
+ int ret;
+
+ ret = sof_mixer_check_values(sm, scontrol, ucontrol);
+ if (ret)
+ return ret;
if (tplg_ops && tplg_ops->control && tplg_ops->control->switch_put)
return tplg_ops->control->switch_put(scontrol, ucontrol);
--
2.43.0
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-11-14 2:17 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-14 2:17 [PATCH] ASoC: SOF: control: Reject out of range volume and switch values HyeongJun An
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®