349-mac80211-always-allocate-struct-ieee802_11_elems.patch 37 KB

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