Message ID | 20220517011201.23530-1-tannayir@gmail.com |
---|---|
State | New |
Headers | show |
Series | ASoC: ops: Fix the bounds checking in snd_soc_put_volsw_sx and snd_soc_put_xr_sx | expand |
On Tue, May 17, 2022 at 04:12:04AM +0300, Tan Nayir wrote: > The $val in both functions has a range between 0 and an arbitrary limit > whereas the range specified with the $min and $max can start > from a negative number. To do the out of bound check correctly, the > $val must be added the $min offset. > val = ucontrol->value.integer.value[0]; > - if (mc->platform_max && val > mc->platform_max) > + if (mc->platform_max && ((int)val + min) > mc->platform_max) No, the minimum value we expose to userspace is always scaled so that userspace sees a range starting from zero and that's where platform_max is referenced to - we're applying this limit before we start remapping to actual register values. The code would be a lot simpler if we didn't do this rescaling. Please don't send new patches in reply to old patches or serieses, this makes it harder for both people and tools to understand what is going on - it can bury things in mailboxes and make it difficult to keep track of what current patches are, both for the new patches and the old ones.
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index e693070f5..42191968c 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -433,7 +433,7 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, if (ucontrol->value.integer.value[0] < 0) return -EINVAL; val = ucontrol->value.integer.value[0]; - if (mc->platform_max && val > mc->platform_max) + if (mc->platform_max && ((int)val + min) > mc->platform_max) return -EINVAL; if (val > max - min) return -EINVAL; @@ -910,11 +910,12 @@ int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol, unsigned int invert = mc->invert; unsigned long mask = (1UL<<mc->nbits)-1; long max = mc->max; + long min = mc->min; long val = ucontrol->value.integer.value[0]; int ret = 0; unsigned int i; - if (val < mc->min || val > mc->max) + if (val < mc->min || ((int)val + min) > mc->max) return -EINVAL; if (invert) val = max - val;
The $val in both functions has a range between 0 and an arbitrary limit whereas the range specified with the $min and $max can start from a negative number. To do the out of bound check correctly, the $val must be added the $min offset. Previous-discussion: https://lore.kernel.org/all/c2163c71-2f71-9011-3966-baeab8e8dc8f@gmail.com/ Fixes: 4f1e50d6a9cf9 ("ASoC: ops: Reject out of bounds values in snd_soc_put_volsw_sx()") Fixes: 4cf28e9ae6e2e ("ASoC: ops: Reject out of bounds values in snd_soc_put_xr_sx()") Signed-off-by: Tan Nayir <tannayir@gmail.com> --- sound/soc/soc-ops.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)