mac80211: fix regression in skb resizing optimization in monitor mode (FS#2254)

struct ieee80211_local needs to be passed in separately instead of
dereferencing the (potentially NULL) sdata

Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
Felix Fietkau 2019-04-24 09:32:22 +02:00
parent 82625374ee
commit 6e7e2f4421

View File

@ -24,11 +24,12 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- a/net/mac80211/ieee80211_i.h --- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h
@@ -1761,6 +1761,8 @@ void ieee80211_clear_fast_xmit(struct st @@ -1761,6 +1761,9 @@ void ieee80211_clear_fast_xmit(struct st
int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev, int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
const u8 *buf, size_t len, const u8 *buf, size_t len,
const u8 *dest, __be16 proto, bool unencrypted); const u8 *dest, __be16 proto, bool unencrypted);
+int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata, +int ieee80211_skb_resize(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, int hdrlen, int hdr_add); + struct sk_buff *skb, int hdrlen, int hdr_add);
/* HT */ /* HT */
@ -39,7 +40,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
} }
} }
+ if (ieee80211_skb_resize(NULL, skb, 0, 0)) { + if (ieee80211_skb_resize(local, NULL, skb, 0, 0)) {
+ dev_kfree_skb(skb); + dev_kfree_skb(skb);
+ return; + return;
+ } + }
@ -57,28 +58,23 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
-static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata, -static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb, - struct sk_buff *skb,
- int head_need, bool may_encrypt) - int head_need, bool may_encrypt)
+int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata, +int ieee80211_skb_resize(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, int hdr_len, int hdr_extra) + struct sk_buff *skb, int hdr_len, int hdr_extra)
{ {
struct ieee80211_local *local = sdata->local; - struct ieee80211_local *local = sdata->local;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
- bool enc_tailroom; - bool enc_tailroom;
- int tail_need = 0; - int tail_need = 0;
- + int head_need, head_max;
+ int tail_need, tail_max;
+ bool enc_tailroom = false;
- hdr = (struct ieee80211_hdr *) skb->data; - hdr = (struct ieee80211_hdr *) skb->data;
- enc_tailroom = may_encrypt && - enc_tailroom = may_encrypt &&
- (sdata->crypto_tx_tailroom_needed_cnt || - (sdata->crypto_tx_tailroom_needed_cnt ||
- ieee80211_is_mgmt(hdr->frame_control)); - ieee80211_is_mgmt(hdr->frame_control));
-
- if (enc_tailroom) {
- tail_need = IEEE80211_ENCRYPT_TAILROOM;
- tail_need -= skb_tailroom(skb);
- tail_need = max_t(int, tail_need, 0);
+ int head_need, head_max;
+ int tail_need, tail_max;
+ bool enc_tailroom = false;
+
+ if (sdata && !hdr_len && + if (sdata && !hdr_len &&
+ !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) { + !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) {
+ hdr = (struct ieee80211_hdr *) skb->data; + hdr = (struct ieee80211_hdr *) skb->data;
@ -86,7 +82,11 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+ ieee80211_is_mgmt(hdr->frame_control)); + ieee80211_is_mgmt(hdr->frame_control));
+ hdr_len += sdata->encrypt_headroom; + hdr_len += sdata->encrypt_headroom;
+ } + }
+
- if (enc_tailroom) {
- tail_need = IEEE80211_ENCRYPT_TAILROOM;
- tail_need -= skb_tailroom(skb);
- tail_need = max_t(int, tail_need, 0);
+ head_need = head_max = hdr_len; + head_need = head_max = hdr_len;
+ tail_need = tail_max = 0; + tail_need = tail_max = 0;
+ if (!sdata) { + if (!sdata) {
@ -129,15 +129,15 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
- bool may_encrypt; - bool may_encrypt;
- -
- may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT); - may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT);
-
- headroom = local->tx_headroom; - headroom = local->tx_headroom;
- if (may_encrypt) - if (may_encrypt)
- headroom += sdata->encrypt_headroom; - headroom += sdata->encrypt_headroom;
- headroom -= skb_headroom(skb); - headroom -= skb_headroom(skb);
- headroom = max_t(int, 0, headroom); - headroom = max_t(int, 0, headroom);
-
- if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) { - if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) {
+ if (ieee80211_skb_resize(sdata, skb, 0, 0)) { + if (ieee80211_skb_resize(local, sdata, skb, 0, 0)) {
ieee80211_free_txskb(&local->hw, skb); ieee80211_free_txskb(&local->hw, skb);
return; return;
} }
@ -170,7 +170,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
- skb = NULL; - skb = NULL;
- return ERR_PTR(-ENOMEM); - return ERR_PTR(-ENOMEM);
- } - }
+ if (ieee80211_skb_resize(sdata, skb, head_need, + if (ieee80211_skb_resize(local, sdata, skb, head_need,
+ sdata->encrypt_headroom)) { + sdata->encrypt_headroom)) {
+ ieee80211_free_txskb(&local->hw, skb); + ieee80211_free_txskb(&local->hw, skb);
+ skb = NULL; + skb = NULL;
@ -194,7 +194,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
- max_t(int, extra_head + hw_headroom - - max_t(int, extra_head + hw_headroom -
- skb_headroom(skb), 0), - skb_headroom(skb), 0),
- false))) { - false))) {
+ if (unlikely(ieee80211_skb_resize(sdata, skb, extra_head, 0))) { + if (unlikely(ieee80211_skb_resize(local, sdata, skb, extra_head, 0))) {
kfree_skb(skb); kfree_skb(skb);
return true; return true;
} }