[020/119] sound: rawmidi: fix MIDI device O_APPEND error handling

Greg KH
2009-12-07T00:33:56Z

[-- Attachment #1: sound-rawmidi-fix-midi-device-o_append-error-handling.patch --]
[-- Type: text/plain, Size: 2456 bytes --]

2.6.31-stable review patch. If anyone has any objections, please let us know.

------------------
From: Clemens Ladisch <clemens@ladisch.de>

commit b7fe750fcceda4fa6bef399b0e2812562728ea82 upstream.

Commit 9a1b64caac82aa02cb74587ffc798e6f42c6170a in 2.6.30 broke the
error handling code in rawmidi_open_priv().

If only the output substream of a RawMIDI device has been opened and
if this device is then opened with O_RDWR | O_APPEND and if the
initialization of the input substream fails (either because of low
memory or because the device driver's open callback fails), then the
runtime structure of the already open output substream will be freed
and all following writes through the first handle will cause
snd_rawmidi_write() to use the NULL runtime pointer.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
sound/core/rawmidi.c | 19 +++++++------------
1 file changed, 7 insertions(+), 12 deletions(-)

--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -272,8 +272,10 @@ static int open_substream(struct snd_raw
if (err < 0)
return err;
err = substream->ops->open(substream);
- if (err < 0)
+ if (err < 0) {
+ snd_rawmidi_runtime_free(substream);
return err;
+ }
substream->opened = 1;
substream->active_sensing = 0;
if (mode & SNDRV_RAWMIDI_LFLG_APPEND)
@@ -300,27 +302,27 @@ static int rawmidi_open_priv(struct snd_
SNDRV_RAWMIDI_STREAM_INPUT,
mode, &sinput);
if (err < 0)
- goto __error;
+ return err;
}
if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) {
err = assign_substream(rmidi, subdevice,
SNDRV_RAWMIDI_STREAM_OUTPUT,
mode, &soutput);
if (err < 0)
- goto __error;
+ return err;
}

if (sinput) {
err = open_substream(rmidi, sinput, mode);
if (err < 0)
- goto __error;
+ return err;
}
if (soutput) {
err = open_substream(rmidi, soutput, mode);
if (err < 0) {
if (sinput)
close_substream(rmidi, sinput, 0);
- goto __error;
+ return err;
}
}

@@ -328,13 +330,6 @@ static int rawmidi_open_priv(struct snd_
rfile->input = sinput;
rfile->output = soutput;
return 0;
-
- __error:
- if (sinput && sinput->runtime)
- snd_rawmidi_runtime_free(sinput);
- if (soutput && soutput->runtime)
- snd_rawmidi_runtime_free(soutput);
- return err;
}

/* called from sound/core/seq/seq_midi.c */