DragonFlyBSD Kernel Audit
DF-0733 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/netproto/802_11/wlan_acl/ieee80211_acl.c b/sys/netproto/802_11/wlan_acl/ieee80211_acl.c
--- a/sys/netproto/802_11/wlan_acl/ieee80211_acl.c
+++ b/sys/netproto/802_11/wlan_acl/ieee80211_acl.c
@@ -167,10 +167,27 @@
 	case ACL_POLICY_OPEN:
 	case ACL_POLICY_RADIUS:
 		return 1;
-	case ACL_POLICY_ALLOW:
-		return _find_acl(as, wh->i_addr2) != NULL;
-	case ACL_POLICY_DENY:
-		return _find_acl(as, wh->i_addr2) == NULL;
+	case ACL_POLICY_ALLOW: {
+		int found;
+		/*
+		 * DF-0733: serialize the hash walk against concurrent
+		 * acl_remove/acl_free_all (both of which take ACL_LOCK and
+		 * _acl_free the entry via LIST_REMOVE + IEEE80211_FREE).
+		 * Without this lock the LIST_FOREACH in _find_acl could read
+		 * acl_hash.le_next from an entry freed under us -> UAF.
+		 */
+		ACL_LOCK(as);
+		found = (_find_acl(as, wh->i_addr2) != NULL);
+		ACL_UNLOCK(as);
+		return found;
+	}
+	case ACL_POLICY_DENY: {
+		int found;
+		ACL_LOCK(as);
+		found = (_find_acl(as, wh->i_addr2) != NULL);
+		ACL_UNLOCK(as);
+		return !found;
+	}
 	}
 	return 0;		/* should not happen */
 }