From 2b9600b4497b864e88321fafc4a1e288cac35354 Mon Sep 17 00:00:00 2001 From: "Andrey V. Elsukov" Date: Fri, 20 Apr 2018 09:57:31 +0000 Subject: [PATCH] Add dead_bpf_if structure, that should be used as fake bpf_if during ifnet detach. Since destroying interface is not atomic operation and due to the lack of synhronization during destroy, it is possible, that in the time between bpfdetach() and if_free() some queued on destroying interface mbuf will be used by ether_input_internal() and bpf_peers_present() can dereference NULL bpf_if pointer. To protect from this, assign pointer to empty bpf_if_ext structure instead of NULL pointer after bpfdetach(). Reviewed by: melifaro, eugen Obtained from: Yandex LLC MFC after: 1 week Sponsored by: Yandex LLC Differential Revision: https://reviews.freebsd.org/D15083 --- sys/net/bpf.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sys/net/bpf.c b/sys/net/bpf.c index 0927b3de2f4..b3b5c6a1df2 100644 --- a/sys/net/bpf.c +++ b/sys/net/bpf.c @@ -98,6 +98,10 @@ __FBSDID("$FreeBSD$"); MALLOC_DEFINE(M_BPF, "BPF", "BPF data"); +static struct bpf_if_ext dead_bpf_if = { + .bif_dlist = LIST_HEAD_INITIALIZER() +}; + struct bpf_if { #define bif_next bif_ext.bif_next #define bif_dlist bif_ext.bif_dlist @@ -2659,7 +2663,7 @@ bpfdetach(struct ifnet *ifp) */ BPFIF_WLOCK(bp); bp->bif_flags |= BPFIF_FLAG_DYING; - *bp->bif_bpf = NULL; + *bp->bif_bpf = (struct bpf_if *)&dead_bpf_if;; BPFIF_WUNLOCK(bp); CTR4(KTR_NET, "%s: sheduling free for encap %d (%p) for if %p",