Skip to content

Commit

Permalink
Merge tag 'mac80211-for-net-2020-11-13' of git://git.kernel.org/pub/s…
Browse files Browse the repository at this point in the history
…cm/linux/kernel/git/jberg/mac80211

Johannes Berg says:

====================
A handful of fixes:
 * a use-after-free fix in rfkill
 * a memory leak fix in the mac80211 TX status path
 * some rate scaling fixes
 * a fix for the often-reported (by syzbot) sleeping
   in atomic issue with mac80211's station removal

* tag 'mac80211-for-net-2020-11-13' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211:
  mac80211: free sta in sta_info_insert_finish() on errors
  mac80211: minstrel: fix tx status processing corner case
  mac80211: minstrel: remove deferred sampling code
  mac80211: fix memory leak on filtered powersave frames
  rfkill: Fix use-after-free in rfkill_resume()
====================

Link: https://lore.kernel.org/r/20201113093421.24025-1-johannes@sipsolutions.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Jakub Kicinski committed Nov 13, 2020
2 parents 4ee18c1 + 7bc40ae commit 1395f8d
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 43 deletions.
27 changes: 5 additions & 22 deletions net/mac80211/rc80211_minstrel.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
success = !!(info->flags & IEEE80211_TX_STAT_ACK);

for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
if (ar[i].idx < 0)
if (ar[i].idx < 0 || !ar[i].count)
break;

ndx = rix_to_ndx(mi, ar[i].idx);
Expand All @@ -287,12 +287,6 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
mi->r[ndx].stats.success += success;
}

if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0))
mi->sample_packets++;

if (mi->sample_deferred > 0)
mi->sample_deferred--;

if (time_after(jiffies, mi->last_stats_update +
mp->update_interval / (mp->new_avg ? 2 : 1)))
minstrel_update_stats(mp, mi);
Expand Down Expand Up @@ -367,7 +361,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
return;

delta = (mi->total_packets * sampling_ratio / 100) -
(mi->sample_packets + mi->sample_deferred / 2);
mi->sample_packets;

/* delta < 0: no sampling required */
prev_sample = mi->prev_sample;
Expand All @@ -376,7 +370,6 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
return;

if (mi->total_packets >= 10000) {
mi->sample_deferred = 0;
mi->sample_packets = 0;
mi->total_packets = 0;
} else if (delta > mi->n_rates * 2) {
Expand All @@ -401,19 +394,8 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
* rate sampling method should be used.
* Respect such rates that are not sampled for 20 interations.
*/
if (mrr_capable &&
msr->perfect_tx_time > mr->perfect_tx_time &&
msr->stats.sample_skipped < 20) {
/* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark
* packets that have the sampling rate deferred to the
* second MRR stage. Increase the sample counter only
* if the deferred sample rate was actually used.
* Use the sample_deferred counter to make sure that
* the sampling is not done in large bursts */
info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
rate++;
mi->sample_deferred++;
} else {
if (msr->perfect_tx_time < mr->perfect_tx_time ||
msr->stats.sample_skipped >= 20) {
if (!msr->sample_limit)
return;

Expand All @@ -433,6 +415,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,

rate->idx = mi->r[ndx].rix;
rate->count = minstrel_get_retry_count(&mi->r[ndx], info);
info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
}


Expand Down
1 change: 0 additions & 1 deletion net/mac80211/rc80211_minstrel.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ struct minstrel_sta_info {
u8 max_prob_rate;
unsigned int total_packets;
unsigned int sample_packets;
int sample_deferred;

unsigned int sample_row;
unsigned int sample_column;
Expand Down
14 changes: 4 additions & 10 deletions net/mac80211/sta_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
out_drop_sta:
local->num_sta--;
synchronize_net();
__cleanup_single_sta(sta);
cleanup_single_sta(sta);
out_err:
mutex_unlock(&local->sta_mtx);
kfree(sinfo);
Expand All @@ -724,19 +724,13 @@ int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU)

err = sta_info_insert_check(sta);
if (err) {
sta_info_free(local, sta);
mutex_unlock(&local->sta_mtx);
rcu_read_lock();
goto out_free;
return err;
}

err = sta_info_insert_finish(sta);
if (err)
goto out_free;

return 0;
out_free:
sta_info_free(local, sta);
return err;
return sta_info_insert_finish(sta);
}

int sta_info_insert(struct sta_info *sta)
Expand Down
18 changes: 8 additions & 10 deletions net/mac80211/status.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
int ac;

if (info->flags & (IEEE80211_TX_CTL_NO_PS_BUFFER |
IEEE80211_TX_CTL_AMPDU)) {
IEEE80211_TX_CTL_AMPDU |
IEEE80211_TX_CTL_HW_80211_ENCAP)) {
ieee80211_free_txskb(&local->hw, skb);
return;
}
Expand Down Expand Up @@ -915,15 +916,6 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
ieee80211_mpsp_trigger_process(
ieee80211_get_qos_ctl(hdr), sta, true, acked);

if (!acked && test_sta_flag(sta, WLAN_STA_PS_STA)) {
/*
* The STA is in power save mode, so assume
* that this TX packet failed because of that.
*/
ieee80211_handle_filtered_frame(local, sta, skb);
return;
}

if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL) &&
(ieee80211_is_data(hdr->frame_control)) &&
(rates_idx != -1))
Expand Down Expand Up @@ -1150,6 +1142,12 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw,
-info->status.ack_signal);
}
} else if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
/*
* The STA is in power save mode, so assume
* that this TX packet failed because of that.
*/
if (skb)
ieee80211_handle_filtered_frame(local, sta, skb);
return;
} else if (noack_success) {
/* nothing to do here, do not account as lost */
Expand Down
3 changes: 3 additions & 0 deletions net/rfkill/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,9 @@ static int rfkill_resume(struct device *dev)

rfkill->suspended = false;

if (!rfkill->registered)
return 0;

if (!rfkill->persistent) {
cur = !!(rfkill->state & RFKILL_BLOCK_SW);
rfkill_set_block(rfkill, cur);
Expand Down

0 comments on commit 1395f8d

Please sign in to comment.