Commit 77abb2f0 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] sb_mixer bounds checking

From: Muli Ben-Yehuda <mulix@mulix.org>

This patch add proper bounds checking to the sb_mixer.c code, found by the
stanford checker[0].  It fixes bugzilla bugs 252[1], 253[2] and 254[3]. 
Patch is against 2.6.5-rc2.  It was tested by Rene Herman on SN AWE64 gold
and sound still works.  The issue was previously discussed on lkml[4], but
apparently no fix was applied.

The patch is a bit more intrusive than I would've liked, but I don't think
it can be helped without really intrusive changes.  sb_devc has a pointer
to an array (iomap) that is set at run time to point to arrays of variable
sizes.  The patch adds an 'iomap_sz' member to sb_devc that is set to the
length of the array, and does bounds checking in sb_common_mixer_set() and
smw_mixer_set() agains that.
parent 59b46ce5
...@@ -110,6 +110,7 @@ typedef struct sb_devc { ...@@ -110,6 +110,7 @@ typedef struct sb_devc {
/* Mixer fields */ /* Mixer fields */
int *levels; int *levels;
mixer_tab *iomap; mixer_tab *iomap;
size_t iomap_sz; /* number or records in the iomap table */
int mixer_caps, recmask, outmask, supported_devices; int mixer_caps, recmask, outmask, supported_devices;
int supported_rec_devices, supported_out_devices; int supported_rec_devices, supported_out_devices;
int my_mixerdev; int my_mixerdev;
......
...@@ -1638,8 +1638,10 @@ printk (KERN_INFO "FKS: ess_mixer_init dup = %d\n", devc->duplex); ...@@ -1638,8 +1638,10 @@ printk (KERN_INFO "FKS: ess_mixer_init dup = %d\n", devc->duplex);
#endif #endif
if (devc->duplex) { if (devc->duplex) {
devc->iomap = &es1887_mix; devc->iomap = &es1887_mix;
devc->iomap_sz = ARRAY_SIZE(es1887_mix);
} else { } else {
devc->iomap = &es_rec_mix; devc->iomap = &es_rec_mix;
devc->iomap_sz = ARRAY_SIZE(es_rec_mix);
} }
break; break;
default: default:
...@@ -1647,6 +1649,7 @@ printk (KERN_INFO "FKS: ess_mixer_init dup = %d\n", devc->duplex); ...@@ -1647,6 +1649,7 @@ printk (KERN_INFO "FKS: ess_mixer_init dup = %d\n", devc->duplex);
devc->supported_devices = ES688_MIXER_DEVICES; devc->supported_devices = ES688_MIXER_DEVICES;
devc->supported_rec_devices = ES688_RECORDING_DEVICES; devc->supported_rec_devices = ES688_RECORDING_DEVICES;
devc->iomap = &es688_mix; devc->iomap = &es688_mix;
devc->iomap_sz = ARRAY_SIZE(es688_mix);
} else { } else {
/* /*
* es1688 has 4 bits master vol. * es1688 has 4 bits master vol.
...@@ -1656,8 +1659,10 @@ printk (KERN_INFO "FKS: ess_mixer_init dup = %d\n", devc->duplex); ...@@ -1656,8 +1659,10 @@ printk (KERN_INFO "FKS: ess_mixer_init dup = %d\n", devc->duplex);
devc->supported_rec_devices = ES1688_RECORDING_DEVICES; devc->supported_rec_devices = ES1688_RECORDING_DEVICES;
if (devc->submodel < 0x10) { if (devc->submodel < 0x10) {
devc->iomap = &es1688_mix; devc->iomap = &es1688_mix;
devc->iomap_sz = ARRAY_SIZE(es688_mix);
} else { } else {
devc->iomap = &es1688later_mix; devc->iomap = &es1688later_mix;
devc->iomap_sz = ARRAY_SIZE(es1688later_mix);
} }
} }
} }
......
...@@ -278,6 +278,9 @@ int sb_common_mixer_set(sb_devc * devc, int dev, int left, int right) ...@@ -278,6 +278,9 @@ int sb_common_mixer_set(sb_devc * devc, int dev, int left, int right)
if (regoffs == 0) if (regoffs == 0)
return -EINVAL; return -EINVAL;
if ((dev < 0) || (dev >= devc->iomap_sz))
return -EINVAL;
val = sb_getmixer(devc, regoffs); val = sb_getmixer(devc, regoffs);
change_bits(devc, &val, dev, LEFT_CHN, left); change_bits(devc, &val, dev, LEFT_CHN, left);
...@@ -333,6 +336,9 @@ static int smw_mixer_set(sb_devc * devc, int dev, int left, int right) ...@@ -333,6 +336,9 @@ static int smw_mixer_set(sb_devc * devc, int dev, int left, int right)
break; break;
default: default:
/* bounds check */
if (dev < 0 || dev >= ARRAY_SIZE(smw_mix_regs))
return -EINVAL;
reg = smw_mix_regs[dev]; reg = smw_mix_regs[dev];
if (reg == 0) if (reg == 0)
return -EINVAL; return -EINVAL;
...@@ -355,7 +361,7 @@ static int sb_mixer_set(sb_devc * devc, int dev, int value) ...@@ -355,7 +361,7 @@ static int sb_mixer_set(sb_devc * devc, int dev, int value)
if (right > 100) if (right > 100)
right = 100; right = 100;
if (dev > 31) if ((dev < 0) || (dev > 31))
return -EINVAL; return -EINVAL;
if (!(devc->supported_devices & (1 << dev))) /* if (!(devc->supported_devices & (1 << dev))) /*
...@@ -684,6 +690,7 @@ int sb_mixer_init(sb_devc * devc, struct module *owner) ...@@ -684,6 +690,7 @@ int sb_mixer_init(sb_devc * devc, struct module *owner)
devc->supported_devices = SBPRO_MIXER_DEVICES; devc->supported_devices = SBPRO_MIXER_DEVICES;
devc->supported_rec_devices = SBPRO_RECORDING_DEVICES; devc->supported_rec_devices = SBPRO_RECORDING_DEVICES;
devc->iomap = &sbpro_mix; devc->iomap = &sbpro_mix;
devc->iomap_sz = ARRAY_SIZE(sbpro_mix);
break; break;
case MDL_ESS: case MDL_ESS:
...@@ -695,6 +702,7 @@ int sb_mixer_init(sb_devc * devc, struct module *owner) ...@@ -695,6 +702,7 @@ int sb_mixer_init(sb_devc * devc, struct module *owner)
devc->supported_devices = 0; devc->supported_devices = 0;
devc->supported_rec_devices = 0; devc->supported_rec_devices = 0;
devc->iomap = &sbpro_mix; devc->iomap = &sbpro_mix;
devc->iomap_sz = ARRAY_SIZE(sbpro_mix);
smw_mixer_init(devc); smw_mixer_init(devc);
break; break;
...@@ -706,11 +714,13 @@ int sb_mixer_init(sb_devc * devc, struct module *owner) ...@@ -706,11 +714,13 @@ int sb_mixer_init(sb_devc * devc, struct module *owner)
{ {
devc->supported_devices = SB16_MIXER_DEVICES; devc->supported_devices = SB16_MIXER_DEVICES;
devc->iomap = &sb16_mix; devc->iomap = &sb16_mix;
devc->iomap_sz = ARRAY_SIZE(sb16_mix);
} }
else else
{ {
devc->supported_devices = ALS007_MIXER_DEVICES; devc->supported_devices = ALS007_MIXER_DEVICES;
devc->iomap = &als007_mix; devc->iomap = &als007_mix;
devc->iomap_sz = ARRAY_SIZE(als007_mix);
} }
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment