diff options
author | Vitaliy Makkoveev <mvs@cvs.openbsd.org> | 2023-10-23 10:22:06 +0000 |
---|---|---|
committer | Vitaliy Makkoveev <mvs@cvs.openbsd.org> | 2023-10-23 10:22:06 +0000 |
commit | 141880599181e12d0254e7ae0cf0ea7d0e5b0074 (patch) | |
tree | a962abbabf4e1e02ecc1ae9076ef0c6addcfc846 /sys/net/if_wg.c | |
parent | 3db2cb25860d504f2b90b98e49818ce08694f963 (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.c | 10 |
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(); |