summaryrefslogtreecommitdiff
path: root/sys/dev/wscons/wsmux.c
diff options
context:
space:
mode:
authoranton <anton@cvs.openbsd.org>2020-03-24 07:53:25 +0000
committeranton <anton@cvs.openbsd.org>2020-03-24 07:53:25 +0000
commitaa4910f158268756bcef7355540d09db97ebaa11 (patch)
treeea20d162620135f4747b62a43bdddba4da25ff82 /sys/dev/wscons/wsmux.c
parentc79e869a7eb314bb7d27132a1a35e27b8e5fb64f (diff)
Ensure that me_evp is still NULL before assignment during open of wscons
devices. This condition is checked early on during open but since the same routine could end up sleeping before assigning me_evp, a race against adding the same wscons device to a wsmux could be lost. This in turn can cause a NULL deference during close. ok mpi@ Reported-by: syzbot+34c3041bfd96c888c8bd@syzkaller.appspotmail.com
Diffstat (limited to 'sys/dev/wscons/wsmux.c')
-rw-r--r--sys/dev/wscons/wsmux.c28
1 files changed, 14 insertions, 14 deletions
diff --git a/sys/dev/wscons/wsmux.c b/sys/dev/wscons/wsmux.c
index ede38d63714..ce6b237d802 100644
--- a/sys/dev/wscons/wsmux.c
+++ b/sys/dev/wscons/wsmux.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wsmux.c,v 1.49 2020/01/08 16:27:41 visa Exp $ */
+/* $OpenBSD: wsmux.c,v 1.50 2020/03/24 07:53:24 anton Exp $ */
/* $NetBSD: wsmux.c,v 1.37 2005/04/30 03:47:12 augustss Exp $ */
/*
@@ -90,7 +90,7 @@ int wsmuxdebug = 0;
int wsmux_mux_open(struct wsevsrc *, struct wseventvar *);
int wsmux_mux_close(struct wsevsrc *);
-void wsmux_do_open(struct wsmux_softc *, struct wseventvar *);
+int wsmux_do_open(struct wsmux_softc *, struct wseventvar *);
void wsmux_do_close(struct wsmux_softc *);
#if NWSDISPLAY > 0
@@ -184,7 +184,7 @@ wsmuxopen(dev_t dev, int flags, int mode, struct proc *p)
{
struct wsmux_softc *sc;
struct wseventvar *evar;
- int unit;
+ int error, unit;
unit = minor(dev);
sc = wsmux_getmux(unit);
@@ -215,9 +215,10 @@ wsmuxopen(dev_t dev, int flags, int mode, struct proc *p)
sc->sc_rawkbd = 0;
#endif
- wsmux_do_open(sc, evar);
-
- return (0);
+ error = wsmux_do_open(sc, evar);
+ if (error)
+ wsevent_fini(evar);
+ return (error);
}
/*
@@ -229,23 +230,17 @@ wsmux_mux_open(struct wsevsrc *me, struct wseventvar *evar)
struct wsmux_softc *sc = (struct wsmux_softc *)me;
#ifdef DIAGNOSTIC
- if (sc->sc_base.me_evp != NULL) {
- printf("wsmux_mux_open: busy\n");
- return (EBUSY);
- }
if (sc->sc_base.me_parent == NULL) {
printf("wsmux_mux_open: no parent\n");
return (EINVAL);
}
#endif
- wsmux_do_open(sc, evar);
-
- return (0);
+ return (wsmux_do_open(sc, evar));
}
/* Common part of opening a mux. */
-void
+int
wsmux_do_open(struct wsmux_softc *sc, struct wseventvar *evar)
{
struct wsevsrc *me;
@@ -253,6 +248,9 @@ wsmux_do_open(struct wsmux_softc *sc, struct wseventvar *evar)
int error;
#endif
+ /* The device could already be attached to a mux. */
+ if (sc->sc_base.me_evp != NULL)
+ return (EBUSY);
sc->sc_base.me_evp = evar; /* remember event variable, mark as open */
/* Open all children. */
@@ -280,6 +278,8 @@ wsmux_do_open(struct wsmux_softc *sc, struct wseventvar *evar)
#endif
}
rw_exit_read(&sc->sc_lock);
+
+ return (0);
}
/*