git: d4062b9f16e4 - main - vlan: plug a new panic associated with interface removal
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 17 Dec 2025 21:16:02 UTC
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)