diff options
author | 2020-12-06 07:58:54 +0000 | |
---|---|---|
committer | 2020-12-06 07:58:54 +0000 | |
commit | 996a5b4d63fafd69b234669968225849b5adfda2 (patch) | |
tree | fde3ee34a1057dc19db9af2934d35620d04e96fd | |
parent | Mark bitmask_{start,end}_values[] and g_probable_mtu[] const. (diff) | |
download | wireguard-openbsd-996a5b4d63fafd69b234669968225849b5adfda2.tar.xz wireguard-openbsd-996a5b4d63fafd69b234669968225849b5adfda2.zip |
Fix yet another wscons race. In the same subsystem, the following
properties must always hold true:
1. A device (wsmouse0 is this scenario) can only be opened in rw mode
once. Such device cannot be a child of a wsmux at this point as it
operates on its own event queue.
2. A device being a child of a wsmux must use the wsmux event queue
assuming the wsmux is open. Otherwise, its event queue must be NULL.
There's a race in wsmux_attach_sc() allowing a device to be part of a
mux while using its own event queue. This in turn can cause a NULL
pointer deference in wsevent_fini() while closing the same device. The
solution is to check if the race was lost, i.e. another thread managed
to open the device in rw mode while sleeping in wsmux_attach_sc().
ok gnezdo@ visa@
Reported-by: syzbot+684707f0312345a090ef@syzkaller.appspotmail.com
-rw-r--r-- | sys/dev/wscons/wsmux.c | 11 |
1 files changed, 5 insertions, 6 deletions
diff --git a/sys/dev/wscons/wsmux.c b/sys/dev/wscons/wsmux.c index 91d3ebdf0a3..35c0c008ef5 100644 --- a/sys/dev/wscons/wsmux.c +++ b/sys/dev/wscons/wsmux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: wsmux.c,v 1.51 2020/07/29 05:53:52 anton Exp $ */ +/* $OpenBSD: wsmux.c,v 1.52 2020/12/06 07:58:54 anton Exp $ */ /* $NetBSD: wsmux.c,v 1.37 2005/04/30 03:47:12 augustss Exp $ */ /* @@ -705,13 +705,12 @@ wsmux_attach_sc(struct wsmux_softc *sc, struct wsevsrc *me) } #endif if (sc->sc_base.me_evp != NULL) { - /* Mux is open, so open the new subdevice */ - DPRINTF(("%s: %s: calling open of %s\n", __func__, - sc->sc_base.me_dv.dv_xname, me->me_dv.dv_xname)); + /* Mux is open, try to open the subdevice. */ error = wsevsrc_open(me, sc->sc_base.me_evp); } else { - DPRINTF(("%s: %s not open\n", __func__, - sc->sc_base.me_dv.dv_xname)); + /* Mux is closed, ensure that the subdevice is also closed. */ + if (me->me_evp != NULL) + error = EBUSY; } if (error) { |