diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3633e49239c7..21549a440b38 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1613,6 +1613,14 @@ struct ieee802_11_elems { /* whether a parse error occurred while retrieving these elements */ bool parse_error; + + /* + * scratch buffer that can be used for various element parsing related + * tasks, e.g., element de-fragmentation etc. + */ + size_t scratch_len; + u8 *scratch_pos; + u8 scratch[]; }; static inline struct ieee80211_local *hw_to_local( diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 2ac61e68b6b4..354badd32793 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1475,24 +1475,25 @@ struct ieee802_11_elems *ieee802_11_parse_elems_crc(const u8 *start, size_t len, u8 *nontransmitted_profile; int nontransmitted_profile_len = 0; - elems = kzalloc(sizeof(*elems), GFP_ATOMIC); + elems = kzalloc(sizeof(*elems) + len, GFP_ATOMIC); if (!elems) return NULL; elems->ie_start = start; elems->total_len = len; - nontransmitted_profile = kmalloc(len, GFP_ATOMIC); - if (nontransmitted_profile) { - nontransmitted_profile_len = - ieee802_11_find_bssid_profile(start, len, elems, - transmitter_bssid, - bss_bssid, - nontransmitted_profile); - non_inherit = - cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE, - nontransmitted_profile, - nontransmitted_profile_len); - } + elems->scratch_len = len; + elems->scratch_pos = elems->scratch; + + nontransmitted_profile = elems->scratch_pos; + nontransmitted_profile_len = + ieee802_11_find_bssid_profile(start, len, elems, + transmitter_bssid, + bss_bssid, + nontransmitted_profile); + non_inherit = + cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE, + nontransmitted_profile, + nontransmitted_profile_len); crc = _ieee802_11_parse_elems_crc(start, len, action, elems, filter, crc, non_inherit); @@ -1521,8 +1522,6 @@ struct ieee802_11_elems *ieee802_11_parse_elems_crc(const u8 *start, size_t len, offsetofend(struct ieee80211_bssid_index, dtim_count)) elems->dtim_count = elems->bssid_index->dtim_count; - kfree(nontransmitted_profile); - elems->crc = crc; return elems;