]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/linux/linux-5.15-wifi-security-patches-12.patch
dnsdist: Update to 1.7.3
[people/pmueller/ipfire-2.x.git] / src / patches / linux / linux-5.15-wifi-security-patches-12.patch
CommitLineData
ee2e7db9
PM
1From fee48f3bdd7516bb63da507213916227cf147211 Mon Sep 17 00:00:00 2001
2From: Johannes Berg <johannes.berg@intel.com>
3Date: Thu, 13 Oct 2022 20:15:59 +0200
4Subject: [PATCH] mac80211: always allocate struct ieee802_11_elems
5
6As the 802.11 spec evolves, we need to parse more and more
7elements. This is causing the struct to grow, and we can no
8longer get away with putting it on the stack.
9
10Change the API to always dynamically allocate and return an
11allocated pointer that must be kfree()d later.
12
13As an alternative, I contemplated a scheme whereby we'd say
14in the code which elements we needed, e.g.
15
16 DECLARE_ELEMENT_PARSER(elems,
17 SUPPORTED_CHANNELS,
18 CHANNEL_SWITCH,
19 EXT(KEY_DELIVERY));
20
21 ieee802_11_parse_elems(..., &elems, ...);
22
23and while I think this is possible and will save us a lot
24since most individual places only care about a small subset
25of the elements, it ended up being a bit more work since a
26lot of places do the parsing and then pass the struct to
27other functions, sometimes with multiple levels.
28
29Link: https://lore.kernel.org/r/20210920154009.26caff6b5998.I05ae58768e990e611aee8eca8abefd9d7bc15e05@changeid
30Signed-off-by: Johannes Berg <johannes.berg@intel.com>
31Cc: Felix Fietkau <nbd@nbd.name>
32Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
33---
34 net/mac80211/agg-rx.c | 11 +--
35 net/mac80211/ibss.c | 25 +++---
36 net/mac80211/ieee80211_i.h | 22 ++---
37 net/mac80211/mesh.c | 85 ++++++++++--------
38 net/mac80211/mesh_hwmp.c | 44 +++++-----
39 net/mac80211/mesh_plink.c | 11 +--
40 net/mac80211/mlme.c | 176 +++++++++++++++++++++----------------
41 net/mac80211/scan.c | 16 ++--
42 net/mac80211/tdls.c | 63 +++++++------
43 net/mac80211/util.c | 20 +++--
44 10 files changed, 272 insertions(+), 201 deletions(-)
45
46diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
47index e43176794149..ffa4f31f6c2b 100644
48--- a/net/mac80211/agg-rx.c
49+++ b/net/mac80211/agg-rx.c
50@@ -478,7 +478,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
51 size_t len)
52 {
53 u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num;
54- struct ieee802_11_elems elems = { };
55+ struct ieee802_11_elems *elems = NULL;
56 u8 dialog_token;
57 int ies_len;
58
59@@ -496,16 +496,17 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
60 ies_len = len - offsetof(struct ieee80211_mgmt,
61 u.action.u.addba_req.variable);
62 if (ies_len) {
63- ieee802_11_parse_elems(mgmt->u.action.u.addba_req.variable,
64- ies_len, true, &elems, mgmt->bssid, NULL);
65- if (elems.parse_error)
66+ elems = ieee802_11_parse_elems(mgmt->u.action.u.addba_req.variable,
67+ ies_len, true, mgmt->bssid, NULL);
68+ if (!elems || elems->parse_error)
69 return;
70 }
71
72 __ieee80211_start_rx_ba_session(sta, dialog_token, timeout,
73 start_seq_num, ba_policy, tid,
74 buf_size, true, false,
75- elems.addba_ext_ie);
76+ elems ? elems->addba_ext_ie : NULL);
77+ kfree(elems);
78 }
79
80 void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif,
81diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
82index 1e133ca58e78..4b721b48f86a 100644
83--- a/net/mac80211/ibss.c
84+++ b/net/mac80211/ibss.c
85@@ -9,7 +9,7 @@
86 * Copyright 2009, Johannes Berg <johannes@sipsolutions.net>
87 * Copyright 2013-2014 Intel Mobile Communications GmbH
88 * Copyright(c) 2016 Intel Deutschland GmbH
89- * Copyright(c) 2018-2020 Intel Corporation
90+ * Copyright(c) 2018-2021 Intel Corporation
91 */
92
93 #include <linux/delay.h>
94@@ -1593,7 +1593,7 @@ void ieee80211_rx_mgmt_probe_beacon(struct ieee80211_sub_if_data *sdata,
95 struct ieee80211_rx_status *rx_status)
96 {
97 size_t baselen;
98- struct ieee802_11_elems elems;
99+ struct ieee802_11_elems *elems;
100
101 BUILD_BUG_ON(offsetof(typeof(mgmt->u.probe_resp), variable) !=
102 offsetof(typeof(mgmt->u.beacon), variable));
103@@ -1606,10 +1606,14 @@ void ieee80211_rx_mgmt_probe_beacon(struct ieee80211_sub_if_data *sdata,
104 if (baselen > len)
105 return;
106
107- ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
108- false, &elems, mgmt->bssid, NULL);
109+ elems = ieee802_11_parse_elems(mgmt->u.probe_resp.variable,
110+ len - baselen, false,
111+ mgmt->bssid, NULL);
112
113- ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
114+ if (elems) {
115+ ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, elems);
116+ kfree(elems);
117+ }
118 }
119
120 void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
121@@ -1618,7 +1622,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
122 struct ieee80211_rx_status *rx_status;
123 struct ieee80211_mgmt *mgmt;
124 u16 fc;
125- struct ieee802_11_elems elems;
126+ struct ieee802_11_elems *elems;
127 int ies_len;
128
129 rx_status = IEEE80211_SKB_RXCB(skb);
130@@ -1655,15 +1659,16 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
131 if (ies_len < 0)
132 break;
133
134- ieee802_11_parse_elems(
135+ elems = ieee802_11_parse_elems(
136 mgmt->u.action.u.chan_switch.variable,
137- ies_len, true, &elems, mgmt->bssid, NULL);
138+ ies_len, true, mgmt->bssid, NULL);
139
140- if (elems.parse_error)
141+ if (!elems || elems->parse_error)
142 break;
143
144 ieee80211_rx_mgmt_spectrum_mgmt(sdata, mgmt, skb->len,
145- rx_status, &elems);
146+ rx_status, elems);
147+ kfree(elems);
148 break;
149 }
150 }
151diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
152index c5f0ff805010..3633e49239c7 100644
153--- a/net/mac80211/ieee80211_i.h
154+++ b/net/mac80211/ieee80211_i.h
155@@ -2217,18 +2217,18 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
156 ieee80211_tx_skb_tid(sdata, skb, 7);
157 }
158
159-void ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
160- struct ieee802_11_elems *elems,
161- u64 filter, u32 crc, u8 *transmitter_bssid,
162- u8 *bss_bssid);
163-static inline void ieee802_11_parse_elems(const u8 *start, size_t len,
164- bool action,
165- struct ieee802_11_elems *elems,
166- u8 *transmitter_bssid,
167- u8 *bss_bssid)
168+struct ieee802_11_elems *ieee802_11_parse_elems_crc(const u8 *start, size_t len,
169+ bool action,
170+ u64 filter, u32 crc,
171+ const u8 *transmitter_bssid,
172+ const u8 *bss_bssid);
173+static inline struct ieee802_11_elems *
174+ieee802_11_parse_elems(const u8 *start, size_t len, bool action,
175+ const u8 *transmitter_bssid,
176+ const u8 *bss_bssid)
177 {
178- ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0,
179- transmitter_bssid, bss_bssid);
180+ return ieee802_11_parse_elems_crc(start, len, action, 0, 0,
181+ transmitter_bssid, bss_bssid);
182 }
183
184
185diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
186index 9f6414a68d71..6847fdf93439 100644
187--- a/net/mac80211/mesh.c
188+++ b/net/mac80211/mesh.c
189@@ -1247,7 +1247,7 @@ ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata,
190 struct sk_buff *presp;
191 struct beacon_data *bcn;
192 struct ieee80211_mgmt *hdr;
193- struct ieee802_11_elems elems;
194+ struct ieee802_11_elems *elems;
195 size_t baselen;
196 u8 *pos;
197
198@@ -1256,22 +1256,24 @@ ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata,
199 if (baselen > len)
200 return;
201
202- ieee802_11_parse_elems(pos, len - baselen, false, &elems, mgmt->bssid,
203- NULL);
204-
205- if (!elems.mesh_id)
206+ elems = ieee802_11_parse_elems(pos, len - baselen, false, mgmt->bssid,
207+ NULL);
208+ if (!elems)
209 return;
210
211+ if (!elems->mesh_id)
212+ goto free;
213+
214 /* 802.11-2012 10.1.4.3.2 */
215 if ((!ether_addr_equal(mgmt->da, sdata->vif.addr) &&
216 !is_broadcast_ether_addr(mgmt->da)) ||
217- elems.ssid_len != 0)
218- return;
219+ elems->ssid_len != 0)
220+ goto free;
221
222- if (elems.mesh_id_len != 0 &&
223- (elems.mesh_id_len != ifmsh->mesh_id_len ||
224- memcmp(elems.mesh_id, ifmsh->mesh_id, ifmsh->mesh_id_len)))
225- return;
226+ if (elems->mesh_id_len != 0 &&
227+ (elems->mesh_id_len != ifmsh->mesh_id_len ||
228+ memcmp(elems->mesh_id, ifmsh->mesh_id, ifmsh->mesh_id_len)))
229+ goto free;
230
231 rcu_read_lock();
232 bcn = rcu_dereference(ifmsh->beacon);
233@@ -1295,6 +1297,8 @@ ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata,
234 ieee80211_tx_skb(sdata, presp);
235 out:
236 rcu_read_unlock();
237+free:
238+ kfree(elems);
239 }
240
241 static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
242@@ -1305,7 +1309,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
243 {
244 struct ieee80211_local *local = sdata->local;
245 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
246- struct ieee802_11_elems elems;
247+ struct ieee802_11_elems *elems;
248 struct ieee80211_channel *channel;
249 size_t baselen;
250 int freq;
251@@ -1320,42 +1324,47 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
252 if (baselen > len)
253 return;
254
255- ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
256- false, &elems, mgmt->bssid, NULL);
257+ elems = ieee802_11_parse_elems(mgmt->u.probe_resp.variable,
258+ len - baselen,
259+ false, mgmt->bssid, NULL);
260+ if (!elems)
261+ return;
262
263 /* ignore non-mesh or secure / unsecure mismatch */
264- if ((!elems.mesh_id || !elems.mesh_config) ||
265- (elems.rsn && sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) ||
266- (!elems.rsn && sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE))
267- return;
268+ if ((!elems->mesh_id || !elems->mesh_config) ||
269+ (elems->rsn && sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) ||
270+ (!elems->rsn && sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE))
271+ goto free;
272
273- if (elems.ds_params)
274- freq = ieee80211_channel_to_frequency(elems.ds_params[0], band);
275+ if (elems->ds_params)
276+ freq = ieee80211_channel_to_frequency(elems->ds_params[0], band);
277 else
278 freq = rx_status->freq;
279
280 channel = ieee80211_get_channel(local->hw.wiphy, freq);
281
282 if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
283- return;
284+ goto free;
285
286- if (mesh_matches_local(sdata, &elems)) {
287+ if (mesh_matches_local(sdata, elems)) {
288 mpl_dbg(sdata, "rssi_threshold=%d,rx_status->signal=%d\n",
289 sdata->u.mesh.mshcfg.rssi_threshold, rx_status->signal);
290 if (!sdata->u.mesh.user_mpm ||
291 sdata->u.mesh.mshcfg.rssi_threshold == 0 ||
292 sdata->u.mesh.mshcfg.rssi_threshold < rx_status->signal)
293- mesh_neighbour_update(sdata, mgmt->sa, &elems,
294+ mesh_neighbour_update(sdata, mgmt->sa, elems,
295 rx_status);
296
297 if (ifmsh->csa_role != IEEE80211_MESH_CSA_ROLE_INIT &&
298 !sdata->vif.csa_active)
299- ieee80211_mesh_process_chnswitch(sdata, &elems, true);
300+ ieee80211_mesh_process_chnswitch(sdata, elems, true);
301 }
302
303 if (ifmsh->sync_ops)
304 ifmsh->sync_ops->rx_bcn_presp(sdata, stype, mgmt, len,
305- elems.mesh_config, rx_status);
306+ elems->mesh_config, rx_status);
307+free:
308+ kfree(elems);
309 }
310
311 int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata)
312@@ -1447,7 +1456,7 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
313 struct ieee80211_mgmt *mgmt, size_t len)
314 {
315 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
316- struct ieee802_11_elems elems;
317+ struct ieee802_11_elems *elems;
318 u16 pre_value;
319 bool fwd_csa = true;
320 size_t baselen;
321@@ -1460,33 +1469,37 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
322 pos = mgmt->u.action.u.chan_switch.variable;
323 baselen = offsetof(struct ieee80211_mgmt,
324 u.action.u.chan_switch.variable);
325- ieee802_11_parse_elems(pos, len - baselen, true, &elems,
326- mgmt->bssid, NULL);
327-
328- if (!mesh_matches_local(sdata, &elems))
329+ elems = ieee802_11_parse_elems(pos, len - baselen, true,
330+ mgmt->bssid, NULL);
331+ if (!elems)
332 return;
333
334- ifmsh->chsw_ttl = elems.mesh_chansw_params_ie->mesh_ttl;
335+ if (!mesh_matches_local(sdata, elems))
336+ goto free;
337+
338+ ifmsh->chsw_ttl = elems->mesh_chansw_params_ie->mesh_ttl;
339 if (!--ifmsh->chsw_ttl)
340 fwd_csa = false;
341
342- pre_value = le16_to_cpu(elems.mesh_chansw_params_ie->mesh_pre_value);
343+ pre_value = le16_to_cpu(elems->mesh_chansw_params_ie->mesh_pre_value);
344 if (ifmsh->pre_value >= pre_value)
345- return;
346+ goto free;
347
348 ifmsh->pre_value = pre_value;
349
350 if (!sdata->vif.csa_active &&
351- !ieee80211_mesh_process_chnswitch(sdata, &elems, false)) {
352+ !ieee80211_mesh_process_chnswitch(sdata, elems, false)) {
353 mcsa_dbg(sdata, "Failed to process CSA action frame");
354- return;
355+ goto free;
356 }
357
358 /* forward or re-broadcast the CSA frame */
359 if (fwd_csa) {
360- if (mesh_fwd_csa_frame(sdata, mgmt, len, &elems) < 0)
361+ if (mesh_fwd_csa_frame(sdata, mgmt, len, elems) < 0)
362 mcsa_dbg(sdata, "Failed to forward the CSA frame");
363 }
364+free:
365+ kfree(elems);
366 }
367
368 static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata,
369diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
370index a05b615deb51..44a6fdb6efbd 100644
371--- a/net/mac80211/mesh_hwmp.c
372+++ b/net/mac80211/mesh_hwmp.c
373@@ -1,7 +1,7 @@
374 // SPDX-License-Identifier: GPL-2.0-only
375 /*
376 * Copyright (c) 2008, 2009 open80211s Ltd.
377- * Copyright (C) 2019 Intel Corporation
378+ * Copyright (C) 2019, 2021 Intel Corporation
379 * Author: Luis Carlos Cobo <luisca@cozybit.com>
380 */
381
382@@ -908,7 +908,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
383 void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
384 struct ieee80211_mgmt *mgmt, size_t len)
385 {
386- struct ieee802_11_elems elems;
387+ struct ieee802_11_elems *elems;
388 size_t baselen;
389 u32 path_metric;
390 struct sta_info *sta;
391@@ -926,37 +926,41 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
392 rcu_read_unlock();
393
394 baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt;
395- ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
396- len - baselen, false, &elems, mgmt->bssid, NULL);
397+ elems = ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
398+ len - baselen, false, mgmt->bssid, NULL);
399+ if (!elems)
400+ return;
401
402- if (elems.preq) {
403- if (elems.preq_len != 37)
404+ if (elems->preq) {
405+ if (elems->preq_len != 37)
406 /* Right now we support just 1 destination and no AE */
407- return;
408- path_metric = hwmp_route_info_get(sdata, mgmt, elems.preq,
409+ goto free;
410+ path_metric = hwmp_route_info_get(sdata, mgmt, elems->preq,
411 MPATH_PREQ);
412 if (path_metric)
413- hwmp_preq_frame_process(sdata, mgmt, elems.preq,
414+ hwmp_preq_frame_process(sdata, mgmt, elems->preq,
415 path_metric);
416 }
417- if (elems.prep) {
418- if (elems.prep_len != 31)
419+ if (elems->prep) {
420+ if (elems->prep_len != 31)
421 /* Right now we support no AE */
422- return;
423- path_metric = hwmp_route_info_get(sdata, mgmt, elems.prep,
424+ goto free;
425+ path_metric = hwmp_route_info_get(sdata, mgmt, elems->prep,
426 MPATH_PREP);
427 if (path_metric)
428- hwmp_prep_frame_process(sdata, mgmt, elems.prep,
429+ hwmp_prep_frame_process(sdata, mgmt, elems->prep,
430 path_metric);
431 }
432- if (elems.perr) {
433- if (elems.perr_len != 15)
434+ if (elems->perr) {
435+ if (elems->perr_len != 15)
436 /* Right now we support only one destination per PERR */
437- return;
438- hwmp_perr_frame_process(sdata, mgmt, elems.perr);
439+ goto free;
440+ hwmp_perr_frame_process(sdata, mgmt, elems->perr);
441 }
442- if (elems.rann)
443- hwmp_rann_frame_process(sdata, mgmt, elems.rann);
444+ if (elems->rann)
445+ hwmp_rann_frame_process(sdata, mgmt, elems->rann);
446+free:
447+ kfree(elems);
448 }
449
450 /**
451diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
452index a6915847d78a..a829470dd59e 100644
453--- a/net/mac80211/mesh_plink.c
454+++ b/net/mac80211/mesh_plink.c
455@@ -1,7 +1,7 @@
456 // SPDX-License-Identifier: GPL-2.0-only
457 /*
458 * Copyright (c) 2008, 2009 open80211s Ltd.
459- * Copyright (C) 2019 Intel Corporation
460+ * Copyright (C) 2019, 2021 Intel Corporation
461 * Author: Luis Carlos Cobo <luisca@cozybit.com>
462 */
463 #include <linux/gfp.h>
464@@ -1200,7 +1200,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
465 struct ieee80211_mgmt *mgmt, size_t len,
466 struct ieee80211_rx_status *rx_status)
467 {
468- struct ieee802_11_elems elems;
469+ struct ieee802_11_elems *elems;
470 size_t baselen;
471 u8 *baseaddr;
472
473@@ -1228,7 +1228,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
474 if (baselen > len)
475 return;
476 }
477- ieee802_11_parse_elems(baseaddr, len - baselen, true, &elems,
478- mgmt->bssid, NULL);
479- mesh_process_plink_frame(sdata, mgmt, &elems, rx_status);
480+ elems = ieee802_11_parse_elems(baseaddr, len - baselen, true,
481+ mgmt->bssid, NULL);
482+ mesh_process_plink_frame(sdata, mgmt, elems, rx_status);
483+ kfree(elems);
484 }
485diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
486index 548cd14c5503..45efa1d1c550 100644
487--- a/net/mac80211/mlme.c
488+++ b/net/mac80211/mlme.c
489@@ -3317,8 +3317,11 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
490 aid = 0; /* TODO */
491 }
492 capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
493- ieee802_11_parse_elems(pos, len - (pos - (u8 *)mgmt), false, elems,
494- mgmt->bssid, assoc_data->bss->bssid);
495+ elems = ieee802_11_parse_elems(pos, len - (pos - (u8 *)mgmt), false,
496+ mgmt->bssid, assoc_data->bss->bssid);
497+
498+ if (!elems)
499+ return false;
500
501 if (elems->aid_resp)
502 aid = le16_to_cpu(elems->aid_resp->aid);
503@@ -3340,7 +3343,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
504
505 if (!is_s1g && !elems->supp_rates) {
506 sdata_info(sdata, "no SuppRates element in AssocResp\n");
507- return false;
508+ ret = false;
509+ goto out;
510 }
511
512 sdata->vif.bss_conf.aid = aid;
513@@ -3362,7 +3366,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
514 (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
515 (!elems->vht_cap_elem || !elems->vht_operation)))) {
516 const struct cfg80211_bss_ies *ies;
517- struct ieee802_11_elems bss_elems;
518+ struct ieee802_11_elems *bss_elems;
519
520 rcu_read_lock();
521 ies = rcu_dereference(cbss->ies);
522@@ -3373,13 +3377,17 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
523 if (!bss_ies)
524 return false;
525
526- ieee802_11_parse_elems(bss_ies->data, bss_ies->len,
527- false, &bss_elems,
528- mgmt->bssid,
529- assoc_data->bss->bssid);
530+ bss_elems = ieee802_11_parse_elems(bss_ies->data, bss_ies->len,
531+ false, mgmt->bssid,
532+ assoc_data->bss->bssid);
533+ if (!bss_elems) {
534+ ret = false;
535+ goto out;
536+ }
537+
538 if (assoc_data->wmm &&
539- !elems->wmm_param && bss_elems.wmm_param) {
540- elems->wmm_param = bss_elems.wmm_param;
541+ !elems->wmm_param && bss_elems->wmm_param) {
542+ elems->wmm_param = bss_elems->wmm_param;
543 sdata_info(sdata,
544 "AP bug: WMM param missing from AssocResp\n");
545 }
546@@ -3388,30 +3396,32 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
547 * Also check if we requested HT/VHT, otherwise the AP doesn't
548 * have to include the IEs in the (re)association response.
549 */
550- if (!elems->ht_cap_elem && bss_elems.ht_cap_elem &&
551+ if (!elems->ht_cap_elem && bss_elems->ht_cap_elem &&
552 !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
553- elems->ht_cap_elem = bss_elems.ht_cap_elem;
554+ elems->ht_cap_elem = bss_elems->ht_cap_elem;
555 sdata_info(sdata,
556 "AP bug: HT capability missing from AssocResp\n");
557 }
558- if (!elems->ht_operation && bss_elems.ht_operation &&
559+ if (!elems->ht_operation && bss_elems->ht_operation &&
560 !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
561- elems->ht_operation = bss_elems.ht_operation;
562+ elems->ht_operation = bss_elems->ht_operation;
563 sdata_info(sdata,
564 "AP bug: HT operation missing from AssocResp\n");
565 }
566- if (!elems->vht_cap_elem && bss_elems.vht_cap_elem &&
567+ if (!elems->vht_cap_elem && bss_elems->vht_cap_elem &&
568 !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
569- elems->vht_cap_elem = bss_elems.vht_cap_elem;
570+ elems->vht_cap_elem = bss_elems->vht_cap_elem;
571 sdata_info(sdata,
572 "AP bug: VHT capa missing from AssocResp\n");
573 }
574- if (!elems->vht_operation && bss_elems.vht_operation &&
575+ if (!elems->vht_operation && bss_elems->vht_operation &&
576 !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
577- elems->vht_operation = bss_elems.vht_operation;
578+ elems->vht_operation = bss_elems->vht_operation;
579 sdata_info(sdata,
580 "AP bug: VHT operation missing from AssocResp\n");
581 }
582+
583+ kfree(bss_elems);
584 }
585
586 /*
587@@ -3662,6 +3672,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
588
589 ret = true;
590 out:
591+ kfree(elems);
592 kfree(bss_ies);
593 return ret;
594 }
595@@ -3673,7 +3684,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
596 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
597 struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
598 u16 capab_info, status_code, aid;
599- struct ieee802_11_elems elems;
600+ struct ieee802_11_elems *elems;
601 int ac, uapsd_queues = -1;
602 u8 *pos;
603 bool reassoc;
604@@ -3730,14 +3741,16 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
605 fils_decrypt_assoc_resp(sdata, (u8 *)mgmt, &len, assoc_data) < 0)
606 return;
607
608- ieee802_11_parse_elems(pos, len - (pos - (u8 *)mgmt), false, &elems,
609- mgmt->bssid, assoc_data->bss->bssid);
610+ elems = ieee802_11_parse_elems(pos, len - (pos - (u8 *)mgmt), false,
611+ mgmt->bssid, assoc_data->bss->bssid);
612+ if (!elems)
613+ goto notify_driver;
614
615 if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
616- elems.timeout_int &&
617- elems.timeout_int->type == WLAN_TIMEOUT_ASSOC_COMEBACK) {
618+ elems->timeout_int &&
619+ elems->timeout_int->type == WLAN_TIMEOUT_ASSOC_COMEBACK) {
620 u32 tu, ms;
621- tu = le32_to_cpu(elems.timeout_int->value);
622+ tu = le32_to_cpu(elems->timeout_int->value);
623 ms = tu * 1024 / 1000;
624 sdata_info(sdata,
625 "%pM rejected association temporarily; comeback duration %u TU (%u ms)\n",
626@@ -3757,7 +3770,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
627 event.u.mlme.reason = status_code;
628 drv_event_callback(sdata->local, sdata, &event);
629 } else {
630- if (!ieee80211_assoc_success(sdata, cbss, mgmt, len, &elems)) {
631+ if (!ieee80211_assoc_success(sdata, cbss, mgmt, len, elems)) {
632 /* oops -- internal error -- send timeout for now */
633 ieee80211_destroy_assoc_data(sdata, false, false);
634 cfg80211_assoc_timeout(sdata->dev, cbss);
635@@ -3787,6 +3800,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
636 ifmgd->assoc_req_ies, ifmgd->assoc_req_ies_len);
637 notify_driver:
638 drv_mgd_complete_tx(sdata->local, sdata, &info);
639+ kfree(elems);
640 }
641
642 static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
643@@ -3991,7 +4005,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
644 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
645 struct ieee80211_mgmt *mgmt = (void *) hdr;
646 size_t baselen;
647- struct ieee802_11_elems elems;
648+ struct ieee802_11_elems *elems;
649 struct ieee80211_local *local = sdata->local;
650 struct ieee80211_chanctx_conf *chanctx_conf;
651 struct ieee80211_channel *chan;
652@@ -4037,15 +4051,16 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
653
654 if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon &&
655 ieee80211_rx_our_beacon(bssid, ifmgd->assoc_data->bss)) {
656- ieee802_11_parse_elems(variable,
657- len - baselen, false, &elems,
658- bssid,
659- ifmgd->assoc_data->bss->bssid);
660+ elems = ieee802_11_parse_elems(variable, len - baselen, false,
661+ bssid,
662+ ifmgd->assoc_data->bss->bssid);
663+ if (!elems)
664+ return;
665
666 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status);
667
668- if (elems.dtim_period)
669- ifmgd->dtim_period = elems.dtim_period;
670+ if (elems->dtim_period)
671+ ifmgd->dtim_period = elems->dtim_period;
672 ifmgd->have_beacon = true;
673 ifmgd->assoc_data->need_beacon = false;
674 if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) {
675@@ -4053,17 +4068,17 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
676 le64_to_cpu(mgmt->u.beacon.timestamp);
677 sdata->vif.bss_conf.sync_device_ts =
678 rx_status->device_timestamp;
679- sdata->vif.bss_conf.sync_dtim_count = elems.dtim_count;
680+ sdata->vif.bss_conf.sync_dtim_count = elems->dtim_count;
681 }
682
683- if (elems.mbssid_config_ie)
684+ if (elems->mbssid_config_ie)
685 bss_conf->profile_periodicity =
686- elems.mbssid_config_ie->profile_periodicity;
687+ elems->mbssid_config_ie->profile_periodicity;
688 else
689 bss_conf->profile_periodicity = 0;
690
691- if (elems.ext_capab_len >= 11 &&
692- (elems.ext_capab[10] & WLAN_EXT_CAPA11_EMA_SUPPORT))
693+ if (elems->ext_capab_len >= 11 &&
694+ (elems->ext_capab[10] & WLAN_EXT_CAPA11_EMA_SUPPORT))
695 bss_conf->ema_ap = true;
696 else
697 bss_conf->ema_ap = false;
698@@ -4072,6 +4087,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
699 ifmgd->assoc_data->timeout = jiffies;
700 ifmgd->assoc_data->timeout_started = true;
701 run_again(sdata, ifmgd->assoc_data->timeout);
702+ kfree(elems);
703 return;
704 }
705
706@@ -4103,14 +4119,15 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
707 */
708 if (!ieee80211_is_s1g_beacon(hdr->frame_control))
709 ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4);
710- ieee802_11_parse_elems_crc(variable,
711- len - baselen, false, &elems,
712- care_about_ies, ncrc,
713- mgmt->bssid, bssid);
714- ncrc = elems.crc;
715+ elems = ieee802_11_parse_elems_crc(variable, len - baselen,
716+ false, care_about_ies, ncrc,
717+ mgmt->bssid, bssid);
718+ if (!elems)
719+ return;
720+ ncrc = elems->crc;
721
722 if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK) &&
723- ieee80211_check_tim(elems.tim, elems.tim_len, bss_conf->aid)) {
724+ ieee80211_check_tim(elems->tim, elems->tim_len, bss_conf->aid)) {
725 if (local->hw.conf.dynamic_ps_timeout > 0) {
726 if (local->hw.conf.flags & IEEE80211_CONF_PS) {
727 local->hw.conf.flags &= ~IEEE80211_CONF_PS;
728@@ -4180,12 +4197,12 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
729 le64_to_cpu(mgmt->u.beacon.timestamp);
730 sdata->vif.bss_conf.sync_device_ts =
731 rx_status->device_timestamp;
732- sdata->vif.bss_conf.sync_dtim_count = elems.dtim_count;
733+ sdata->vif.bss_conf.sync_dtim_count = elems->dtim_count;
734 }
735
736 if ((ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid) ||
737 ieee80211_is_s1g_short_beacon(mgmt->frame_control))
738- return;
739+ goto free;
740 ifmgd->beacon_crc = ncrc;
741 ifmgd->beacon_crc_valid = true;
742
743@@ -4193,12 +4210,12 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
744
745 ieee80211_sta_process_chanswitch(sdata, rx_status->mactime,
746 rx_status->device_timestamp,
747- &elems, true);
748+ elems, true);
749
750 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM) &&
751- ieee80211_sta_wmm_params(local, sdata, elems.wmm_param,
752- elems.wmm_param_len,
753- elems.mu_edca_param_set))
754+ ieee80211_sta_wmm_params(local, sdata, elems->wmm_param,
755+ elems->wmm_param_len,
756+ elems->mu_edca_param_set))
757 changed |= BSS_CHANGED_QOS;
758
759 /*
760@@ -4207,7 +4224,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
761 */
762 if (!ifmgd->have_beacon) {
763 /* a few bogus AP send dtim_period = 0 or no TIM IE */
764- bss_conf->dtim_period = elems.dtim_period ?: 1;
765+ bss_conf->dtim_period = elems->dtim_period ?: 1;
766
767 changed |= BSS_CHANGED_BEACON_INFO;
768 ifmgd->have_beacon = true;
769@@ -4219,9 +4236,9 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
770 ieee80211_recalc_ps_vif(sdata);
771 }
772
773- if (elems.erp_info) {
774+ if (elems->erp_info) {
775 erp_valid = true;
776- erp_value = elems.erp_info[0];
777+ erp_value = elems->erp_info[0];
778 } else {
779 erp_valid = false;
780 }
781@@ -4234,12 +4251,12 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
782 mutex_lock(&local->sta_mtx);
783 sta = sta_info_get(sdata, bssid);
784
785- changed |= ieee80211_recalc_twt_req(sdata, sta, &elems);
786+ changed |= ieee80211_recalc_twt_req(sdata, sta, elems);
787
788- if (ieee80211_config_bw(sdata, sta, elems.ht_cap_elem,
789- elems.vht_cap_elem, elems.ht_operation,
790- elems.vht_operation, elems.he_operation,
791- elems.s1g_oper, bssid, &changed)) {
792+ if (ieee80211_config_bw(sdata, sta, elems->ht_cap_elem,
793+ elems->vht_cap_elem, elems->ht_operation,
794+ elems->vht_operation, elems->he_operation,
795+ elems->s1g_oper, bssid, &changed)) {
796 mutex_unlock(&local->sta_mtx);
797 sdata_info(sdata,
798 "failed to follow AP %pM bandwidth change, disconnect\n",
799@@ -4251,21 +4268,23 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
800 sizeof(deauth_buf), true,
801 WLAN_REASON_DEAUTH_LEAVING,
802 false);
803- return;
804+ goto free;
805 }
806
807- if (sta && elems.opmode_notif)
808- ieee80211_vht_handle_opmode(sdata, sta, *elems.opmode_notif,
809+ if (sta && elems->opmode_notif)
810+ ieee80211_vht_handle_opmode(sdata, sta, *elems->opmode_notif,
811 rx_status->band);
812 mutex_unlock(&local->sta_mtx);
813
814 changed |= ieee80211_handle_pwr_constr(sdata, chan, mgmt,
815- elems.country_elem,
816- elems.country_elem_len,
817- elems.pwr_constr_elem,
818- elems.cisco_dtpc_elem);
819+ elems->country_elem,
820+ elems->country_elem_len,
821+ elems->pwr_constr_elem,
822+ elems->cisco_dtpc_elem);
823
824 ieee80211_bss_info_change_notify(sdata, changed);
825+free:
826+ kfree(elems);
827 }
828
829 void ieee80211_sta_rx_queued_ext(struct ieee80211_sub_if_data *sdata,
830@@ -4294,7 +4313,6 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
831 struct ieee80211_rx_status *rx_status;
832 struct ieee80211_mgmt *mgmt;
833 u16 fc;
834- struct ieee802_11_elems elems;
835 int ies_len;
836
837 rx_status = (struct ieee80211_rx_status *) skb->cb;
838@@ -4326,6 +4344,8 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
839 break;
840 case IEEE80211_STYPE_ACTION:
841 if (mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) {
842+ struct ieee802_11_elems *elems;
843+
844 ies_len = skb->len -
845 offsetof(struct ieee80211_mgmt,
846 u.action.u.chan_switch.variable);
847@@ -4334,18 +4354,21 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
848 break;
849
850 /* CSA IE cannot be overridden, no need for BSSID */
851- ieee802_11_parse_elems(
852- mgmt->u.action.u.chan_switch.variable,
853- ies_len, true, &elems, mgmt->bssid, NULL);
854+ elems = ieee802_11_parse_elems(
855+ mgmt->u.action.u.chan_switch.variable,
856+ ies_len, true, mgmt->bssid, NULL);
857
858- if (elems.parse_error)
859+ if (!elems || elems->parse_error)
860 break;
861
862 ieee80211_sta_process_chanswitch(sdata,
863 rx_status->mactime,
864 rx_status->device_timestamp,
865- &elems, false);
866+ elems, false);
867+ kfree(elems);
868 } else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) {
869+ struct ieee802_11_elems *elems;
870+
871 ies_len = skb->len -
872 offsetof(struct ieee80211_mgmt,
873 u.action.u.ext_chan_switch.variable);
874@@ -4357,21 +4380,22 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
875 * extended CSA IE can't be overridden, no need for
876 * BSSID
877 */
878- ieee802_11_parse_elems(
879- mgmt->u.action.u.ext_chan_switch.variable,
880- ies_len, true, &elems, mgmt->bssid, NULL);
881+ elems = ieee802_11_parse_elems(
882+ mgmt->u.action.u.ext_chan_switch.variable,
883+ ies_len, true, mgmt->bssid, NULL);
884
885- if (elems.parse_error)
886+ if (!elems || elems->parse_error)
887 break;
888
889 /* for the handling code pretend this was also an IE */
890- elems.ext_chansw_ie =
891+ elems->ext_chansw_ie =
892 &mgmt->u.action.u.ext_chan_switch.data;
893
894 ieee80211_sta_process_chanswitch(sdata,
895 rx_status->mactime,
896 rx_status->device_timestamp,
897- &elems, false);
898+ elems, false);
899+ kfree(elems);
900 }
901 break;
902 }
903diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
904index d6afaacaf7ef..e692a2487eb5 100644
905--- a/net/mac80211/scan.c
906+++ b/net/mac80211/scan.c
907@@ -9,7 +9,7 @@
908 * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
909 * Copyright 2013-2015 Intel Mobile Communications GmbH
910 * Copyright 2016-2017 Intel Deutschland GmbH
911- * Copyright (C) 2018-2020 Intel Corporation
912+ * Copyright (C) 2018-2021 Intel Corporation
913 */
914
915 #include <linux/if_arp.h>
916@@ -155,7 +155,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
917 };
918 bool signal_valid;
919 struct ieee80211_sub_if_data *scan_sdata;
920- struct ieee802_11_elems elems;
921+ struct ieee802_11_elems *elems;
922 size_t baselen;
923 u8 *elements;
924
925@@ -209,8 +209,10 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
926 if (baselen > len)
927 return NULL;
928
929- ieee802_11_parse_elems(elements, len - baselen, false, &elems,
930- mgmt->bssid, cbss->bssid);
931+ elems = ieee802_11_parse_elems(elements, len - baselen, false,
932+ mgmt->bssid, cbss->bssid);
933+ if (!elems)
934+ return NULL;
935
936 /* In case the signal is invalid update the status */
937 signal_valid = channel == cbss->channel;
938@@ -218,15 +220,17 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
939 rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
940
941 bss = (void *)cbss->priv;
942- ieee80211_update_bss_from_elems(local, bss, &elems, rx_status, beacon);
943+ ieee80211_update_bss_from_elems(local, bss, elems, rx_status, beacon);
944
945 list_for_each_entry(non_tx_cbss, &cbss->nontrans_list, nontrans_list) {
946 non_tx_bss = (void *)non_tx_cbss->priv;
947
948- ieee80211_update_bss_from_elems(local, non_tx_bss, &elems,
949+ ieee80211_update_bss_from_elems(local, non_tx_bss, elems,
950 rx_status, beacon);
951 }
952
953+ kfree(elems);
954+
955 return bss;
956 }
957
958diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c
959index 45e532ad1215..137be9ec94af 100644
960--- a/net/mac80211/tdls.c
961+++ b/net/mac80211/tdls.c
962@@ -6,7 +6,7 @@
963 * Copyright 2014, Intel Corporation
964 * Copyright 2014 Intel Mobile Communications GmbH
965 * Copyright 2015 - 2016 Intel Deutschland GmbH
966- * Copyright (C) 2019 Intel Corporation
967+ * Copyright (C) 2019, 2021 Intel Corporation
968 */
969
970 #include <linux/ieee80211.h>
971@@ -1684,7 +1684,7 @@ ieee80211_process_tdls_channel_switch_resp(struct ieee80211_sub_if_data *sdata,
972 struct sk_buff *skb)
973 {
974 struct ieee80211_local *local = sdata->local;
975- struct ieee802_11_elems elems;
976+ struct ieee802_11_elems *elems = NULL;
977 struct sta_info *sta;
978 struct ieee80211_tdls_data *tf = (void *)skb->data;
979 bool local_initiator;
980@@ -1718,16 +1718,20 @@ ieee80211_process_tdls_channel_switch_resp(struct ieee80211_sub_if_data *sdata,
981 goto call_drv;
982 }
983
984- ieee802_11_parse_elems(tf->u.chan_switch_resp.variable,
985- skb->len - baselen, false, &elems,
986- NULL, NULL);
987- if (elems.parse_error) {
988+ elems = ieee802_11_parse_elems(tf->u.chan_switch_resp.variable,
989+ skb->len - baselen, false, NULL, NULL);
990+ if (!elems) {
991+ ret = -ENOMEM;
992+ goto out;
993+ }
994+
995+ if (elems->parse_error) {
996 tdls_dbg(sdata, "Invalid IEs in TDLS channel switch resp\n");
997 ret = -EINVAL;
998 goto out;
999 }
1000
1001- if (!elems.ch_sw_timing || !elems.lnk_id) {
1002+ if (!elems->ch_sw_timing || !elems->lnk_id) {
1003 tdls_dbg(sdata, "TDLS channel switch resp - missing IEs\n");
1004 ret = -EINVAL;
1005 goto out;
1006@@ -1735,15 +1739,15 @@ ieee80211_process_tdls_channel_switch_resp(struct ieee80211_sub_if_data *sdata,
1007
1008 /* validate the initiator is set correctly */
1009 local_initiator =
1010- !memcmp(elems.lnk_id->init_sta, sdata->vif.addr, ETH_ALEN);
1011+ !memcmp(elems->lnk_id->init_sta, sdata->vif.addr, ETH_ALEN);
1012 if (local_initiator == sta->sta.tdls_initiator) {
1013 tdls_dbg(sdata, "TDLS chan switch invalid lnk-id initiator\n");
1014 ret = -EINVAL;
1015 goto out;
1016 }
1017
1018- params.switch_time = le16_to_cpu(elems.ch_sw_timing->switch_time);
1019- params.switch_timeout = le16_to_cpu(elems.ch_sw_timing->switch_timeout);
1020+ params.switch_time = le16_to_cpu(elems->ch_sw_timing->switch_time);
1021+ params.switch_timeout = le16_to_cpu(elems->ch_sw_timing->switch_timeout);
1022
1023 params.tmpl_skb =
1024 ieee80211_tdls_ch_sw_resp_tmpl_get(sta, &params.ch_sw_tm_ie);
1025@@ -1763,6 +1767,7 @@ call_drv:
1026 out:
1027 mutex_unlock(&local->sta_mtx);
1028 dev_kfree_skb_any(params.tmpl_skb);
1029+ kfree(elems);
1030 return ret;
1031 }
1032
1033@@ -1771,7 +1776,7 @@ ieee80211_process_tdls_channel_switch_req(struct ieee80211_sub_if_data *sdata,
1034 struct sk_buff *skb)
1035 {
1036 struct ieee80211_local *local = sdata->local;
1037- struct ieee802_11_elems elems;
1038+ struct ieee802_11_elems *elems;
1039 struct cfg80211_chan_def chandef;
1040 struct ieee80211_channel *chan;
1041 enum nl80211_channel_type chan_type;
1042@@ -1831,22 +1836,27 @@ ieee80211_process_tdls_channel_switch_req(struct ieee80211_sub_if_data *sdata,
1043 return -EINVAL;
1044 }
1045
1046- ieee802_11_parse_elems(tf->u.chan_switch_req.variable,
1047- skb->len - baselen, false, &elems, NULL, NULL);
1048- if (elems.parse_error) {
1049+ elems = ieee802_11_parse_elems(tf->u.chan_switch_req.variable,
1050+ skb->len - baselen, false, NULL, NULL);
1051+ if (!elems)
1052+ return -ENOMEM;
1053+
1054+ if (elems->parse_error) {
1055 tdls_dbg(sdata, "Invalid IEs in TDLS channel switch req\n");
1056- return -EINVAL;
1057+ ret = -EINVAL;
1058+ goto free;
1059 }
1060
1061- if (!elems.ch_sw_timing || !elems.lnk_id) {
1062+ if (!elems->ch_sw_timing || !elems->lnk_id) {
1063 tdls_dbg(sdata, "TDLS channel switch req - missing IEs\n");
1064- return -EINVAL;
1065+ ret = -EINVAL;
1066+ goto free;
1067 }
1068
1069- if (!elems.sec_chan_offs) {
1070+ if (!elems->sec_chan_offs) {
1071 chan_type = NL80211_CHAN_HT20;
1072 } else {
1073- switch (elems.sec_chan_offs->sec_chan_offs) {
1074+ switch (elems->sec_chan_offs->sec_chan_offs) {
1075 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
1076 chan_type = NL80211_CHAN_HT40PLUS;
1077 break;
1078@@ -1865,7 +1875,8 @@ ieee80211_process_tdls_channel_switch_req(struct ieee80211_sub_if_data *sdata,
1079 if (!cfg80211_reg_can_beacon_relax(sdata->local->hw.wiphy, &chandef,
1080 sdata->wdev.iftype)) {
1081 tdls_dbg(sdata, "TDLS chan switch to forbidden channel\n");
1082- return -EINVAL;
1083+ ret = -EINVAL;
1084+ goto free;
1085 }
1086
1087 mutex_lock(&local->sta_mtx);
1088@@ -1881,7 +1892,7 @@ ieee80211_process_tdls_channel_switch_req(struct ieee80211_sub_if_data *sdata,
1089
1090 /* validate the initiator is set correctly */
1091 local_initiator =
1092- !memcmp(elems.lnk_id->init_sta, sdata->vif.addr, ETH_ALEN);
1093+ !memcmp(elems->lnk_id->init_sta, sdata->vif.addr, ETH_ALEN);
1094 if (local_initiator == sta->sta.tdls_initiator) {
1095 tdls_dbg(sdata, "TDLS chan switch invalid lnk-id initiator\n");
1096 ret = -EINVAL;
1097@@ -1889,16 +1900,16 @@ ieee80211_process_tdls_channel_switch_req(struct ieee80211_sub_if_data *sdata,
1098 }
1099
1100 /* peer should have known better */
1101- if (!sta->sta.ht_cap.ht_supported && elems.sec_chan_offs &&
1102- elems.sec_chan_offs->sec_chan_offs) {
1103+ if (!sta->sta.ht_cap.ht_supported && elems->sec_chan_offs &&
1104+ elems->sec_chan_offs->sec_chan_offs) {
1105 tdls_dbg(sdata, "TDLS chan switch - wide chan unsupported\n");
1106 ret = -ENOTSUPP;
1107 goto out;
1108 }
1109
1110 params.chandef = &chandef;
1111- params.switch_time = le16_to_cpu(elems.ch_sw_timing->switch_time);
1112- params.switch_timeout = le16_to_cpu(elems.ch_sw_timing->switch_timeout);
1113+ params.switch_time = le16_to_cpu(elems->ch_sw_timing->switch_time);
1114+ params.switch_timeout = le16_to_cpu(elems->ch_sw_timing->switch_timeout);
1115
1116 params.tmpl_skb =
1117 ieee80211_tdls_ch_sw_resp_tmpl_get(sta,
1118@@ -1917,6 +1928,8 @@ ieee80211_process_tdls_channel_switch_req(struct ieee80211_sub_if_data *sdata,
1119 out:
1120 mutex_unlock(&local->sta_mtx);
1121 dev_kfree_skb_any(params.tmpl_skb);
1122+free:
1123+ kfree(elems);
1124 return ret;
1125 }
1126
1127diff --git a/net/mac80211/util.c b/net/mac80211/util.c
1128index 664c32b6db19..2ac61e68b6b4 100644
1129--- a/net/mac80211/util.c
1130+++ b/net/mac80211/util.c
1131@@ -1396,8 +1396,8 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
1132
1133 static size_t ieee802_11_find_bssid_profile(const u8 *start, size_t len,
1134 struct ieee802_11_elems *elems,
1135- u8 *transmitter_bssid,
1136- u8 *bss_bssid,
1137+ const u8 *transmitter_bssid,
1138+ const u8 *bss_bssid,
1139 u8 *nontransmitted_profile)
1140 {
1141 const struct element *elem, *sub;
1142@@ -1464,16 +1464,20 @@ static size_t ieee802_11_find_bssid_profile(const u8 *start, size_t len,
1143 return found ? profile_len : 0;
1144 }
1145
1146-void ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
1147- struct ieee802_11_elems *elems,
1148- u64 filter, u32 crc, u8 *transmitter_bssid,
1149- u8 *bss_bssid)
1150+struct ieee802_11_elems *ieee802_11_parse_elems_crc(const u8 *start, size_t len,
1151+ bool action, u64 filter,
1152+ u32 crc,
1153+ const u8 *transmitter_bssid,
1154+ const u8 *bss_bssid)
1155 {
1156+ struct ieee802_11_elems *elems;
1157 const struct element *non_inherit = NULL;
1158 u8 *nontransmitted_profile;
1159 int nontransmitted_profile_len = 0;
1160
1161- memset(elems, 0, sizeof(*elems));
1162+ elems = kzalloc(sizeof(*elems), GFP_ATOMIC);
1163+ if (!elems)
1164+ return NULL;
1165 elems->ie_start = start;
1166 elems->total_len = len;
1167
1168@@ -1520,6 +1524,8 @@ void ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
1169 kfree(nontransmitted_profile);
1170
1171 elems->crc = crc;
1172+
1173+ return elems;
1174 }
1175
1176 void ieee80211_regulatory_limit_wmm_params(struct ieee80211_sub_if_data *sdata,
1177--
11782.30.2
1179