Browse Source

qcacmn: Add length check in beacon IE parsing function

Add length check in scan beacon IE processing function for the below IEs to
avoid any possible memory corruption.
1. WLAN_EXTN_ELEMID_SRP
2. WLAN_EXTN_ELEMID_HEOP
3. WLAN_EXTN_ELEMID_MUEDCA
4. WLAN_EXTN_ELEMID_HE_6G_CAP
5. WLAN_ELEMID_XRATES
6. WLAN_VENDOR_WPA_IE_LEN
7. WLAN_VENDOR_WME_IE_LEN
8. WLAN_VENDOR_ATHCAPS_IE_LEN
9. WLAN_VENDOR_ATH_EXTCAP_IE_LEN
10. WLAN_VENDOR_SFA_IE_LEN
11. WLAN_VENDOR_SON_IE_LEN
12. WLAN_BWNSS_MAP_OFFSET

Change-Id: I8441178c8e9da6f9e7a16915e7664bca090fe86e
CRs-Fixed: 2874025
Shashikala Prabhu 4 years ago
parent
commit
a5d8ab2306

+ 22 - 3
umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h

@@ -128,7 +128,8 @@
 
 /* Individual element IEs length checks */
 
-#define WLAN_SUPPORTED_RATES_IE_MAX_LEN          12
+/* Maximum supported basic/mandatory rates are 8. */
+#define WLAN_SUPPORTED_RATES_IE_MAX_LEN          8
 #define WLAN_FH_PARAM_IE_MAX_LEN                 5
 #define WLAN_DS_PARAM_IE_MAX_LEN                 1
 #define WLAN_CF_PARAM_IE_MAX_LEN                 6
@@ -137,7 +138,14 @@
 #define WLAN_CSA_IE_MAX_LEN                      3
 #define WLAN_XCSA_IE_MAX_LEN                     4
 #define WLAN_SECCHANOFF_IE_MAX_LEN               1
-#define WLAN_EXT_SUPPORTED_RATES_IE_MAX_LEN      12
+
+#define WLAN_MAX_SUPPORTED_RATES                 44
+/* Maximum extended supported rates is equal to WLAN_MAX_SUPPORTED_RATES minus
+ * WLAN_SUPPORTED_RATES_IE_MAX_LEN.
+ */
+#define WLAN_EXT_SUPPORTED_RATES_IE_MAX_LEN      \
+	(WLAN_MAX_SUPPORTED_RATES - WLAN_SUPPORTED_RATES_IE_MAX_LEN)
+
 #define WLAN_EXTCAP_IE_MAX_LEN                   15
 #define WLAN_FILS_INDICATION_IE_MIN_LEN          2
 #define WLAN_MOBILITY_DOMAIN_IE_MAX_LEN          3
@@ -161,6 +169,11 @@
 /* Max channel switch time IE length */
 #define WLAN_MAX_CHAN_SWITCH_TIME_IE_LEN         4
 
+#define WLAN_MAX_SRP_IE_LEN                      21
+#define WLAN_MAX_MUEDCA_IE_LEN                   14
+#define WLAN_MAX_HE_6G_CAP_IE_LEN                3
+#define WLAN_MAX_HEOP_IE_LEN                     16
+
 /* HT capability flags */
 #define WLAN_HTCAP_C_ADVCODING             0x0001
 #define WLAN_HTCAP_C_CHWIDTH40             0x0002
@@ -1613,6 +1626,7 @@ struct oce_reduced_wan_metrics {
 	uint8_t uplink_av_cap:4;
 };
 
+#define WLAN_VENDOR_WPA_IE_LEN 28
 /**
  * is_wpa_oui() - If vendor IE is WPA type
  * @frm: vendor IE pointer
@@ -1671,6 +1685,7 @@ is_wcn_oui(uint8_t *frm)
 		((WCN_OUI_TYPE << 24) | WCN_OUI));
 }
 
+#define WLAN_VENDOR_WME_IE_LEN 24
 /**
  * is_wme_param() - If vendor IE is WME param type
  * @frm: vendor IE pointer
@@ -1703,6 +1718,7 @@ is_wme_info(const uint8_t *frm)
 		(frm[6] == WME_INFO_OUI_SUBTYPE);
 }
 
+#define WLAN_VENDOR_ATHCAPS_IE_LEN 9
 /**
  * is_atheros_oui() - If vendor IE is Atheros type
  * @frm: vendor IE pointer
@@ -1718,6 +1734,7 @@ is_atheros_oui(const uint8_t *frm)
 		((ATH_OUI_TYPE << 24) | ATH_OUI);
 }
 
+#define WLAN_VENDOR_ATH_EXTCAP_IE_LEN 10
 /**
  * is_atheros_extcap_oui() - If vendor IE is Atheros ext cap
  * @frm: vendor IE pointer
@@ -1733,6 +1750,7 @@ is_atheros_extcap_oui(uint8_t *frm)
 		((ATH_OUI_EXTCAP_TYPE << 24) | ATH_OUI));
 }
 
+#define WLAN_VENDOR_SFA_IE_LEN 5
 /**
  * is_sfa_oui() - If vendor IE is SFA type
  * @frm: vendor IE pointer
@@ -1768,6 +1786,7 @@ is_p2p_oui(const uint8_t *frm)
 		(frm[5] == P2P_WFA_VER);
 }
 
+#define WLAN_VENDOR_SON_IE_LEN 31
 /**
  * is_qca_son_oui() - If vendor IE is QCA WHC type
  * @frm: vendor IE pointer
@@ -1847,7 +1866,7 @@ is_bwnss_oui(uint8_t *frm)
 		((ATH_OUI_BW_NSS_MAP_TYPE << 24) | ATH_OUI));
 }
 
-#define WLAN_BWNSS_MAP_OFFSET 6
+#define WLAN_BWNSS_MAP_OFFSET 7
 
 /**
  * is_he_cap_oui() - If vendor IE is HE CAP OUI

+ 28 - 0
umac/scan/dispatcher/src/wlan_scan_utils_api.c

@@ -773,21 +773,29 @@ util_scan_parse_extn_ie(struct scan_cache_entry *scan_params,
 		scan_params->ie_list.mcst  = (uint8_t *)ie;
 		break;
 	case WLAN_EXTN_ELEMID_SRP:
+		if (extn_ie->ie_len > WLAN_MAX_SRP_IE_LEN)
+			return QDF_STATUS_E_INVAL;
 		scan_params->ie_list.srp   = (uint8_t *)ie;
 		break;
 	case WLAN_EXTN_ELEMID_HECAP:
 		scan_params->ie_list.hecap = (uint8_t *)ie;
 		break;
 	case WLAN_EXTN_ELEMID_HEOP:
+		if (extn_ie->ie_len > WLAN_MAX_HEOP_IE_LEN)
+			return QDF_STATUS_E_INVAL;
 		scan_params->ie_list.heop  = (uint8_t *)ie;
 		break;
 	case WLAN_EXTN_ELEMID_ESP:
 		scan_params->ie_list.esp = (uint8_t *)ie;
 		break;
 	case WLAN_EXTN_ELEMID_MUEDCA:
+		if (extn_ie->ie_len > WLAN_MAX_MUEDCA_IE_LEN)
+			return QDF_STATUS_E_INVAL;
 		scan_params->ie_list.muedca = (uint8_t *)ie;
 		break;
 	case WLAN_EXTN_ELEMID_HE_6G_CAP:
+		if (extn_ie->ie_len > WLAN_MAX_HE_6G_CAP_IE_LEN)
+			return QDF_STATUS_E_INVAL;
 		scan_params->ie_list.hecap_6g = (uint8_t *)ie;
 		break;
 	default:
@@ -804,6 +812,9 @@ util_scan_parse_vendor_ie(struct scan_cache_entry *scan_params,
 		scan_params->ie_list.vendor = (uint8_t *)ie;
 
 	if (is_wpa_oui((uint8_t *)ie)) {
+		if (ie->ie_len > WLAN_VENDOR_WPA_IE_LEN)
+			return QDF_STATUS_E_INVAL;
+
 		scan_params->ie_list.wpa = (uint8_t *)ie;
 	} else if (is_wps_oui((uint8_t *)ie)) {
 		scan_params->ie_list.wps = (uint8_t *)ie;
@@ -811,19 +822,34 @@ util_scan_parse_vendor_ie(struct scan_cache_entry *scan_params,
 		if (is_wcn_oui((uint8_t *)ie))
 			scan_params->ie_list.wcn = (uint8_t *)ie;
 	} else if (is_wme_param((uint8_t *)ie)) {
+		if (ie->ie_len > WLAN_VENDOR_WME_IE_LEN)
+			return QDF_STATUS_E_INVAL;
+
 		scan_params->ie_list.wmeparam = (uint8_t *)ie;
 	} else if (is_wme_info((uint8_t *)ie)) {
 		scan_params->ie_list.wmeinfo = (uint8_t *)ie;
 	} else if (is_atheros_oui((uint8_t *)ie)) {
+		if (ie->ie_len > WLAN_VENDOR_ATHCAPS_IE_LEN)
+			return QDF_STATUS_E_INVAL;
+
 		scan_params->ie_list.athcaps = (uint8_t *)ie;
 	} else if (is_atheros_extcap_oui((uint8_t *)ie)) {
+		if (ie->ie_len > WLAN_VENDOR_ATH_EXTCAP_IE_LEN)
+			return QDF_STATUS_E_INVAL;
+
 		scan_params->ie_list.athextcaps = (uint8_t *)ie;
 	} else if (is_sfa_oui((uint8_t *)ie)) {
+		if (ie->ie_len > WLAN_VENDOR_SFA_IE_LEN)
+			return QDF_STATUS_E_INVAL;
+
 		scan_params->ie_list.sfa = (uint8_t *)ie;
 	} else if (is_p2p_oui((uint8_t *)ie)) {
 		scan_params->ie_list.p2p = (uint8_t *)ie;
 	} else if (is_qca_son_oui((uint8_t *)ie,
 				  QCA_OUI_WHC_AP_INFO_SUBTYPE)) {
+		if (ie->ie_len > WLAN_VENDOR_SON_IE_LEN)
+			return QDF_STATUS_E_INVAL;
+
 		scan_params->ie_list.sonadv = (uint8_t *)ie;
 	} else if (is_ht_cap((uint8_t *)ie)) {
 		/* we only care if there isn't already an HT IE (ANA) */
@@ -1041,6 +1067,8 @@ util_scan_populate_bcn_ie_list(struct wlan_objmgr_pdev *pdev,
 			scan_params->ie_list.rsn = (uint8_t *)ie;
 			break;
 		case WLAN_ELEMID_XRATES:
+			if (ie->ie_len > WLAN_EXT_SUPPORTED_RATES_IE_MAX_LEN)
+				goto err;
 			scan_params->ie_list.xrates = (uint8_t *)ie;
 			break;
 		case WLAN_ELEMID_EXTCHANSWITCHANN: