forked from Minki/linux
mwifiex: guard station nodes access by station list lock
Station node entries should be guarded for whole of their reference instead of just while getting node entry from station list. It may happen that station node is retrieved may be deleted by deauthentication event while it is still in use. Reported by: Tim Shepard <shep@xplot.org> Signed-off-by: Avinash Patil <patila@marvell.com> Signed-off-by: Cathy Luo <cluo@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
9817fffbf0
commit
c11fb9857f
@ -544,6 +544,7 @@ int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac)
|
|||||||
u32 tx_win_size = priv->add_ba_param.tx_win_size;
|
u32 tx_win_size = priv->add_ba_param.tx_win_size;
|
||||||
static u8 dialog_tok;
|
static u8 dialog_tok;
|
||||||
int ret;
|
int ret;
|
||||||
|
unsigned long flags;
|
||||||
u16 block_ack_param_set;
|
u16 block_ack_param_set;
|
||||||
|
|
||||||
dev_dbg(priv->adapter->dev, "cmd: %s: tid %d\n", __func__, tid);
|
dev_dbg(priv->adapter->dev, "cmd: %s: tid %d\n", __func__, tid);
|
||||||
@ -554,15 +555,18 @@ int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac)
|
|||||||
memcmp(priv->cfg_bssid, peer_mac, ETH_ALEN)) {
|
memcmp(priv->cfg_bssid, peer_mac, ETH_ALEN)) {
|
||||||
struct mwifiex_sta_node *sta_ptr;
|
struct mwifiex_sta_node *sta_ptr;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||||
sta_ptr = mwifiex_get_sta_entry(priv, peer_mac);
|
sta_ptr = mwifiex_get_sta_entry(priv, peer_mac);
|
||||||
if (!sta_ptr) {
|
if (!sta_ptr) {
|
||||||
dev_warn(priv->adapter->dev,
|
dev_warn(priv->adapter->dev,
|
||||||
"BA setup with unknown TDLS peer %pM!\n",
|
"BA setup with unknown TDLS peer %pM!\n",
|
||||||
peer_mac);
|
peer_mac);
|
||||||
|
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (sta_ptr->is_11ac_enabled)
|
if (sta_ptr->is_11ac_enabled)
|
||||||
tx_win_size = MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE;
|
tx_win_size = MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE;
|
||||||
|
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
block_ack_param_set = (u16)((tid << BLOCKACKPARAM_TID_POS) |
|
block_ack_param_set = (u16)((tid << BLOCKACKPARAM_TID_POS) |
|
||||||
|
@ -351,6 +351,7 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
|
|||||||
new_node->init_win = seq_num;
|
new_node->init_win = seq_num;
|
||||||
new_node->flags = 0;
|
new_node->flags = 0;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||||
if (mwifiex_queuing_ra_based(priv)) {
|
if (mwifiex_queuing_ra_based(priv)) {
|
||||||
dev_dbg(priv->adapter->dev,
|
dev_dbg(priv->adapter->dev,
|
||||||
"info: AP/ADHOC:last_seq=%d start_win=%d\n",
|
"info: AP/ADHOC:last_seq=%d start_win=%d\n",
|
||||||
@ -367,6 +368,7 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
|
|||||||
else
|
else
|
||||||
last_seq = priv->rx_seq[tid];
|
last_seq = priv->rx_seq[tid];
|
||||||
}
|
}
|
||||||
|
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||||
|
|
||||||
if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM &&
|
if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM &&
|
||||||
last_seq >= new_node->start_win) {
|
last_seq >= new_node->start_win) {
|
||||||
@ -455,22 +457,26 @@ int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,
|
|||||||
u32 rx_win_size = priv->add_ba_param.rx_win_size;
|
u32 rx_win_size = priv->add_ba_param.rx_win_size;
|
||||||
u8 tid;
|
u8 tid;
|
||||||
int win_size;
|
int win_size;
|
||||||
|
unsigned long flags;
|
||||||
uint16_t block_ack_param_set;
|
uint16_t block_ack_param_set;
|
||||||
|
|
||||||
if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
|
if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
|
||||||
ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
|
ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
|
||||||
priv->adapter->is_hw_11ac_capable &&
|
priv->adapter->is_hw_11ac_capable &&
|
||||||
memcmp(priv->cfg_bssid, cmd_addba_req->peer_mac_addr, ETH_ALEN)) {
|
memcmp(priv->cfg_bssid, cmd_addba_req->peer_mac_addr, ETH_ALEN)) {
|
||||||
|
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||||
sta_ptr = mwifiex_get_sta_entry(priv,
|
sta_ptr = mwifiex_get_sta_entry(priv,
|
||||||
cmd_addba_req->peer_mac_addr);
|
cmd_addba_req->peer_mac_addr);
|
||||||
if (!sta_ptr) {
|
if (!sta_ptr) {
|
||||||
dev_warn(priv->adapter->dev,
|
dev_warn(priv->adapter->dev,
|
||||||
"BA setup with unknown TDLS peer %pM!\n",
|
"BA setup with unknown TDLS peer %pM!\n",
|
||||||
cmd_addba_req->peer_mac_addr);
|
cmd_addba_req->peer_mac_addr);
|
||||||
|
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (sta_ptr->is_11ac_enabled)
|
if (sta_ptr->is_11ac_enabled)
|
||||||
rx_win_size = MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE;
|
rx_win_size = MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE;
|
||||||
|
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_RSP);
|
cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_RSP);
|
||||||
|
@ -266,6 +266,7 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
|
|||||||
struct rx_packet_hdr *rx_pkt_hdr;
|
struct rx_packet_hdr *rx_pkt_hdr;
|
||||||
u16 rx_pkt_type;
|
u16 rx_pkt_type;
|
||||||
u8 ta[ETH_ALEN], pkt_type;
|
u8 ta[ETH_ALEN], pkt_type;
|
||||||
|
unsigned long flags;
|
||||||
struct mwifiex_sta_node *node;
|
struct mwifiex_sta_node *node;
|
||||||
|
|
||||||
uap_rx_pd = (struct uap_rxpd *)(skb->data);
|
uap_rx_pd = (struct uap_rxpd *)(skb->data);
|
||||||
@ -294,10 +295,12 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
|
|||||||
memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN);
|
memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN);
|
||||||
|
|
||||||
if (rx_pkt_type != PKT_TYPE_BAR && uap_rx_pd->priority < MAX_NUM_TID) {
|
if (rx_pkt_type != PKT_TYPE_BAR && uap_rx_pd->priority < MAX_NUM_TID) {
|
||||||
|
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||||
node = mwifiex_get_sta_entry(priv, ta);
|
node = mwifiex_get_sta_entry(priv, ta);
|
||||||
if (node)
|
if (node)
|
||||||
node->rx_seq[uap_rx_pd->priority] =
|
node->rx_seq[uap_rx_pd->priority] =
|
||||||
le16_to_cpu(uap_rx_pd->seq_num);
|
le16_to_cpu(uap_rx_pd->seq_num);
|
||||||
|
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!priv->ap_11n_enabled ||
|
if (!priv->ap_11n_enabled ||
|
||||||
|
@ -147,9 +147,6 @@ void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra)
|
|||||||
struct mwifiex_sta_node *node;
|
struct mwifiex_sta_node *node;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
|
||||||
node = mwifiex_get_sta_entry(priv, ra);
|
|
||||||
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_NUM_TID; ++i) {
|
for (i = 0; i < MAX_NUM_TID; ++i) {
|
||||||
ra_list = mwifiex_wmm_allocate_ralist_node(adapter, ra);
|
ra_list = mwifiex_wmm_allocate_ralist_node(adapter, ra);
|
||||||
@ -170,10 +167,13 @@ void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra)
|
|||||||
ra_list->is_11n_enabled = IS_11N_ENABLED(priv);
|
ra_list->is_11n_enabled = IS_11N_ENABLED(priv);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
|
||||||
|
node = mwifiex_get_sta_entry(priv, ra);
|
||||||
ra_list->is_11n_enabled =
|
ra_list->is_11n_enabled =
|
||||||
mwifiex_is_sta_11n_enabled(priv, node);
|
mwifiex_is_sta_11n_enabled(priv, node);
|
||||||
if (ra_list->is_11n_enabled)
|
if (ra_list->is_11n_enabled)
|
||||||
ra_list->max_amsdu = node->max_amsdu;
|
ra_list->max_amsdu = node->max_amsdu;
|
||||||
|
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_dbg(adapter->dev, "data: ralist %p: is_11n_enabled=%d\n",
|
dev_dbg(adapter->dev, "data: ralist %p: is_11n_enabled=%d\n",
|
||||||
|
Loading…
Reference in New Issue
Block a user