Update of /cvsroot/alsa/alsa-kernel/core/seq/oss
In directory sc8-pr-cvs1:/tmp/cvs-serv14051

Modified Files:
        seq_oss_init.c seq_oss_synth.c 
Log Message:
Fixed double-free (thus OOPS) problem

Index: seq_oss_init.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/core/seq/oss/seq_oss_init.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- seq_oss_init.c      5 Mar 2003 11:31:12 -0000       1.9
+++ seq_oss_init.c      11 Mar 2003 20:16:01 -0000      1.10
@@ -51,7 +51,7 @@
 static int create_port(seq_oss_devinfo_t *dp);
 static int delete_port(seq_oss_devinfo_t *dp);
 static int alloc_seq_queue(seq_oss_devinfo_t *dp);
-static int delete_seq_queue(seq_oss_devinfo_t *dp);
+static int delete_seq_queue(int queue);
 static void free_devinfo(void *private);
 
 #define call_ctl(type,rec) snd_seq_kernel_client_ctl(system_client, type, rec)
@@ -186,6 +186,7 @@
                snd_printk(KERN_ERR "can't malloc device info\n");
                return -ENOMEM;
        }
+       debug_printk(("oss_open: dp = %p\n", dp));
 
        for (i = 0; i < SNDRV_SEQ_OSS_MAX_CLIENTS; i++) {
                if (client_table[i] == NULL)
@@ -215,12 +216,14 @@
        }
 
        /* create port */
+       debug_printk(("create new port\n"));
        if ((rc = create_port(dp)) < 0) {
                snd_printk(KERN_ERR "can't create port\n");
                goto _error;
        }
 
        /* allocate queue */
+       debug_printk(("allocate queue\n"));
        if ((rc = alloc_seq_queue(dp)) < 0)
                goto _error;
 
@@ -236,6 +239,7 @@
        dp->file_mode = translate_mode(file);
 
        /* initialize read queue */
+       debug_printk(("initialize read queue\n"));
        if (is_read_mode(dp->file_mode)) {
                if ((dp->readq = snd_seq_oss_readq_new(dp, maxqlen)) == NULL) {
                        rc = -ENOMEM;
@@ -244,6 +248,7 @@
        }
 
        /* initialize write queue */
+       debug_printk(("initialize write queue\n"));
        if (is_write_mode(dp->file_mode)) {
                dp->writeq = snd_seq_oss_writeq_new(dp, maxqlen);
                if (dp->writeq == NULL) {
@@ -253,11 +258,13 @@
        }
 
        /* initialize timer */
+       debug_printk(("initialize timer\n"));
        if ((dp->timer = snd_seq_oss_timer_new(dp)) == NULL) {
                snd_printk(KERN_ERR "can't alloc timer\n");
                rc = -ENOMEM;
                goto _error;
        }
+       debug_printk(("timer initialized\n"));
 
        /* set private data pointer */
        file->private_data = dp;
@@ -275,10 +282,11 @@
        return 0;
 
  _error:
-       delete_seq_queue(dp);
-       delete_port(dp);
        snd_seq_oss_synth_cleanup(dp);
        snd_seq_oss_midi_cleanup(dp);
+       i = dp->queue;
+       delete_port(dp);
+       delete_seq_queue(i);
 
        return rc;
 }
@@ -346,6 +354,7 @@
        if (dp->port < 0)
                return 0;
 
+       debug_printk(("delete_port %i\n", dp->port));
        memset(&port_info, 0, sizeof(port_info));
        port_info.addr.client = dp->cseq;
        port_info.addr.port = dp->port;
@@ -377,15 +386,19 @@
  * release queue
  */
 static int
-delete_seq_queue(seq_oss_devinfo_t *dp)
+delete_seq_queue(int queue)
 {
        snd_seq_queue_info_t qinfo;
+       int rc;
 
-       if (dp->queue < 0)
+       if (queue < 0)
                return 0;
        memset(&qinfo, 0, sizeof(qinfo));
-       qinfo.queue = dp->queue;
-       return call_ctl(SNDRV_SEQ_IOCTL_DELETE_QUEUE, &qinfo);
+       qinfo.queue = queue;
+       rc = call_ctl(SNDRV_SEQ_IOCTL_DELETE_QUEUE, &qinfo);
+       if (rc < 0)
+               printk(KERN_ERR "seq-oss: unable to delete queue %d (%d)\n", queue, 
rc);
+       return rc;
 }
 
 
@@ -416,6 +429,8 @@
 void
 snd_seq_oss_release(seq_oss_devinfo_t *dp)
 {
+       int queue;
+
        client_table[dp->index] = NULL;
        num_clients--;
 
@@ -428,10 +443,10 @@
 
        /* clear slot */
        debug_printk(("releasing resource..\n"));
+       queue = dp->queue;
        if (dp->port >= 0)
                delete_port(dp);
-       if (dp->queue >= 0)
-               delete_seq_queue(dp);
+       delete_seq_queue(queue);
 
        debug_printk(("release done\n"));
 }

Index: seq_oss_synth.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/core/seq/oss/seq_oss_synth.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- seq_oss_synth.c     19 Dec 2002 15:59:18 -0000      1.11
+++ seq_oss_synth.c     11 Mar 2003 20:16:02 -0000      1.12
@@ -302,29 +302,36 @@
        seq_oss_synth_t *rec;
        seq_oss_synthinfo_t *info;
 
+       snd_assert(dp->max_synthdev <= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS, return);
        for (i = 0; i < dp->max_synthdev; i++) {
                info = &dp->synths[i];
                if (! info->opened)
                        continue;
                if (info->is_midi) {
-                       snd_seq_oss_midi_close(dp, info->midi_mapped);
-                       midi_synth_dev.opened--;
+                       if (midi_synth_dev.opened > 0) {
+                               snd_seq_oss_midi_close(dp, info->midi_mapped);
+                               midi_synth_dev.opened--;
+                       }
                } else {
                        rec = get_sdev(i);
                        if (rec == NULL)
                                continue;
-                       if (rec->opened) {
+                       if (rec->opened > 0) {
                                debug_printk(("synth %d closed\n", i));
                                rec->oper.close(&info->arg);
                                module_put(rec->oper.owner);
-                               rec->opened--;
+                               rec->opened = 0;
                        }
                        snd_use_lock_free(&rec->use_lock);
                }
-               if (info->sysex)
+               if (info->sysex) {
                        kfree(info->sysex);
-               if (info->ch)
+                       info->sysex = NULL;
+               }
+               if (info->ch) {
                        kfree(info->ch);
+                       info->ch = NULL;
+               }
        }
        dp->synth_opened = 0;
        dp->max_synthdev = 0;
@@ -401,15 +408,21 @@
                info->sysex->len = 0; /* reset sysex */
        reset_channels(info);
        if (info->is_midi) {
+               if (midi_synth_dev.opened <= 0)
+                       return;
                snd_seq_oss_midi_reset(dp, info->midi_mapped);
                if (snd_seq_oss_midi_open(dp, info->midi_mapped,
                                          dp->file_mode) < 0) {
                        midi_synth_dev.opened--;
                        info->opened = 0;
-                       if (info->sysex)
+                       if (info->sysex) {
                                kfree(info->sysex);
-                       if (info->ch)
+                               info->sysex = NULL;
+                       }
+                       if (info->ch) {
                                kfree(info->ch);
+                               info->ch = NULL;
+                       }
                }
                return;
        }



-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open! 
Get cracking and register here for some mind boggling fun and 
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
_______________________________________________
Alsa-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-cvslog

Reply via email to