Chuck Ebbert a4789a
From: Takashi Iwai <tiwai@suse.de>
Chuck Ebbert a4789a
Date: Mon, 6 Sep 2010 07:13:45 +0000 (+0200)
Chuck Ebbert a4789a
Subject: ALSA: seq/oss - Fix double-free at error path of snd_seq_oss_open()
Chuck Ebbert a4789a
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=27f7ad53829f79e799a253285318bff79ece15bd
Chuck Ebbert a4789a
Chuck Ebbert a4789a
ALSA: seq/oss - Fix double-free at error path of snd_seq_oss_open()
Chuck Ebbert a4789a
Chuck Ebbert a4789a
The error handling in snd_seq_oss_open() has several bad codes that
Chuck Ebbert a4789a
do dereferecing released pointers and double-free of kmalloc'ed data.
Chuck Ebbert a4789a
The object dp is release in free_devinfo() that is called via
Chuck Ebbert a4789a
private_free callback.  The rest shouldn't touch this object any more.
Chuck Ebbert a4789a
Chuck Ebbert a4789a
The patch changes delete_port() to call kfree() in any case, and gets
Chuck Ebbert a4789a
rid of unnecessary calls of destructors in snd_seq_oss_open().
Chuck Ebbert a4789a
Chuck Ebbert a4789a
Fixes CVE-2010-3080.
Chuck Ebbert a4789a
Chuck Ebbert a4789a
Reported-and-tested-by: Tavis Ormandy <taviso@cmpxchg8b.com>
Chuck Ebbert a4789a
Cc: <stable@kernel.org>
Chuck Ebbert a4789a
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Chuck Ebbert a4789a
---
Chuck Ebbert a4789a
Chuck Ebbert a4789a
diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c
Chuck Ebbert a4789a
index 6857122..69cd7b3 100644
Chuck Ebbert a4789a
--- a/sound/core/seq/oss/seq_oss_init.c
Chuck Ebbert a4789a
+++ b/sound/core/seq/oss/seq_oss_init.c
Chuck Ebbert a4789a
@@ -281,13 +281,10 @@ snd_seq_oss_open(struct file *file, int level)
Chuck Ebbert a4789a
 	return 0;
Chuck Ebbert a4789a
 
Chuck Ebbert a4789a
  _error:
Chuck Ebbert a4789a
-	snd_seq_oss_writeq_delete(dp->writeq);
Chuck Ebbert a4789a
-	snd_seq_oss_readq_delete(dp->readq);
Chuck Ebbert a4789a
 	snd_seq_oss_synth_cleanup(dp);
Chuck Ebbert a4789a
 	snd_seq_oss_midi_cleanup(dp);
Chuck Ebbert a4789a
-	delete_port(dp);
Chuck Ebbert a4789a
 	delete_seq_queue(dp->queue);
Chuck Ebbert a4789a
-	kfree(dp);
Chuck Ebbert a4789a
+	delete_port(dp);
Chuck Ebbert a4789a
 
Chuck Ebbert a4789a
 	return rc;
Chuck Ebbert a4789a
 }
Chuck Ebbert a4789a
@@ -350,8 +347,10 @@ create_port(struct seq_oss_devinfo *dp)
Chuck Ebbert a4789a
 static int
Chuck Ebbert a4789a
 delete_port(struct seq_oss_devinfo *dp)
Chuck Ebbert a4789a
 {
Chuck Ebbert a4789a
-	if (dp->port < 0)
Chuck Ebbert a4789a
+	if (dp->port < 0) {
Chuck Ebbert a4789a
+		kfree(dp);
Chuck Ebbert a4789a
 		return 0;
Chuck Ebbert a4789a
+	}
Chuck Ebbert a4789a
 
Chuck Ebbert a4789a
 	debug_printk(("delete_port %i\n", dp->port));
Chuck Ebbert a4789a
 	return snd_seq_event_port_detach(dp->cseq, dp->port);