mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-16 00:34:20 +08:00
Merge ath-current from ath.git
ath.git fixes for 4.14. Major changes: ath10k * fix security vulnerability with missing PN check on certain hardware * revert ath10k napi fix as it caused regressions on QCA6174 wcn36xx * remove unnecessary rcu_read_unlock() from error path
This commit is contained in:
commit
c29f56b9f4
@ -550,6 +550,11 @@ static int ath10k_htt_rx_crypto_param_len(struct ath10k *ar,
|
||||
return IEEE80211_TKIP_IV_LEN;
|
||||
case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2:
|
||||
return IEEE80211_CCMP_HDR_LEN;
|
||||
case HTT_RX_MPDU_ENCRYPT_AES_CCM256_WPA2:
|
||||
return IEEE80211_CCMP_256_HDR_LEN;
|
||||
case HTT_RX_MPDU_ENCRYPT_AES_GCMP_WPA2:
|
||||
case HTT_RX_MPDU_ENCRYPT_AES_GCMP256_WPA2:
|
||||
return IEEE80211_GCMP_HDR_LEN;
|
||||
case HTT_RX_MPDU_ENCRYPT_WEP128:
|
||||
case HTT_RX_MPDU_ENCRYPT_WAPI:
|
||||
break;
|
||||
@ -575,6 +580,11 @@ static int ath10k_htt_rx_crypto_tail_len(struct ath10k *ar,
|
||||
return IEEE80211_TKIP_ICV_LEN;
|
||||
case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2:
|
||||
return IEEE80211_CCMP_MIC_LEN;
|
||||
case HTT_RX_MPDU_ENCRYPT_AES_CCM256_WPA2:
|
||||
return IEEE80211_CCMP_256_MIC_LEN;
|
||||
case HTT_RX_MPDU_ENCRYPT_AES_GCMP_WPA2:
|
||||
case HTT_RX_MPDU_ENCRYPT_AES_GCMP256_WPA2:
|
||||
return IEEE80211_GCMP_MIC_LEN;
|
||||
case HTT_RX_MPDU_ENCRYPT_WEP128:
|
||||
case HTT_RX_MPDU_ENCRYPT_WAPI:
|
||||
break;
|
||||
@ -1051,9 +1061,21 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar,
|
||||
hdr = (void *)msdu->data;
|
||||
|
||||
/* Tail */
|
||||
if (status->flag & RX_FLAG_IV_STRIPPED)
|
||||
if (status->flag & RX_FLAG_IV_STRIPPED) {
|
||||
skb_trim(msdu, msdu->len -
|
||||
ath10k_htt_rx_crypto_tail_len(ar, enctype));
|
||||
} else {
|
||||
/* MIC */
|
||||
if ((status->flag & RX_FLAG_MIC_STRIPPED) &&
|
||||
enctype == HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2)
|
||||
skb_trim(msdu, msdu->len - 8);
|
||||
|
||||
/* ICV */
|
||||
if (status->flag & RX_FLAG_ICV_STRIPPED &&
|
||||
enctype != HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2)
|
||||
skb_trim(msdu, msdu->len -
|
||||
ath10k_htt_rx_crypto_tail_len(ar, enctype));
|
||||
}
|
||||
|
||||
/* MMIC */
|
||||
if ((status->flag & RX_FLAG_MMIC_STRIPPED) &&
|
||||
@ -1075,7 +1097,8 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar,
|
||||
static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar,
|
||||
struct sk_buff *msdu,
|
||||
struct ieee80211_rx_status *status,
|
||||
const u8 first_hdr[64])
|
||||
const u8 first_hdr[64],
|
||||
enum htt_rx_mpdu_encrypt_type enctype)
|
||||
{
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct htt_rx_desc *rxd;
|
||||
@ -1083,6 +1106,7 @@ static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar,
|
||||
u8 da[ETH_ALEN];
|
||||
u8 sa[ETH_ALEN];
|
||||
int l3_pad_bytes;
|
||||
int bytes_aligned = ar->hw_params.decap_align_bytes;
|
||||
|
||||
/* Delivered decapped frame:
|
||||
* [nwifi 802.11 header] <-- replaced with 802.11 hdr
|
||||
@ -1111,6 +1135,14 @@ static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar,
|
||||
/* push original 802.11 header */
|
||||
hdr = (struct ieee80211_hdr *)first_hdr;
|
||||
hdr_len = ieee80211_hdrlen(hdr->frame_control);
|
||||
|
||||
if (!(status->flag & RX_FLAG_IV_STRIPPED)) {
|
||||
memcpy(skb_push(msdu,
|
||||
ath10k_htt_rx_crypto_param_len(ar, enctype)),
|
||||
(void *)hdr + round_up(hdr_len, bytes_aligned),
|
||||
ath10k_htt_rx_crypto_param_len(ar, enctype));
|
||||
}
|
||||
|
||||
memcpy(skb_push(msdu, hdr_len), hdr, hdr_len);
|
||||
|
||||
/* original 802.11 header has a different DA and in
|
||||
@ -1171,6 +1203,7 @@ static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar,
|
||||
u8 sa[ETH_ALEN];
|
||||
int l3_pad_bytes;
|
||||
struct htt_rx_desc *rxd;
|
||||
int bytes_aligned = ar->hw_params.decap_align_bytes;
|
||||
|
||||
/* Delivered decapped frame:
|
||||
* [eth header] <-- replaced with 802.11 hdr & rfc1042/llc
|
||||
@ -1199,6 +1232,14 @@ static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar,
|
||||
/* push original 802.11 header */
|
||||
hdr = (struct ieee80211_hdr *)first_hdr;
|
||||
hdr_len = ieee80211_hdrlen(hdr->frame_control);
|
||||
|
||||
if (!(status->flag & RX_FLAG_IV_STRIPPED)) {
|
||||
memcpy(skb_push(msdu,
|
||||
ath10k_htt_rx_crypto_param_len(ar, enctype)),
|
||||
(void *)hdr + round_up(hdr_len, bytes_aligned),
|
||||
ath10k_htt_rx_crypto_param_len(ar, enctype));
|
||||
}
|
||||
|
||||
memcpy(skb_push(msdu, hdr_len), hdr, hdr_len);
|
||||
|
||||
/* original 802.11 header has a different DA and in
|
||||
@ -1212,12 +1253,14 @@ static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar,
|
||||
static void ath10k_htt_rx_h_undecap_snap(struct ath10k *ar,
|
||||
struct sk_buff *msdu,
|
||||
struct ieee80211_rx_status *status,
|
||||
const u8 first_hdr[64])
|
||||
const u8 first_hdr[64],
|
||||
enum htt_rx_mpdu_encrypt_type enctype)
|
||||
{
|
||||
struct ieee80211_hdr *hdr;
|
||||
size_t hdr_len;
|
||||
int l3_pad_bytes;
|
||||
struct htt_rx_desc *rxd;
|
||||
int bytes_aligned = ar->hw_params.decap_align_bytes;
|
||||
|
||||
/* Delivered decapped frame:
|
||||
* [amsdu header] <-- replaced with 802.11 hdr
|
||||
@ -1233,6 +1276,14 @@ static void ath10k_htt_rx_h_undecap_snap(struct ath10k *ar,
|
||||
|
||||
hdr = (struct ieee80211_hdr *)first_hdr;
|
||||
hdr_len = ieee80211_hdrlen(hdr->frame_control);
|
||||
|
||||
if (!(status->flag & RX_FLAG_IV_STRIPPED)) {
|
||||
memcpy(skb_push(msdu,
|
||||
ath10k_htt_rx_crypto_param_len(ar, enctype)),
|
||||
(void *)hdr + round_up(hdr_len, bytes_aligned),
|
||||
ath10k_htt_rx_crypto_param_len(ar, enctype));
|
||||
}
|
||||
|
||||
memcpy(skb_push(msdu, hdr_len), hdr, hdr_len);
|
||||
}
|
||||
|
||||
@ -1267,13 +1318,15 @@ static void ath10k_htt_rx_h_undecap(struct ath10k *ar,
|
||||
is_decrypted);
|
||||
break;
|
||||
case RX_MSDU_DECAP_NATIVE_WIFI:
|
||||
ath10k_htt_rx_h_undecap_nwifi(ar, msdu, status, first_hdr);
|
||||
ath10k_htt_rx_h_undecap_nwifi(ar, msdu, status, first_hdr,
|
||||
enctype);
|
||||
break;
|
||||
case RX_MSDU_DECAP_ETHERNET2_DIX:
|
||||
ath10k_htt_rx_h_undecap_eth(ar, msdu, status, first_hdr, enctype);
|
||||
break;
|
||||
case RX_MSDU_DECAP_8023_SNAP_LLC:
|
||||
ath10k_htt_rx_h_undecap_snap(ar, msdu, status, first_hdr);
|
||||
ath10k_htt_rx_h_undecap_snap(ar, msdu, status, first_hdr,
|
||||
enctype);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1316,7 +1369,8 @@ static void ath10k_htt_rx_h_csum_offload(struct sk_buff *msdu)
|
||||
|
||||
static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
|
||||
struct sk_buff_head *amsdu,
|
||||
struct ieee80211_rx_status *status)
|
||||
struct ieee80211_rx_status *status,
|
||||
bool fill_crypt_header)
|
||||
{
|
||||
struct sk_buff *first;
|
||||
struct sk_buff *last;
|
||||
@ -1326,7 +1380,6 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
|
||||
enum htt_rx_mpdu_encrypt_type enctype;
|
||||
u8 first_hdr[64];
|
||||
u8 *qos;
|
||||
size_t hdr_len;
|
||||
bool has_fcs_err;
|
||||
bool has_crypto_err;
|
||||
bool has_tkip_err;
|
||||
@ -1351,15 +1404,17 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
|
||||
* decapped header. It'll be used for undecapping of each MSDU.
|
||||
*/
|
||||
hdr = (void *)rxd->rx_hdr_status;
|
||||
hdr_len = ieee80211_hdrlen(hdr->frame_control);
|
||||
memcpy(first_hdr, hdr, hdr_len);
|
||||
memcpy(first_hdr, hdr, RX_HTT_HDR_STATUS_LEN);
|
||||
|
||||
/* Each A-MSDU subframe will use the original header as the base and be
|
||||
* reported as a separate MSDU so strip the A-MSDU bit from QoS Ctl.
|
||||
*/
|
||||
hdr = (void *)first_hdr;
|
||||
qos = ieee80211_get_qos_ctl(hdr);
|
||||
qos[0] &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
|
||||
|
||||
if (ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
qos = ieee80211_get_qos_ctl(hdr);
|
||||
qos[0] &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
|
||||
}
|
||||
|
||||
/* Some attention flags are valid only in the last MSDU. */
|
||||
last = skb_peek_tail(amsdu);
|
||||
@ -1406,9 +1461,14 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
|
||||
status->flag |= RX_FLAG_DECRYPTED;
|
||||
|
||||
if (likely(!is_mgmt))
|
||||
status->flag |= RX_FLAG_IV_STRIPPED |
|
||||
RX_FLAG_MMIC_STRIPPED;
|
||||
}
|
||||
status->flag |= RX_FLAG_MMIC_STRIPPED;
|
||||
|
||||
if (fill_crypt_header)
|
||||
status->flag |= RX_FLAG_MIC_STRIPPED |
|
||||
RX_FLAG_ICV_STRIPPED;
|
||||
else
|
||||
status->flag |= RX_FLAG_IV_STRIPPED;
|
||||
}
|
||||
|
||||
skb_queue_walk(amsdu, msdu) {
|
||||
ath10k_htt_rx_h_csum_offload(msdu);
|
||||
@ -1424,6 +1484,9 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
|
||||
if (is_mgmt)
|
||||
continue;
|
||||
|
||||
if (fill_crypt_header)
|
||||
continue;
|
||||
|
||||
hdr = (void *)msdu->data;
|
||||
hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED);
|
||||
}
|
||||
@ -1434,6 +1497,9 @@ static void ath10k_htt_rx_h_deliver(struct ath10k *ar,
|
||||
struct ieee80211_rx_status *status)
|
||||
{
|
||||
struct sk_buff *msdu;
|
||||
struct sk_buff *first_subframe;
|
||||
|
||||
first_subframe = skb_peek(amsdu);
|
||||
|
||||
while ((msdu = __skb_dequeue(amsdu))) {
|
||||
/* Setup per-MSDU flags */
|
||||
@ -1442,6 +1508,13 @@ static void ath10k_htt_rx_h_deliver(struct ath10k *ar,
|
||||
else
|
||||
status->flag |= RX_FLAG_AMSDU_MORE;
|
||||
|
||||
if (msdu == first_subframe) {
|
||||
first_subframe = NULL;
|
||||
status->flag &= ~RX_FLAG_ALLOW_SAME_PN;
|
||||
} else {
|
||||
status->flag |= RX_FLAG_ALLOW_SAME_PN;
|
||||
}
|
||||
|
||||
ath10k_process_rx(ar, status, msdu);
|
||||
}
|
||||
}
|
||||
@ -1584,7 +1657,7 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt)
|
||||
ath10k_htt_rx_h_unchain(ar, &amsdu);
|
||||
|
||||
ath10k_htt_rx_h_filter(ar, &amsdu, rx_status);
|
||||
ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status);
|
||||
ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true);
|
||||
ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status);
|
||||
|
||||
return num_msdus;
|
||||
@ -1745,8 +1818,7 @@ static void ath10k_htt_rx_delba(struct ath10k *ar, struct htt_resp *resp)
|
||||
}
|
||||
|
||||
static int ath10k_htt_rx_extract_amsdu(struct sk_buff_head *list,
|
||||
struct sk_buff_head *amsdu,
|
||||
int budget_left)
|
||||
struct sk_buff_head *amsdu)
|
||||
{
|
||||
struct sk_buff *msdu;
|
||||
struct htt_rx_desc *rxd;
|
||||
@ -1757,9 +1829,8 @@ static int ath10k_htt_rx_extract_amsdu(struct sk_buff_head *list,
|
||||
if (WARN_ON(!skb_queue_empty(amsdu)))
|
||||
return -EINVAL;
|
||||
|
||||
while ((msdu = __skb_dequeue(list)) && budget_left) {
|
||||
while ((msdu = __skb_dequeue(list))) {
|
||||
__skb_queue_tail(amsdu, msdu);
|
||||
budget_left--;
|
||||
|
||||
rxd = (void *)msdu->data - sizeof(*rxd);
|
||||
if (rxd->msdu_end.common.info0 &
|
||||
@ -1850,8 +1921,7 @@ static int ath10k_htt_rx_h_rx_offload(struct ath10k *ar,
|
||||
return num_msdu;
|
||||
}
|
||||
|
||||
static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb,
|
||||
int budget_left)
|
||||
static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
|
||||
{
|
||||
struct ath10k_htt *htt = &ar->htt;
|
||||
struct htt_resp *resp = (void *)skb->data;
|
||||
@ -1908,9 +1978,9 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb,
|
||||
if (offload)
|
||||
num_msdus = ath10k_htt_rx_h_rx_offload(ar, &list);
|
||||
|
||||
while (!skb_queue_empty(&list) && budget_left) {
|
||||
while (!skb_queue_empty(&list)) {
|
||||
__skb_queue_head_init(&amsdu);
|
||||
ret = ath10k_htt_rx_extract_amsdu(&list, &amsdu, budget_left);
|
||||
ret = ath10k_htt_rx_extract_amsdu(&list, &amsdu);
|
||||
switch (ret) {
|
||||
case 0:
|
||||
/* Note: The in-order indication may report interleaved
|
||||
@ -1920,10 +1990,9 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb,
|
||||
* should still give an idea about rx rate to the user.
|
||||
*/
|
||||
num_msdus += skb_queue_len(&amsdu);
|
||||
budget_left -= skb_queue_len(&amsdu);
|
||||
ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id);
|
||||
ath10k_htt_rx_h_filter(ar, &amsdu, status);
|
||||
ath10k_htt_rx_h_mpdu(ar, &amsdu, status);
|
||||
ath10k_htt_rx_h_mpdu(ar, &amsdu, status, false);
|
||||
ath10k_htt_rx_h_deliver(ar, &amsdu, status);
|
||||
break;
|
||||
case -EAGAIN:
|
||||
@ -2563,8 +2632,7 @@ int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget)
|
||||
}
|
||||
|
||||
spin_lock_bh(&htt->rx_ring.lock);
|
||||
num_rx_msdus = ath10k_htt_rx_in_ord_ind(ar, skb,
|
||||
(budget - quota));
|
||||
num_rx_msdus = ath10k_htt_rx_in_ord_ind(ar, skb);
|
||||
spin_unlock_bh(&htt->rx_ring.lock);
|
||||
if (num_rx_msdus < 0) {
|
||||
resched_napi = true;
|
||||
|
@ -239,6 +239,9 @@ enum htt_rx_mpdu_encrypt_type {
|
||||
HTT_RX_MPDU_ENCRYPT_WAPI = 5,
|
||||
HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2 = 6,
|
||||
HTT_RX_MPDU_ENCRYPT_NONE = 7,
|
||||
HTT_RX_MPDU_ENCRYPT_AES_CCM256_WPA2 = 8,
|
||||
HTT_RX_MPDU_ENCRYPT_AES_GCMP_WPA2 = 9,
|
||||
HTT_RX_MPDU_ENCRYPT_AES_GCMP256_WPA2 = 10,
|
||||
};
|
||||
|
||||
#define RX_MPDU_START_INFO0_PEER_IDX_MASK 0x000007ff
|
||||
|
@ -812,7 +812,6 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
|
||||
if (!sta) {
|
||||
wcn36xx_err("sta %pM is not found\n",
|
||||
bss_conf->bssid);
|
||||
rcu_read_unlock();
|
||||
goto out;
|
||||
}
|
||||
sta_priv = wcn36xx_sta_to_priv(sta);
|
||||
|
Loading…
Reference in New Issue
Block a user