079dd2a86865a014ae7416a479fe85e53c251684
[librecmc/librecmc.git] /
1 From: Johannes Berg <johannes.berg@intel.com>
2 Date: Wed, 29 Mar 2023 16:46:26 +0200
3 Subject: [PATCH] wifi: ieee80211: correctly mark FTM frames non-bufferable
4
5 The checks of whether or not a frame is bufferable were not
6 taking into account that some action frames aren't, such as
7 FTM. Check this, which requires some changes to the function
8 ieee80211_is_bufferable_mmpdu() since we need the whole skb
9 for the checks now.
10
11 Signed-off-by: Johannes Berg <johannes.berg@intel.com>
12 Reviewed-by: Greenman, Gregory <gregory.greenman@intel.com>
13 Reviewed-by: Peer, Ilan <ilan.peer@intel.com>
14 ---
15
16 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
17 +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
18 @@ -601,8 +601,9 @@ static void iwl_mvm_skb_prepare_status(s
19  
20  static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,
21                                       struct ieee80211_tx_info *info,
22 -                                     struct ieee80211_hdr *hdr)
23 +                                     struct sk_buff *skb)
24  {
25 +       struct ieee80211_hdr *hdr = (void *)skb->data;
26         struct iwl_mvm_vif *mvmvif =
27                 iwl_mvm_vif_from_mac80211(info->control.vif);
28         __le16 fc = hdr->frame_control;
29 @@ -621,7 +622,7 @@ static int iwl_mvm_get_ctrl_vif_queue(st
30                  * reason 7 ("Class 3 frame received from nonassociated STA").
31                  */
32                 if (ieee80211_is_mgmt(fc) &&
33 -                   (!ieee80211_is_bufferable_mmpdu(fc) ||
34 +                   (!ieee80211_is_bufferable_mmpdu(skb) ||
35                      ieee80211_is_deauth(fc) || ieee80211_is_disassoc(fc)))
36                         return mvm->probe_queue;
37  
38 @@ -740,7 +741,7 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mv
39                         else
40                                 sta_id = mvmvif->mcast_sta.sta_id;
41  
42 -                       queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info, hdr);
43 +                       queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info, skb);
44                 } else if (info.control.vif->type == NL80211_IFTYPE_MONITOR) {
45                         queue = mvm->snif_queue;
46                         sta_id = mvm->snif_sta.sta_id;
47 --- a/include/linux/ieee80211.h
48 +++ b/include/linux/ieee80211.h
49 @@ -772,20 +772,6 @@ static inline bool ieee80211_is_any_null
50  }
51  
52  /**
53 - * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU
54 - * @fc: frame control field in little-endian byteorder
55 - */
56 -static inline bool ieee80211_is_bufferable_mmpdu(__le16 fc)
57 -{
58 -       /* IEEE 802.11-2012, definition of "bufferable management frame";
59 -        * note that this ignores the IBSS special case. */
60 -       return ieee80211_is_mgmt(fc) &&
61 -              (ieee80211_is_action(fc) ||
62 -               ieee80211_is_disassoc(fc) ||
63 -               ieee80211_is_deauth(fc));
64 -}
65 -
66 -/**
67   * ieee80211_is_first_frag - check if IEEE80211_SCTL_FRAG is not set
68   * @seq_ctrl: frame sequence control bytes in little-endian byteorder
69   */
70 @@ -4121,6 +4107,44 @@ static inline u8 *ieee80211_get_DA(struc
71  }
72  
73  /**
74 + * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU
75 + * @skb: the skb to check, starting with the 802.11 header
76 + */
77 +static inline bool ieee80211_is_bufferable_mmpdu(struct sk_buff *skb)
78 +{
79 +       struct ieee80211_mgmt *mgmt = (void *)skb->data;
80 +       __le16 fc = mgmt->frame_control;
81 +
82 +       /*
83 +        * IEEE 802.11 REVme D2.0 definition of bufferable MMPDU;
84 +        * note that this ignores the IBSS special case.
85 +        */
86 +       if (!ieee80211_is_mgmt(fc))
87 +               return false;
88 +
89 +       if (ieee80211_is_disassoc(fc) || ieee80211_is_deauth(fc))
90 +               return true;
91 +
92 +       if (!ieee80211_is_action(fc))
93 +               return false;
94 +
95 +       if (skb->len < offsetofend(typeof(*mgmt), u.action.u.ftm.action_code))
96 +               return true;
97 +
98 +       /* action frame - additionally check for non-bufferable FTM */
99 +
100 +       if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC &&
101 +           mgmt->u.action.category != WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION)
102 +               return true;
103 +
104 +       if (mgmt->u.action.u.ftm.action_code == WLAN_PUB_ACTION_FTM_REQUEST ||
105 +           mgmt->u.action.u.ftm.action_code == WLAN_PUBLIC_ACTION_FTM_RESPONSE)
106 +               return false;
107 +
108 +       return true;
109 +}
110 +
111 +/**
112   * _ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame
113   * @hdr: the frame (buffer must include at least the first octet of payload)
114   */
115 --- a/net/mac80211/tx.c
116 +++ b/net/mac80211/tx.c
117 @@ -488,7 +488,7 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
118                 int ac = skb_get_queue_mapping(tx->skb);
119  
120                 if (ieee80211_is_mgmt(hdr->frame_control) &&
121 -                   !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) {
122 +                   !ieee80211_is_bufferable_mmpdu(tx->skb)) {
123                         info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
124                         return TX_CONTINUE;
125                 }
126 @@ -1326,7 +1326,7 @@ static struct txq_info *ieee80211_get_tx
127         if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
128             unlikely(!ieee80211_is_data_present(hdr->frame_control))) {
129                 if ((!ieee80211_is_mgmt(hdr->frame_control) ||
130 -                    ieee80211_is_bufferable_mmpdu(hdr->frame_control) ||
131 +                    ieee80211_is_bufferable_mmpdu(skb) ||
132                      vif->type == NL80211_IFTYPE_STATION) &&
133                     sta && sta->uploaded) {
134                         /*