Commit b7fe750f authored by Clemens Ladisch's avatar Clemens Ladisch Committed by Takashi Iwai

sound: rawmidi: fix MIDI device O_APPEND error handling

Commit 9a1b64ca 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: default avatarClemens Ladisch <clemens@ladisch.de>
Cc: <stable@kernel.org>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 16fb1096
...@@ -272,8 +272,10 @@ static int open_substream(struct snd_rawmidi *rmidi, ...@@ -272,8 +272,10 @@ static int open_substream(struct snd_rawmidi *rmidi,
if (err < 0) if (err < 0)
return err; return err;
err = substream->ops->open(substream); err = substream->ops->open(substream);
if (err < 0) if (err < 0) {
snd_rawmidi_runtime_free(substream);
return err; return err;
}
substream->opened = 1; substream->opened = 1;
substream->active_sensing = 0; substream->active_sensing = 0;
if (mode & SNDRV_RAWMIDI_LFLG_APPEND) if (mode & SNDRV_RAWMIDI_LFLG_APPEND)
...@@ -300,27 +302,27 @@ static int rawmidi_open_priv(struct snd_rawmidi *rmidi, int subdevice, int mode, ...@@ -300,27 +302,27 @@ static int rawmidi_open_priv(struct snd_rawmidi *rmidi, int subdevice, int mode,
SNDRV_RAWMIDI_STREAM_INPUT, SNDRV_RAWMIDI_STREAM_INPUT,
mode, &sinput); mode, &sinput);
if (err < 0) if (err < 0)
goto __error; return err;
} }
if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) { if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) {
err = assign_substream(rmidi, subdevice, err = assign_substream(rmidi, subdevice,
SNDRV_RAWMIDI_STREAM_OUTPUT, SNDRV_RAWMIDI_STREAM_OUTPUT,
mode, &soutput); mode, &soutput);
if (err < 0) if (err < 0)
goto __error; return err;
} }
if (sinput) { if (sinput) {
err = open_substream(rmidi, sinput, mode); err = open_substream(rmidi, sinput, mode);
if (err < 0) if (err < 0)
goto __error; return err;
} }
if (soutput) { if (soutput) {
err = open_substream(rmidi, soutput, mode); err = open_substream(rmidi, soutput, mode);
if (err < 0) { if (err < 0) {
if (sinput) if (sinput)
close_substream(rmidi, sinput, 0); 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, ...@@ -328,13 +330,6 @@ static int rawmidi_open_priv(struct snd_rawmidi *rmidi, int subdevice, int mode,
rfile->input = sinput; rfile->input = sinput;
rfile->output = soutput; rfile->output = soutput;
return 0; 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 */ /* called from sound/core/seq/seq_midi.c */
......
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