1 From: Johannes Berg <johannes.berg@intel.com>
2 Date: Mon, 20 Sep 2021 15:40:10 +0200
3 Subject: [PATCH] mac80211: always allocate struct ieee802_11_elems
5 As the 802.11 spec evolves, we need to parse more and more
6 elements. This is causing the struct to grow, and we can no
7 longer get away with putting it on the stack.
9 Change the API to always dynamically allocate and return an
10 allocated pointer that must be kfree()d later.
12 As an alternative, I contemplated a scheme whereby we'd say
13 in the code which elements we needed, e.g.
15 DECLARE_ELEMENT_PARSER(elems,
20 ieee802_11_parse_elems(..., &elems, ...);
22 and while I think this is possible and will save us a lot
23 since most individual places only care about a small subset
24 of the elements, it ended up being a bit more work since a
25 lot of places do the parsing and then pass the struct to
26 other functions, sometimes with multiple levels.
28 Link: https://lore.kernel.org/r/20210920154009.26caff6b5998.I05ae58768e990e611aee8eca8abefd9d7bc15e05@changeid
29 Signed-off-by: Johannes Berg <johannes.berg@intel.com>
32 --- a/net/mac80211/agg-rx.c
33 +++ b/net/mac80211/agg-rx.c
34 @@ -478,7 +478,7 @@ void ieee80211_process_addba_request(str
37 u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num;
38 - struct ieee802_11_elems elems = { };
39 + struct ieee802_11_elems *elems = NULL;
43 @@ -496,16 +496,17 @@ void ieee80211_process_addba_request(str
44 ies_len = len - offsetof(struct ieee80211_mgmt,
45 u.action.u.addba_req.variable);
47 - ieee802_11_parse_elems(mgmt->u.action.u.addba_req.variable,
48 - ies_len, true, &elems, mgmt->bssid, NULL);
49 - if (elems.parse_error)
50 + elems = ieee802_11_parse_elems(mgmt->u.action.u.addba_req.variable,
51 + ies_len, true, mgmt->bssid, NULL);
52 + if (!elems || elems->parse_error)
56 __ieee80211_start_rx_ba_session(sta, dialog_token, timeout,
57 start_seq_num, ba_policy, tid,
58 buf_size, true, false,
59 - elems.addba_ext_ie);
60 + elems ? elems->addba_ext_ie : NULL);
64 void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif,
65 --- a/net/mac80211/ibss.c
66 +++ b/net/mac80211/ibss.c
68 * Copyright 2009, Johannes Berg <johannes@sipsolutions.net>
69 * Copyright 2013-2014 Intel Mobile Communications GmbH
70 * Copyright(c) 2016 Intel Deutschland GmbH
71 - * Copyright(c) 2018-2020 Intel Corporation
72 + * Copyright(c) 2018-2021 Intel Corporation
75 #include <linux/delay.h>
76 @@ -1589,7 +1589,7 @@ void ieee80211_rx_mgmt_probe_beacon(stru
77 struct ieee80211_rx_status *rx_status)
80 - struct ieee802_11_elems elems;
81 + struct ieee802_11_elems *elems;
83 BUILD_BUG_ON(offsetof(typeof(mgmt->u.probe_resp), variable) !=
84 offsetof(typeof(mgmt->u.beacon), variable));
85 @@ -1602,10 +1602,14 @@ void ieee80211_rx_mgmt_probe_beacon(stru
89 - ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
90 - false, &elems, mgmt->bssid, NULL);
92 - ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
93 + elems = ieee802_11_parse_elems(mgmt->u.probe_resp.variable,
94 + len - baselen, false,
98 + ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, elems);
103 void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
104 @@ -1614,7 +1618,7 @@ void ieee80211_ibss_rx_queued_mgmt(struc
105 struct ieee80211_rx_status *rx_status;
106 struct ieee80211_mgmt *mgmt;
108 - struct ieee802_11_elems elems;
109 + struct ieee802_11_elems *elems;
112 rx_status = IEEE80211_SKB_RXCB(skb);
113 @@ -1651,15 +1655,16 @@ void ieee80211_ibss_rx_queued_mgmt(struc
117 - ieee802_11_parse_elems(
118 + elems = ieee802_11_parse_elems(
119 mgmt->u.action.u.chan_switch.variable,
120 - ies_len, true, &elems, mgmt->bssid, NULL);
121 + ies_len, true, mgmt->bssid, NULL);
123 - if (elems.parse_error)
124 + if (!elems || elems->parse_error)
127 ieee80211_rx_mgmt_spectrum_mgmt(sdata, mgmt, skb->len,
128 - rx_status, &elems);
134 --- a/net/mac80211/ieee80211_i.h
135 +++ b/net/mac80211/ieee80211_i.h
136 @@ -2088,18 +2088,18 @@ static inline void ieee80211_tx_skb(stru
137 ieee80211_tx_skb_tid(sdata, skb, 7);
140 -void ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
141 - struct ieee802_11_elems *elems,
142 - u64 filter, u32 crc, u8 *transmitter_bssid,
144 -static inline void ieee802_11_parse_elems(const u8 *start, size_t len,
146 - struct ieee802_11_elems *elems,
147 - u8 *transmitter_bssid,
149 +struct ieee802_11_elems *ieee802_11_parse_elems_crc(const u8 *start, size_t len,
151 + u64 filter, u32 crc,
152 + const u8 *transmitter_bssid,
153 + const u8 *bss_bssid);
154 +static inline struct ieee802_11_elems *
155 +ieee802_11_parse_elems(const u8 *start, size_t len, bool action,
156 + const u8 *transmitter_bssid,
157 + const u8 *bss_bssid)
159 - ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0,
160 - transmitter_bssid, bss_bssid);
161 + return ieee802_11_parse_elems_crc(start, len, action, 0, 0,
162 + transmitter_bssid, bss_bssid);
166 --- a/net/mac80211/mesh.c
167 +++ b/net/mac80211/mesh.c
168 @@ -1247,7 +1247,7 @@ ieee80211_mesh_rx_probe_req(struct ieee8
169 struct sk_buff *presp;
170 struct beacon_data *bcn;
171 struct ieee80211_mgmt *hdr;
172 - struct ieee802_11_elems elems;
173 + struct ieee802_11_elems *elems;
177 @@ -1256,22 +1256,24 @@ ieee80211_mesh_rx_probe_req(struct ieee8
181 - ieee802_11_parse_elems(pos, len - baselen, false, &elems, mgmt->bssid,
184 - if (!elems.mesh_id)
185 + elems = ieee802_11_parse_elems(pos, len - baselen, false, mgmt->bssid,
190 + if (!elems->mesh_id)
193 /* 802.11-2012 10.1.4.3.2 */
194 if ((!ether_addr_equal(mgmt->da, sdata->vif.addr) &&
195 !is_broadcast_ether_addr(mgmt->da)) ||
196 - elems.ssid_len != 0)
198 + elems->ssid_len != 0)
201 - if (elems.mesh_id_len != 0 &&
202 - (elems.mesh_id_len != ifmsh->mesh_id_len ||
203 - memcmp(elems.mesh_id, ifmsh->mesh_id, ifmsh->mesh_id_len)))
205 + if (elems->mesh_id_len != 0 &&
206 + (elems->mesh_id_len != ifmsh->mesh_id_len ||
207 + memcmp(elems->mesh_id, ifmsh->mesh_id, ifmsh->mesh_id_len)))
211 bcn = rcu_dereference(ifmsh->beacon);
212 @@ -1295,6 +1297,8 @@ ieee80211_mesh_rx_probe_req(struct ieee8
213 ieee80211_tx_skb(sdata, presp);
220 static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
221 @@ -1305,7 +1309,7 @@ static void ieee80211_mesh_rx_bcn_presp(
223 struct ieee80211_local *local = sdata->local;
224 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
225 - struct ieee802_11_elems elems;
226 + struct ieee802_11_elems *elems;
227 struct ieee80211_channel *channel;
230 @@ -1320,42 +1324,47 @@ static void ieee80211_mesh_rx_bcn_presp(
234 - ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
235 - false, &elems, mgmt->bssid, NULL);
236 + elems = ieee802_11_parse_elems(mgmt->u.probe_resp.variable,
238 + false, mgmt->bssid, NULL);
242 /* ignore non-mesh or secure / unsecure mismatch */
243 - if ((!elems.mesh_id || !elems.mesh_config) ||
244 - (elems.rsn && sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) ||
245 - (!elems.rsn && sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE))
247 + if ((!elems->mesh_id || !elems->mesh_config) ||
248 + (elems->rsn && sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) ||
249 + (!elems->rsn && sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE))
252 - if (elems.ds_params)
253 - freq = ieee80211_channel_to_frequency(elems.ds_params[0], band);
254 + if (elems->ds_params)
255 + freq = ieee80211_channel_to_frequency(elems->ds_params[0], band);
257 freq = rx_status->freq;
259 channel = ieee80211_get_channel(local->hw.wiphy, freq);
261 if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
265 - if (mesh_matches_local(sdata, &elems)) {
266 + if (mesh_matches_local(sdata, elems)) {
267 mpl_dbg(sdata, "rssi_threshold=%d,rx_status->signal=%d\n",
268 sdata->u.mesh.mshcfg.rssi_threshold, rx_status->signal);
269 if (!sdata->u.mesh.user_mpm ||
270 sdata->u.mesh.mshcfg.rssi_threshold == 0 ||
271 sdata->u.mesh.mshcfg.rssi_threshold < rx_status->signal)
272 - mesh_neighbour_update(sdata, mgmt->sa, &elems,
273 + mesh_neighbour_update(sdata, mgmt->sa, elems,
276 if (ifmsh->csa_role != IEEE80211_MESH_CSA_ROLE_INIT &&
277 !sdata->vif.csa_active)
278 - ieee80211_mesh_process_chnswitch(sdata, &elems, true);
279 + ieee80211_mesh_process_chnswitch(sdata, elems, true);
283 ifmsh->sync_ops->rx_bcn_presp(sdata, stype, mgmt, len,
284 - elems.mesh_config, rx_status);
285 + elems->mesh_config, rx_status);
290 int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata)
291 @@ -1447,7 +1456,7 @@ static void mesh_rx_csa_frame(struct iee
292 struct ieee80211_mgmt *mgmt, size_t len)
294 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
295 - struct ieee802_11_elems elems;
296 + struct ieee802_11_elems *elems;
300 @@ -1460,33 +1469,37 @@ static void mesh_rx_csa_frame(struct iee
301 pos = mgmt->u.action.u.chan_switch.variable;
302 baselen = offsetof(struct ieee80211_mgmt,
303 u.action.u.chan_switch.variable);
304 - ieee802_11_parse_elems(pos, len - baselen, true, &elems,
305 - mgmt->bssid, NULL);
307 - if (!mesh_matches_local(sdata, &elems))
308 + elems = ieee802_11_parse_elems(pos, len - baselen, true,
309 + mgmt->bssid, NULL);
313 - ifmsh->chsw_ttl = elems.mesh_chansw_params_ie->mesh_ttl;
314 + if (!mesh_matches_local(sdata, elems))
317 + ifmsh->chsw_ttl = elems->mesh_chansw_params_ie->mesh_ttl;
318 if (!--ifmsh->chsw_ttl)
321 - pre_value = le16_to_cpu(elems.mesh_chansw_params_ie->mesh_pre_value);
322 + pre_value = le16_to_cpu(elems->mesh_chansw_params_ie->mesh_pre_value);
323 if (ifmsh->pre_value >= pre_value)
327 ifmsh->pre_value = pre_value;
329 if (!sdata->vif.csa_active &&
330 - !ieee80211_mesh_process_chnswitch(sdata, &elems, false)) {
331 + !ieee80211_mesh_process_chnswitch(sdata, elems, false)) {
332 mcsa_dbg(sdata, "Failed to process CSA action frame");
337 /* forward or re-broadcast the CSA frame */
339 - if (mesh_fwd_csa_frame(sdata, mgmt, len, &elems) < 0)
340 + if (mesh_fwd_csa_frame(sdata, mgmt, len, elems) < 0)
341 mcsa_dbg(sdata, "Failed to forward the CSA frame");
347 static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata,
348 --- a/net/mac80211/mesh_hwmp.c
349 +++ b/net/mac80211/mesh_hwmp.c
351 // SPDX-License-Identifier: GPL-2.0-only
353 * Copyright (c) 2008, 2009 open80211s Ltd.
354 - * Copyright (C) 2019 Intel Corporation
355 + * Copyright (C) 2019, 2021 Intel Corporation
356 * Author: Luis Carlos Cobo <luisca@cozybit.com>
359 @@ -908,7 +908,7 @@ static void hwmp_rann_frame_process(stru
360 void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
361 struct ieee80211_mgmt *mgmt, size_t len)
363 - struct ieee802_11_elems elems;
364 + struct ieee802_11_elems *elems;
367 struct sta_info *sta;
368 @@ -926,37 +926,41 @@ void mesh_rx_path_sel_frame(struct ieee8
371 baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt;
372 - ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
373 - len - baselen, false, &elems, mgmt->bssid, NULL);
374 + elems = ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
375 + len - baselen, false, mgmt->bssid, NULL);
380 - if (elems.preq_len != 37)
382 + if (elems->preq_len != 37)
383 /* Right now we support just 1 destination and no AE */
385 - path_metric = hwmp_route_info_get(sdata, mgmt, elems.preq,
387 + path_metric = hwmp_route_info_get(sdata, mgmt, elems->preq,
390 - hwmp_preq_frame_process(sdata, mgmt, elems.preq,
391 + hwmp_preq_frame_process(sdata, mgmt, elems->preq,
395 - if (elems.prep_len != 31)
397 + if (elems->prep_len != 31)
398 /* Right now we support no AE */
400 - path_metric = hwmp_route_info_get(sdata, mgmt, elems.prep,
402 + path_metric = hwmp_route_info_get(sdata, mgmt, elems->prep,
405 - hwmp_prep_frame_process(sdata, mgmt, elems.prep,
406 + hwmp_prep_frame_process(sdata, mgmt, elems->prep,
410 - if (elems.perr_len != 15)
412 + if (elems->perr_len != 15)
413 /* Right now we support only one destination per PERR */
415 - hwmp_perr_frame_process(sdata, mgmt, elems.perr);
417 + hwmp_perr_frame_process(sdata, mgmt, elems->perr);
420 - hwmp_rann_frame_process(sdata, mgmt, elems.rann);
422 + hwmp_rann_frame_process(sdata, mgmt, elems->rann);
428 --- a/net/mac80211/mesh_plink.c
429 +++ b/net/mac80211/mesh_plink.c
431 // SPDX-License-Identifier: GPL-2.0-only
433 * Copyright (c) 2008, 2009 open80211s Ltd.
434 - * Copyright (C) 2019 Intel Corporation
435 + * Copyright (C) 2019, 2021 Intel Corporation
436 * Author: Luis Carlos Cobo <luisca@cozybit.com>
438 #include <linux/gfp.h>
439 @@ -1200,7 +1200,7 @@ void mesh_rx_plink_frame(struct ieee8021
440 struct ieee80211_mgmt *mgmt, size_t len,
441 struct ieee80211_rx_status *rx_status)
443 - struct ieee802_11_elems elems;
444 + struct ieee802_11_elems *elems;
448 @@ -1228,7 +1228,8 @@ void mesh_rx_plink_frame(struct ieee8021
452 - ieee802_11_parse_elems(baseaddr, len - baselen, true, &elems,
453 - mgmt->bssid, NULL);
454 - mesh_process_plink_frame(sdata, mgmt, &elems, rx_status);
455 + elems = ieee802_11_parse_elems(baseaddr, len - baselen, true,
456 + mgmt->bssid, NULL);
457 + mesh_process_plink_frame(sdata, mgmt, elems, rx_status);
460 --- a/net/mac80211/mlme.c
461 +++ b/net/mac80211/mlme.c
462 @@ -3317,8 +3317,11 @@ static bool ieee80211_assoc_success(stru
465 capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
466 - ieee802_11_parse_elems(pos, len - (pos - (u8 *)mgmt), false, elems,
467 - mgmt->bssid, assoc_data->bss->bssid);
468 + elems = ieee802_11_parse_elems(pos, len - (pos - (u8 *)mgmt), false,
469 + mgmt->bssid, assoc_data->bss->bssid);
475 aid = le16_to_cpu(elems->aid_resp->aid);
476 @@ -3340,7 +3343,8 @@ static bool ieee80211_assoc_success(stru
478 if (!is_s1g && !elems->supp_rates) {
479 sdata_info(sdata, "no SuppRates element in AssocResp\n");
485 sdata->vif.bss_conf.aid = aid;
486 @@ -3362,7 +3366,7 @@ static bool ieee80211_assoc_success(stru
487 (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
488 (!elems->vht_cap_elem || !elems->vht_operation)))) {
489 const struct cfg80211_bss_ies *ies;
490 - struct ieee802_11_elems bss_elems;
491 + struct ieee802_11_elems *bss_elems;
494 ies = rcu_dereference(cbss->ies);
495 @@ -3373,13 +3377,17 @@ static bool ieee80211_assoc_success(stru
499 - ieee802_11_parse_elems(bss_ies->data, bss_ies->len,
502 - assoc_data->bss->bssid);
503 + bss_elems = ieee802_11_parse_elems(bss_ies->data, bss_ies->len,
504 + false, mgmt->bssid,
505 + assoc_data->bss->bssid);
511 if (assoc_data->wmm &&
512 - !elems->wmm_param && bss_elems.wmm_param) {
513 - elems->wmm_param = bss_elems.wmm_param;
514 + !elems->wmm_param && bss_elems->wmm_param) {
515 + elems->wmm_param = bss_elems->wmm_param;
517 "AP bug: WMM param missing from AssocResp\n");
519 @@ -3388,30 +3396,32 @@ static bool ieee80211_assoc_success(stru
520 * Also check if we requested HT/VHT, otherwise the AP doesn't
521 * have to include the IEs in the (re)association response.
523 - if (!elems->ht_cap_elem && bss_elems.ht_cap_elem &&
524 + if (!elems->ht_cap_elem && bss_elems->ht_cap_elem &&
525 !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
526 - elems->ht_cap_elem = bss_elems.ht_cap_elem;
527 + elems->ht_cap_elem = bss_elems->ht_cap_elem;
529 "AP bug: HT capability missing from AssocResp\n");
531 - if (!elems->ht_operation && bss_elems.ht_operation &&
532 + if (!elems->ht_operation && bss_elems->ht_operation &&
533 !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
534 - elems->ht_operation = bss_elems.ht_operation;
535 + elems->ht_operation = bss_elems->ht_operation;
537 "AP bug: HT operation missing from AssocResp\n");
539 - if (!elems->vht_cap_elem && bss_elems.vht_cap_elem &&
540 + if (!elems->vht_cap_elem && bss_elems->vht_cap_elem &&
541 !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
542 - elems->vht_cap_elem = bss_elems.vht_cap_elem;
543 + elems->vht_cap_elem = bss_elems->vht_cap_elem;
545 "AP bug: VHT capa missing from AssocResp\n");
547 - if (!elems->vht_operation && bss_elems.vht_operation &&
548 + if (!elems->vht_operation && bss_elems->vht_operation &&
549 !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
550 - elems->vht_operation = bss_elems.vht_operation;
551 + elems->vht_operation = bss_elems->vht_operation;
553 "AP bug: VHT operation missing from AssocResp\n");
560 @@ -3662,6 +3672,7 @@ static bool ieee80211_assoc_success(stru
568 @@ -3673,7 +3684,7 @@ static void ieee80211_rx_mgmt_assoc_resp
569 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
570 struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
571 u16 capab_info, status_code, aid;
572 - struct ieee802_11_elems elems;
573 + struct ieee802_11_elems *elems;
574 int ac, uapsd_queues = -1;
577 @@ -3730,14 +3741,16 @@ static void ieee80211_rx_mgmt_assoc_resp
578 fils_decrypt_assoc_resp(sdata, (u8 *)mgmt, &len, assoc_data) < 0)
581 - ieee802_11_parse_elems(pos, len - (pos - (u8 *)mgmt), false, &elems,
582 - mgmt->bssid, assoc_data->bss->bssid);
583 + elems = ieee802_11_parse_elems(pos, len - (pos - (u8 *)mgmt), false,
584 + mgmt->bssid, assoc_data->bss->bssid);
586 + goto notify_driver;
588 if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
589 - elems.timeout_int &&
590 - elems.timeout_int->type == WLAN_TIMEOUT_ASSOC_COMEBACK) {
591 + elems->timeout_int &&
592 + elems->timeout_int->type == WLAN_TIMEOUT_ASSOC_COMEBACK) {
594 - tu = le32_to_cpu(elems.timeout_int->value);
595 + tu = le32_to_cpu(elems->timeout_int->value);
596 ms = tu * 1024 / 1000;
598 "%pM rejected association temporarily; comeback duration %u TU (%u ms)\n",
599 @@ -3757,7 +3770,7 @@ static void ieee80211_rx_mgmt_assoc_resp
600 event.u.mlme.reason = status_code;
601 drv_event_callback(sdata->local, sdata, &event);
603 - if (!ieee80211_assoc_success(sdata, cbss, mgmt, len, &elems)) {
604 + if (!ieee80211_assoc_success(sdata, cbss, mgmt, len, elems)) {
605 /* oops -- internal error -- send timeout for now */
606 ieee80211_destroy_assoc_data(sdata, false, false);
607 cfg80211_assoc_timeout(sdata->dev, cbss);
608 @@ -3787,6 +3800,7 @@ static void ieee80211_rx_mgmt_assoc_resp
609 ifmgd->assoc_req_ies, ifmgd->assoc_req_ies_len);
611 drv_mgd_complete_tx(sdata->local, sdata, &info);
615 static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
616 @@ -3991,7 +4005,7 @@ static void ieee80211_rx_mgmt_beacon(str
617 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
618 struct ieee80211_mgmt *mgmt = (void *) hdr;
620 - struct ieee802_11_elems elems;
621 + struct ieee802_11_elems *elems;
622 struct ieee80211_local *local = sdata->local;
623 struct ieee80211_chanctx_conf *chanctx_conf;
624 struct ieee80211_channel *chan;
625 @@ -4037,15 +4051,16 @@ static void ieee80211_rx_mgmt_beacon(str
627 if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon &&
628 ieee80211_rx_our_beacon(bssid, ifmgd->assoc_data->bss)) {
629 - ieee802_11_parse_elems(variable,
630 - len - baselen, false, &elems,
632 - ifmgd->assoc_data->bss->bssid);
633 + elems = ieee802_11_parse_elems(variable, len - baselen, false,
635 + ifmgd->assoc_data->bss->bssid);
639 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status);
641 - if (elems.dtim_period)
642 - ifmgd->dtim_period = elems.dtim_period;
643 + if (elems->dtim_period)
644 + ifmgd->dtim_period = elems->dtim_period;
645 ifmgd->have_beacon = true;
646 ifmgd->assoc_data->need_beacon = false;
647 if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) {
648 @@ -4053,17 +4068,17 @@ static void ieee80211_rx_mgmt_beacon(str
649 le64_to_cpu(mgmt->u.beacon.timestamp);
650 sdata->vif.bss_conf.sync_device_ts =
651 rx_status->device_timestamp;
652 - sdata->vif.bss_conf.sync_dtim_count = elems.dtim_count;
653 + sdata->vif.bss_conf.sync_dtim_count = elems->dtim_count;
656 - if (elems.mbssid_config_ie)
657 + if (elems->mbssid_config_ie)
658 bss_conf->profile_periodicity =
659 - elems.mbssid_config_ie->profile_periodicity;
660 + elems->mbssid_config_ie->profile_periodicity;
662 bss_conf->profile_periodicity = 0;
664 - if (elems.ext_capab_len >= 11 &&
665 - (elems.ext_capab[10] & WLAN_EXT_CAPA11_EMA_SUPPORT))
666 + if (elems->ext_capab_len >= 11 &&
667 + (elems->ext_capab[10] & WLAN_EXT_CAPA11_EMA_SUPPORT))
668 bss_conf->ema_ap = true;
670 bss_conf->ema_ap = false;
671 @@ -4072,6 +4087,7 @@ static void ieee80211_rx_mgmt_beacon(str
672 ifmgd->assoc_data->timeout = jiffies;
673 ifmgd->assoc_data->timeout_started = true;
674 run_again(sdata, ifmgd->assoc_data->timeout);
679 @@ -4103,14 +4119,15 @@ static void ieee80211_rx_mgmt_beacon(str
681 if (!ieee80211_is_s1g_beacon(hdr->frame_control))
682 ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4);
683 - ieee802_11_parse_elems_crc(variable,
684 - len - baselen, false, &elems,
685 - care_about_ies, ncrc,
686 - mgmt->bssid, bssid);
688 + elems = ieee802_11_parse_elems_crc(variable, len - baselen,
689 + false, care_about_ies, ncrc,
690 + mgmt->bssid, bssid);
695 if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK) &&
696 - ieee80211_check_tim(elems.tim, elems.tim_len, bss_conf->aid)) {
697 + ieee80211_check_tim(elems->tim, elems->tim_len, bss_conf->aid)) {
698 if (local->hw.conf.dynamic_ps_timeout > 0) {
699 if (local->hw.conf.flags & IEEE80211_CONF_PS) {
700 local->hw.conf.flags &= ~IEEE80211_CONF_PS;
701 @@ -4180,12 +4197,12 @@ static void ieee80211_rx_mgmt_beacon(str
702 le64_to_cpu(mgmt->u.beacon.timestamp);
703 sdata->vif.bss_conf.sync_device_ts =
704 rx_status->device_timestamp;
705 - sdata->vif.bss_conf.sync_dtim_count = elems.dtim_count;
706 + sdata->vif.bss_conf.sync_dtim_count = elems->dtim_count;
709 if ((ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid) ||
710 ieee80211_is_s1g_short_beacon(mgmt->frame_control))
713 ifmgd->beacon_crc = ncrc;
714 ifmgd->beacon_crc_valid = true;
716 @@ -4193,12 +4210,12 @@ static void ieee80211_rx_mgmt_beacon(str
718 ieee80211_sta_process_chanswitch(sdata, rx_status->mactime,
719 rx_status->device_timestamp,
723 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM) &&
724 - ieee80211_sta_wmm_params(local, sdata, elems.wmm_param,
725 - elems.wmm_param_len,
726 - elems.mu_edca_param_set))
727 + ieee80211_sta_wmm_params(local, sdata, elems->wmm_param,
728 + elems->wmm_param_len,
729 + elems->mu_edca_param_set))
730 changed |= BSS_CHANGED_QOS;
733 @@ -4207,7 +4224,7 @@ static void ieee80211_rx_mgmt_beacon(str
735 if (!ifmgd->have_beacon) {
736 /* a few bogus AP send dtim_period = 0 or no TIM IE */
737 - bss_conf->dtim_period = elems.dtim_period ?: 1;
738 + bss_conf->dtim_period = elems->dtim_period ?: 1;
740 changed |= BSS_CHANGED_BEACON_INFO;
741 ifmgd->have_beacon = true;
742 @@ -4219,9 +4236,9 @@ static void ieee80211_rx_mgmt_beacon(str
743 ieee80211_recalc_ps_vif(sdata);
746 - if (elems.erp_info) {
747 + if (elems->erp_info) {
749 - erp_value = elems.erp_info[0];
750 + erp_value = elems->erp_info[0];
754 @@ -4234,12 +4251,12 @@ static void ieee80211_rx_mgmt_beacon(str
755 mutex_lock(&local->sta_mtx);
756 sta = sta_info_get(sdata, bssid);
758 - changed |= ieee80211_recalc_twt_req(sdata, sta, &elems);
759 + changed |= ieee80211_recalc_twt_req(sdata, sta, elems);
761 - if (ieee80211_config_bw(sdata, sta, elems.ht_cap_elem,
762 - elems.vht_cap_elem, elems.ht_operation,
763 - elems.vht_operation, elems.he_operation,
764 - elems.s1g_oper, bssid, &changed)) {
765 + if (ieee80211_config_bw(sdata, sta, elems->ht_cap_elem,
766 + elems->vht_cap_elem, elems->ht_operation,
767 + elems->vht_operation, elems->he_operation,
768 + elems->s1g_oper, bssid, &changed)) {
769 mutex_unlock(&local->sta_mtx);
771 "failed to follow AP %pM bandwidth change, disconnect\n",
772 @@ -4251,21 +4268,23 @@ static void ieee80211_rx_mgmt_beacon(str
773 sizeof(deauth_buf), true,
774 WLAN_REASON_DEAUTH_LEAVING,
780 - if (sta && elems.opmode_notif)
781 - ieee80211_vht_handle_opmode(sdata, sta, *elems.opmode_notif,
782 + if (sta && elems->opmode_notif)
783 + ieee80211_vht_handle_opmode(sdata, sta, *elems->opmode_notif,
785 mutex_unlock(&local->sta_mtx);
787 changed |= ieee80211_handle_pwr_constr(sdata, chan, mgmt,
788 - elems.country_elem,
789 - elems.country_elem_len,
790 - elems.pwr_constr_elem,
791 - elems.cisco_dtpc_elem);
792 + elems->country_elem,
793 + elems->country_elem_len,
794 + elems->pwr_constr_elem,
795 + elems->cisco_dtpc_elem);
797 ieee80211_bss_info_change_notify(sdata, changed);
802 void ieee80211_sta_rx_queued_ext(struct ieee80211_sub_if_data *sdata,
803 @@ -4294,7 +4313,6 @@ void ieee80211_sta_rx_queued_mgmt(struct
804 struct ieee80211_rx_status *rx_status;
805 struct ieee80211_mgmt *mgmt;
807 - struct ieee802_11_elems elems;
810 rx_status = (struct ieee80211_rx_status *) skb->cb;
811 @@ -4326,6 +4344,8 @@ void ieee80211_sta_rx_queued_mgmt(struct
813 case IEEE80211_STYPE_ACTION:
814 if (mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) {
815 + struct ieee802_11_elems *elems;
818 offsetof(struct ieee80211_mgmt,
819 u.action.u.chan_switch.variable);
820 @@ -4334,18 +4354,21 @@ void ieee80211_sta_rx_queued_mgmt(struct
823 /* CSA IE cannot be overridden, no need for BSSID */
824 - ieee802_11_parse_elems(
825 - mgmt->u.action.u.chan_switch.variable,
826 - ies_len, true, &elems, mgmt->bssid, NULL);
827 + elems = ieee802_11_parse_elems(
828 + mgmt->u.action.u.chan_switch.variable,
829 + ies_len, true, mgmt->bssid, NULL);
831 - if (elems.parse_error)
832 + if (!elems || elems->parse_error)
835 ieee80211_sta_process_chanswitch(sdata,
837 rx_status->device_timestamp,
841 } else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) {
842 + struct ieee802_11_elems *elems;
845 offsetof(struct ieee80211_mgmt,
846 u.action.u.ext_chan_switch.variable);
847 @@ -4357,21 +4380,22 @@ void ieee80211_sta_rx_queued_mgmt(struct
848 * extended CSA IE can't be overridden, no need for
851 - ieee802_11_parse_elems(
852 - mgmt->u.action.u.ext_chan_switch.variable,
853 - ies_len, true, &elems, mgmt->bssid, NULL);
854 + elems = ieee802_11_parse_elems(
855 + mgmt->u.action.u.ext_chan_switch.variable,
856 + ies_len, true, mgmt->bssid, NULL);
858 - if (elems.parse_error)
859 + if (!elems || elems->parse_error)
862 /* for the handling code pretend this was also an IE */
863 - elems.ext_chansw_ie =
864 + elems->ext_chansw_ie =
865 &mgmt->u.action.u.ext_chan_switch.data;
867 ieee80211_sta_process_chanswitch(sdata,
869 rx_status->device_timestamp,
876 --- a/net/mac80211/scan.c
877 +++ b/net/mac80211/scan.c
879 * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
880 * Copyright 2013-2015 Intel Mobile Communications GmbH
881 * Copyright 2016-2017 Intel Deutschland GmbH
882 - * Copyright (C) 2018-2020 Intel Corporation
883 + * Copyright (C) 2018-2021 Intel Corporation
886 #include <linux/if_arp.h>
887 @@ -155,7 +155,7 @@ ieee80211_bss_info_update(struct ieee802
890 struct ieee80211_sub_if_data *scan_sdata;
891 - struct ieee802_11_elems elems;
892 + struct ieee802_11_elems *elems;
896 @@ -209,8 +209,10 @@ ieee80211_bss_info_update(struct ieee802
900 - ieee802_11_parse_elems(elements, len - baselen, false, &elems,
901 - mgmt->bssid, cbss->bssid);
902 + elems = ieee802_11_parse_elems(elements, len - baselen, false,
903 + mgmt->bssid, cbss->bssid);
907 /* In case the signal is invalid update the status */
908 signal_valid = channel == cbss->channel;
909 @@ -218,15 +220,17 @@ ieee80211_bss_info_update(struct ieee802
910 rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
912 bss = (void *)cbss->priv;
913 - ieee80211_update_bss_from_elems(local, bss, &elems, rx_status, beacon);
914 + ieee80211_update_bss_from_elems(local, bss, elems, rx_status, beacon);
916 list_for_each_entry(non_tx_cbss, &cbss->nontrans_list, nontrans_list) {
917 non_tx_bss = (void *)non_tx_cbss->priv;
919 - ieee80211_update_bss_from_elems(local, non_tx_bss, &elems,
920 + ieee80211_update_bss_from_elems(local, non_tx_bss, elems,
929 --- a/net/mac80211/tdls.c
930 +++ b/net/mac80211/tdls.c
932 * Copyright 2014, Intel Corporation
933 * Copyright 2014 Intel Mobile Communications GmbH
934 * Copyright 2015 - 2016 Intel Deutschland GmbH
935 - * Copyright (C) 2019 Intel Corporation
936 + * Copyright (C) 2019, 2021 Intel Corporation
939 #include <linux/ieee80211.h>
940 @@ -1684,7 +1684,7 @@ ieee80211_process_tdls_channel_switch_re
943 struct ieee80211_local *local = sdata->local;
944 - struct ieee802_11_elems elems;
945 + struct ieee802_11_elems *elems = NULL;
946 struct sta_info *sta;
947 struct ieee80211_tdls_data *tf = (void *)skb->data;
948 bool local_initiator;
949 @@ -1718,16 +1718,20 @@ ieee80211_process_tdls_channel_switch_re
953 - ieee802_11_parse_elems(tf->u.chan_switch_resp.variable,
954 - skb->len - baselen, false, &elems,
956 - if (elems.parse_error) {
957 + elems = ieee802_11_parse_elems(tf->u.chan_switch_resp.variable,
958 + skb->len - baselen, false, NULL, NULL);
964 + if (elems->parse_error) {
965 tdls_dbg(sdata, "Invalid IEs in TDLS channel switch resp\n");
970 - if (!elems.ch_sw_timing || !elems.lnk_id) {
971 + if (!elems->ch_sw_timing || !elems->lnk_id) {
972 tdls_dbg(sdata, "TDLS channel switch resp - missing IEs\n");
975 @@ -1735,15 +1739,15 @@ ieee80211_process_tdls_channel_switch_re
977 /* validate the initiator is set correctly */
979 - !memcmp(elems.lnk_id->init_sta, sdata->vif.addr, ETH_ALEN);
980 + !memcmp(elems->lnk_id->init_sta, sdata->vif.addr, ETH_ALEN);
981 if (local_initiator == sta->sta.tdls_initiator) {
982 tdls_dbg(sdata, "TDLS chan switch invalid lnk-id initiator\n");
987 - params.switch_time = le16_to_cpu(elems.ch_sw_timing->switch_time);
988 - params.switch_timeout = le16_to_cpu(elems.ch_sw_timing->switch_timeout);
989 + params.switch_time = le16_to_cpu(elems->ch_sw_timing->switch_time);
990 + params.switch_timeout = le16_to_cpu(elems->ch_sw_timing->switch_timeout);
993 ieee80211_tdls_ch_sw_resp_tmpl_get(sta, ¶ms.ch_sw_tm_ie);
994 @@ -1763,6 +1767,7 @@ call_drv:
996 mutex_unlock(&local->sta_mtx);
997 dev_kfree_skb_any(params.tmpl_skb);
1002 @@ -1771,7 +1776,7 @@ ieee80211_process_tdls_channel_switch_re
1003 struct sk_buff *skb)
1005 struct ieee80211_local *local = sdata->local;
1006 - struct ieee802_11_elems elems;
1007 + struct ieee802_11_elems *elems;
1008 struct cfg80211_chan_def chandef;
1009 struct ieee80211_channel *chan;
1010 enum nl80211_channel_type chan_type;
1011 @@ -1831,22 +1836,27 @@ ieee80211_process_tdls_channel_switch_re
1015 - ieee802_11_parse_elems(tf->u.chan_switch_req.variable,
1016 - skb->len - baselen, false, &elems, NULL, NULL);
1017 - if (elems.parse_error) {
1018 + elems = ieee802_11_parse_elems(tf->u.chan_switch_req.variable,
1019 + skb->len - baselen, false, NULL, NULL);
1023 + if (elems->parse_error) {
1024 tdls_dbg(sdata, "Invalid IEs in TDLS channel switch req\n");
1030 - if (!elems.ch_sw_timing || !elems.lnk_id) {
1031 + if (!elems->ch_sw_timing || !elems->lnk_id) {
1032 tdls_dbg(sdata, "TDLS channel switch req - missing IEs\n");
1038 - if (!elems.sec_chan_offs) {
1039 + if (!elems->sec_chan_offs) {
1040 chan_type = NL80211_CHAN_HT20;
1042 - switch (elems.sec_chan_offs->sec_chan_offs) {
1043 + switch (elems->sec_chan_offs->sec_chan_offs) {
1044 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
1045 chan_type = NL80211_CHAN_HT40PLUS;
1047 @@ -1865,7 +1875,8 @@ ieee80211_process_tdls_channel_switch_re
1048 if (!cfg80211_reg_can_beacon_relax(sdata->local->hw.wiphy, &chandef,
1049 sdata->wdev.iftype)) {
1050 tdls_dbg(sdata, "TDLS chan switch to forbidden channel\n");
1056 mutex_lock(&local->sta_mtx);
1057 @@ -1881,7 +1892,7 @@ ieee80211_process_tdls_channel_switch_re
1059 /* validate the initiator is set correctly */
1061 - !memcmp(elems.lnk_id->init_sta, sdata->vif.addr, ETH_ALEN);
1062 + !memcmp(elems->lnk_id->init_sta, sdata->vif.addr, ETH_ALEN);
1063 if (local_initiator == sta->sta.tdls_initiator) {
1064 tdls_dbg(sdata, "TDLS chan switch invalid lnk-id initiator\n");
1066 @@ -1889,16 +1900,16 @@ ieee80211_process_tdls_channel_switch_re
1069 /* peer should have known better */
1070 - if (!sta->sta.ht_cap.ht_supported && elems.sec_chan_offs &&
1071 - elems.sec_chan_offs->sec_chan_offs) {
1072 + if (!sta->sta.ht_cap.ht_supported && elems->sec_chan_offs &&
1073 + elems->sec_chan_offs->sec_chan_offs) {
1074 tdls_dbg(sdata, "TDLS chan switch - wide chan unsupported\n");
1079 params.chandef = &chandef;
1080 - params.switch_time = le16_to_cpu(elems.ch_sw_timing->switch_time);
1081 - params.switch_timeout = le16_to_cpu(elems.ch_sw_timing->switch_timeout);
1082 + params.switch_time = le16_to_cpu(elems->ch_sw_timing->switch_time);
1083 + params.switch_timeout = le16_to_cpu(elems->ch_sw_timing->switch_timeout);
1086 ieee80211_tdls_ch_sw_resp_tmpl_get(sta,
1087 @@ -1917,6 +1928,8 @@ ieee80211_process_tdls_channel_switch_re
1089 mutex_unlock(&local->sta_mtx);
1090 dev_kfree_skb_any(params.tmpl_skb);
1096 --- a/net/mac80211/util.c
1097 +++ b/net/mac80211/util.c
1098 @@ -1399,8 +1399,8 @@ _ieee802_11_parse_elems_crc(const u8 *st
1100 static size_t ieee802_11_find_bssid_profile(const u8 *start, size_t len,
1101 struct ieee802_11_elems *elems,
1102 - u8 *transmitter_bssid,
1104 + const u8 *transmitter_bssid,
1105 + const u8 *bss_bssid,
1106 u8 *nontransmitted_profile)
1108 const struct element *elem, *sub;
1109 @@ -1465,16 +1465,20 @@ static size_t ieee802_11_find_bssid_prof
1110 return found ? profile_len : 0;
1113 -void ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
1114 - struct ieee802_11_elems *elems,
1115 - u64 filter, u32 crc, u8 *transmitter_bssid,
1117 +struct ieee802_11_elems *ieee802_11_parse_elems_crc(const u8 *start, size_t len,
1118 + bool action, u64 filter,
1120 + const u8 *transmitter_bssid,
1121 + const u8 *bss_bssid)
1123 + struct ieee802_11_elems *elems;
1124 const struct element *non_inherit = NULL;
1125 u8 *nontransmitted_profile;
1126 int nontransmitted_profile_len = 0;
1128 - memset(elems, 0, sizeof(*elems));
1129 + elems = kzalloc(sizeof(*elems), GFP_ATOMIC);
1132 elems->ie_start = start;
1133 elems->total_len = len;
1135 @@ -1521,6 +1525,8 @@ void ieee802_11_parse_elems_crc(const u8
1136 kfree(nontransmitted_profile);
1143 void ieee80211_regulatory_limit_wmm_params(struct ieee80211_sub_if_data *sdata,