mwifiex: Fix heap overflow in mwifiex_uap_parse_tail_ies() (CVE-2019-10126)

This commit is contained in:
Ben Hutchings 2019-06-17 19:32:38 +01:00
parent e5664e23f5
commit 4ea468554d
3 changed files with 121 additions and 0 deletions

2
debian/changelog vendored
View File

@ -13,6 +13,8 @@ linux (4.19.37-4) UNRELEASED; urgency=medium
* mwifiex: Abort at too short BSS descriptor element
* mwifiex: Don't abort on small, spec-compliant vendor IEs
* mm/mincore.c: make mincore() more conservative (CVE-2019-5489)
* mwifiex: Fix heap overflow in mwifiex_uap_parse_tail_ies()
(CVE-2019-10126)
[ Romain Perier ]
* [rt] Update to 4.19.37-rt20

View File

@ -0,0 +1,118 @@
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 31 May 2019 15:18:41 +0200
Subject: mwifiex: Fix heap overflow in mwifiex_uap_parse_tail_ies()
Origin: https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers.git/commit?id=69ae4f6aac1578575126319d3f55550e7e440449
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-10126
A few places in mwifiex_uap_parse_tail_ies() perform memcpy()
unconditionally, which may lead to either buffer overflow or read over
boundary.
This patch addresses the issues by checking the read size and the
destination size at each place more properly. Along with the fixes,
the patch cleans up the code slightly by introducing a temporary
variable for the token size, and unifies the error path with the
standard goto statement.
Reported-by: huangwen <huangwen@venustech.com.cn>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
[bwh: Backported to 4.19: adjust context]
---
drivers/net/wireless/marvell/mwifiex/ie.c | 47 +++++++++++++++--------
1 file changed, 31 insertions(+), 16 deletions(-)
--- a/drivers/net/wireless/marvell/mwifiex/ie.c
+++ b/drivers/net/wireless/marvell/mwifiex/ie.c
@@ -329,6 +329,8 @@ static int mwifiex_uap_parse_tail_ies(st
struct ieee80211_vendor_ie *vendorhdr;
u16 gen_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0;
int left_len, parsed_len = 0;
+ unsigned int token_len;
+ int err = 0;
if (!info->tail || !info->tail_len)
return 0;
@@ -344,6 +346,12 @@ static int mwifiex_uap_parse_tail_ies(st
*/
while (left_len > sizeof(struct ieee_types_header)) {
hdr = (void *)(info->tail + parsed_len);
+ token_len = hdr->len + sizeof(struct ieee_types_header);
+ if (token_len > left_len) {
+ err = -EINVAL;
+ goto out;
+ }
+
switch (hdr->element_id) {
case WLAN_EID_SSID:
case WLAN_EID_SUPP_RATES:
@@ -361,16 +369,19 @@ static int mwifiex_uap_parse_tail_ies(st
if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
WLAN_OUI_TYPE_MICROSOFT_WMM,
(const u8 *)hdr,
- hdr->len + sizeof(struct ieee_types_header)))
+ token_len))
break;
default:
- memcpy(gen_ie->ie_buffer + ie_len, hdr,
- hdr->len + sizeof(struct ieee_types_header));
- ie_len += hdr->len + sizeof(struct ieee_types_header);
+ if (ie_len + token_len > IEEE_MAX_IE_SIZE) {
+ err = -EINVAL;
+ goto out;
+ }
+ memcpy(gen_ie->ie_buffer + ie_len, hdr, token_len);
+ ie_len += token_len;
break;
}
- left_len -= hdr->len + sizeof(struct ieee_types_header);
- parsed_len += hdr->len + sizeof(struct ieee_types_header);
+ left_len -= token_len;
+ parsed_len += token_len;
}
/* parse only WPA vendor IE from tail, WMM IE is configured by
@@ -380,15 +391,17 @@ static int mwifiex_uap_parse_tail_ies(st
WLAN_OUI_TYPE_MICROSOFT_WPA,
info->tail, info->tail_len);
if (vendorhdr) {
- memcpy(gen_ie->ie_buffer + ie_len, vendorhdr,
- vendorhdr->len + sizeof(struct ieee_types_header));
- ie_len += vendorhdr->len + sizeof(struct ieee_types_header);
+ token_len = vendorhdr->len + sizeof(struct ieee_types_header);
+ if (ie_len + token_len > IEEE_MAX_IE_SIZE) {
+ err = -EINVAL;
+ goto out;
+ }
+ memcpy(gen_ie->ie_buffer + ie_len, vendorhdr, token_len);
+ ie_len += token_len;
}
- if (!ie_len) {
- kfree(gen_ie);
- return 0;
- }
+ if (!ie_len)
+ goto out;
gen_ie->ie_index = cpu_to_le16(gen_idx);
gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON |
@@ -398,13 +411,15 @@ static int mwifiex_uap_parse_tail_ies(st
if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL, NULL,
NULL, NULL)) {
- kfree(gen_ie);
- return -1;
+ err = -EINVAL;
+ goto out;
}
priv->gen_idx = gen_idx;
+
+ out:
kfree(gen_ie);
- return 0;
+ return err;
}
/* This function parses different IEs-head & tail IEs, beacon IEs,

View File

@ -221,6 +221,7 @@ bugfix/all/mwifiex-fix-possible-buffer-overflows-at-parsing-bss.patch
bugfix/all/mwifiex-abort-at-too-short-bss-descriptor-element.patch
bugfix/all/mwifiex-don-t-abort-on-small-spec-compliant-vendor-ies.patch
bugfix/all/mm-mincore.c-make-mincore-more-conservative.patch
bugfix/all/mwifiex-fix-heap-overflow-in-mwifiex_uap_parse_tail_.patch
# Fix exported symbol versions
bugfix/all/module-disable-matching-missing-version-crc.patch