Commit 80b08a8d authored by Felix Fietkau's avatar Felix Fietkau Committed by John W. Linville

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: default avatarFelix Fietkau <nbd@openwrt.org>
Reported-by: default avatarThomas Hühn <thomas@net.t-labs.tu-berlin.de>
Acked-by: default avatarSujith Manoharan <c_manoha@qca.qualcomm.com>
Cc: stable@vger.kernel.org [3.4]
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 76591bea
...@@ -214,6 +214,7 @@ struct ath_frame_info { ...@@ -214,6 +214,7 @@ struct ath_frame_info {
enum ath9k_key_type keytype; enum ath9k_key_type keytype;
u8 keyix; u8 keyix;
u8 retries; u8 retries;
u8 rtscts_rate;
}; };
struct ath_buf_state { struct ath_buf_state {
......
...@@ -938,6 +938,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, ...@@ -938,6 +938,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
struct ieee80211_tx_rate *rates; struct ieee80211_tx_rate *rates;
const struct ieee80211_rate *rate; const struct ieee80211_rate *rate;
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
int i; int i;
u8 rix = 0; u8 rix = 0;
...@@ -948,18 +949,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, ...@@ -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 */ /* set dur_update_en for l-sig computation except for PS-Poll frames */
info->dur_update = !ieee80211_is_pspoll(hdr->frame_control); info->dur_update = !ieee80211_is_pspoll(hdr->frame_control);
info->rtscts_rate = fi->rtscts_rate;
/*
* 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;
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
bool is_40, is_sgi, is_sp; bool is_40, is_sgi, is_sp;
...@@ -1776,10 +1766,22 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, ...@@ -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_sta *sta = tx_info->control.sta;
struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 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_frame_info *fi = get_frame_info(skb);
struct ath_node *an = NULL; struct ath_node *an = NULL;
enum ath9k_key_type keytype; 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); keytype = ath9k_cmn_get_hw_crypto_keytype(skb);
if (sta) if (sta)
...@@ -1794,6 +1796,9 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, ...@@ -1794,6 +1796,9 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
fi->keyix = ATH9K_TXKEYIX_INVALID; fi->keyix = ATH9K_TXKEYIX_INVALID;
fi->keytype = keytype; fi->keytype = keytype;
fi->framelen = framelen; 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) u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment