From 145aef1dfa36c01e1c152bb6388c197e25f66a2d Mon Sep 17 00:00:00 2001 From: Zhang Qian Date: Thu, 14 Dec 2017 16:30:21 +0800 Subject: [PATCH] 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 --- hif/src/usb/hif_usb.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/hif/src/usb/hif_usb.c b/hif/src/usb/hif_usb.c index 41bf6e560ae0..fc269ce2e0fe 100644 --- a/hif/src/usb/hif_usb.c +++ b/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. * @@ -133,21 +133,22 @@ static QDF_STATUS hif_send_internal(HIF_DEVICE_USB *hif_usb_device, int i; struct hif_usb_send_context *send_context; 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; HIF_DBG("+%s pipe : %d, buf:0x%pK nbytes %u", __func__, pipe_id, buf, nbytes); frag_count = qdf_nbuf_get_num_frags(buf); - if (frag_count > 1) { + if (frag_count == 1) { /* * | hif_usb_send_context | netbuf->data */ 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 * | hif_usb_send_context | fragments except internal buffer | * 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); while (tmp_frag_count < (frag_count - 1)) { 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; } } else { /* Extra fragments overflow */ 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; }