vlan: plug a new panic associated with interface removal

The ac6a7f6216 enabled execution of vlan_clone_dump_nl(), which
previously was effectively disabled.  The function itself was added back
in 089104e0e0.  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
This commit is contained in:
Gleb Smirnoff 2025-12-17 13:05:04 -08:00
parent 0bf42a0a05
commit d4062b9f16

View file

@ -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)