From a9d080a15aeda1cea283ae85cd165b7a99108402 Mon Sep 17 00:00:00 2001 From: Zhenlei Huang Date: Tue, 4 Feb 2025 23:04:59 +0800 Subject: [PATCH] ifnet: Detach BPF descriptors on interface vmove event When an interface is moving to/from a vnet jail, it may still have BPF descriptors attached. The userland (e.g. tcpdump) does not get noticed that the interface is departing and still opens BPF descriptors thus may result in leaking sensitive traffic (e.g. an interface is moved back to parent jail but a user is still sniffing traffic over it in the child jail). Detach BPF descriptors so that the userland will be signaled. Reviewed by: ae MFC after: 3 days Differential Revision: https://reviews.freebsd.org/D45727 (cherry picked from commit 1ed9b381d4701fc9f66741256e93b96e22273217) ifnet: Fix build without BPF The newly introduced function bpf_ifdetach() is only available when device bpf is enabled. Fixes: 1ed9b381d470 ifnet: Detach BPF descriptors on interface vmove event (cherry picked from commit d8413a1c3ba235a79ae6b8cc35767a861855c7e2) --- sys/net/bpf.c | 27 +++++++++++++++++++++++++++ sys/net/bpf.h | 1 + sys/net/if.c | 7 +++++++ 3 files changed, 35 insertions(+) diff --git a/sys/net/bpf.c b/sys/net/bpf.c index 7c7f6e84d9e..e8c9aa7ce4f 100644 --- a/sys/net/bpf.c +++ b/sys/net/bpf.c @@ -2849,6 +2849,33 @@ bpf_get_bp_params(struct bpf_if *bp, u_int *bif_dlt, u_int *bif_hdrlen) return (0); } + +/* + * Detach descriptors on interface's vmove event. + */ +void +bpf_ifdetach(struct ifnet *ifp) +{ + struct bpf_if *bp; + struct bpf_d *d; + + BPF_LOCK(); + CK_LIST_FOREACH(bp, &bpf_iflist, bif_next) { + if (bp->bif_ifp != ifp) + continue; + + /* Detach common descriptors */ + while ((d = CK_LIST_FIRST(&bp->bif_dlist)) != NULL) { + bpf_detachd_locked(d, true); + } + + /* Detach writer-only descriptors */ + while ((d = CK_LIST_FIRST(&bp->bif_wlist)) != NULL) { + bpf_detachd_locked(d, true); + } + } + BPF_UNLOCK(); +} #endif /* diff --git a/sys/net/bpf.h b/sys/net/bpf.h index 991d50bcd68..c4132d2e633 100644 --- a/sys/net/bpf.h +++ b/sys/net/bpf.h @@ -431,6 +431,7 @@ void bpfdetach(struct ifnet *); bool bpf_peers_present_if(struct ifnet *); #ifdef VIMAGE int bpf_get_bp_params(struct bpf_if *, u_int *, u_int *); +void bpf_ifdetach(struct ifnet *); #endif void bpfilterattach(int); diff --git a/sys/net/if.c b/sys/net/if.c index ad8dd9703c5..4bc626b2de7 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1266,6 +1266,13 @@ finish_vnet_shutdown: static void if_vmove(struct ifnet *ifp, struct vnet *new_vnet) { +#ifdef DEV_BPF + /* + * Detach BPF file descriptors from its interface. + */ + bpf_ifdetach(ifp); +#endif + /* * Detach from current vnet, but preserve LLADDR info, do not * mark as dead etc. so that the ifnet can be reattached later.