From b769f49463711205d57286e64cf535ed4daf59e9 Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Wed, 23 Mar 2011 10:53:41 -0400 Subject: sound/oss: remove offset from load_patch callbacks Was: [PATCH] sound/oss/midi_synth: prevent underflow, use of uninitialized value, and signedness issue The offset passed to midi_synth_load_patch() can be essentially arbitrary. If it's greater than the header length, this will result in a copy_from_user(dst, src, negative_val). While this will just return -EFAULT on x86, on other architectures this may cause memory corruption. Additionally, the length field of the sysex_info structure may not be initialized prior to its use. Finally, a signed comparison may result in an unintentionally large loop. On suggestion by Takashi Iwai, version two removes the offset argument from the load_patch callbacks entirely, which also resolves similar issues in opl3. Compile tested only. v3 adjusts comments and hopefully gets copy offsets right. Signed-off-by: Dan Rosenberg Signed-off-by: Takashi Iwai --- sound/oss/opl3.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'sound/oss/opl3.c') diff --git a/sound/oss/opl3.c b/sound/oss/opl3.c index 938c48c4358..cbf957424d5 100644 --- a/sound/oss/opl3.c +++ b/sound/oss/opl3.c @@ -820,7 +820,7 @@ static void opl3_hw_control(int dev, unsigned char *event) } static int opl3_load_patch(int dev, int format, const char __user *addr, - int offs, int count, int pmgr_flag) + int count, int pmgr_flag) { struct sbi_instrument ins; @@ -830,11 +830,7 @@ static int opl3_load_patch(int dev, int format, const char __user *addr, return -EINVAL; } - /* - * What the fuck is going on here? We leave junk in the beginning - * of ins and then check the field pretty close to that beginning? - */ - if(copy_from_user(&((char *) &ins)[offs], addr + offs, sizeof(ins) - offs)) + if (copy_from_user(&ins, addr, sizeof(ins))) return -EFAULT; if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR) -- cgit v1.2.3-70-g09d2 From 4d00135a680727f6c3be78f8befaac009030e4df Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Wed, 23 Mar 2011 11:42:57 -0400 Subject: sound/oss/opl3: validate voice and channel indexes User-controllable indexes for voice and channel values may cause reading and writing beyond the bounds of their respective arrays, leading to potentially exploitable memory corruption. Validate these indexes. Signed-off-by: Dan Rosenberg Cc: stable@kernel.org Signed-off-by: Takashi Iwai --- sound/oss/opl3.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'sound/oss/opl3.c') diff --git a/sound/oss/opl3.c b/sound/oss/opl3.c index cbf957424d5..407cd677950 100644 --- a/sound/oss/opl3.c +++ b/sound/oss/opl3.c @@ -845,6 +845,10 @@ static int opl3_load_patch(int dev, int format, const char __user *addr, static void opl3_panning(int dev, int voice, int value) { + + if (voice < 0 || voice >= devc->nr_voice) + return; + devc->voc[voice].panning = value; } @@ -1062,8 +1066,15 @@ static int opl3_alloc_voice(int dev, int chn, int note, struct voice_alloc_info static void opl3_setup_voice(int dev, int voice, int chn) { - struct channel_info *info = - &synth_devs[dev]->chn_info[chn]; + struct channel_info *info; + + if (voice < 0 || voice >= devc->nr_voice) + return; + + if (chn < 0 || chn > 15) + return; + + info = &synth_devs[dev]->chn_info[chn]; opl3_set_instr(dev, voice, info->pgm_num); -- cgit v1.2.3-70-g09d2