Ver código fonte

qcacmn: Fix potential buffer overflow

Fragment count will be larger than the upper limit which
would lead to an overread of fragment length. Upper limit
check for fragment count is added in this change.

Change-Id: Icc078b2efee554ac84377b5edd90d0a5c7a61f98
CRs-Fixed: 2158922
Zhang Qian 7 anos atrás
pai
commit
145aef1dfa
1 arquivos alterados com 11 adições e 10 exclusões
  1. 11 10
      hif/src/usb/hif_usb.c

+ 11 - 10
hif/src/usb/hif_usb.c

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
  *
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
  *
@@ -133,21 +133,22 @@ static QDF_STATUS hif_send_internal(HIF_DEVICE_USB *hif_usb_device,
 	int i;
 	int i;
 	struct hif_usb_send_context *send_context;
 	struct hif_usb_send_context *send_context;
 	uint8_t frag_count;
 	uint8_t frag_count;
-	int head_data_len, tmp_frag_count = 0;
+	uint32_t head_data_len, tmp_frag_count = 0;
 	unsigned char *data_ptr;
 	unsigned char *data_ptr;
 
 
 	HIF_DBG("+%s pipe : %d, buf:0x%pK nbytes %u",
 	HIF_DBG("+%s pipe : %d, buf:0x%pK nbytes %u",
 		__func__, pipe_id, buf, nbytes);
 		__func__, pipe_id, buf, nbytes);
 
 
 	frag_count = qdf_nbuf_get_num_frags(buf);
 	frag_count = qdf_nbuf_get_num_frags(buf);
-	if (frag_count > 1) {
+	if (frag_count == 1) {
 		/*
 		/*
 		 * | hif_usb_send_context | netbuf->data
 		 * | hif_usb_send_context | netbuf->data
 		 */
 		 */
 		head_data_len = sizeof(struct hif_usb_send_context);
 		head_data_len = sizeof(struct hif_usb_send_context);
-	} else if ((frag_count - 1) < CVG_NBUF_MAX_EXTRA_FRAGS) {
-		/* means have extra fragment buf in skb */
-		/* header data length should be total sending length substract
+	} else if ((frag_count - 1) <= QDF_NBUF_CB_TX_MAX_EXTRA_FRAGS) {
+		/*
+		 * means have extra fragment buf in skb
+		 * header data length should be total sending length substract
 		 * internal data length of netbuf
 		 * internal data length of netbuf
 		 * | hif_usb_send_context | fragments except internal buffer |
 		 * | hif_usb_send_context | fragments except internal buffer |
 		 * netbuf->data
 		 * netbuf->data
@@ -155,15 +156,15 @@ static QDF_STATUS hif_send_internal(HIF_DEVICE_USB *hif_usb_device,
 		head_data_len = sizeof(struct hif_usb_send_context);
 		head_data_len = sizeof(struct hif_usb_send_context);
 		while (tmp_frag_count < (frag_count - 1)) {
 		while (tmp_frag_count < (frag_count - 1)) {
 			head_data_len =
 			head_data_len =
-			    head_data_len +
-			    qdf_nbuf_get_frag_len(buf, tmp_frag_count);
+				head_data_len + qdf_nbuf_get_frag_len(buf,
+						tmp_frag_count);
 			tmp_frag_count = tmp_frag_count + 1;
 			tmp_frag_count = tmp_frag_count + 1;
 		}
 		}
 	} else {
 	} else {
 		/* Extra fragments overflow */
 		/* Extra fragments overflow */
 		HIF_ERROR("%s Extra fragments count overflow : %d\n",
 		HIF_ERROR("%s Extra fragments count overflow : %d\n",
-			__func__, frag_count);
-		status = QDF_STATUS_E_FAILURE;
+			  __func__, frag_count);
+		status = QDF_STATUS_E_RESOURCES;
 		goto err;
 		goto err;
 	}
 	}