git: 6b81815307b0 - stable/13 - ifnet: Detach BPF descriptors on interface vmove event

From: Zhenlei Huang <zlei_at_FreeBSD.org>
Date: Thu, 06 Feb 2025 19:18:23 UTC
The branch stable/13 has been updated by zlei:

URL: https://cgit.FreeBSD.org/src/commit/?id=6b81815307b00d37b81f71d68a51f67c72a2edb0

commit 6b81815307b00d37b81f71d68a51f67c72a2edb0
Author:     Zhenlei Huang <zlei@FreeBSD.org>
AuthorDate: 2025-02-04 15:04:59 +0000
Commit:     Zhenlei Huang <zlei@FreeBSD.org>
CommitDate: 2025-02-06 19:06:42 +0000

    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)
    (cherry picked from commit 2e4eaf3c13d2b5aa76f9759e51e35faf29d56993)
---
 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 70232ffd75bd..b720c70bdbfa 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -2789,6 +2789,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 d6213ebd10f4..2fe4c87cc534 100644
--- a/sys/net/bpf.h
+++ b/sys/net/bpf.h
@@ -426,6 +426,7 @@ void	bpfattach2(struct ifnet *, u_int, u_int, struct bpf_if **);
 void	bpfdetach(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 e30e1c7e5dca..46ebabe09a51 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1287,6 +1287,13 @@ if_vmove(struct ifnet *ifp, struct vnet *new_vnet)
 {
 	void *old;
 
+#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.