summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Ratchov <ratchov@cvs.openbsd.org>2010-06-25 07:32:06 +0000
committerAlexandre Ratchov <ratchov@cvs.openbsd.org>2010-06-25 07:32:06 +0000
commit5391d7a0f83d8a9499059a78ad8939ed9e58757f (patch)
tree057ae2e61c99c87fb18ee140738fddb1ac23d4d3
parent3bc361ce722cd2e583d357787c855db75cb54b18 (diff)
don't attempt to drain devices after they are destroyed, which
results in a use after free(). Catched by jakemsr@ with MALLOC_OPTIONS=J
-rw-r--r--usr.bin/aucat/aucat.c10
-rw-r--r--usr.bin/aucat/dev.c15
-rw-r--r--usr.bin/aucat/dev.h3
3 files changed, 20 insertions, 8 deletions
diff --git a/usr.bin/aucat/aucat.c b/usr.bin/aucat/aucat.c
index 3db6b56a4da..42f4fc3cea9 100644
--- a/usr.bin/aucat/aucat.c
+++ b/usr.bin/aucat/aucat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: aucat.c,v 1.95 2010/06/20 11:32:54 ratchov Exp $ */
+/* $OpenBSD: aucat.c,v 1.96 2010/06/25 07:32:05 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -817,14 +817,16 @@ aucat_main(int argc, char **argv)
fatal:
if (l_flag)
file_close(&listen->file);
- while (dev_list)
- dev_del(dev_list);
-
/*
* give a chance to drain
*/
+ for (d = dev_list; d != NULL; d = d->next)
+ dev_drain(d);
while (file_poll())
; /* nothing */
+
+ while (dev_list)
+ dev_del(dev_list);
filelist_done();
if (l_flag) {
if (rmdir(base) < 0 && errno != ENOTEMPTY && errno != EPERM)
diff --git a/usr.bin/aucat/dev.c b/usr.bin/aucat/dev.c
index 5815d84b733..0b5005c4356 100644
--- a/usr.bin/aucat/dev.c
+++ b/usr.bin/aucat/dev.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dev.c,v 1.59 2010/06/05 16:14:44 ratchov Exp $ */
+/* $OpenBSD: dev.c,v 1.60 2010/06/25 07:32:05 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -533,6 +533,16 @@ dev_close(struct dev *d)
}
/*
+ * Unless the device is already in process of closing, request it to close
+ */
+void
+dev_drain(struct dev *d)
+{
+ if (d->pstate != DEV_CLOSED)
+ dev_close(d);
+}
+
+/*
* Free the device
*/
void
@@ -540,8 +550,7 @@ dev_del(struct dev *d)
{
struct dev **p;
- if (d->pstate != DEV_CLOSED)
- dev_close(d);
+ dev_drain(d);
for (p = &dev_list; *p != d; p = &(*p)->next) {
#ifdef DEBUG
if (*p == NULL) {
diff --git a/usr.bin/aucat/dev.h b/usr.bin/aucat/dev.h
index ab8f412fd23..ca34ea0cc5b 100644
--- a/usr.bin/aucat/dev.h
+++ b/usr.bin/aucat/dev.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dev.h,v 1.25 2010/06/05 16:00:52 ratchov Exp $ */
+/* $OpenBSD: dev.h,v 1.26 2010/06/25 07:32:05 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -59,6 +59,7 @@ int dev_ref(struct dev *);
void dev_unref(struct dev *);
void dev_del(struct dev *);
void dev_wakeup(struct dev *);
+void dev_drain(struct dev *);
struct dev *dev_new_thru(void);
struct dev *dev_new_loop(struct aparams *, struct aparams *, unsigned);
struct dev *dev_new_sio(char *, unsigned,