DragonFlyBSD Kernel Audit
DF-0289 / fix.diff
← back to finding ↓ download raw
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);