summaryrefslogtreecommitdiff
path: root/sys/net/if_wg.c
diff options
context:
space:
mode:
authorVitaliy Makkoveev <mvs@cvs.openbsd.org>2023-10-23 10:22:06 +0000
committerVitaliy Makkoveev <mvs@cvs.openbsd.org>2023-10-23 10:22:06 +0000
commit141880599181e12d0254e7ae0cf0ea7d0e5b0074 (patch)
treea962abbabf4e1e02ecc1ae9076ef0c6addcfc846 /sys/net/if_wg.c
parent3db2cb25860d504f2b90b98e49818ce08694f963 (diff)
Prevent wg(4) stuck on peer destruction.
While interface going down and output stopped, packets could rest in `if_snd' queue. So the (!ifq_empty(&sc->sc_if.if_snd)) condition will always be true and wg_peer_destroy() will sleep until interface became up and stuck packets transmitted. Check IFF_RUNNING flag within (!ifq_empty(&sc->sc_if.if_snd)) loop in wg_peer_destroy(). If the flag is not set that means interface is down, so drain the `if_snd' queue manually to prevent wg_peer_destroy() stuck. Problem reported and fix tested by Kirill Miazine. ok bluhm@
Diffstat (limited to 'sys/net/if_wg.c')
-rw-r--r--sys/net/if_wg.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/sys/net/if_wg.c b/sys/net/if_wg.c
index 856759977da..b6fc0c85e5a 100644
--- a/sys/net/if_wg.c
+++ b/sys/net/if_wg.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_wg.c,v 1.31 2023/09/26 15:16:44 sthen Exp $ */
+/* $OpenBSD: if_wg.c,v 1.32 2023/10/23 10:22:05 mvs Exp $ */
/*
* Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
@@ -509,6 +509,14 @@ wg_peer_destroy(struct wg_peer *peer)
NET_LOCK();
while (!ifq_empty(&sc->sc_if.if_snd)) {
+ /*
+ * XXX: `if_snd' of stopped interface could still
+ * contain packets
+ */
+ if (!ISSET(sc->sc_if.if_flags, IFF_RUNNING)) {
+ ifq_purge(&sc->sc_if.if_snd);
+ continue;
+ }
NET_UNLOCK();
tsleep_nsec(sc, PWAIT, "wg_ifq", 1000);
NET_LOCK();