Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 10 Feb 2025 14:47:46 GMT
From:      Mateusz Guzik <mjg@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: efd368784eeb - main - mroute: serialize parallel teardown of the same vnet
Message-ID:  <202502101447.51AElkxO010641@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by mjg:

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

commit efd368784eebcc62324f7e1884776a22a73c4688
Author:     Mateusz Guzik <mjg@FreeBSD.org>
AuthorDate: 2025-02-10 14:44:39 +0000
Commit:     Mateusz Guzik <mjg@FreeBSD.org>
CommitDate: 2025-02-10 14:45:32 +0000

    mroute: serialize parallel teardown of the same vnet
    
    Otherwise 2 threads calling here can crash the kernel.
    
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
---
 sys/netinet/ip_mroute.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c
index 501b3e0d9a43..6e6ecd43e9fe 100644
--- a/sys/netinet/ip_mroute.c
+++ b/sys/netinet/ip_mroute.c
@@ -139,6 +139,13 @@ static MALLOC_DEFINE(M_MRTABLE, "mroutetbl", "multicast forwarding cache");
  * structures.
  */
 
+static struct sx __exclusive_cache_line mrouter_teardown;
+#define	MRW_TEARDOWN_WLOCK()	sx_xlock(&mrouter_teardown)
+#define	MRW_TEARDOWN_WUNLOCK()	sx_xunlock(&mrouter_teardown)
+#define	MRW_TEARDOWN_LOCK_INIT()				\
+	sx_init(&mrouter_teardown, "IPv4 multicast forwarding teardown")
+#define	MRW_TEARDOWN_LOCK_DESTROY()	sx_destroy(&mrouter_teardown)
+
 static struct rwlock mrouter_lock;
 #define	MRW_RLOCK()		rw_rlock(&mrouter_lock)
 #define	MRW_WLOCK()		rw_wlock(&mrouter_lock)
@@ -692,15 +699,18 @@ ip_mrouter_init(struct socket *so, int version)
 	if (version != 1)
 		return ENOPROTOOPT;
 
+	MRW_TEARDOWN_WLOCK();
 	MRW_WLOCK();
 
 	if (ip_mrouter_unloading) {
 		MRW_WUNLOCK();
+		MRW_TEARDOWN_WUNLOCK();
 		return ENOPROTOOPT;
 	}
 
 	if (V_ip_mrouter != NULL) {
 		MRW_WUNLOCK();
+		MRW_TEARDOWN_WUNLOCK();
 		return EADDRINUSE;
 	}
 
@@ -708,6 +718,7 @@ ip_mrouter_init(struct socket *so, int version)
 	    HASH_NOWAIT);
 	if (V_mfchashtbl == NULL) {
 		MRW_WUNLOCK();
+		MRW_TEARDOWN_WUNLOCK();
 		return (ENOMEM);
 	}
 
@@ -717,6 +728,7 @@ ip_mrouter_init(struct socket *so, int version)
 	    M_NOWAIT, &V_bw_upcalls_ring_mtx);
 	if (!V_bw_upcalls_ring) {
 		MRW_WUNLOCK();
+		MRW_TEARDOWN_WUNLOCK();
 		return (ENOMEM);
 	}
 
@@ -736,6 +748,7 @@ ip_mrouter_init(struct socket *so, int version)
 	mtx_init(&V_buf_ring_mtx, "mroute buf_ring mtx", NULL, MTX_DEF);
 
 	MRW_WUNLOCK();
+	MRW_TEARDOWN_WUNLOCK();
 
 	CTR1(KTR_IPMF, "%s: done", __func__);
 
@@ -754,8 +767,12 @@ X_ip_mrouter_done(void)
 	vifi_t vifi;
 	struct bw_upcall *bu;
 
-	if (V_ip_mrouter == NULL)
+	MRW_TEARDOWN_WLOCK();
+
+	if (V_ip_mrouter == NULL) {
+		MRW_TEARDOWN_WUNLOCK();
 		return (EINVAL);
+	}
 
 	/*
 	 * Detach/disable hooks to the reset of the system.
@@ -830,6 +847,7 @@ X_ip_mrouter_done(void)
 	mtx_destroy(&V_buf_ring_mtx);
 
 	MRW_WUNLOCK();
+	MRW_TEARDOWN_WUNLOCK();
 
 	/*
 	 * Now drop our claim on promiscuous multicast on the interfaces recorded
@@ -2809,6 +2827,7 @@ ip_mroute_modevent(module_t mod, int type, void *unused)
 
 	switch (type) {
 	case MOD_LOAD:
+		MRW_TEARDOWN_LOCK_INIT();
 		MRW_LOCK_INIT();
 
 		if_detach_event_tag = EVENTHANDLER_REGISTER(ifnet_departure_event,
@@ -2880,6 +2899,7 @@ ip_mroute_modevent(module_t mod, int type, void *unused)
 		rsvp_input_p = NULL;
 
 		MRW_LOCK_DESTROY();
+		MRW_TEARDOWN_LOCK_DESTROY();
 		break;
 
 	default:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202502101447.51AElkxO010641>