From 4ea468554d0ad088f0665fc66e63a7bf11dfe095 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 17 Jun 2019 19:32:38 +0100 Subject: [PATCH] mwifiex: Fix heap overflow in mwifiex_uap_parse_tail_ies() (CVE-2019-10126) --- debian/changelog | 2 + ...-overflow-in-mwifiex_uap_parse_tail_.patch | 118 ++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 121 insertions(+) create mode 100644 debian/patches/bugfix/all/mwifiex-fix-heap-overflow-in-mwifiex_uap_parse_tail_.patch diff --git a/debian/changelog b/debian/changelog index 5c2d06a14..9ddfe6a3d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -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 diff --git a/debian/patches/bugfix/all/mwifiex-fix-heap-overflow-in-mwifiex_uap_parse_tail_.patch b/debian/patches/bugfix/all/mwifiex-fix-heap-overflow-in-mwifiex_uap_parse_tail_.patch new file mode 100644 index 000000000..1456e36bc --- /dev/null +++ b/debian/patches/bugfix/all/mwifiex-fix-heap-overflow-in-mwifiex_uap_parse_tail_.patch @@ -0,0 +1,118 @@ +From: Takashi Iwai +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 +Signed-off-by: Takashi Iwai +Signed-off-by: Kalle Valo +[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, diff --git a/debian/patches/series b/debian/patches/series index df2100c53..ba723b226 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -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