aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2009-10-21 03:11:43 -0400
committerTakashi Iwai <tiwai@suse.de>2009-11-10 10:22:59 -0500
commitb7fe750fcceda4fa6bef399b0e2812562728ea82 (patch)
treeb309dee386e4c0d5b47166338e5a81af50a58eb6 /sound
parent16fb109644b5644e42ececeff644514de6f4bd03 (diff)
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,
272 if (err < 0) 272 if (err < 0)
273 return err; 273 return err;
274 err = substream->ops->open(substream); 274 err = substream->ops->open(substream);
275 if (err < 0) 275 if (err < 0) {
276 snd_rawmidi_runtime_free(substream);
276 return err; 277 return err;
278 }
277 substream->opened = 1; 279 substream->opened = 1;
278 substream->active_sensing = 0; 280 substream->active_sensing = 0;
279 if (mode & SNDRV_RAWMIDI_LFLG_APPEND) 281 if (mode & SNDRV_RAWMIDI_LFLG_APPEND)
@@ -300,27 +302,27 @@ static int rawmidi_open_priv(struct snd_rawmidi *rmidi, int subdevice, int mode,
300 SNDRV_RAWMIDI_STREAM_INPUT, 302 SNDRV_RAWMIDI_STREAM_INPUT,
301 mode, &sinput); 303 mode, &sinput);
302 if (err < 0) 304 if (err < 0)
303 goto __error; 305 return err;
304 } 306 }
305 if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) { 307 if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) {
306 err = assign_substream(rmidi, subdevice, 308 err = assign_substream(rmidi, subdevice,
307 SNDRV_RAWMIDI_STREAM_OUTPUT, 309 SNDRV_RAWMIDI_STREAM_OUTPUT,
308 mode, &soutput); 310 mode, &soutput);
309 if (err < 0) 311 if (err < 0)
310 goto __error; 312 return err;
311 } 313 }
312 314
313 if (sinput) { 315 if (sinput) {
314 err = open_substream(rmidi, sinput, mode); 316 err = open_substream(rmidi, sinput, mode);
315 if (err < 0) 317 if (err < 0)
316 goto __error; 318 return err;
317 } 319 }
318 if (soutput) { 320 if (soutput) {
319 err = open_substream(rmidi, soutput, mode); 321 err = open_substream(rmidi, soutput, mode);
320 if (err < 0) { 322 if (err < 0) {
321 if (sinput) 323 if (sinput)
322 close_substream(rmidi, sinput, 0); 324 close_substream(rmidi, sinput, 0);
323 goto __error; 325 return err;
324 } 326 }
325 } 327 }
326 328
@@ -328,13 +330,6 @@ static int rawmidi_open_priv(struct snd_rawmidi *rmidi, int subdevice, int mode,
328 rfile->input = sinput; 330 rfile->input = sinput;
329 rfile->output = soutput; 331 rfile->output = soutput;
330 return 0; 332 return 0;
331
332 __error:
333 if (sinput && sinput->runtime)
334 snd_rawmidi_runtime_free(sinput);
335 if (soutput && soutput->runtime)
336 snd_rawmidi_runtime_free(soutput);
337 return err;
338} 333}
339 334
340/* called from sound/core/seq/seq_midi.c */ 335/* called from sound/core/seq/seq_midi.c */