summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoranton <anton@cvs.openbsd.org>2019-05-22 18:52:15 +0000
committeranton <anton@cvs.openbsd.org>2019-05-22 18:52:15 +0000
commit3f1dd8d2335d348d20376202ec9ef7098662248e (patch)
tree83150de3ebaf48c58ed281a512f08e7baf90b000
parent0218d2364b8dbd7d1fac92150c117dd08e20c7b6 (diff)
A wscons device may only be opened in read/write mode once. However,
after checking for exclusive access, malloc() can sleep in wsevent_init() opening up for a potential race where more than one thread may be able open the device. Prevent this by checking if the race was won after calling malloc(). While here, switch to mallocarray as proposed by both cheloha@ and mpi@ ok mpi@
-rw-r--r--sys/dev/wscons/wsevent.c22
-rw-r--r--sys/dev/wscons/wseventvar.h4
-rw-r--r--sys/dev/wscons/wskbd.c5
-rw-r--r--sys/dev/wscons/wsmouse.c5
-rw-r--r--sys/dev/wscons/wsmux.c5
5 files changed, 25 insertions, 16 deletions
diff --git a/sys/dev/wscons/wsevent.c b/sys/dev/wscons/wsevent.c
index be015534317..8518bfc56e1 100644
--- a/sys/dev/wscons/wsevent.c
+++ b/sys/dev/wscons/wsevent.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wsevent.c,v 1.19 2019/02/01 17:23:08 anton Exp $ */
+/* $OpenBSD: wsevent.c,v 1.20 2019/05/22 18:52:14 anton Exp $ */
/* $NetBSD: wsevent.c,v 1.16 2003/08/07 16:31:29 agc Exp $ */
/*
@@ -98,21 +98,27 @@ const struct filterops wsevent_filtops = {
/*
* Initialize a wscons_event queue.
*/
-void
+int
wsevent_init(struct wseventvar *ev)
{
+ struct wscons_event *queue;
+
+ if (ev->q != NULL)
+ return (0);
+ queue = mallocarray(WSEVENT_QSIZE, sizeof(struct wscons_event),
+ M_DEVBUF, M_WAITOK | M_ZERO);
if (ev->q != NULL) {
-#ifdef DIAGNOSTIC
- printf("wsevent_init: already initialized\n");
-#endif
- return;
+ free(queue, M_DEVBUF, WSEVENT_QSIZE * sizeof(struct wscons_event));
+ return (1);
}
+
+ ev->q = queue;
ev->get = ev->put = 0;
- ev->q = malloc(WSEVENT_QSIZE * sizeof(struct wscons_event),
- M_DEVBUF, M_WAITOK | M_ZERO);
sigio_init(&ev->sigio);
+
+ return (0);
}
/*
diff --git a/sys/dev/wscons/wseventvar.h b/sys/dev/wscons/wseventvar.h
index 5424fff9dc5..5042b81cb9c 100644
--- a/sys/dev/wscons/wseventvar.h
+++ b/sys/dev/wscons/wseventvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: wseventvar.h,v 1.9 2018/11/19 19:19:24 anton Exp $ */
+/* $OpenBSD: wseventvar.h,v 1.10 2019/05/22 18:52:14 anton Exp $ */
/* $NetBSD: wseventvar.h,v 1.1 1998/03/22 14:24:03 drochner Exp $ */
/*
@@ -104,7 +104,7 @@ struct wseventvar {
pgsigio(&(ev)->sigio, SIGIO, 0); \
}
-void wsevent_init(struct wseventvar *);
+int wsevent_init(struct wseventvar *);
void wsevent_fini(struct wseventvar *);
int wsevent_read(struct wseventvar *, struct uio *, int);
int wsevent_poll(struct wseventvar *, int, struct proc *);
diff --git a/sys/dev/wscons/wskbd.c b/sys/dev/wscons/wskbd.c
index 49a08976c3a..b89e95f9b33 100644
--- a/sys/dev/wscons/wskbd.c
+++ b/sys/dev/wscons/wskbd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wskbd.c,v 1.96 2019/02/19 07:01:02 anton Exp $ */
+/* $OpenBSD: wskbd.c,v 1.97 2019/05/22 18:52:14 anton Exp $ */
/* $NetBSD: wskbd.c,v 1.80 2005/05/04 01:52:16 augustss Exp $ */
/*
@@ -824,7 +824,8 @@ wskbdopen(dev_t dev, int flags, int mode, struct proc *p)
return (EBUSY);
evar = &sc->sc_base.me_evar;
- wsevent_init(evar);
+ if (wsevent_init(evar))
+ return (EBUSY);
error = wskbd_do_open(sc, evar);
if (error) {
diff --git a/sys/dev/wscons/wsmouse.c b/sys/dev/wscons/wsmouse.c
index 73c304bd53e..57ea83a6aab 100644
--- a/sys/dev/wscons/wsmouse.c
+++ b/sys/dev/wscons/wsmouse.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wsmouse.c,v 1.52 2019/03/24 18:04:02 bru Exp $ */
+/* $OpenBSD: wsmouse.c,v 1.53 2019/05/22 18:52:14 anton Exp $ */
/* $NetBSD: wsmouse.c,v 1.35 2005/02/27 00:27:52 perry Exp $ */
/*
@@ -330,7 +330,8 @@ wsmouseopen(dev_t dev, int flags, int mode, struct proc *p)
return (EBUSY);
evar = &sc->sc_base.me_evar;
- wsevent_init(evar);
+ if (wsevent_init(evar))
+ return (EBUSY);
error = wsmousedoopen(sc, evar);
if (error) {
diff --git a/sys/dev/wscons/wsmux.c b/sys/dev/wscons/wsmux.c
index 28f6815d91f..ca733362175 100644
--- a/sys/dev/wscons/wsmux.c
+++ b/sys/dev/wscons/wsmux.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wsmux.c,v 1.46 2019/05/21 20:57:10 anton Exp $ */
+/* $OpenBSD: wsmux.c,v 1.47 2019/05/22 18:52:14 anton Exp $ */
/* $NetBSD: wsmux.c,v 1.37 2005/04/30 03:47:12 augustss Exp $ */
/*
@@ -209,7 +209,8 @@ wsmuxopen(dev_t dev, int flags, int mode, struct proc *p)
return (EBUSY);
evar = &sc->sc_base.me_evar;
- wsevent_init(evar);
+ if (wsevent_init(evar))
+ return (EBUSY);
#ifdef WSDISPLAY_COMPAT_RAWKBD
sc->sc_rawkbd = 0;
#endif