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@
-/* $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 $ */
/*
/* 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
NET_LOCK();
s = splnet();
- ifp->if_qstart = if_detached_qstart;
ifp->if_ioctl = if_detached_ioctl;
ifp->if_watchdog = NULL;