| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143 |
- From: Johannes Berg <[email protected]>
- Date: Mon, 20 Sep 2021 15:40:10 +0200
- Subject: [PATCH] mac80211: always allocate struct ieee802_11_elems
- As the 802.11 spec evolves, we need to parse more and more
- elements. This is causing the struct to grow, and we can no
- longer get away with putting it on the stack.
- Change the API to always dynamically allocate and return an
- allocated pointer that must be kfree()d later.
- As an alternative, I contemplated a scheme whereby we'd say
- in the code which elements we needed, e.g.
- DECLARE_ELEMENT_PARSER(elems,
- SUPPORTED_CHANNELS,
- CHANNEL_SWITCH,
- EXT(KEY_DELIVERY));
- ieee802_11_parse_elems(..., &elems, ...);
- and while I think this is possible and will save us a lot
- since most individual places only care about a small subset
- of the elements, it ended up being a bit more work since a
- lot of places do the parsing and then pass the struct to
- other functions, sometimes with multiple levels.
- Link: https://lore.kernel.org/r/20210920154009.26caff6b5998.I05ae58768e990e611aee8eca8abefd9d7bc15e05@changeid
- Signed-off-by: Johannes Berg <[email protected]>
- ---
- --- a/net/mac80211/agg-rx.c
- +++ b/net/mac80211/agg-rx.c
- @@ -478,7 +478,7 @@ void ieee80211_process_addba_request(str
- size_t len)
- {
- u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num;
- - struct ieee802_11_elems elems = { };
- + struct ieee802_11_elems *elems = NULL;
- u8 dialog_token;
- int ies_len;
-
- @@ -496,16 +496,17 @@ void ieee80211_process_addba_request(str
- ies_len = len - offsetof(struct ieee80211_mgmt,
- u.action.u.addba_req.variable);
- if (ies_len) {
- - ieee802_11_parse_elems(mgmt->u.action.u.addba_req.variable,
- - ies_len, true, &elems, mgmt->bssid, NULL);
- - if (elems.parse_error)
- + elems = ieee802_11_parse_elems(mgmt->u.action.u.addba_req.variable,
- + ies_len, true, mgmt->bssid, NULL);
- + if (!elems || elems->parse_error)
- return;
- }
-
- __ieee80211_start_rx_ba_session(sta, dialog_token, timeout,
- start_seq_num, ba_policy, tid,
- buf_size, true, false,
- - elems.addba_ext_ie);
- + elems ? elems->addba_ext_ie : NULL);
- + kfree(elems);
- }
-
- void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif,
- --- a/net/mac80211/ibss.c
- +++ b/net/mac80211/ibss.c
- @@ -9,7 +9,7 @@
- * Copyright 2009, Johannes Berg <[email protected]>
- * Copyright 2013-2014 Intel Mobile Communications GmbH
- * Copyright(c) 2016 Intel Deutschland GmbH
- - * Copyright(c) 2018-2020 Intel Corporation
- + * Copyright(c) 2018-2021 Intel Corporation
- */
-
- #include <linux/delay.h>
- @@ -1589,7 +1589,7 @@ void ieee80211_rx_mgmt_probe_beacon(stru
- struct ieee80211_rx_status *rx_status)
- {
- size_t baselen;
- - struct ieee802_11_elems elems;
- + struct ieee802_11_elems *elems;
-
- BUILD_BUG_ON(offsetof(typeof(mgmt->u.probe_resp), variable) !=
- offsetof(typeof(mgmt->u.beacon), variable));
- @@ -1602,10 +1602,14 @@ void ieee80211_rx_mgmt_probe_beacon(stru
- if (baselen > len)
- return;
-
- - ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
- - false, &elems, mgmt->bssid, NULL);
- -
- - ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
- + elems = ieee802_11_parse_elems(mgmt->u.probe_resp.variable,
- + len - baselen, false,
- + mgmt->bssid, NULL);
- +
- + if (elems) {
- + ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, elems);
- + kfree(elems);
- + }
- }
-
- void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
- @@ -1614,7 +1618,7 @@ void ieee80211_ibss_rx_queued_mgmt(struc
- struct ieee80211_rx_status *rx_status;
- struct ieee80211_mgmt *mgmt;
- u16 fc;
- - struct ieee802_11_elems elems;
- + struct ieee802_11_elems *elems;
- int ies_len;
-
- rx_status = IEEE80211_SKB_RXCB(skb);
- @@ -1651,15 +1655,16 @@ void ieee80211_ibss_rx_queued_mgmt(struc
- if (ies_len < 0)
- break;
-
- - ieee802_11_parse_elems(
- + elems = ieee802_11_parse_elems(
- mgmt->u.action.u.chan_switch.variable,
- - ies_len, true, &elems, mgmt->bssid, NULL);
- + ies_len, true, mgmt->bssid, NULL);
-
- - if (elems.parse_error)
- + if (!elems || elems->parse_error)
- break;
-
- ieee80211_rx_mgmt_spectrum_mgmt(sdata, mgmt, skb->len,
- - rx_status, &elems);
- + rx_status, elems);
- + kfree(elems);
- break;
- }
- }
- --- a/net/mac80211/ieee80211_i.h
- +++ b/net/mac80211/ieee80211_i.h
- @@ -2088,18 +2088,18 @@ static inline void ieee80211_tx_skb(stru
- ieee80211_tx_skb_tid(sdata, skb, 7);
- }
-
- -void ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
- - struct ieee802_11_elems *elems,
- - u64 filter, u32 crc, u8 *transmitter_bssid,
- - u8 *bss_bssid);
- -static inline void ieee802_11_parse_elems(const u8 *start, size_t len,
- - bool action,
- - struct ieee802_11_elems *elems,
- - u8 *transmitter_bssid,
- - u8 *bss_bssid)
- +struct ieee802_11_elems *ieee802_11_parse_elems_crc(const u8 *start, size_t len,
- + bool action,
- + u64 filter, u32 crc,
- + const u8 *transmitter_bssid,
- + const u8 *bss_bssid);
- +static inline struct ieee802_11_elems *
- +ieee802_11_parse_elems(const u8 *start, size_t len, bool action,
- + const u8 *transmitter_bssid,
- + const u8 *bss_bssid)
- {
- - ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0,
- - transmitter_bssid, bss_bssid);
- + return ieee802_11_parse_elems_crc(start, len, action, 0, 0,
- + transmitter_bssid, bss_bssid);
- }
-
-
- --- a/net/mac80211/mesh.c
- +++ b/net/mac80211/mesh.c
- @@ -1247,7 +1247,7 @@ ieee80211_mesh_rx_probe_req(struct ieee8
- struct sk_buff *presp;
- struct beacon_data *bcn;
- struct ieee80211_mgmt *hdr;
- - struct ieee802_11_elems elems;
- + struct ieee802_11_elems *elems;
- size_t baselen;
- u8 *pos;
-
- @@ -1256,22 +1256,24 @@ ieee80211_mesh_rx_probe_req(struct ieee8
- if (baselen > len)
- return;
-
- - ieee802_11_parse_elems(pos, len - baselen, false, &elems, mgmt->bssid,
- - NULL);
- -
- - if (!elems.mesh_id)
- + elems = ieee802_11_parse_elems(pos, len - baselen, false, mgmt->bssid,
- + NULL);
- + if (!elems)
- return;
-
- + if (!elems->mesh_id)
- + goto free;
- +
- /* 802.11-2012 10.1.4.3.2 */
- if ((!ether_addr_equal(mgmt->da, sdata->vif.addr) &&
- !is_broadcast_ether_addr(mgmt->da)) ||
- - elems.ssid_len != 0)
- - return;
- + elems->ssid_len != 0)
- + goto free;
-
- - if (elems.mesh_id_len != 0 &&
- - (elems.mesh_id_len != ifmsh->mesh_id_len ||
- - memcmp(elems.mesh_id, ifmsh->mesh_id, ifmsh->mesh_id_len)))
- - return;
- + if (elems->mesh_id_len != 0 &&
- + (elems->mesh_id_len != ifmsh->mesh_id_len ||
- + memcmp(elems->mesh_id, ifmsh->mesh_id, ifmsh->mesh_id_len)))
- + goto free;
-
- rcu_read_lock();
- bcn = rcu_dereference(ifmsh->beacon);
- @@ -1295,6 +1297,8 @@ ieee80211_mesh_rx_probe_req(struct ieee8
- ieee80211_tx_skb(sdata, presp);
- out:
- rcu_read_unlock();
- +free:
- + kfree(elems);
- }
-
- static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
- @@ -1305,7 +1309,7 @@ static void ieee80211_mesh_rx_bcn_presp(
- {
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
- - struct ieee802_11_elems elems;
- + struct ieee802_11_elems *elems;
- struct ieee80211_channel *channel;
- size_t baselen;
- int freq;
- @@ -1320,42 +1324,47 @@ static void ieee80211_mesh_rx_bcn_presp(
- if (baselen > len)
- return;
-
- - ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
- - false, &elems, mgmt->bssid, NULL);
- + elems = ieee802_11_parse_elems(mgmt->u.probe_resp.variable,
- + len - baselen,
- + false, mgmt->bssid, NULL);
- + if (!elems)
- + return;
-
- /* ignore non-mesh or secure / unsecure mismatch */
- - if ((!elems.mesh_id || !elems.mesh_config) ||
- - (elems.rsn && sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) ||
- - (!elems.rsn && sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE))
- - return;
- + if ((!elems->mesh_id || !elems->mesh_config) ||
- + (elems->rsn && sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) ||
- + (!elems->rsn && sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE))
- + goto free;
-
- - if (elems.ds_params)
- - freq = ieee80211_channel_to_frequency(elems.ds_params[0], band);
- + if (elems->ds_params)
- + freq = ieee80211_channel_to_frequency(elems->ds_params[0], band);
- else
- freq = rx_status->freq;
-
- channel = ieee80211_get_channel(local->hw.wiphy, freq);
-
- if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
- - return;
- + goto free;
-
- - if (mesh_matches_local(sdata, &elems)) {
- + if (mesh_matches_local(sdata, elems)) {
- mpl_dbg(sdata, "rssi_threshold=%d,rx_status->signal=%d\n",
- sdata->u.mesh.mshcfg.rssi_threshold, rx_status->signal);
- if (!sdata->u.mesh.user_mpm ||
- sdata->u.mesh.mshcfg.rssi_threshold == 0 ||
- sdata->u.mesh.mshcfg.rssi_threshold < rx_status->signal)
- - mesh_neighbour_update(sdata, mgmt->sa, &elems,
- + mesh_neighbour_update(sdata, mgmt->sa, elems,
- rx_status);
-
- if (ifmsh->csa_role != IEEE80211_MESH_CSA_ROLE_INIT &&
- !sdata->vif.csa_active)
- - ieee80211_mesh_process_chnswitch(sdata, &elems, true);
- + ieee80211_mesh_process_chnswitch(sdata, elems, true);
- }
-
- if (ifmsh->sync_ops)
- ifmsh->sync_ops->rx_bcn_presp(sdata, stype, mgmt, len,
- - elems.mesh_config, rx_status);
- + elems->mesh_config, rx_status);
- +free:
- + kfree(elems);
- }
-
- int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata)
- @@ -1447,7 +1456,7 @@ static void mesh_rx_csa_frame(struct iee
- struct ieee80211_mgmt *mgmt, size_t len)
- {
- struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
- - struct ieee802_11_elems elems;
- + struct ieee802_11_elems *elems;
- u16 pre_value;
- bool fwd_csa = true;
- size_t baselen;
- @@ -1460,33 +1469,37 @@ static void mesh_rx_csa_frame(struct iee
- pos = mgmt->u.action.u.chan_switch.variable;
- baselen = offsetof(struct ieee80211_mgmt,
- u.action.u.chan_switch.variable);
- - ieee802_11_parse_elems(pos, len - baselen, true, &elems,
- - mgmt->bssid, NULL);
- -
- - if (!mesh_matches_local(sdata, &elems))
- + elems = ieee802_11_parse_elems(pos, len - baselen, true,
- + mgmt->bssid, NULL);
- + if (!elems)
- return;
-
- - ifmsh->chsw_ttl = elems.mesh_chansw_params_ie->mesh_ttl;
- + if (!mesh_matches_local(sdata, elems))
- + goto free;
- +
- + ifmsh->chsw_ttl = elems->mesh_chansw_params_ie->mesh_ttl;
- if (!--ifmsh->chsw_ttl)
- fwd_csa = false;
-
- - pre_value = le16_to_cpu(elems.mesh_chansw_params_ie->mesh_pre_value);
- + pre_value = le16_to_cpu(elems->mesh_chansw_params_ie->mesh_pre_value);
- if (ifmsh->pre_value >= pre_value)
- - return;
- + goto free;
-
- ifmsh->pre_value = pre_value;
-
- if (!sdata->vif.csa_active &&
- - !ieee80211_mesh_process_chnswitch(sdata, &elems, false)) {
- + !ieee80211_mesh_process_chnswitch(sdata, elems, false)) {
- mcsa_dbg(sdata, "Failed to process CSA action frame");
- - return;
- + goto free;
- }
-
- /* forward or re-broadcast the CSA frame */
- if (fwd_csa) {
- - if (mesh_fwd_csa_frame(sdata, mgmt, len, &elems) < 0)
- + if (mesh_fwd_csa_frame(sdata, mgmt, len, elems) < 0)
- mcsa_dbg(sdata, "Failed to forward the CSA frame");
- }
- +free:
- + kfree(elems);
- }
-
- static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata,
- --- a/net/mac80211/mesh_hwmp.c
- +++ b/net/mac80211/mesh_hwmp.c
- @@ -1,7 +1,7 @@
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * Copyright (c) 2008, 2009 open80211s Ltd.
- - * Copyright (C) 2019 Intel Corporation
- + * Copyright (C) 2019, 2021 Intel Corporation
- * Author: Luis Carlos Cobo <[email protected]>
- */
-
- @@ -908,7 +908,7 @@ static void hwmp_rann_frame_process(stru
- void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_mgmt *mgmt, size_t len)
- {
- - struct ieee802_11_elems elems;
- + struct ieee802_11_elems *elems;
- size_t baselen;
- u32 path_metric;
- struct sta_info *sta;
- @@ -926,37 +926,41 @@ void mesh_rx_path_sel_frame(struct ieee8
- rcu_read_unlock();
-
- baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt;
- - ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
- - len - baselen, false, &elems, mgmt->bssid, NULL);
- + elems = ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
- + len - baselen, false, mgmt->bssid, NULL);
- + if (!elems)
- + return;
-
- - if (elems.preq) {
- - if (elems.preq_len != 37)
- + if (elems->preq) {
- + if (elems->preq_len != 37)
- /* Right now we support just 1 destination and no AE */
- - return;
- - path_metric = hwmp_route_info_get(sdata, mgmt, elems.preq,
- + goto free;
- + path_metric = hwmp_route_info_get(sdata, mgmt, elems->preq,
- MPATH_PREQ);
- if (path_metric)
- - hwmp_preq_frame_process(sdata, mgmt, elems.preq,
- + hwmp_preq_frame_process(sdata, mgmt, elems->preq,
- path_metric);
- }
- - if (elems.prep) {
- - if (elems.prep_len != 31)
- + if (elems->prep) {
- + if (elems->prep_len != 31)
- /* Right now we support no AE */
- - return;
- - path_metric = hwmp_route_info_get(sdata, mgmt, elems.prep,
- + goto free;
- + path_metric = hwmp_route_info_get(sdata, mgmt, elems->prep,
- MPATH_PREP);
- if (path_metric)
- - hwmp_prep_frame_process(sdata, mgmt, elems.prep,
- + hwmp_prep_frame_process(sdata, mgmt, elems->prep,
- path_metric);
- }
- - if (elems.perr) {
- - if (elems.perr_len != 15)
- + if (elems->perr) {
- + if (elems->perr_len != 15)
- /* Right now we support only one destination per PERR */
- - return;
- - hwmp_perr_frame_process(sdata, mgmt, elems.perr);
- + goto free;
- + hwmp_perr_frame_process(sdata, mgmt, elems->perr);
- }
- - if (elems.rann)
- - hwmp_rann_frame_process(sdata, mgmt, elems.rann);
- + if (elems->rann)
- + hwmp_rann_frame_process(sdata, mgmt, elems->rann);
- +free:
- + kfree(elems);
- }
-
- /**
- --- a/net/mac80211/mesh_plink.c
- +++ b/net/mac80211/mesh_plink.c
- @@ -1,7 +1,7 @@
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * Copyright (c) 2008, 2009 open80211s Ltd.
- - * Copyright (C) 2019 Intel Corporation
- + * Copyright (C) 2019, 2021 Intel Corporation
- * Author: Luis Carlos Cobo <[email protected]>
- */
- #include <linux/gfp.h>
- @@ -1200,7 +1200,7 @@ void mesh_rx_plink_frame(struct ieee8021
- struct ieee80211_mgmt *mgmt, size_t len,
- struct ieee80211_rx_status *rx_status)
- {
- - struct ieee802_11_elems elems;
- + struct ieee802_11_elems *elems;
- size_t baselen;
- u8 *baseaddr;
-
- @@ -1228,7 +1228,8 @@ void mesh_rx_plink_frame(struct ieee8021
- if (baselen > len)
- return;
- }
- - ieee802_11_parse_elems(baseaddr, len - baselen, true, &elems,
- - mgmt->bssid, NULL);
- - mesh_process_plink_frame(sdata, mgmt, &elems, rx_status);
- + elems = ieee802_11_parse_elems(baseaddr, len - baselen, true,
- + mgmt->bssid, NULL);
- + mesh_process_plink_frame(sdata, mgmt, elems, rx_status);
- + kfree(elems);
- }
- --- a/net/mac80211/mlme.c
- +++ b/net/mac80211/mlme.c
- @@ -3317,8 +3317,11 @@ static bool ieee80211_assoc_success(stru
- aid = 0; /* TODO */
- }
- capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
- - ieee802_11_parse_elems(pos, len - (pos - (u8 *)mgmt), false, elems,
- - mgmt->bssid, assoc_data->bss->bssid);
- + elems = ieee802_11_parse_elems(pos, len - (pos - (u8 *)mgmt), false,
- + mgmt->bssid, assoc_data->bss->bssid);
- +
- + if (!elems)
- + return false;
-
- if (elems->aid_resp)
- aid = le16_to_cpu(elems->aid_resp->aid);
- @@ -3340,7 +3343,8 @@ static bool ieee80211_assoc_success(stru
-
- if (!is_s1g && !elems->supp_rates) {
- sdata_info(sdata, "no SuppRates element in AssocResp\n");
- - return false;
- + ret = false;
- + goto out;
- }
-
- sdata->vif.bss_conf.aid = aid;
- @@ -3362,7 +3366,7 @@ static bool ieee80211_assoc_success(stru
- (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
- (!elems->vht_cap_elem || !elems->vht_operation)))) {
- const struct cfg80211_bss_ies *ies;
- - struct ieee802_11_elems bss_elems;
- + struct ieee802_11_elems *bss_elems;
-
- rcu_read_lock();
- ies = rcu_dereference(cbss->ies);
- @@ -3373,13 +3377,17 @@ static bool ieee80211_assoc_success(stru
- if (!bss_ies)
- return false;
-
- - ieee802_11_parse_elems(bss_ies->data, bss_ies->len,
- - false, &bss_elems,
- - mgmt->bssid,
- - assoc_data->bss->bssid);
- + bss_elems = ieee802_11_parse_elems(bss_ies->data, bss_ies->len,
- + false, mgmt->bssid,
- + assoc_data->bss->bssid);
- + if (!bss_elems) {
- + ret = false;
- + goto out;
- + }
- +
- if (assoc_data->wmm &&
- - !elems->wmm_param && bss_elems.wmm_param) {
- - elems->wmm_param = bss_elems.wmm_param;
- + !elems->wmm_param && bss_elems->wmm_param) {
- + elems->wmm_param = bss_elems->wmm_param;
- sdata_info(sdata,
- "AP bug: WMM param missing from AssocResp\n");
- }
- @@ -3388,30 +3396,32 @@ static bool ieee80211_assoc_success(stru
- * Also check if we requested HT/VHT, otherwise the AP doesn't
- * have to include the IEs in the (re)association response.
- */
- - if (!elems->ht_cap_elem && bss_elems.ht_cap_elem &&
- + if (!elems->ht_cap_elem && bss_elems->ht_cap_elem &&
- !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
- - elems->ht_cap_elem = bss_elems.ht_cap_elem;
- + elems->ht_cap_elem = bss_elems->ht_cap_elem;
- sdata_info(sdata,
- "AP bug: HT capability missing from AssocResp\n");
- }
- - if (!elems->ht_operation && bss_elems.ht_operation &&
- + if (!elems->ht_operation && bss_elems->ht_operation &&
- !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
- - elems->ht_operation = bss_elems.ht_operation;
- + elems->ht_operation = bss_elems->ht_operation;
- sdata_info(sdata,
- "AP bug: HT operation missing from AssocResp\n");
- }
- - if (!elems->vht_cap_elem && bss_elems.vht_cap_elem &&
- + if (!elems->vht_cap_elem && bss_elems->vht_cap_elem &&
- !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
- - elems->vht_cap_elem = bss_elems.vht_cap_elem;
- + elems->vht_cap_elem = bss_elems->vht_cap_elem;
- sdata_info(sdata,
- "AP bug: VHT capa missing from AssocResp\n");
- }
- - if (!elems->vht_operation && bss_elems.vht_operation &&
- + if (!elems->vht_operation && bss_elems->vht_operation &&
- !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
- - elems->vht_operation = bss_elems.vht_operation;
- + elems->vht_operation = bss_elems->vht_operation;
- sdata_info(sdata,
- "AP bug: VHT operation missing from AssocResp\n");
- }
- +
- + kfree(bss_elems);
- }
-
- /*
- @@ -3662,6 +3672,7 @@ static bool ieee80211_assoc_success(stru
-
- ret = true;
- out:
- + kfree(elems);
- kfree(bss_ies);
- return ret;
- }
- @@ -3673,7 +3684,7 @@ static void ieee80211_rx_mgmt_assoc_resp
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
- u16 capab_info, status_code, aid;
- - struct ieee802_11_elems elems;
- + struct ieee802_11_elems *elems;
- int ac, uapsd_queues = -1;
- u8 *pos;
- bool reassoc;
- @@ -3730,14 +3741,16 @@ static void ieee80211_rx_mgmt_assoc_resp
- fils_decrypt_assoc_resp(sdata, (u8 *)mgmt, &len, assoc_data) < 0)
- return;
-
- - ieee802_11_parse_elems(pos, len - (pos - (u8 *)mgmt), false, &elems,
- - mgmt->bssid, assoc_data->bss->bssid);
- + elems = ieee802_11_parse_elems(pos, len - (pos - (u8 *)mgmt), false,
- + mgmt->bssid, assoc_data->bss->bssid);
- + if (!elems)
- + goto notify_driver;
-
- if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
- - elems.timeout_int &&
- - elems.timeout_int->type == WLAN_TIMEOUT_ASSOC_COMEBACK) {
- + elems->timeout_int &&
- + elems->timeout_int->type == WLAN_TIMEOUT_ASSOC_COMEBACK) {
- u32 tu, ms;
- - tu = le32_to_cpu(elems.timeout_int->value);
- + tu = le32_to_cpu(elems->timeout_int->value);
- ms = tu * 1024 / 1000;
- sdata_info(sdata,
- "%pM rejected association temporarily; comeback duration %u TU (%u ms)\n",
- @@ -3757,7 +3770,7 @@ static void ieee80211_rx_mgmt_assoc_resp
- event.u.mlme.reason = status_code;
- drv_event_callback(sdata->local, sdata, &event);
- } else {
- - if (!ieee80211_assoc_success(sdata, cbss, mgmt, len, &elems)) {
- + if (!ieee80211_assoc_success(sdata, cbss, mgmt, len, elems)) {
- /* oops -- internal error -- send timeout for now */
- ieee80211_destroy_assoc_data(sdata, false, false);
- cfg80211_assoc_timeout(sdata->dev, cbss);
- @@ -3787,6 +3800,7 @@ static void ieee80211_rx_mgmt_assoc_resp
- ifmgd->assoc_req_ies, ifmgd->assoc_req_ies_len);
- notify_driver:
- drv_mgd_complete_tx(sdata->local, sdata, &info);
- + kfree(elems);
- }
-
- static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
- @@ -3991,7 +4005,7 @@ static void ieee80211_rx_mgmt_beacon(str
- struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
- struct ieee80211_mgmt *mgmt = (void *) hdr;
- size_t baselen;
- - struct ieee802_11_elems elems;
- + struct ieee802_11_elems *elems;
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_chanctx_conf *chanctx_conf;
- struct ieee80211_channel *chan;
- @@ -4037,15 +4051,16 @@ static void ieee80211_rx_mgmt_beacon(str
-
- if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon &&
- ieee80211_rx_our_beacon(bssid, ifmgd->assoc_data->bss)) {
- - ieee802_11_parse_elems(variable,
- - len - baselen, false, &elems,
- - bssid,
- - ifmgd->assoc_data->bss->bssid);
- + elems = ieee802_11_parse_elems(variable, len - baselen, false,
- + bssid,
- + ifmgd->assoc_data->bss->bssid);
- + if (!elems)
- + return;
-
- ieee80211_rx_bss_info(sdata, mgmt, len, rx_status);
-
- - if (elems.dtim_period)
- - ifmgd->dtim_period = elems.dtim_period;
- + if (elems->dtim_period)
- + ifmgd->dtim_period = elems->dtim_period;
- ifmgd->have_beacon = true;
- ifmgd->assoc_data->need_beacon = false;
- if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) {
- @@ -4053,17 +4068,17 @@ static void ieee80211_rx_mgmt_beacon(str
- le64_to_cpu(mgmt->u.beacon.timestamp);
- sdata->vif.bss_conf.sync_device_ts =
- rx_status->device_timestamp;
- - sdata->vif.bss_conf.sync_dtim_count = elems.dtim_count;
- + sdata->vif.bss_conf.sync_dtim_count = elems->dtim_count;
- }
-
- - if (elems.mbssid_config_ie)
- + if (elems->mbssid_config_ie)
- bss_conf->profile_periodicity =
- - elems.mbssid_config_ie->profile_periodicity;
- + elems->mbssid_config_ie->profile_periodicity;
- else
- bss_conf->profile_periodicity = 0;
-
- - if (elems.ext_capab_len >= 11 &&
- - (elems.ext_capab[10] & WLAN_EXT_CAPA11_EMA_SUPPORT))
- + if (elems->ext_capab_len >= 11 &&
- + (elems->ext_capab[10] & WLAN_EXT_CAPA11_EMA_SUPPORT))
- bss_conf->ema_ap = true;
- else
- bss_conf->ema_ap = false;
- @@ -4072,6 +4087,7 @@ static void ieee80211_rx_mgmt_beacon(str
- ifmgd->assoc_data->timeout = jiffies;
- ifmgd->assoc_data->timeout_started = true;
- run_again(sdata, ifmgd->assoc_data->timeout);
- + kfree(elems);
- return;
- }
-
- @@ -4103,14 +4119,15 @@ static void ieee80211_rx_mgmt_beacon(str
- */
- if (!ieee80211_is_s1g_beacon(hdr->frame_control))
- ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4);
- - ieee802_11_parse_elems_crc(variable,
- - len - baselen, false, &elems,
- - care_about_ies, ncrc,
- - mgmt->bssid, bssid);
- - ncrc = elems.crc;
- + elems = ieee802_11_parse_elems_crc(variable, len - baselen,
- + false, care_about_ies, ncrc,
- + mgmt->bssid, bssid);
- + if (!elems)
- + return;
- + ncrc = elems->crc;
-
- if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK) &&
- - ieee80211_check_tim(elems.tim, elems.tim_len, bss_conf->aid)) {
- + ieee80211_check_tim(elems->tim, elems->tim_len, bss_conf->aid)) {
- if (local->hw.conf.dynamic_ps_timeout > 0) {
- if (local->hw.conf.flags & IEEE80211_CONF_PS) {
- local->hw.conf.flags &= ~IEEE80211_CONF_PS;
- @@ -4180,12 +4197,12 @@ static void ieee80211_rx_mgmt_beacon(str
- le64_to_cpu(mgmt->u.beacon.timestamp);
- sdata->vif.bss_conf.sync_device_ts =
- rx_status->device_timestamp;
- - sdata->vif.bss_conf.sync_dtim_count = elems.dtim_count;
- + sdata->vif.bss_conf.sync_dtim_count = elems->dtim_count;
- }
-
- if ((ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid) ||
- ieee80211_is_s1g_short_beacon(mgmt->frame_control))
- - return;
- + goto free;
- ifmgd->beacon_crc = ncrc;
- ifmgd->beacon_crc_valid = true;
-
- @@ -4193,12 +4210,12 @@ static void ieee80211_rx_mgmt_beacon(str
-
- ieee80211_sta_process_chanswitch(sdata, rx_status->mactime,
- rx_status->device_timestamp,
- - &elems, true);
- + elems, true);
-
- if (!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM) &&
- - ieee80211_sta_wmm_params(local, sdata, elems.wmm_param,
- - elems.wmm_param_len,
- - elems.mu_edca_param_set))
- + ieee80211_sta_wmm_params(local, sdata, elems->wmm_param,
- + elems->wmm_param_len,
- + elems->mu_edca_param_set))
- changed |= BSS_CHANGED_QOS;
-
- /*
- @@ -4207,7 +4224,7 @@ static void ieee80211_rx_mgmt_beacon(str
- */
- if (!ifmgd->have_beacon) {
- /* a few bogus AP send dtim_period = 0 or no TIM IE */
- - bss_conf->dtim_period = elems.dtim_period ?: 1;
- + bss_conf->dtim_period = elems->dtim_period ?: 1;
-
- changed |= BSS_CHANGED_BEACON_INFO;
- ifmgd->have_beacon = true;
- @@ -4219,9 +4236,9 @@ static void ieee80211_rx_mgmt_beacon(str
- ieee80211_recalc_ps_vif(sdata);
- }
-
- - if (elems.erp_info) {
- + if (elems->erp_info) {
- erp_valid = true;
- - erp_value = elems.erp_info[0];
- + erp_value = elems->erp_info[0];
- } else {
- erp_valid = false;
- }
- @@ -4234,12 +4251,12 @@ static void ieee80211_rx_mgmt_beacon(str
- mutex_lock(&local->sta_mtx);
- sta = sta_info_get(sdata, bssid);
-
- - changed |= ieee80211_recalc_twt_req(sdata, sta, &elems);
- + changed |= ieee80211_recalc_twt_req(sdata, sta, elems);
-
- - if (ieee80211_config_bw(sdata, sta, elems.ht_cap_elem,
- - elems.vht_cap_elem, elems.ht_operation,
- - elems.vht_operation, elems.he_operation,
- - elems.s1g_oper, bssid, &changed)) {
- + if (ieee80211_config_bw(sdata, sta, elems->ht_cap_elem,
- + elems->vht_cap_elem, elems->ht_operation,
- + elems->vht_operation, elems->he_operation,
- + elems->s1g_oper, bssid, &changed)) {
- mutex_unlock(&local->sta_mtx);
- sdata_info(sdata,
- "failed to follow AP %pM bandwidth change, disconnect\n",
- @@ -4251,21 +4268,23 @@ static void ieee80211_rx_mgmt_beacon(str
- sizeof(deauth_buf), true,
- WLAN_REASON_DEAUTH_LEAVING,
- false);
- - return;
- + goto free;
- }
-
- - if (sta && elems.opmode_notif)
- - ieee80211_vht_handle_opmode(sdata, sta, *elems.opmode_notif,
- + if (sta && elems->opmode_notif)
- + ieee80211_vht_handle_opmode(sdata, sta, *elems->opmode_notif,
- rx_status->band);
- mutex_unlock(&local->sta_mtx);
-
- changed |= ieee80211_handle_pwr_constr(sdata, chan, mgmt,
- - elems.country_elem,
- - elems.country_elem_len,
- - elems.pwr_constr_elem,
- - elems.cisco_dtpc_elem);
- + elems->country_elem,
- + elems->country_elem_len,
- + elems->pwr_constr_elem,
- + elems->cisco_dtpc_elem);
-
- ieee80211_bss_info_change_notify(sdata, changed);
- +free:
- + kfree(elems);
- }
-
- void ieee80211_sta_rx_queued_ext(struct ieee80211_sub_if_data *sdata,
- @@ -4294,7 +4313,6 @@ void ieee80211_sta_rx_queued_mgmt(struct
- struct ieee80211_rx_status *rx_status;
- struct ieee80211_mgmt *mgmt;
- u16 fc;
- - struct ieee802_11_elems elems;
- int ies_len;
-
- rx_status = (struct ieee80211_rx_status *) skb->cb;
- @@ -4326,6 +4344,8 @@ void ieee80211_sta_rx_queued_mgmt(struct
- break;
- case IEEE80211_STYPE_ACTION:
- if (mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) {
- + struct ieee802_11_elems *elems;
- +
- ies_len = skb->len -
- offsetof(struct ieee80211_mgmt,
- u.action.u.chan_switch.variable);
- @@ -4334,18 +4354,21 @@ void ieee80211_sta_rx_queued_mgmt(struct
- break;
-
- /* CSA IE cannot be overridden, no need for BSSID */
- - ieee802_11_parse_elems(
- - mgmt->u.action.u.chan_switch.variable,
- - ies_len, true, &elems, mgmt->bssid, NULL);
- + elems = ieee802_11_parse_elems(
- + mgmt->u.action.u.chan_switch.variable,
- + ies_len, true, mgmt->bssid, NULL);
-
- - if (elems.parse_error)
- + if (!elems || elems->parse_error)
- break;
-
- ieee80211_sta_process_chanswitch(sdata,
- rx_status->mactime,
- rx_status->device_timestamp,
- - &elems, false);
- + elems, false);
- + kfree(elems);
- } else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) {
- + struct ieee802_11_elems *elems;
- +
- ies_len = skb->len -
- offsetof(struct ieee80211_mgmt,
- u.action.u.ext_chan_switch.variable);
- @@ -4357,21 +4380,22 @@ void ieee80211_sta_rx_queued_mgmt(struct
- * extended CSA IE can't be overridden, no need for
- * BSSID
- */
- - ieee802_11_parse_elems(
- - mgmt->u.action.u.ext_chan_switch.variable,
- - ies_len, true, &elems, mgmt->bssid, NULL);
- + elems = ieee802_11_parse_elems(
- + mgmt->u.action.u.ext_chan_switch.variable,
- + ies_len, true, mgmt->bssid, NULL);
-
- - if (elems.parse_error)
- + if (!elems || elems->parse_error)
- break;
-
- /* for the handling code pretend this was also an IE */
- - elems.ext_chansw_ie =
- + elems->ext_chansw_ie =
- &mgmt->u.action.u.ext_chan_switch.data;
-
- ieee80211_sta_process_chanswitch(sdata,
- rx_status->mactime,
- rx_status->device_timestamp,
- - &elems, false);
- + elems, false);
- + kfree(elems);
- }
- break;
- }
- --- a/net/mac80211/scan.c
- +++ b/net/mac80211/scan.c
- @@ -9,7 +9,7 @@
- * Copyright 2007, Michael Wu <[email protected]>
- * Copyright 2013-2015 Intel Mobile Communications GmbH
- * Copyright 2016-2017 Intel Deutschland GmbH
- - * Copyright (C) 2018-2020 Intel Corporation
- + * Copyright (C) 2018-2021 Intel Corporation
- */
-
- #include <linux/if_arp.h>
- @@ -155,7 +155,7 @@ ieee80211_bss_info_update(struct ieee802
- };
- bool signal_valid;
- struct ieee80211_sub_if_data *scan_sdata;
- - struct ieee802_11_elems elems;
- + struct ieee802_11_elems *elems;
- size_t baselen;
- u8 *elements;
-
- @@ -209,8 +209,10 @@ ieee80211_bss_info_update(struct ieee802
- if (baselen > len)
- return NULL;
-
- - ieee802_11_parse_elems(elements, len - baselen, false, &elems,
- - mgmt->bssid, cbss->bssid);
- + elems = ieee802_11_parse_elems(elements, len - baselen, false,
- + mgmt->bssid, cbss->bssid);
- + if (!elems)
- + return NULL;
-
- /* In case the signal is invalid update the status */
- signal_valid = channel == cbss->channel;
- @@ -218,15 +220,17 @@ ieee80211_bss_info_update(struct ieee802
- rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
-
- bss = (void *)cbss->priv;
- - ieee80211_update_bss_from_elems(local, bss, &elems, rx_status, beacon);
- + ieee80211_update_bss_from_elems(local, bss, elems, rx_status, beacon);
-
- list_for_each_entry(non_tx_cbss, &cbss->nontrans_list, nontrans_list) {
- non_tx_bss = (void *)non_tx_cbss->priv;
-
- - ieee80211_update_bss_from_elems(local, non_tx_bss, &elems,
- + ieee80211_update_bss_from_elems(local, non_tx_bss, elems,
- rx_status, beacon);
- }
-
- + kfree(elems);
- +
- return bss;
- }
-
- --- a/net/mac80211/tdls.c
- +++ b/net/mac80211/tdls.c
- @@ -6,7 +6,7 @@
- * Copyright 2014, Intel Corporation
- * Copyright 2014 Intel Mobile Communications GmbH
- * Copyright 2015 - 2016 Intel Deutschland GmbH
- - * Copyright (C) 2019 Intel Corporation
- + * Copyright (C) 2019, 2021 Intel Corporation
- */
-
- #include <linux/ieee80211.h>
- @@ -1684,7 +1684,7 @@ ieee80211_process_tdls_channel_switch_re
- struct sk_buff *skb)
- {
- struct ieee80211_local *local = sdata->local;
- - struct ieee802_11_elems elems;
- + struct ieee802_11_elems *elems = NULL;
- struct sta_info *sta;
- struct ieee80211_tdls_data *tf = (void *)skb->data;
- bool local_initiator;
- @@ -1718,16 +1718,20 @@ ieee80211_process_tdls_channel_switch_re
- goto call_drv;
- }
-
- - ieee802_11_parse_elems(tf->u.chan_switch_resp.variable,
- - skb->len - baselen, false, &elems,
- - NULL, NULL);
- - if (elems.parse_error) {
- + elems = ieee802_11_parse_elems(tf->u.chan_switch_resp.variable,
- + skb->len - baselen, false, NULL, NULL);
- + if (!elems) {
- + ret = -ENOMEM;
- + goto out;
- + }
- +
- + if (elems->parse_error) {
- tdls_dbg(sdata, "Invalid IEs in TDLS channel switch resp\n");
- ret = -EINVAL;
- goto out;
- }
-
- - if (!elems.ch_sw_timing || !elems.lnk_id) {
- + if (!elems->ch_sw_timing || !elems->lnk_id) {
- tdls_dbg(sdata, "TDLS channel switch resp - missing IEs\n");
- ret = -EINVAL;
- goto out;
- @@ -1735,15 +1739,15 @@ ieee80211_process_tdls_channel_switch_re
-
- /* validate the initiator is set correctly */
- local_initiator =
- - !memcmp(elems.lnk_id->init_sta, sdata->vif.addr, ETH_ALEN);
- + !memcmp(elems->lnk_id->init_sta, sdata->vif.addr, ETH_ALEN);
- if (local_initiator == sta->sta.tdls_initiator) {
- tdls_dbg(sdata, "TDLS chan switch invalid lnk-id initiator\n");
- ret = -EINVAL;
- goto out;
- }
-
- - params.switch_time = le16_to_cpu(elems.ch_sw_timing->switch_time);
- - params.switch_timeout = le16_to_cpu(elems.ch_sw_timing->switch_timeout);
- + params.switch_time = le16_to_cpu(elems->ch_sw_timing->switch_time);
- + params.switch_timeout = le16_to_cpu(elems->ch_sw_timing->switch_timeout);
-
- params.tmpl_skb =
- ieee80211_tdls_ch_sw_resp_tmpl_get(sta, ¶ms.ch_sw_tm_ie);
- @@ -1763,6 +1767,7 @@ call_drv:
- out:
- mutex_unlock(&local->sta_mtx);
- dev_kfree_skb_any(params.tmpl_skb);
- + kfree(elems);
- return ret;
- }
-
- @@ -1771,7 +1776,7 @@ ieee80211_process_tdls_channel_switch_re
- struct sk_buff *skb)
- {
- struct ieee80211_local *local = sdata->local;
- - struct ieee802_11_elems elems;
- + struct ieee802_11_elems *elems;
- struct cfg80211_chan_def chandef;
- struct ieee80211_channel *chan;
- enum nl80211_channel_type chan_type;
- @@ -1831,22 +1836,27 @@ ieee80211_process_tdls_channel_switch_re
- return -EINVAL;
- }
-
- - ieee802_11_parse_elems(tf->u.chan_switch_req.variable,
- - skb->len - baselen, false, &elems, NULL, NULL);
- - if (elems.parse_error) {
- + elems = ieee802_11_parse_elems(tf->u.chan_switch_req.variable,
- + skb->len - baselen, false, NULL, NULL);
- + if (!elems)
- + return -ENOMEM;
- +
- + if (elems->parse_error) {
- tdls_dbg(sdata, "Invalid IEs in TDLS channel switch req\n");
- - return -EINVAL;
- + ret = -EINVAL;
- + goto free;
- }
-
- - if (!elems.ch_sw_timing || !elems.lnk_id) {
- + if (!elems->ch_sw_timing || !elems->lnk_id) {
- tdls_dbg(sdata, "TDLS channel switch req - missing IEs\n");
- - return -EINVAL;
- + ret = -EINVAL;
- + goto free;
- }
-
- - if (!elems.sec_chan_offs) {
- + if (!elems->sec_chan_offs) {
- chan_type = NL80211_CHAN_HT20;
- } else {
- - switch (elems.sec_chan_offs->sec_chan_offs) {
- + switch (elems->sec_chan_offs->sec_chan_offs) {
- case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
- chan_type = NL80211_CHAN_HT40PLUS;
- break;
- @@ -1865,7 +1875,8 @@ ieee80211_process_tdls_channel_switch_re
- if (!cfg80211_reg_can_beacon_relax(sdata->local->hw.wiphy, &chandef,
- sdata->wdev.iftype)) {
- tdls_dbg(sdata, "TDLS chan switch to forbidden channel\n");
- - return -EINVAL;
- + ret = -EINVAL;
- + goto free;
- }
-
- mutex_lock(&local->sta_mtx);
- @@ -1881,7 +1892,7 @@ ieee80211_process_tdls_channel_switch_re
-
- /* validate the initiator is set correctly */
- local_initiator =
- - !memcmp(elems.lnk_id->init_sta, sdata->vif.addr, ETH_ALEN);
- + !memcmp(elems->lnk_id->init_sta, sdata->vif.addr, ETH_ALEN);
- if (local_initiator == sta->sta.tdls_initiator) {
- tdls_dbg(sdata, "TDLS chan switch invalid lnk-id initiator\n");
- ret = -EINVAL;
- @@ -1889,16 +1900,16 @@ ieee80211_process_tdls_channel_switch_re
- }
-
- /* peer should have known better */
- - if (!sta->sta.ht_cap.ht_supported && elems.sec_chan_offs &&
- - elems.sec_chan_offs->sec_chan_offs) {
- + if (!sta->sta.ht_cap.ht_supported && elems->sec_chan_offs &&
- + elems->sec_chan_offs->sec_chan_offs) {
- tdls_dbg(sdata, "TDLS chan switch - wide chan unsupported\n");
- ret = -ENOTSUPP;
- goto out;
- }
-
- params.chandef = &chandef;
- - params.switch_time = le16_to_cpu(elems.ch_sw_timing->switch_time);
- - params.switch_timeout = le16_to_cpu(elems.ch_sw_timing->switch_timeout);
- + params.switch_time = le16_to_cpu(elems->ch_sw_timing->switch_time);
- + params.switch_timeout = le16_to_cpu(elems->ch_sw_timing->switch_timeout);
-
- params.tmpl_skb =
- ieee80211_tdls_ch_sw_resp_tmpl_get(sta,
- @@ -1917,6 +1928,8 @@ ieee80211_process_tdls_channel_switch_re
- out:
- mutex_unlock(&local->sta_mtx);
- dev_kfree_skb_any(params.tmpl_skb);
- +free:
- + kfree(elems);
- return ret;
- }
-
- --- a/net/mac80211/util.c
- +++ b/net/mac80211/util.c
- @@ -1399,8 +1399,8 @@ _ieee802_11_parse_elems_crc(const u8 *st
-
- static size_t ieee802_11_find_bssid_profile(const u8 *start, size_t len,
- struct ieee802_11_elems *elems,
- - u8 *transmitter_bssid,
- - u8 *bss_bssid,
- + const u8 *transmitter_bssid,
- + const u8 *bss_bssid,
- u8 *nontransmitted_profile)
- {
- const struct element *elem, *sub;
- @@ -1465,16 +1465,20 @@ static size_t ieee802_11_find_bssid_prof
- return found ? profile_len : 0;
- }
-
- -void ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
- - struct ieee802_11_elems *elems,
- - u64 filter, u32 crc, u8 *transmitter_bssid,
- - u8 *bss_bssid)
- +struct ieee802_11_elems *ieee802_11_parse_elems_crc(const u8 *start, size_t len,
- + bool action, u64 filter,
- + u32 crc,
- + const u8 *transmitter_bssid,
- + const u8 *bss_bssid)
- {
- + struct ieee802_11_elems *elems;
- const struct element *non_inherit = NULL;
- u8 *nontransmitted_profile;
- int nontransmitted_profile_len = 0;
-
- - memset(elems, 0, sizeof(*elems));
- + elems = kzalloc(sizeof(*elems), GFP_ATOMIC);
- + if (!elems)
- + return NULL;
- elems->ie_start = start;
- elems->total_len = len;
-
- @@ -1521,6 +1525,8 @@ void ieee802_11_parse_elems_crc(const u8
- kfree(nontransmitted_profile);
-
- elems->crc = crc;
- +
- + return elems;
- }
-
- void ieee80211_regulatory_limit_wmm_params(struct ieee80211_sub_if_data *sdata,
|