From 8579d2d7779d7ff41ea2a0183015e0e5038f1043 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 21 Oct 2009 09:09:38 +0200 Subject: sound: rawmidi: fix double init when opening MIDI device with O_APPEND Commit 9a1b64caac82aa02cb74587ffc798e6f42c6170a in 2.6.30 moved the substream initialization code to where it would be executed every time the substream is opened. This had the consequence that any further opening would drop and leak the data in the existing buffer, and that the device driver's open callback would be called multiple times, unexpectedly. Signed-off-by: Clemens Ladisch Cc: Signed-off-by: Takashi Iwai --- sound/core/rawmidi.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'sound/core') diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index c0adc14c91f..3071e6f5801 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -266,17 +266,19 @@ static int open_substream(struct snd_rawmidi *rmidi, { int err; - err = snd_rawmidi_runtime_create(substream); - if (err < 0) - return err; - err = substream->ops->open(substream); - if (err < 0) - return err; - substream->opened = 1; - if (substream->use_count++ == 0) + if (substream->use_count == 0) { + err = snd_rawmidi_runtime_create(substream); + if (err < 0) + return err; + err = substream->ops->open(substream); + if (err < 0) + return err; + substream->opened = 1; substream->active_sensing = 0; - if (mode & SNDRV_RAWMIDI_LFLG_APPEND) - substream->append = 1; + if (mode & SNDRV_RAWMIDI_LFLG_APPEND) + substream->append = 1; + } + substream->use_count++; rmidi->streams[substream->stream].substream_opened++; return 0; } -- cgit v1.2.3 From 16fb109644b5644e42ececeff644514de6f4bd03 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 21 Oct 2009 09:10:16 +0200 Subject: sound: rawmidi: fix checking of O_APPEND when opening MIDI device Commit 9a1b64caac82aa02cb74587ffc798e6f42c6170a in 2.6.30 dropped the check that a substream must already have been opened with O_APPEND to be able to open it a second time. This would make it possible for a substream to be switched to append mode, which would mean that non-atomic writes would fail unexpectedly. Signed-off-by: Clemens Ladisch Cc: Signed-off-by: Takashi Iwai --- sound/core/rawmidi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound/core') diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 3071e6f5801..091405385e1 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -248,7 +248,8 @@ static int assign_substream(struct snd_rawmidi *rmidi, int subdevice, list_for_each_entry(substream, &s->substreams, list) { if (substream->opened) { if (stream == SNDRV_RAWMIDI_STREAM_INPUT || - !(mode & SNDRV_RAWMIDI_LFLG_APPEND)) + !(mode & SNDRV_RAWMIDI_LFLG_APPEND) || + !substream->append) continue; } if (subdevice < 0 || subdevice == substream->number) { -- cgit v1.2.3 From b7fe750fcceda4fa6bef399b0e2812562728ea82 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 21 Oct 2009 09:11:43 +0200 Subject: 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 Cc: Signed-off-by: Takashi Iwai --- sound/core/rawmidi.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'sound/core') diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 091405385e1..70d6f25ba52 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 */ -- cgit v1.2.3