diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index 069ba7016654..ff47d4827722 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c @@ -1639,7 +1639,7 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr) if (!msgbuf->tx_pktids) goto fail; msgbuf->rx_pktids = brcmf_msgbuf_init_pktids(NR_RX_PKTIDS, - DMA_FROM_DEVICE); + DMA_BIDIRECTIONAL); if (!msgbuf->rx_pktids) goto fail; diff --git a/drivers/net/wireless/rsi/rsi_91x_core.c b/drivers/net/wireless/rsi/rsi_91x_core.c index ead4d4e04328..3281fc94e107 100644 --- a/drivers/net/wireless/rsi/rsi_91x_core.c +++ b/drivers/net/wireless/rsi/rsi_91x_core.c @@ -458,7 +458,7 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb) tx_params->sta_id = 0; } - if (rsta) { + if (rsta && tid < IEEE80211_NUM_TIDS) { /* Start aggregation if not done for this tid */ if (!rsta->start_tx_aggr[tid]) { rsta->start_tx_aggr[tid] = true; diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h index b80e474cb0aa..632618d9ff93 100644 --- a/include/net/iw_handler.h +++ b/include/net/iw_handler.h @@ -201,6 +201,8 @@ #include /* IOCTL user space API */ #include +struct net; + /***************************** VERSION *****************************/ /* * This constant is used to know which version of the driver API is @@ -411,10 +413,10 @@ struct iw_spy_data { void wireless_send_event(struct net_device *dev, unsigned int cmd, union iwreq_data *wrqu, const char *extra); #ifdef CONFIG_WEXT_CORE -/* flush all previous wext events - if work is done from netdev notifiers */ -void wireless_nlevent_flush(void); +/* Flush previous wext events in this netns from netdev notifiers. */ +void wireless_nlevent_flush(struct net *net); #else -static inline void wireless_nlevent_flush(void) {} +static inline void wireless_nlevent_flush(struct net *net) {} #endif /* We may need a function to send a stream of events to user space. diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c index 68bd64328937..8ae01c277fd2 100644 --- a/net/mac80211/tdls.c +++ b/net/mac80211/tdls.c @@ -2021,7 +2021,7 @@ void ieee80211_process_tdls_channel_switch(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) { - struct ieee80211_tdls_data *tf = (void *)skb->data; + struct ieee80211_tdls_data *tf; struct wiphy *wiphy = sdata->local->hw.wiphy; lockdep_assert_wiphy(wiphy); @@ -2037,6 +2037,7 @@ ieee80211_process_tdls_channel_switch(struct ieee80211_sub_if_data *sdata, * The packet/size was already validated by mac80211 Rx path, only look * at the action type. */ + tf = (void *)skb->data; switch (tf->action_code) { case WLAN_TDLS_CHANNEL_SWITCH_REQUEST: ieee80211_process_tdls_channel_switch_req(sdata, skb); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e9b6a0415d6a..0f46b5ff0c4a 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1164,6 +1164,7 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, struct sk_buff *purge_skb = NULL; if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) { + info->flags |= IEEE80211_TX_CTL_AMPDU; reset_agg_timer = true; } else if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { /* @@ -1195,6 +1196,7 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, if (!tid_tx) { /* do nothing, let packet pass through */ } else if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) { + info->flags |= IEEE80211_TX_CTL_AMPDU; reset_agg_timer = true; } else { queued = true; diff --git a/net/wireless/core.c b/net/wireless/core.c index f4153c249599..8cca6ef632d1 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -1944,7 +1944,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, return NOTIFY_DONE; } - wireless_nlevent_flush(); + wireless_nlevent_flush(dev_net(dev)); return NOTIFY_OK; } diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 50f50e768f01..5cd3880ee384 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -680,6 +680,9 @@ static bool valid_rule(const u8 *data, unsigned int size, u16 rule_ptr) /* mandatory fields */ if (rule->len < offsetofend(struct fwdb_rule, max_bw)) return false; + /* the rule must lie entirely within the database */ + if ((u8 *)rule + rule->len > data + size) + return false; if (rule->len >= offsetofend(struct fwdb_rule, wmm_ptr)) { u32 wmm_ptr = be16_to_cpu(rule->wmm_ptr) << 2; struct fwdb_wmm_rule *wmm; diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c index db77912b3994..f09c589ff94c 100644 --- a/net/wireless/wext-core.c +++ b/net/wireless/wext-core.c @@ -342,32 +342,28 @@ static const int compat_event_type_size[] = { /* IW event code */ -void wireless_nlevent_flush(void) +void wireless_nlevent_flush(struct net *net) { struct sk_buff *skb; - struct net *net; - down_read(&net_rwsem); - for_each_net(net) { - while ((skb = skb_dequeue(&net->wext_nlevents))) - rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, - GFP_KERNEL); - } - up_read(&net_rwsem); + while ((skb = skb_dequeue(&net->wext_nlevents))) + rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL); } EXPORT_SYMBOL_GPL(wireless_nlevent_flush); static int wext_netdev_notifier_call(struct notifier_block *nb, unsigned long state, void *ptr) { + struct net_device *dev = netdev_notifier_info_to_dev(ptr); + /* - * When a netdev changes state in any way, flush all pending messages - * to avoid them going out in a strange order, e.g. RTM_NEWLINK after - * RTM_DELLINK, or with IFF_UP after without IFF_UP during dev_close() - * or similar - all of which could otherwise happen due to delays from - * schedule_work(). + * When a netdev changes state in any way, flush all pending messages in + * its network namespace to avoid them going out in a strange order, + * e.g. RTM_NEWLINK after RTM_DELLINK, or with IFF_UP after without + * IFF_UP during dev_close() or similar - all of which could otherwise + * happen due to delays from schedule_work(). */ - wireless_nlevent_flush(); + wireless_nlevent_flush(dev_net(dev)); return NOTIFY_OK; } @@ -410,7 +406,12 @@ subsys_initcall(wireless_nlevent_init); /* Process events generated by the wireless layer or the driver. */ static void wireless_nlevent_process(struct work_struct *work) { - wireless_nlevent_flush(); + struct net *net; + + down_read(&net_rwsem); + for_each_net(net) + wireless_nlevent_flush(net); + up_read(&net_rwsem); } static DECLARE_WORK(wireless_nlevent_work, wireless_nlevent_process);