Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 17 Dec 2025 21:16:02 +0000
Message-ID:  <69431d92.4167e.7b9e2bd6@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by glebius:

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

commit d4062b9f16e46f039f2b5b40dd35592b5dabf00c
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2025-12-17 21:05:04 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2025-12-17 21:13:42 +0000

    vlan: plug a new panic associated with interface removal
    
    The ac6a7f621668 enabled execution of vlan_clone_dump_nl(), which
    previously was effectively disabled.  The function itself was added back
    in 089104e0e01f0.  This exposed a bug when Netlink dumps info on all
    interfaces using a dangerous KPI if_foreach_sleep(), which may call its
    callbacks on completely detached interfaces, hanging on the last
    reference.  The ifc_dump_ifp_nl_default() is able to digest such interface
    without a panic, but vlan_clone_dump_nl() can't.  Neither of the above
    revisions is the actual culprit, rather it is design problem of detaching
    interfaces and if_foreach_sleep().
    
    Plug the problem with removing pointer to freed memory on detach and
    making a NULL check later.
    
    Reported by:    pho
---
 sys/net/if_vlan.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c
index 61000018e5a4..afc3fa3fc79e 100644
--- a/sys/net/if_vlan.c
+++ b/sys/net/if_vlan.c
@@ -1341,12 +1341,19 @@ vlan_clone_modify_nl(struct ifnet *ifp, struct ifc_data_nl *ifd)
 static void
 vlan_clone_dump_nl(struct ifnet *ifp, struct nl_writer *nw)
 {
+	struct ifvlan *ifv;
 	uint32_t parent_index = 0;
 	uint16_t vlan_id = 0;
 	uint16_t vlan_proto = 0;
 
 	VLAN_SLOCK();
-	struct ifvlan *ifv = ifp->if_softc;
+	if (__predict_false((ifv = ifp->if_softc) == NULL)) {
+		/*
+		 * XXXGL: the interface already went through if_dead().  This
+		 * check to be removed when we got better interface removal.
+		 */
+		return;
+	}
 	if (TRUNK(ifv) != NULL)
 		parent_index = PARENT(ifv)->if_index;
 	vlan_id = ifv->ifv_vid;
@@ -1390,6 +1397,7 @@ vlan_clone_destroy(struct if_clone *ifc, struct ifnet *ifp, uint32_t flags)
 	 */
 	taskqueue_drain(taskqueue_thread, &ifv->lladdr_task);
 	NET_EPOCH_WAIT();
+	ifp->if_softc = NULL;
 	if_free(ifp);
 	free(ifv, M_VLAN);
 	if (unit != IF_DUNIT_NONE)


help

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69431d92.4167e.7b9e2bd6>