diff --git a/sys/netproto/802_11/wlan/ieee80211_mesh.c b/sys/netproto/802_11/wlan/ieee80211_mesh.c --- a/sys/netproto/802_11/wlan/ieee80211_mesh.c +++ b/sys/netproto/802_11/wlan/ieee80211_mesh.c @@ -1143,8 +1143,13 @@ rt_dest->rt_metric = rt_gate->rt_metric; rt_dest->rt_nhops = rt_gate->rt_nhops; ieee80211_mesh_rt_update(rt_dest, ms->ms_ppath->mpp_inact); - MESH_RT_UNLOCK(ms); - /* XXX: lock?? */ + /* DF-0289: Do NOT release MESH_RT_LOCK here. The previous code + * did MESH_RT_UNLOCK / transmit / MESH_RT_LOCK inside the + * TAILQ_FOREACH_SAFE loop, which allowed ms_cleantimer to free + * the 'next' gate route while the lock was dropped -- a UAF. + * Collect the transmit work and do it after the loop, under + * the lock for the entire iteration. + */ mcopy = m_dup(m, M_NOWAIT); for (; mcopy != NULL; mcopy = next) { next = mcopy->m_nextpkt; @@ -1155,7 +1160,6 @@ mcopy->m_pkthdr.len); mesh_transmit_to_gate(vap, mcopy, rt_gate); } - MESH_RT_LOCK(ms); } rt_dest->rt_flags = 0; /* Mark invalid */ m_freem(m);