2006-05-14 02:20:00

by Jesper Juhl

[permalink] [raw]
Subject: [PATCH] fix potential NULL pointer deref in snd_sb8dsp_midi_interrupt()

First testing if a pointer is NULL and if it is (or might be), proceeding
with code that dereferences that same pointer is clearly a mistake.
This happens in sound/isa/sb/sb8_midi.c::snd_sb8dsp_midi_interrupt()
The patch below reworks the code so this unfortunate case doesn't happen.
Also remove some blank comments.

Found by the Coverity checker as bug #367

Patch is compile testted only due to lack of hardware.


Signed-off-by: Jesper Juhl <[email protected]>
---

sound/isa/sb/sb8_midi.c | 20 +++++++-------------
1 files changed, 7 insertions(+), 13 deletions(-)


--- linux-2.6.17-rc4-git2-orig/sound/isa/sb/sb8_midi.c 2006-03-20 06:53:29.000000000 +0100
+++ linux-2.6.17-rc4-git2/sound/isa/sb/sb8_midi.c 2006-05-14 04:12:33.000000000 +0200
@@ -32,20 +32,22 @@
#include <sound/core.h>
#include <sound/sb.h>

-/*

- */
-
-irqreturn_t snd_sb8dsp_midi_interrupt(struct snd_sb * chip)
+irqreturn_t snd_sb8dsp_midi_interrupt(struct snd_sb *chip)
{
struct snd_rawmidi *rmidi;
int max = 64;
char byte;

- if (chip == NULL || (rmidi = chip->rmidi) == NULL) {
+ if (!chip)
+ return IRQ_NONE;
+
+ rmidi = chip->rmidi;
+ if (!rmidi) {
inb(SBP(chip, DATA_AVAIL)); /* ack interrupt */
return IRQ_NONE;
}
+
spin_lock(&chip->midi_input_lock);
while (max-- > 0) {
if (inb(SBP(chip, DATA_AVAIL)) & 0x80) {
@@ -59,10 +61,6 @@ irqreturn_t snd_sb8dsp_midi_interrupt(st
return IRQ_HANDLED;
}

-/*
-
- */
-
static int snd_sb8dsp_midi_input_open(struct snd_rawmidi_substream *substream)
{
unsigned long flags;
@@ -252,10 +250,6 @@ static void snd_sb8dsp_midi_output_trigg
snd_sb8dsp_midi_output_write(substream);
}

-/*
-
- */
-
static struct snd_rawmidi_ops snd_sb8dsp_midi_output =
{
.open = snd_sb8dsp_midi_output_open,



2006-05-14 14:25:24

by Alexey Dobriyan

[permalink] [raw]
Subject: Re: [PATCH] fix potential NULL pointer deref in snd_sb8dsp_midi_interrupt()

On Sun, May 14, 2006 at 04:20:52AM +0200, Jesper Juhl wrote:
> First testing if a pointer is NULL and if it is (or might be), proceeding
> with code that dereferences that same pointer is clearly a mistake.
> This happens in sound/isa/sb/sb8_midi.c::snd_sb8dsp_midi_interrupt()
> The patch below reworks the code so this unfortunate case doesn't happen.

All callers of snd_sb8dsp_midi_interrupt() dereference "chip" right
before calling.

> --- linux-2.6.17-rc4-git2-orig/sound/isa/sb/sb8_midi.c
> +++ linux-2.6.17-rc4-git2/sound/isa/sb/sb8_midi.c
> -irqreturn_t snd_sb8dsp_midi_interrupt(struct snd_sb * chip)
> +irqreturn_t snd_sb8dsp_midi_interrupt(struct snd_sb *chip)
> {
> struct snd_rawmidi *rmidi;
> int max = 64;
> char byte;
>
> - if (chip == NULL || (rmidi = chip->rmidi) == NULL) {
> + if (!chip)
> + return IRQ_NONE;
> +
> + rmidi = chip->rmidi;
> + if (!rmidi) {
> inb(SBP(chip, DATA_AVAIL)); /* ack interrupt */
> return IRQ_NONE;
> }

2006-05-14 14:41:07

by Willy Tarreau

[permalink] [raw]
Subject: Re: [PATCH] fix potential NULL pointer deref in snd_sb8dsp_midi_interrupt()

On Sun, May 14, 2006 at 06:24:09PM +0400, Alexey Dobriyan wrote:
> On Sun, May 14, 2006 at 04:20:52AM +0200, Jesper Juhl wrote:
> > First testing if a pointer is NULL and if it is (or might be), proceeding
> > with code that dereferences that same pointer is clearly a mistake.
> > This happens in sound/isa/sb/sb8_midi.c::snd_sb8dsp_midi_interrupt()
> > The patch below reworks the code so this unfortunate case doesn't happen.
>
> All callers of snd_sb8dsp_midi_interrupt() dereference "chip" right
> before calling.

So the "if (chip == NULL)" part should be removed to avoid confusion.

>
> > --- linux-2.6.17-rc4-git2-orig/sound/isa/sb/sb8_midi.c
> > +++ linux-2.6.17-rc4-git2/sound/isa/sb/sb8_midi.c
> > -irqreturn_t snd_sb8dsp_midi_interrupt(struct snd_sb * chip)
> > +irqreturn_t snd_sb8dsp_midi_interrupt(struct snd_sb *chip)
> > {
> > struct snd_rawmidi *rmidi;
> > int max = 64;
> > char byte;
> >
> > - if (chip == NULL || (rmidi = chip->rmidi) == NULL) {
> > + if (!chip)
> > + return IRQ_NONE;
> > +
> > + rmidi = chip->rmidi;
> > + if (!rmidi) {
> > inb(SBP(chip, DATA_AVAIL)); /* ack interrupt */
> > return IRQ_NONE;
> > }

Willy