Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <000001d51861$e546e2a0$afd4a7e0$@com.cn>
Date: Sat, 1 Jun 2019 18:07:57 +0800
From: "huangwen" <huangwen@...usgroup.com.cn>
To: <oss-security@...ts.openwall.com>
Subject: Marvell Wifi Driver mwifiex_uap_parse_tail_ies Heap Overflow

Hi,

There is heap-based buffer overflow in marvell wifi chip driver in Linux
kernel,allows local users to cause a denial of service(system crash) or
possibly execute arbitrary code.

I provided a patch in mail attachment for reference only. 

 

 

Description

==========

The problem is inside mwifiex_uap_parse_tail_ies function in
drivers/net/wireless/marvell/mwifiex/ie.c. 

There are two memcpy in this function.The memcpy in while loop will be
called when element_id is not equal to WLAN_EID_SSID,WLAN_EID_SUPP_RATES
etc.

The copy dst buffer gen_ie->ie_buffer is a array with size
IEEE_MAX_IE_SIZE(256), the src buffer is element in cfg80211_beacon_data
from user space. 

There is not len check for two memcpy in this function.

If special elements are constructed (E.g.
WLAN_EID_SUPPORTED_OPERATING_CLASSES) to make memcpy called repeatedly, will
finally trigger the overflow.

 

 

struct mwifiex_ie {

         __le16 ie_index;

         __le16 mgmt_subtype_mask;

         __le16 ie_length;

         u8 ie_buffer[IEEE_MAX_IE_SIZE];

} __packed;

 

#define IEEE_MAX_IE_SIZE              256

 

static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,

                                           struct cfg80211_beacon_data
*info)

{

         struct mwifiex_ie *gen_ie;

         struct ieee_types_header *hdr;

         struct ieee80211_vendor_ie *vendorhdr;

         u16 gen_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0;

         int left_len, parsed_len = 0;

 

         if (!info->tail || !info->tail_len)

                   return 0;

 

         gen_ie = kzalloc(sizeof(*gen_ie), GFP_KERNEL);

         if (!gen_ie)

                   return -ENOMEM;

 

         left_len = info->tail_len;

 

         /* Many IEs are generated in FW by parsing bss configuration.

          * Let's not add them here; else we may end up duplicating these
IEs

          */

         while (left_len > sizeof(struct ieee_types_header)) {

                   hdr = (void *)(info->tail + parsed_len);

                   switch (hdr->element_id) {

                   case WLAN_EID_SSID:

                   case WLAN_EID_SUPP_RATES:

                   case WLAN_EID_COUNTRY:

                   case WLAN_EID_PWR_CONSTRAINT:

                   case WLAN_EID_ERP_INFO:

                   case WLAN_EID_EXT_SUPP_RATES:

                   case WLAN_EID_HT_CAPABILITY:

                   case WLAN_EID_HT_OPERATION:

                   case WLAN_EID_VHT_CAPABILITY:

                   case WLAN_EID_VHT_OPERATION:

                            break;

                   case WLAN_EID_VENDOR_SPECIFIC:

                            /* Skip only Microsoft WMM IE */

                            if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,

 
WLAN_OUI_TYPE_MICROSOFT_WMM,

                                                            (const u8 *)hdr,

                                                            hdr->len +
sizeof(struct ieee_types_header)))

                                     break;

                            /* fall through */

                   default:

                            memcpy(gen_ie->ie_buffer + ie_len, hdr,
//!!!!!!overflow

                                   hdr->len + sizeof(struct
ieee_types_header));

                            ie_len += hdr->len + sizeof(struct
ieee_types_header);

                            break;

                   }

                   left_len -= hdr->len + sizeof(struct ieee_types_header);

                   parsed_len += hdr->len + sizeof(struct
ieee_types_header);

         }

 

         /* parse only WPA vendor IE from tail, WMM IE is configured by

          * bss_config command

          */

         vendorhdr = (void *)cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,

 
WLAN_OUI_TYPE_MICROSOFT_WPA,

                                                            info->tail,
info->tail_len);

         if (vendorhdr) {

                   memcpy(gen_ie->ie_buffer + ie_len, vendorhdr,
//!!!!!!overflow

                          vendorhdr->len + sizeof(struct
ieee_types_header));

                   ie_len += vendorhdr->len + sizeof(struct
ieee_types_header);

         }

         .....

}

 

 

Credit

==========

This issue was discovered by huangwen of ADLab of Venustech

 

 

Patch

=====

https://lore.kernel.org/linux-wireless/20190531131841.7552-1-tiwai@suse.de

 


Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.