From a007b9a25614e4a61616d55c2a9e5af5aab95494 Mon Sep 17 00:00:00 2001 From: Tiger Yu Date: Fri, 8 Dec 2017 16:39:17 +0800 Subject: [PATCH] qcacld-3.0: Fix potential buffer overflow for TX_COMPL_IND qcacld-2.0 to qcacld-3.0 propagation Check for the validity of num_msdus when received the htt message of HTT_T2H_MSG_TYPE_TX_COMPL_IND or HTT_T2H_MSG_TYPE_TX_INSPECT_IND from firmware to ensure the buffer overflow does not happen. Change-Id: Ic6ce75f34c5e2705d174eda014350e6ef0391388 CRs-Fixed: 2146869 --- core/dp/htt/htt_t2h.c | 63 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/core/dp/htt/htt_t2h.c b/core/dp/htt/htt_t2h.c index 5c857ddbee29..0be256720dcb 100644 --- a/core/dp/htt/htt_t2h.c +++ b/core/dp/htt/htt_t2h.c @@ -582,6 +582,9 @@ static void htt_t2h_lp_msg_handler(void *context, qdf_nbuf_t htt_t2h_msg, qdf_nbuf_free(htt_t2h_msg); } +#define HTT_TX_COMPL_HEAD_SZ 4 +#define HTT_TX_COMPL_BYTES_PER_MSDU_ID 2 + /** * Generic Target to host Msg/event handler for low priority messages * Low priority message are handler in a different handler called from @@ -673,10 +676,26 @@ void htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) int old_credit; int num_msdus; enum htt_tx_status status; + int msg_len = qdf_nbuf_len(htt_t2h_msg); /* status - no enum translation needed */ status = HTT_TX_COMPL_IND_STATUS_GET(*msg_word); num_msdus = HTT_TX_COMPL_IND_NUM_GET(*msg_word); + + /* + * each desc id will occupy 2 bytes. + * the 4 is for htt msg header + */ + if ((num_msdus * HTT_TX_COMPL_BYTES_PER_MSDU_ID + + HTT_TX_COMPL_HEAD_SZ) > msg_len) { + qdf_print("%s: num_msdus(%d) is invalid," + "adf_nbuf_len = %d\n", + __FUNCTION__, + num_msdus, + msg_len); + break; + } + if (num_msdus & 0x1) { struct htt_tx_compl_ind_base *compl = (void *)msg_word; @@ -765,8 +784,23 @@ void htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) case HTT_T2H_MSG_TYPE_TX_INSPECT_IND: { int num_msdus; + int msg_len = qdf_nbuf_len(htt_t2h_msg); num_msdus = HTT_TX_COMPL_IND_NUM_GET(*msg_word); + /* + * each desc id will occupy 2 bytes. + * the 4 is for htt msg header + */ + if ((num_msdus * HTT_TX_COMPL_BYTES_PER_MSDU_ID + + HTT_TX_COMPL_HEAD_SZ) > msg_len) { + qdf_print("%s: num_msdus(%d) is invalid," + "adf_nbuf_len = %d\n", + __FUNCTION__, + num_msdus, + msg_len); + break; + } + if (num_msdus & 0x1) { struct htt_tx_compl_ind_base *compl = (void *)msg_word; @@ -933,6 +967,21 @@ void htt_t2h_msg_handler_fast(void *context, qdf_nbuf_t *cmpl_msdus, /* status - no enum translation needed */ status = HTT_TX_COMPL_IND_STATUS_GET(*msg_word); num_msdus = HTT_TX_COMPL_IND_NUM_GET(*msg_word); + + /* + * each desc id will occupy 2 bytes. + * the 4 is for htt msg header + */ + if ((num_msdus * HTT_TX_COMPL_BYTES_PER_MSDU_ID + + HTT_TX_COMPL_HEAD_SZ) > msg_len) { + qdf_print("%s: num_msdus(%d) is invalid," + "adf_nbuf_len = %d\n", + __FUNCTION__, + num_msdus, + msg_len); + break; + } + if (num_msdus & 0x1) { struct htt_tx_compl_ind_base *compl = (void *)msg_word; @@ -992,6 +1041,20 @@ void htt_t2h_msg_handler_fast(void *context, qdf_nbuf_t *cmpl_msdus, int num_msdus; num_msdus = HTT_TX_COMPL_IND_NUM_GET(*msg_word); + /* + * each desc id will occupy 2 bytes. + * the 4 is for htt msg header + */ + if ((num_msdus * HTT_TX_COMPL_BYTES_PER_MSDU_ID + + HTT_TX_COMPL_HEAD_SZ) > msg_len) { + qdf_print("%s: num_msdus(%d) is invalid," + "adf_nbuf_len = %d\n", + __FUNCTION__, + num_msdus, + msg_len); + break; + } + if (num_msdus & 0x1) { struct htt_tx_compl_ind_base *compl = (void *)msg_word;