Browse Source

qcacmn: fix out of bound access of memories in wlan_cfg80211_scan

In wlan_cfg80211_scan the number of ssid, ssid length and number of
channels are not checked for max size of array and thus can lead to
Out of bound access of memories.

Fix is to add bound check before copying the params.

Change-Id: Ie6d4e546fb9c884d5988493b611ef7b217f0a95c
CRs-Fixed: 2375217
Abhishek Singh 6 years ago
parent
commit
00f80b6094

+ 16 - 7
os_if/linux/scan/src/wlan_cfg80211_scan.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -1225,17 +1225,24 @@ int wlan_cfg80211_scan(struct wlan_objmgr_vdev *vdev,
 		int j;
 		req->scan_req.num_ssids = request->n_ssids;
 
+		if (req->scan_req.num_ssids > WLAN_SCAN_MAX_NUM_SSID) {
+			cfg80211_info("number of ssid received %d is greater than MAX %d so copy only MAX nuber of SSIDs",
+				      req->scan_req.num_ssids,
+				      WLAN_SCAN_MAX_NUM_SSID);
+			req->scan_req.num_ssids = WLAN_SCAN_MAX_NUM_SSID;
+		}
 		/* copy all the ssid's and their length */
-		for (j = 0; j < request->n_ssids; j++)  {
+		for (j = 0; j < req->scan_req.num_ssids; j++)  {
 			pssid = &req->scan_req.ssid[j];
 			/* get the ssid length */
 			pssid->length = request->ssids[j].ssid_len;
+			if (pssid->length > WLAN_SSID_MAX_LEN)
+				pssid->length = WLAN_SSID_MAX_LEN;
 			qdf_mem_copy(pssid->ssid,
 				     &request->ssids[j].ssid[0],
 				     pssid->length);
-			pssid->ssid[pssid->length] = '\0';
-			cfg80211_notice("SSID number %d: %s", j,
-				    pssid->ssid);
+			cfg80211_info("SSID number %d: %.*s", j, pssid->length,
+				      pssid->ssid);
 		}
 	}
 	if (request->ssids ||
@@ -1321,9 +1328,11 @@ int wlan_cfg80211_scan(struct wlan_objmgr_vdev *vdev,
 				req->scan_req.chan_list.chan[num_chan].phymode =
 					SCAN_PHY_MODE_11A;
 			num_chan++;
+			if (num_chan >= WLAN_SCAN_MAX_NUM_CHANNELS)
+				break;
 		}
-		cfg80211_notice("Channel-List: %s", chl);
-		cfg80211_notice("No. of Scan Channels: %d", num_chan);
+		cfg80211_info("Channel-List: %s", chl);
+		cfg80211_info("No. of Scan Channels: %d", num_chan);
 	}
 	if (!num_chan) {
 		cfg80211_err("Received zero non-dsrc channels");

+ 4 - 4
umac/scan/dispatcher/inc/wlan_scan_public_structs.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -32,9 +32,9 @@
 typedef uint16_t wlan_scan_requester;
 typedef uint32_t wlan_scan_id;
 
-#define WLAN_SCAN_MAX_NUM_SSID          10
-#define WLAN_SCAN_MAX_NUM_BSSID         10
-#define WLAN_SCAN_MAX_NUM_CHANNELS      40
+#define WLAN_SCAN_MAX_NUM_SSID          16
+#define WLAN_SCAN_MAX_NUM_BSSID         4
+#define WLAN_SCAN_MAX_NUM_CHANNELS      68
 
 #define SCM_CANCEL_SCAN_WAIT_TIME 50
 #define SCM_CANCEL_SCAN_WAIT_ITERATION 600

+ 0 - 1
wmi/inc/wmi_unified_param.h

@@ -37,7 +37,6 @@
 
 #define IEEE80211_ADDR_LEN  6  /* size of 802.11 address */
 #define WMI_MAC_MAX_SSID_LENGTH              32
-#define WMI_SCAN_MAX_NUM_SSID                0x0A
 #ifndef CONFIG_HL_SUPPORT
 #define mgmt_tx_dl_frm_len 64
 #else

+ 2 - 2
wmi/src/wmi_unified_tlv.c

@@ -2569,8 +2569,8 @@ static QDF_STATUS send_scan_start_cmd_tlv(wmi_unified_t wmi_handle,
 	buf_ptr += WMI_TLV_HDR_SIZE +
 			(params->chan_list.num_chan * sizeof(uint32_t));
 
-	if (params->num_ssids > WMI_SCAN_MAX_NUM_SSID) {
-		WMI_LOGE("Invalid value for numSsid");
+	if (params->num_ssids > WLAN_SCAN_MAX_NUM_SSID) {
+		WMI_LOGE("Invalid value for num_ssids %d", params->num_ssids);
 		goto error;
 	}