Commit 8a07b00e authored by Brian Norris's avatar Brian Norris Committed by Kleber Sacilotto de Souza

mwifiex: Don't abort on small, spec-compliant vendor IEs

BugLink: https://bugs.launchpad.net/bugs/1838467

commit 63d7ef36 upstream.

Per the 802.11 specification, vendor IEs are (at minimum) only required
to contain an OUI. A type field is also included in ieee80211.h (struct
ieee80211_vendor_ie) but doesn't appear in the specification. The
remaining fields (subtype, version) are a convention used in WMM
headers.

Thus, we should not reject vendor-specific IEs that have only the
minimum length (3 bytes) -- we should skip over them (since we only want
to match longer IEs, that match either WMM or WPA formats). We can
reject elements that don't have the minimum-required 3 byte OUI.

While we're at it, move the non-standard subtype and version fields into
the WMM structs, to avoid this confusion in the future about generic
"vendor header" attributes.

Fixes: 685c9b77 ("mwifiex: Abort at too short BSS descriptor element")
Cc: Takashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarBrian Norris <briannorris@chromium.org>
Reviewed-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarConnor Kuehl <connor.kuehl@canonical.com>
Signed-off-by: default avatarKhalid Elmously <khalid.elmously@canonical.com>
parent 4bac4e2c
...@@ -1613,9 +1613,10 @@ struct mwifiex_ie_types_wmm_queue_status { ...@@ -1613,9 +1613,10 @@ struct mwifiex_ie_types_wmm_queue_status {
struct ieee_types_vendor_header { struct ieee_types_vendor_header {
u8 element_id; u8 element_id;
u8 len; u8 len;
u8 oui[4]; /* 0~2: oui, 3: oui_type */ struct {
u8 oui_subtype; u8 oui[3];
u8 version; u8 oui_type;
} __packed oui;
} __packed; } __packed;
struct ieee_types_wmm_parameter { struct ieee_types_wmm_parameter {
...@@ -1629,6 +1630,9 @@ struct ieee_types_wmm_parameter { ...@@ -1629,6 +1630,9 @@ struct ieee_types_wmm_parameter {
* Version [1] * Version [1]
*/ */
struct ieee_types_vendor_header vend_hdr; struct ieee_types_vendor_header vend_hdr;
u8 oui_subtype;
u8 version;
u8 qos_info_bitmap; u8 qos_info_bitmap;
u8 reserved; u8 reserved;
struct ieee_types_wmm_ac_parameters ac_params[IEEE80211_NUM_ACS]; struct ieee_types_wmm_ac_parameters ac_params[IEEE80211_NUM_ACS];
...@@ -1646,6 +1650,8 @@ struct ieee_types_wmm_info { ...@@ -1646,6 +1650,8 @@ struct ieee_types_wmm_info {
* Version [1] * Version [1]
*/ */
struct ieee_types_vendor_header vend_hdr; struct ieee_types_vendor_header vend_hdr;
u8 oui_subtype;
u8 version;
u8 qos_info_bitmap; u8 qos_info_bitmap;
} __packed; } __packed;
......
...@@ -1332,21 +1332,25 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, ...@@ -1332,21 +1332,25 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
break; break;
case WLAN_EID_VENDOR_SPECIFIC: case WLAN_EID_VENDOR_SPECIFIC:
if (element_len + 2 < sizeof(vendor_ie->vend_hdr))
return -EINVAL;
vendor_ie = (struct ieee_types_vendor_specific *) vendor_ie = (struct ieee_types_vendor_specific *)
current_ptr; current_ptr;
if (!memcmp /* 802.11 requires at least 3-byte OUI. */
(vendor_ie->vend_hdr.oui, wpa_oui, if (element_len < sizeof(vendor_ie->vend_hdr.oui.oui))
sizeof(wpa_oui))) { return -EINVAL;
/* Not long enough for a match? Skip it. */
if (element_len < sizeof(wpa_oui))
break;
if (!memcmp(&vendor_ie->vend_hdr.oui, wpa_oui,
sizeof(wpa_oui))) {
bss_entry->bcn_wpa_ie = bss_entry->bcn_wpa_ie =
(struct ieee_types_vendor_specific *) (struct ieee_types_vendor_specific *)
current_ptr; current_ptr;
bss_entry->wpa_offset = (u16) bss_entry->wpa_offset = (u16)
(current_ptr - bss_entry->beacon_buf); (current_ptr - bss_entry->beacon_buf);
} else if (!memcmp(vendor_ie->vend_hdr.oui, wmm_oui, } else if (!memcmp(&vendor_ie->vend_hdr.oui, wmm_oui,
sizeof(wmm_oui))) { sizeof(wmm_oui))) {
if (total_ie_len == if (total_ie_len ==
sizeof(struct ieee_types_wmm_parameter) || sizeof(struct ieee_types_wmm_parameter) ||
......
...@@ -1326,7 +1326,7 @@ mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr, ...@@ -1326,7 +1326,7 @@ mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr,
pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr; pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr;
/* Test to see if it is a WPA IE, if not, then it is a gen IE */ /* Test to see if it is a WPA IE, if not, then it is a gen IE */
if (((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) && if (((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) &&
(!memcmp(pvendor_ie->oui, wpa_oui, sizeof(wpa_oui)))) || (!memcmp(&pvendor_ie->oui, wpa_oui, sizeof(wpa_oui)))) ||
(pvendor_ie->element_id == WLAN_EID_RSN)) { (pvendor_ie->element_id == WLAN_EID_RSN)) {
/* IE is a WPA/WPA2 IE so call set_wpa function */ /* IE is a WPA/WPA2 IE so call set_wpa function */
...@@ -1351,7 +1351,7 @@ mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr, ...@@ -1351,7 +1351,7 @@ mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr,
*/ */
pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr; pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr;
if ((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) && if ((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) &&
(!memcmp(pvendor_ie->oui, wps_oui, sizeof(wps_oui)))) { (!memcmp(&pvendor_ie->oui, wps_oui, sizeof(wps_oui)))) {
priv->wps.session_enable = true; priv->wps.session_enable = true;
mwifiex_dbg(priv->adapter, INFO, mwifiex_dbg(priv->adapter, INFO,
"info: WPS Session Enabled.\n"); "info: WPS Session Enabled.\n");
......
...@@ -240,7 +240,7 @@ mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv, ...@@ -240,7 +240,7 @@ mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv,
mwifiex_dbg(priv->adapter, INFO, mwifiex_dbg(priv->adapter, INFO,
"info: WMM Parameter IE: version=%d,\t" "info: WMM Parameter IE: version=%d,\t"
"qos_info Parameter Set Count=%d, Reserved=%#x\n", "qos_info Parameter Set Count=%d, Reserved=%#x\n",
wmm_ie->vend_hdr.version, wmm_ie->qos_info_bitmap & wmm_ie->version, wmm_ie->qos_info_bitmap &
IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK, IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK,
wmm_ie->reserved); wmm_ie->reserved);
......
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