Browse Source

qcacmn: Avoid possible integer overflow

In function init_deinit_chainmask_table_alloc, alloc size is declared
as uint32 and is assigned the value the multiplying non zero value
sizeof(struct wlan_psoc_host_chainmask_capabilities) and uint32
value ser_ext_par->chainmask_table[i].num_valid_chainmasks.
This can lead to overflow as multiplies value can be more than uint32.

Change-Id: I9a886d9ee5213ae8989a2c5d4502336cc275418a
CRs-Fixed: 2347650
Bala Venkatesh 6 years ago
parent
commit
c05f8e47be
1 changed files with 23 additions and 16 deletions
  1. 23 16
      target_if/init_deinit/src/service_ready_util.c

+ 23 - 16
target_if/init_deinit/src/service_ready_util.c

@@ -31,25 +31,32 @@ QDF_STATUS init_deinit_chainmask_table_alloc(
 {
 	int i;
 	uint32_t alloc_size;
-	QDF_STATUS status;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
-	if (ser_ext_par->num_chainmask_tables > 0) {
-		status = QDF_STATUS_SUCCESS;
-		for (i = 0; i < ser_ext_par->num_chainmask_tables; i++) {
-			alloc_size =
+	if (ser_ext_par->num_chainmask_tables == 0)
+		return QDF_STATUS_E_NOSUPPORT;
+
+	for (i = 0; i < ser_ext_par->num_chainmask_tables; i++) {
+		if (ser_ext_par->chainmask_table[i].num_valid_chainmasks >
+		    (UINT_MAX / sizeof(
+		     struct wlan_psoc_host_chainmask_capabilities))) {
+			target_if_err("invalid valid chanmask num %d",
+				      ser_ext_par->chainmask_table[i].
+				      num_valid_chainmasks);
+			status = QDF_STATUS_E_FAILURE;
+			break;
+		}
+		alloc_size =
 			(sizeof(struct wlan_psoc_host_chainmask_capabilities) *
-			ser_ext_par->chainmask_table[i].num_valid_chainmasks);
-
-			ser_ext_par->chainmask_table[i].cap_list =
-				qdf_mem_alloc_outline(NULL, alloc_size);
-			if (!ser_ext_par->chainmask_table[i].cap_list) {
-				init_deinit_chainmask_table_free(ser_ext_par);
-				status = QDF_STATUS_E_NOMEM;
-				break;
-			}
+			 ser_ext_par->chainmask_table[i].num_valid_chainmasks);
+
+		ser_ext_par->chainmask_table[i].cap_list =
+			qdf_mem_alloc_outline(NULL, alloc_size);
+		if (!ser_ext_par->chainmask_table[i].cap_list) {
+			init_deinit_chainmask_table_free(ser_ext_par);
+			status = QDF_STATUS_E_NOMEM;
+			break;
 		}
-	} else {
-		status = QDF_STATUS_E_NOSUPPORT;
 	}
 
 	return status;