summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormpi <mpi@openbsd.org>2018-09-25 13:46:44 +0000
committermpi <mpi@openbsd.org>2018-09-25 13:46:44 +0000
commit126b881f7106e87cadecac4b4ad6f06b70f71973 (patch)
tree7032cb17f59b24215e4c766db0de131c1ac7ab7e
parentdisklabel(8) uses hw.physmem to calculate swap and /var sizes. This (diff)
downloadwireguard-openbsd-126b881f7106e87cadecac4b4ad6f06b70f71973.tar.xz
wireguard-openbsd-126b881f7106e87cadecac4b4ad6f06b70f71973.zip
Insert a workaround for per-ifp ioctl being called w/o NET_LOCK().
An example of such code path is vlan_destroy() where we don't want to grab the lock because this driver is already NET_LOCK()-free. The real solution to this problem is to stop holding the NET_LOCK() around driver *_ioctl() routines. Problem reported & fix tested by Élie Bouttier, ok visa@, bluhm@
-rw-r--r--sys/dev/pv/if_vio.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/sys/dev/pv/if_vio.c b/sys/dev/pv/if_vio.c
index 432daf9a32e..46471f04181 100644
--- a/sys/dev/pv/if_vio.c
+++ b/sys/dev/pv/if_vio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_vio.c,v 1.5 2018/02/27 08:44:58 mpi Exp $ */
+/* $OpenBSD: if_vio.c,v 1.6 2018/09/25 13:46:44 mpi Exp $ */
/*
* Copyright (c) 2012 Stefan Fritsch, Alexander Fiveg.
@@ -1270,14 +1270,28 @@ out:
return r;
}
+/*
+ * XXXSMP As long as some per-ifp ioctl(2)s are executed with the
+ * NET_LOCK() deadlocks are possible. So release it here.
+ */
+static inline int
+vio_sleep(struct vio_softc *sc, const char *wmesg)
+{
+ int status = rw_status(&netlock);
+
+ if (status != RW_WRITE && status != RW_READ)
+ return tsleep(&sc->sc_ctrl_inuse, PRIBIO|PCATCH, wmesg, 0);
+
+ return rwsleep(&sc->sc_ctrl_inuse, &netlock, PRIBIO|PCATCH, wmesg, 0);
+}
+
int
vio_wait_ctrl(struct vio_softc *sc)
{
int r = 0;
while (sc->sc_ctrl_inuse != FREE) {
- r = rwsleep(&sc->sc_ctrl_inuse, &netlock, PRIBIO|PCATCH,
- "viowait", 0);
+ r = vio_sleep(sc, "viowait");
if (r == EINTR)
return r;
}
@@ -1296,8 +1310,7 @@ vio_wait_ctrl_done(struct vio_softc *sc)
r = 1;
break;
}
- r = rwsleep(&sc->sc_ctrl_inuse, &netlock, PRIBIO|PCATCH,
- "viodone", 0);
+ r = vio_sleep(sc, "viodone");
if (r == EINTR)
break;
}