summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2009-10-21 09:11:43 +0200
committerTakashi Iwai <tiwai@suse.de>2009-11-10 16:22:59 +0100
commitb7fe750fcceda4fa6bef399b0e2812562728ea82 (patch)
treeb309dee386e4c0d5b47166338e5a81af50a58eb6 /sound
parent16fb109644b5644e42ececeff644514de6f4bd03 (diff)
downloadlinux-b7fe750fcceda4fa6bef399b0e2812562728ea82.tar.gz
linux-b7fe750fcceda4fa6bef399b0e2812562728ea82.tar.bz2
linux-b7fe750fcceda4fa6bef399b0e2812562728ea82.zip
sound: rawmidi: fix MIDI device O_APPEND error handling
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> Cc: <stable@kernel.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/core/rawmidi.c19
1 files changed, 7 insertions, 12 deletions
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 091405385e15..70d6f25ba526 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -272,8 +272,10 @@ static int open_substream(struct snd_rawmidi *rmidi,
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_rawmidi *rmidi, int subdevice, int mode,
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_rawmidi *rmidi, int subdevice, int mode,
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 */