From c853831c35ddbad16eb81c070679e8c3b085fe3a Mon Sep 17 00:00:00 2001 From: mvs Date: Sun, 10 Jul 2022 21:26:55 +0000 Subject: [PATCH] if_detach() should wait until concurrent (*if_qstart)() interface start routines finished. Call ifq_barrier(9) just after we unlinked dying interface from the stack. From this point it is not accessible by if_get(9) and if_unit(9), and all concurrent threads owning interface pointer finished. It also detached from pseudo drivers like bridge(4). We only could have concurrent (*if_qstart)() handlers running, so wait them and then continue destruction. Reported and tested by Hrvoje Popovski. ok bluhm@ --- sys/net/if.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sys/net/if.c b/sys/net/if.c index 19b2f3824c4..d54c7e6041b 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if.c,v 1.657 2022/06/29 09:08:07 mvs Exp $ */ +/* $OpenBSD: if.c,v 1.658 2022/07/10 21:26:55 mvs Exp $ */ /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ /* @@ -1029,6 +1029,10 @@ if_detach(struct ifnet *ifp) /* Other CPUs must not have a reference before we start destroying. */ if_remove(ifp); + ifp->if_qstart = if_detached_qstart; + + /* Wait until the start routines finished. */ + ifq_barrier(&ifp->if_snd); ifq_clr_oactive(&ifp->if_snd); #if NBPFILTER > 0 @@ -1037,7 +1041,6 @@ if_detach(struct ifnet *ifp) NET_LOCK(); s = splnet(); - ifp->if_qstart = if_detached_qstart; ifp->if_ioctl = if_detached_ioctl; ifp->if_watchdog = NULL; -- 2.20.1