Commit 6eb3c282 authored by David S. Miller's avatar David S. Miller

Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless

John W. Linville says:

====================
Please consider pulling this batch of fixes for the 3.13 stream...

For the mac80211 bits, Johannes says:

"Here's a fix for another potential radiotap parser buffer overrun thanks
to Evan Huus, and a fix for a cfg80211 warning in a certain corner case
(reconnecting to the same BSS)."

For the bluetooth bits, Gustavo says:

"Two patches in this pull request. An important fix from Marcel in the
permission check for HCI User Channels, there was a extra check for
CAP_NET_RAW, and it was now removed. These channels should only require
CAP_NET_ADMIN. The other patch is a device id addition."

On top of that...

Sujith Manoharan provides a workaround for a hardware problem that
can result in lost interrupts.

Larry Finger fixes an oops when unloading the rtlwifi driver (Red
Hat bug 852761).

Mathy Vanhoef fixes a somewhat minor MAC address privacy issue
(CVE-2013-4579).
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a68f9614 76ae07df
...@@ -87,6 +87,7 @@ static const struct usb_device_id ath3k_table[] = { ...@@ -87,6 +87,7 @@ static const struct usb_device_id ath3k_table[] = {
{ USB_DEVICE(0x0CF3, 0xE004) }, { USB_DEVICE(0x0CF3, 0xE004) },
{ USB_DEVICE(0x0CF3, 0xE005) }, { USB_DEVICE(0x0CF3, 0xE005) },
{ USB_DEVICE(0x0930, 0x0219) }, { USB_DEVICE(0x0930, 0x0219) },
{ USB_DEVICE(0x0930, 0x0220) },
{ USB_DEVICE(0x0489, 0xe057) }, { USB_DEVICE(0x0489, 0xe057) },
{ USB_DEVICE(0x13d3, 0x3393) }, { USB_DEVICE(0x13d3, 0x3393) },
{ USB_DEVICE(0x0489, 0xe04e) }, { USB_DEVICE(0x0489, 0xe04e) },
...@@ -129,6 +130,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { ...@@ -129,6 +130,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
......
...@@ -154,6 +154,7 @@ static const struct usb_device_id blacklist_table[] = { ...@@ -154,6 +154,7 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
......
...@@ -76,9 +76,16 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) ...@@ -76,9 +76,16 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
mask2 |= ATH9K_INT_CST; mask2 |= ATH9K_INT_CST;
if (isr2 & AR_ISR_S2_TSFOOR) if (isr2 & AR_ISR_S2_TSFOOR)
mask2 |= ATH9K_INT_TSFOOR; mask2 |= ATH9K_INT_TSFOOR;
if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
REG_WRITE(ah, AR_ISR_S2, isr2);
isr &= ~AR_ISR_BCNMISC;
}
} }
isr = REG_READ(ah, AR_ISR_RAC); if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)
isr = REG_READ(ah, AR_ISR_RAC);
if (isr == 0xffffffff) { if (isr == 0xffffffff) {
*masked = 0; *masked = 0;
return false; return false;
...@@ -97,11 +104,23 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) ...@@ -97,11 +104,23 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
*masked |= ATH9K_INT_TX; *masked |= ATH9K_INT_TX;
s0_s = REG_READ(ah, AR_ISR_S0_S); if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) {
s0_s = REG_READ(ah, AR_ISR_S0_S);
s1_s = REG_READ(ah, AR_ISR_S1_S);
} else {
s0_s = REG_READ(ah, AR_ISR_S0);
REG_WRITE(ah, AR_ISR_S0, s0_s);
s1_s = REG_READ(ah, AR_ISR_S1);
REG_WRITE(ah, AR_ISR_S1, s1_s);
isr &= ~(AR_ISR_TXOK |
AR_ISR_TXDESC |
AR_ISR_TXERR |
AR_ISR_TXEOL);
}
ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK); ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK);
ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC); ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC);
s1_s = REG_READ(ah, AR_ISR_S1_S);
ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR); ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR);
ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL); ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL);
} }
...@@ -114,13 +133,15 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) ...@@ -114,13 +133,15 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
*masked |= mask2; *masked |= mask2;
} }
if (AR_SREV_9100(ah)) if (!AR_SREV_9100(ah) && (isr & AR_ISR_GENTMR)) {
return true;
if (isr & AR_ISR_GENTMR) {
u32 s5_s; u32 s5_s;
s5_s = REG_READ(ah, AR_ISR_S5_S); if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) {
s5_s = REG_READ(ah, AR_ISR_S5_S);
} else {
s5_s = REG_READ(ah, AR_ISR_S5);
}
ah->intr_gen_timer_trigger = ah->intr_gen_timer_trigger =
MS(s5_s, AR_ISR_S5_GENTIMER_TRIG); MS(s5_s, AR_ISR_S5_GENTIMER_TRIG);
...@@ -133,8 +154,21 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) ...@@ -133,8 +154,21 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
if ((s5_s & AR_ISR_S5_TIM_TIMER) && if ((s5_s & AR_ISR_S5_TIM_TIMER) &&
!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) !(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
*masked |= ATH9K_INT_TIM_TIMER; *masked |= ATH9K_INT_TIM_TIMER;
if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
REG_WRITE(ah, AR_ISR_S5, s5_s);
isr &= ~AR_ISR_GENTMR;
}
} }
if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
REG_WRITE(ah, AR_ISR, isr);
REG_READ(ah, AR_ISR);
}
if (AR_SREV_9100(ah))
return true;
if (sync_cause) { if (sync_cause) {
ath9k_debug_sync_cause(common, sync_cause); ath9k_debug_sync_cause(common, sync_cause);
fatal_int = fatal_int =
......
...@@ -127,21 +127,26 @@ static void ath9k_htc_bssid_iter(void *data, u8 *mac, struct ieee80211_vif *vif) ...@@ -127,21 +127,26 @@ static void ath9k_htc_bssid_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
struct ath9k_vif_iter_data *iter_data = data; struct ath9k_vif_iter_data *iter_data = data;
int i; int i;
for (i = 0; i < ETH_ALEN; i++) if (iter_data->hw_macaddr != NULL) {
iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]); for (i = 0; i < ETH_ALEN; i++)
iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]);
} else {
iter_data->hw_macaddr = mac;
}
} }
static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv, static void ath9k_htc_set_mac_bssid_mask(struct ath9k_htc_priv *priv,
struct ieee80211_vif *vif) struct ieee80211_vif *vif)
{ {
struct ath_common *common = ath9k_hw_common(priv->ah); struct ath_common *common = ath9k_hw_common(priv->ah);
struct ath9k_vif_iter_data iter_data; struct ath9k_vif_iter_data iter_data;
/* /*
* Use the hardware MAC address as reference, the hardware uses it * Pick the MAC address of the first interface as the new hardware
* together with the BSSID mask when matching addresses. * MAC address. The hardware will use it together with the BSSID mask
* when matching addresses.
*/ */
iter_data.hw_macaddr = common->macaddr; iter_data.hw_macaddr = NULL;
memset(&iter_data.mask, 0xff, ETH_ALEN); memset(&iter_data.mask, 0xff, ETH_ALEN);
if (vif) if (vif)
...@@ -153,6 +158,10 @@ static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv, ...@@ -153,6 +158,10 @@ static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv,
ath9k_htc_bssid_iter, &iter_data); ath9k_htc_bssid_iter, &iter_data);
memcpy(common->bssidmask, iter_data.mask, ETH_ALEN); memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
if (iter_data.hw_macaddr)
memcpy(common->macaddr, iter_data.hw_macaddr, ETH_ALEN);
ath_hw_setbssidmask(common); ath_hw_setbssidmask(common);
} }
...@@ -1063,7 +1072,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, ...@@ -1063,7 +1072,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
goto out; goto out;
} }
ath9k_htc_set_bssid_mask(priv, vif); ath9k_htc_set_mac_bssid_mask(priv, vif);
priv->vif_slot |= (1 << avp->index); priv->vif_slot |= (1 << avp->index);
priv->nvifs++; priv->nvifs++;
...@@ -1128,7 +1137,7 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, ...@@ -1128,7 +1137,7 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
ath9k_htc_set_opmode(priv); ath9k_htc_set_opmode(priv);
ath9k_htc_set_bssid_mask(priv, vif); ath9k_htc_set_mac_bssid_mask(priv, vif);
/* /*
* Stop ANI only if there are no associated station interfaces. * Stop ANI only if there are no associated station interfaces.
......
...@@ -965,8 +965,9 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw, ...@@ -965,8 +965,9 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
/* /*
* Use the hardware MAC address as reference, the hardware uses it * Pick the MAC address of the first interface as the new hardware
* together with the BSSID mask when matching addresses. * MAC address. The hardware will use it together with the BSSID mask
* when matching addresses.
*/ */
memset(iter_data, 0, sizeof(*iter_data)); memset(iter_data, 0, sizeof(*iter_data));
memset(&iter_data->mask, 0xff, ETH_ALEN); memset(&iter_data->mask, 0xff, ETH_ALEN);
......
...@@ -740,6 +740,8 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) ...@@ -740,6 +740,8 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
}; };
int index = rtlpci->rx_ring[rx_queue_idx].idx; int index = rtlpci->rx_ring[rx_queue_idx].idx;
if (rtlpci->driver_is_goingto_unload)
return;
/*RX NORMAL PKT */ /*RX NORMAL PKT */
while (count--) { while (count--) {
/*rx descriptor */ /*rx descriptor */
...@@ -1636,6 +1638,7 @@ static void rtl_pci_stop(struct ieee80211_hw *hw) ...@@ -1636,6 +1638,7 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
*/ */
set_hal_stop(rtlhal); set_hal_stop(rtlhal);
rtlpci->driver_is_goingto_unload = true;
rtlpriv->cfg->ops->disable_interrupt(hw); rtlpriv->cfg->ops->disable_interrupt(hw);
cancel_work_sync(&rtlpriv->works.lps_change_work); cancel_work_sync(&rtlpriv->works.lps_change_work);
...@@ -1653,7 +1656,6 @@ static void rtl_pci_stop(struct ieee80211_hw *hw) ...@@ -1653,7 +1656,6 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
ppsc->rfchange_inprogress = true; ppsc->rfchange_inprogress = true;
spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags); spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags);
rtlpci->driver_is_goingto_unload = true;
rtlpriv->cfg->ops->hw_disable(hw); rtlpriv->cfg->ops->hw_disable(hw);
/* some things are not needed if firmware not available */ /* some things are not needed if firmware not available */
if (!rtlpriv->max_fw_size) if (!rtlpriv->max_fw_size)
......
...@@ -940,8 +940,22 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -940,8 +940,22 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
bt_cb(skb)->pkt_type = *((unsigned char *) skb->data); bt_cb(skb)->pkt_type = *((unsigned char *) skb->data);
skb_pull(skb, 1); skb_pull(skb, 1);
if (hci_pi(sk)->channel == HCI_CHANNEL_RAW && if (hci_pi(sk)->channel == HCI_CHANNEL_USER) {
bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) { /* No permission check is needed for user channel
* since that gets enforced when binding the socket.
*
* However check that the packet type is valid.
*/
if (bt_cb(skb)->pkt_type != HCI_COMMAND_PKT &&
bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT &&
bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) {
err = -EINVAL;
goto drop;
}
skb_queue_tail(&hdev->raw_q, skb);
queue_work(hdev->workqueue, &hdev->tx_work);
} else if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
u16 opcode = get_unaligned_le16(skb->data); u16 opcode = get_unaligned_le16(skb->data);
u16 ogf = hci_opcode_ogf(opcode); u16 ogf = hci_opcode_ogf(opcode);
u16 ocf = hci_opcode_ocf(opcode); u16 ocf = hci_opcode_ocf(opcode);
...@@ -972,14 +986,6 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -972,14 +986,6 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
goto drop; goto drop;
} }
if (hci_pi(sk)->channel == HCI_CHANNEL_USER &&
bt_cb(skb)->pkt_type != HCI_COMMAND_PKT &&
bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT &&
bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) {
err = -EINVAL;
goto drop;
}
skb_queue_tail(&hdev->raw_q, skb); skb_queue_tail(&hdev->raw_q, skb);
queue_work(hdev->workqueue, &hdev->tx_work); queue_work(hdev->workqueue, &hdev->tx_work);
} }
......
...@@ -124,6 +124,10 @@ int ieee80211_radiotap_iterator_init( ...@@ -124,6 +124,10 @@ int ieee80211_radiotap_iterator_init(
/* find payload start allowing for extended bitmap(s) */ /* find payload start allowing for extended bitmap(s) */
if (iterator->_bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT)) { if (iterator->_bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT)) {
if ((unsigned long)iterator->_arg -
(unsigned long)iterator->_rtheader + sizeof(uint32_t) >
(unsigned long)iterator->_max_length)
return -EINVAL;
while (get_unaligned_le32(iterator->_arg) & while (get_unaligned_le32(iterator->_arg) &
(1 << IEEE80211_RADIOTAP_EXT)) { (1 << IEEE80211_RADIOTAP_EXT)) {
iterator->_arg += sizeof(uint32_t); iterator->_arg += sizeof(uint32_t);
......
...@@ -632,6 +632,16 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, ...@@ -632,6 +632,16 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
} }
#endif #endif
if (!bss && (status == WLAN_STATUS_SUCCESS)) {
WARN_ON_ONCE(!wiphy_to_dev(wdev->wiphy)->ops->connect);
bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
wdev->ssid, wdev->ssid_len,
WLAN_CAPABILITY_ESS,
WLAN_CAPABILITY_ESS);
if (bss)
cfg80211_hold_bss(bss_from_pub(bss));
}
if (wdev->current_bss) { if (wdev->current_bss) {
cfg80211_unhold_bss(wdev->current_bss); cfg80211_unhold_bss(wdev->current_bss);
cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub); cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub);
...@@ -649,16 +659,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, ...@@ -649,16 +659,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
return; return;
} }
if (!bss) { if (WARN_ON(!bss))
WARN_ON_ONCE(!wiphy_to_dev(wdev->wiphy)->ops->connect); return;
bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
wdev->ssid, wdev->ssid_len,
WLAN_CAPABILITY_ESS,
WLAN_CAPABILITY_ESS);
if (WARN_ON(!bss))
return;
cfg80211_hold_bss(bss_from_pub(bss));
}
wdev->current_bss = bss_from_pub(bss); wdev->current_bss = bss_from_pub(bss);
......
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