From 8c2c9fccf09e41746c89a6d9626accd14d0bde1a Mon Sep 17 00:00:00 2001 From: mvs Date: Mon, 23 Oct 2023 10:22:05 +0000 Subject: [PATCH] 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@ --- sys/net/if_wg.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) 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 . 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(); -- 2.20.1