From: Benjamin Berg The Link ID Info field in the Reconfiguration Status Duple subfield of the Reconfiguration Response frame only uses the lower four bits for the link ID. The upper bits are reserved and should therefore be ignored. Fixes: 529766edcdbd ("wifi: mac80211: Support dynamic link addition and removal") Signed-off-by: Benjamin Berg Reviewed-by: Ilan Peer Signed-off-by: Miri Korenblit --- include/linux/ieee80211.h | 7 +++++++ net/mac80211/mlme.c | 14 ++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) -- v2: added structs and macros, as required. diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 52db36120314..b5d649db123f 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1194,6 +1194,13 @@ struct ieee80211_mgmt { #define IEEE80211_MIN_ACTION_SIZE(type) offsetofend(struct ieee80211_mgmt, u.action.type) +/* Link Reconfiguration Status Duple field */ +struct ieee80211_ml_reconf_status { + u8 info; + __le16 status; +} __packed; + +#define IEEE80211_ML_RECONF_LINK_ID_MASK 0xf /* Management MIC information element (IEEE 802.11w) for CMAC */ struct ieee80211_mmie { diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 0cd8d07bf668..d40b7d43b14d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -10458,8 +10458,8 @@ void ieee80211_process_ml_reconf_resp(struct ieee80211_sub_if_data *sdata, pos = mgmt->u.action.ml_reconf_resp.variable; len -= offsetofend(typeof(*mgmt), u.action.ml_reconf_resp); - /* each status duple is 3 octets */ - if (len < mgmt->u.action.ml_reconf_resp.count * 3) { + if (len < mgmt->u.action.ml_reconf_resp.count * + sizeof(struct ieee80211_ml_reconf_status)) { sdata_info(sdata, "mlo: reconf: unexpected len=%zu, count=%u\n", len, mgmt->u.action.ml_reconf_resp.count); @@ -10468,9 +10468,11 @@ void ieee80211_process_ml_reconf_resp(struct ieee80211_sub_if_data *sdata, link_mask = sta_changed_links; for (i = 0; i < mgmt->u.action.ml_reconf_resp.count; i++) { - u16 status = get_unaligned_le16(pos + 1); + struct ieee80211_ml_reconf_status *reconf_status = (void *)pos; + u16 status = le16_to_cpu(reconf_status->status); - link_id = *pos; + link_id = u8_get_bits(reconf_status->info, + IEEE80211_ML_RECONF_LINK_ID_MASK); if (!(link_mask & BIT(link_id))) { sdata_info(sdata, @@ -10505,8 +10507,8 @@ void ieee80211_process_ml_reconf_resp(struct ieee80211_sub_if_data *sdata, sdata->u.mgd.reconf.added_links &= ~BIT(link_id); } - pos += 3; - len -= 3; + pos += sizeof(*reconf_status); + len -= sizeof(*reconf_status); } if (link_mask) { -- 2.34.1