mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
ath9k: fix invalid pointer access in the tx path
After setup_frame_info has been called, only info->control.rates is still
valid, other control fields have been overwritten by the ath_frame_info
data. Move the access to info->control.vif for checking short preamble
to setup_frame_info before it gets overwritten.
This regression was introduced in commit d47a61aa
"ath9k: Fix multi-VIF BSS handling"
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Reported-by: Thomas Hühn <thomas@net.t-labs.tu-berlin.de>
Acked-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Cc: stable@vger.kernel.org [3.4]
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
76591bea97
commit
80b08a8d88
2 changed files with 18 additions and 12 deletions
|
@ -214,6 +214,7 @@ struct ath_frame_info {
|
|||
enum ath9k_key_type keytype;
|
||||
u8 keyix;
|
||||
u8 retries;
|
||||
u8 rtscts_rate;
|
||||
};
|
||||
|
||||
struct ath_buf_state {
|
||||
|
|
|
@ -938,6 +938,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
|
|||
struct ieee80211_tx_rate *rates;
|
||||
const struct ieee80211_rate *rate;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
|
||||
int i;
|
||||
u8 rix = 0;
|
||||
|
||||
|
@ -948,18 +949,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
|
|||
|
||||
/* set dur_update_en for l-sig computation except for PS-Poll frames */
|
||||
info->dur_update = !ieee80211_is_pspoll(hdr->frame_control);
|
||||
|
||||
/*
|
||||
* We check if Short Preamble is needed for the CTS rate by
|
||||
* checking the BSS's global flag.
|
||||
* But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
|
||||
*/
|
||||
rate = ieee80211_get_rts_cts_rate(sc->hw, tx_info);
|
||||
info->rtscts_rate = rate->hw_value;
|
||||
|
||||
if (tx_info->control.vif &&
|
||||
tx_info->control.vif->bss_conf.use_short_preamble)
|
||||
info->rtscts_rate |= rate->hw_value_short;
|
||||
info->rtscts_rate = fi->rtscts_rate;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
bool is_40, is_sgi, is_sp;
|
||||
|
@ -1776,10 +1766,22 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|||
struct ieee80211_sta *sta = tx_info->control.sta;
|
||||
struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
const struct ieee80211_rate *rate;
|
||||
struct ath_frame_info *fi = get_frame_info(skb);
|
||||
struct ath_node *an = NULL;
|
||||
enum ath9k_key_type keytype;
|
||||
bool short_preamble = false;
|
||||
|
||||
/*
|
||||
* We check if Short Preamble is needed for the CTS rate by
|
||||
* checking the BSS's global flag.
|
||||
* But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
|
||||
*/
|
||||
if (tx_info->control.vif &&
|
||||
tx_info->control.vif->bss_conf.use_short_preamble)
|
||||
short_preamble = true;
|
||||
|
||||
rate = ieee80211_get_rts_cts_rate(hw, tx_info);
|
||||
keytype = ath9k_cmn_get_hw_crypto_keytype(skb);
|
||||
|
||||
if (sta)
|
||||
|
@ -1794,6 +1796,9 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|||
fi->keyix = ATH9K_TXKEYIX_INVALID;
|
||||
fi->keytype = keytype;
|
||||
fi->framelen = framelen;
|
||||
fi->rtscts_rate = rate->hw_value;
|
||||
if (short_preamble)
|
||||
fi->rtscts_rate |= rate->hw_value_short;
|
||||
}
|
||||
|
||||
u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)
|
||||
|
|
Loading…
Reference in a new issue