1: 40ae3c4863a8 ! 1: 8b57020910b4 wifi: mac80211: fix TPE in channel switch wrapper parsing @@ Commit message wifi: mac80211: fix TPE in channel switch wrapper parsing  WLAN_EID_TX_POWER_ENVELOPE is a regular (non-extended) element, - but I accidentally used find_ext_elem() for it. Fix this. + but I accidentally used cfg80211_find_ext_elem for it, and it + should be a loop since multiple can be given. Fix both issues.  - Fixes: 4540568136fe ("wifi: mac80211: handle TPE element during CSA") Signed-off-by: Johannes Berg   ## net/mac80211/parse.c ## @@ net/mac80211/parse.c: _ieee802_11_parse_elems_full(struct ieee80211_elems_parse_   - subelem = cfg80211_find_ext_elem(WLAN_EID_TX_POWER_ENVELOPE,  - pos, elen); -+ subelem = cfg80211_find_elem(WLAN_EID_TX_POWER_ENVELOPE, -+ pos, elen); - if (subelem) +- if (subelem) ++ for_each_element_id(subelem, WLAN_EID_TX_POWER_ENVELOPE, ++ pos, elen) ieee80211_parse_tpe(&elems->csa_tpe, subelem->data + 1, + subelem->datalen - 1); 2: 1c69fcf08c97 ! 2: 6441a736b273 wifi: cfg80211: type-check (extended) element search functions @@ Metadata Author: Johannes Berg   ## Commit message ## - wifi: cfg80211: type-check (extended) element search functions + wifi: ieee80211: type-check (extended) element functions  - When constants are given as the first argument for the element - or extended element ID, make sure they're from the right enum - by tagging the argument accordingly. + Type-check element finding functions and element iteration macros, + so that when constants are given for the (extended) ID they must + be from the appropriate enum, otherwise an enum compare compiler + warning will trigger. + + Two places are using element iteration for subelements, but don't + have the outer element as a struct element, so they need casts to + avoid the warning now, but overall this will flag issues like the + one in the previous commit.  Signed-off-by: Johannes Berg   + ## include/linux/ieee80211.h ## +@@ include/linux/ieee80211.h: struct element { + u8 data[]; + } __packed; +  ++/* trigger enum comparison warnings if applicable (constant id) */ ++#define element_iteration_typecheck(type, id) \ ++ (((type)0 == (id)) || true) ++ + /* element iteration helpers */ + #define for_each_element(_elem, _data, _datalen) \ + for (_elem = (const struct element *)(_data); \ +@@ include/linux/ieee80211.h: struct element { +  + #define for_each_element_id(element, _id, data, datalen) \ + for_each_element(element, data, datalen) \ +- if (element->id == (_id)) ++ if (element_iteration_typecheck(enum ieee80211_eid, \ ++ _id) && \ ++ element->id == (_id)) +  + #define for_each_element_extid(element, extid, _data, _datalen) \ + for_each_element(element, _data, _datalen) \ +- if (element->id == WLAN_EID_EXTENSION && \ ++ if (element_iteration_typecheck(enum ieee80211_eid_ext, \ ++ extid) && \ ++ element->id == WLAN_EID_EXTENSION && \ + element->datalen > 0 && \ + element->data[0] == (extid)) +  +@@ include/linux/ieee80211.h: struct element { + for_each_element(sub, (element)->data, (element)->datalen) +  + #define for_each_subelement_id(sub, id, element) \ +- for_each_element_id(sub, id, (element)->data, (element)->datalen) ++ for_each_element_id(sub, (u8)id, (element)->data, (element)->datalen) +  + #define for_each_subelement_extid(sub, extid, element) \ +- for_each_element_extid(sub, extid, (element)->data, (element)->datalen) ++ for_each_element_extid(sub, (u8)extid, (element)->data, \ ++ (element)->datalen) +  + /** + * for_each_element_completed - determine if element parsing consumed all data + ## include/net/cfg80211.h ##  @@ include/net/cfg80211.h: unsigned int cfg80211_classify8021d(struct sk_buff *skb, * byte array to match. @@ include/net/cfg80211.h: static inline const u8 *cfg80211_find_ie(u8 eid, const u  /**  + ## net/mac80211/mlme.c ## +@@ net/mac80211/mlme.c: ieee80211_mgd_check_cross_link_csa(struct ieee80211_sub_if_data *sdata, + subelems = (u8 *)elems->ml_basic + common_size; + subelems_len = elems->ml_basic_len - common_size; +  +- for_each_element_id(sub, IEEE80211_MLE_SUBELEM_PER_STA_PROFILE, ++ for_each_element_id(sub, (u8)IEEE80211_MLE_SUBELEM_PER_STA_PROFILE, + subelems, subelems_len) { + struct ieee80211_mle_per_sta_profile *prof = (void *)sub->data; + struct ieee80211_link_data *link; + ## net/wireless/scan.c ##  @@ net/wireless/scan.c: void cfg80211_bss_flush(struct wiphy *wiphy) EXPORT_SYMBOL(cfg80211_bss_flush); @@ net/wireless/scan.c: void cfg80211_bss_flush(struct wiphy *wiphy) const u8 *match, unsigned int match_len, unsigned int match_offset) { +@@ net/wireless/scan.c: cfg80211_defrag_mle(const struct element *mle, const u8 *ie, size_t ielen, + ielen = mle_len - common_size; +  + idx = 0; +- for_each_element_id(elem, IEEE80211_MLE_SUBELEM_PER_STA_PROFILE, ++ for_each_element_id(elem, (u8)IEEE80211_MLE_SUBELEM_PER_STA_PROFILE, + ie, ielen) { + res->sta_prof[idx] = (void *)elem->data; + res->sta_prof_len[idx] = elem->datalen;