From 3f1dd8d2335d348d20376202ec9ef7098662248e Mon Sep 17 00:00:00 2001 From: anton Date: Wed, 22 May 2019 18:52:15 +0000 Subject: 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@ --- sys/dev/wscons/wsevent.c | 22 ++++++++++++++-------- sys/dev/wscons/wseventvar.h | 4 ++-- sys/dev/wscons/wskbd.c | 5 +++-- sys/dev/wscons/wsmouse.c | 5 +++-- sys/dev/wscons/wsmux.c | 5 +++-- 5 files changed, 25 insertions(+), 16 deletions(-) (limited to 'sys/dev') 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 -- cgit v1.2.3