summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorclaudio <claudio@openbsd.org>2020-06-22 09:45:13 +0000
committerclaudio <claudio@openbsd.org>2020-06-22 09:45:13 +0000
commit2646c3b95731d186ec4b1bff5cd3c1458c6f5139 (patch)
tree5b4752cdc95dd0c52844b47c4d2cea13338c5a6a
parentgup: document and work around "COW can break either way" issue (diff)
downloadwireguard-openbsd-2646c3b95731d186ec4b1bff5cd3c1458c6f5139.tar.xz
wireguard-openbsd-2646c3b95731d186ec4b1bff5cd3c1458c6f5139.zip
The interface if_ioctl routine must be called with the NET_LOCK() held.
For example the bridge_ioctl() function calls NET_UNLOCK() unconditionally and so calling if_ioctl() without netlock will trigger an assert because of not holding the netlock. Make sure the ioctl handlers are called with the netlock held and drop the lock for the wg(4) specific ioctls in the wg_ioctl handler. This fixes a panic in bridge_ioctl() triggered by ifconfig(8) issuing a SIOCGWG ioctl against bridge(4). This is just a workaround this needs more cleanup but at least this way the panic can not be triggered anymore. OK stsp@, tested by semarie@
-rw-r--r--sys/net/if.c9
-rw-r--r--sys/net/if_wg.c4
2 files changed, 5 insertions, 8 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index c2d9269114e..fb2f86f4a7c 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.c,v 1.609 2020/06/22 03:07:57 dlg Exp $ */
+/* $OpenBSD: if.c,v 1.610 2020/06/22 09:45:13 claudio Exp $ */
/* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */
/*
@@ -2222,13 +2222,6 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
/* don't take NET_LOCK because i2c reads take a long time */
error = ((*ifp->if_ioctl)(ifp, cmd, data));
break;
- case SIOCSWG:
- case SIOCGWG:
- /* Don't take NET_LOCK to allow wg(4) to continue to send and
- * receive packets while we're loading a large number of
- * peers. wg(4) uses its own lock to serialise access. */
- error = ((*ifp->if_ioctl)(ifp, cmd, data));
- break;
case SIOCSETKALIVE:
case SIOCDIFPHYADDR:
diff --git a/sys/net/if_wg.c b/sys/net/if_wg.c
index 06ae1a05d73..9d7f35a557b 100644
--- a/sys/net/if_wg.c
+++ b/sys/net/if_wg.c
@@ -2450,10 +2450,14 @@ wg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
switch (cmd) {
case SIOCSWG:
+ NET_UNLOCK();
ret = wg_ioctl_set(sc, (struct wg_data_io *) data);
+ NET_LOCK();
break;
case SIOCGWG:
+ NET_UNLOCK();
ret = wg_ioctl_get(sc, (struct wg_data_io *) data);
+ NET_LOCK();
break;
/* Interface IOCTLs */
case SIOCSIFADDR: