Commit 652e8363 authored by Johannes Berg's avatar Johannes Berg

mac80211: handle various extensible elements correctly

Various elements are parsed with a requirement to have an
exact size, when really we should only check that they have
the minimum size that we need. Check only that and therefore
ignore any additional data that they might carry.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20210618133832.cd101f8040a4.Iadf0e9b37b100c6c6e79c7b298cc657c2be9151a@changeidSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent bbc6f03f
...@@ -947,7 +947,7 @@ static void ieee80211_parse_extension_element(u32 *crc, ...@@ -947,7 +947,7 @@ static void ieee80211_parse_extension_element(u32 *crc,
switch (elem->data[0]) { switch (elem->data[0]) {
case WLAN_EID_EXT_HE_MU_EDCA: case WLAN_EID_EXT_HE_MU_EDCA:
if (len == sizeof(*elems->mu_edca_param_set)) { if (len >= sizeof(*elems->mu_edca_param_set)) {
elems->mu_edca_param_set = data; elems->mu_edca_param_set = data;
if (crc) if (crc)
*crc = crc32_be(*crc, (void *)elem, *crc = crc32_be(*crc, (void *)elem,
...@@ -968,7 +968,7 @@ static void ieee80211_parse_extension_element(u32 *crc, ...@@ -968,7 +968,7 @@ static void ieee80211_parse_extension_element(u32 *crc,
} }
break; break;
case WLAN_EID_EXT_UORA: case WLAN_EID_EXT_UORA:
if (len == 1) if (len >= 1)
elems->uora_element = data; elems->uora_element = data;
break; break;
case WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME: case WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME:
...@@ -976,7 +976,7 @@ static void ieee80211_parse_extension_element(u32 *crc, ...@@ -976,7 +976,7 @@ static void ieee80211_parse_extension_element(u32 *crc,
elems->max_channel_switch_time = data; elems->max_channel_switch_time = data;
break; break;
case WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION: case WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION:
if (len == sizeof(*elems->mbssid_config_ie)) if (len >= sizeof(*elems->mbssid_config_ie))
elems->mbssid_config_ie = data; elems->mbssid_config_ie = data;
break; break;
case WLAN_EID_EXT_HE_SPR: case WLAN_EID_EXT_HE_SPR:
...@@ -985,7 +985,7 @@ static void ieee80211_parse_extension_element(u32 *crc, ...@@ -985,7 +985,7 @@ static void ieee80211_parse_extension_element(u32 *crc,
elems->he_spr = data; elems->he_spr = data;
break; break;
case WLAN_EID_EXT_HE_6GHZ_CAPA: case WLAN_EID_EXT_HE_6GHZ_CAPA:
if (len == sizeof(*elems->he_6ghz_capa)) if (len >= sizeof(*elems->he_6ghz_capa))
elems->he_6ghz_capa = data; elems->he_6ghz_capa = data;
break; break;
} }
...@@ -1074,14 +1074,14 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, ...@@ -1074,14 +1074,14 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
switch (id) { switch (id) {
case WLAN_EID_LINK_ID: case WLAN_EID_LINK_ID:
if (elen + 2 != sizeof(struct ieee80211_tdls_lnkie)) { if (elen + 2 < sizeof(struct ieee80211_tdls_lnkie)) {
elem_parse_failed = true; elem_parse_failed = true;
break; break;
} }
elems->lnk_id = (void *)(pos - 2); elems->lnk_id = (void *)(pos - 2);
break; break;
case WLAN_EID_CHAN_SWITCH_TIMING: case WLAN_EID_CHAN_SWITCH_TIMING:
if (elen != sizeof(struct ieee80211_ch_switch_timing)) { if (elen < sizeof(struct ieee80211_ch_switch_timing)) {
elem_parse_failed = true; elem_parse_failed = true;
break; break;
} }
...@@ -1244,7 +1244,7 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, ...@@ -1244,7 +1244,7 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
elems->sec_chan_offs = (void *)pos; elems->sec_chan_offs = (void *)pos;
break; break;
case WLAN_EID_CHAN_SWITCH_PARAM: case WLAN_EID_CHAN_SWITCH_PARAM:
if (elen != if (elen <
sizeof(*elems->mesh_chansw_params_ie)) { sizeof(*elems->mesh_chansw_params_ie)) {
elem_parse_failed = true; elem_parse_failed = true;
break; break;
...@@ -1253,7 +1253,7 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, ...@@ -1253,7 +1253,7 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
break; break;
case WLAN_EID_WIDE_BW_CHANNEL_SWITCH: case WLAN_EID_WIDE_BW_CHANNEL_SWITCH:
if (!action || if (!action ||
elen != sizeof(*elems->wide_bw_chansw_ie)) { elen < sizeof(*elems->wide_bw_chansw_ie)) {
elem_parse_failed = true; elem_parse_failed = true;
break; break;
} }
...@@ -1272,7 +1272,7 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, ...@@ -1272,7 +1272,7 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
ie = cfg80211_find_ie(WLAN_EID_WIDE_BW_CHANNEL_SWITCH, ie = cfg80211_find_ie(WLAN_EID_WIDE_BW_CHANNEL_SWITCH,
pos, elen); pos, elen);
if (ie) { if (ie) {
if (ie[1] == sizeof(*elems->wide_bw_chansw_ie)) if (ie[1] >= sizeof(*elems->wide_bw_chansw_ie))
elems->wide_bw_chansw_ie = elems->wide_bw_chansw_ie =
(void *)(ie + 2); (void *)(ie + 2);
else else
...@@ -1316,7 +1316,7 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, ...@@ -1316,7 +1316,7 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
elems->cisco_dtpc_elem = pos; elems->cisco_dtpc_elem = pos;
break; break;
case WLAN_EID_ADDBA_EXT: case WLAN_EID_ADDBA_EXT:
if (elen != sizeof(struct ieee80211_addba_ext_ie)) { if (elen < sizeof(struct ieee80211_addba_ext_ie)) {
elem_parse_failed = true; elem_parse_failed = true;
break; break;
} }
...@@ -1342,7 +1342,7 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, ...@@ -1342,7 +1342,7 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
elem, elems); elem, elems);
break; break;
case WLAN_EID_S1G_CAPABILITIES: case WLAN_EID_S1G_CAPABILITIES:
if (elen == sizeof(*elems->s1g_capab)) if (elen >= sizeof(*elems->s1g_capab))
elems->s1g_capab = (void *)pos; elems->s1g_capab = (void *)pos;
else else
elem_parse_failed = true; elem_parse_failed = true;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment