Delaying the IBSS station worker while frames arrive from new peers can retain an unbounded number of station allocations. The receive-side limit counts installed stations, while new allocations wait on incomplete_stations until process context inserts them. The list lock does not cover the interval between allocation and list insertion. Reserve one of 128 pending slots per interface before allocation. Release the reservation on allocation failure, after the worker inserts or frees the station, and when disconnect frees the pending list. LLM assistance was used to find the bug and review. Fixes: 8bf11d8d0811 ("mac80211: delay IBSS station insertion") Cc: stable@vger.kernel.org Signed-off-by: Zhao Li --- Validation: A W=1 module build with MODPOST passed. In a QEMU hwsim guest, a 2048-address flood left 293 IBSS stations before the series and 128 after it, with no KASAN report. This is a resource bound, not a memory-safety result. A reproducer is available on request. Sparse C=2 passed. Targeted Smatch introduced no new diagnostics. net/mac80211/ibss.c | 13 ++++++++++++- net/mac80211/ieee80211_i.h | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index bd7dbaa942fa..e7d69869772b 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -680,6 +680,7 @@ static void ieee80211_ibss_disconnect(struct ieee80211_sub_if_data *sdata) spin_unlock_bh(&ifibss->incomplete_lock); sta_info_free(local, sta); + atomic_dec(&ifibss->incomplete_sta_count); spin_lock_bh(&ifibss->incomplete_lock); } spin_unlock_bh(&ifibss->incomplete_lock); @@ -1173,9 +1174,18 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, band = chanctx_conf->def.chan->band; rcu_read_unlock(); + if (!atomic_add_unless(&ifibss->incomplete_sta_count, 1, + IEEE80211_IBSS_MAX_STA_ENTRIES)) { + net_info_ratelimited("%s: No room for a new IBSS STA entry %pM\n", + sdata->name, addr); + return; + } + sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); - if (!sta) + if (!sta) { + atomic_dec(&ifibss->incomplete_sta_count); return; + } /* make sure mandatory rates are always added */ sband = local->hw.wiphy->bands[band]; @@ -1632,6 +1642,7 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata) ieee80211_ibss_finish_sta(sta); rcu_read_unlock(); } + atomic_dec(&ifibss->incomplete_sta_count); spin_lock_bh(&ifibss->incomplete_lock); } spin_unlock_bh(&ifibss->incomplete_lock); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 9374c2942489..cc0d02ca56eb 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -682,6 +682,7 @@ struct ieee80211_if_ibss { spinlock_t incomplete_lock; struct list_head incomplete_stations; + atomic_t incomplete_sta_count; enum { IEEE80211_IBSS_MLME_SEARCH, -- 2.56.0