DF-0733 / fix.diff
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 */ } |