qcacld-2.0: Fix buffer overflow in HTT MSG handling

If the firmware gets compromised, the values sent to
the driver could result in buffer overflows.
Validate HTT MSG "msg_word" to avoid buffer overflows.

Change-Id: I6073029f61a358da32bcc0dcfc339d9bb7ee8218
CRs-Fixed: 2529113
This commit is contained in:
Alok Kumar 2019-09-17 12:32:18 +05:30 committed by L R
parent 4bf0441ae5
commit 452dc79c1c
1 changed files with 62 additions and 1 deletions

View File

@ -177,6 +177,12 @@ htt_t2h_lp_msg_handler(void *context, adf_nbuf_t htt_t2h_msg )
u_int16_t seq_num_start, seq_num_end;
enum htt_rx_flush_action action;
if (adf_nbuf_len(htt_t2h_msg) < HTT_RX_FLUSH_BYTES) {
adf_print("invalid nbuff len");
WARN_ON(1);
break;
}
peer_id = HTT_RX_FLUSH_PEER_ID_GET(*msg_word);
tid = HTT_RX_FLUSH_TID_GET(*msg_word);
seq_num_start = HTT_RX_FLUSH_SEQ_NUM_START_GET(*(msg_word+1));
@ -211,6 +217,13 @@ htt_t2h_lp_msg_handler(void *context, adf_nbuf_t htt_t2h_msg )
{
u_int16_t peer_id;
u_int8_t tid;
int msg_len = adf_nbuf_len(htt_t2h_msg);
if (msg_len < HTT_RX_FRAG_IND_BYTES) {
adf_print("invalid nbuff len");
WARN_ON(1);
break;
}
peer_id = HTT_RX_FRAG_IND_PEER_ID_GET(*msg_word);
tid = HTT_RX_FRAG_IND_EXT_TID_GET(*msg_word);
@ -294,6 +307,12 @@ htt_t2h_lp_msg_handler(void *context, adf_nbuf_t htt_t2h_msg )
u_int16_t peer_id;
u_int8_t vdev_id;
if (adf_nbuf_len(htt_t2h_msg) < HTT_RX_PEER_MAP_BYTES) {
adf_print("invalid nbuff len");
WARN_ON(1);
break;
}
peer_id = HTT_RX_PEER_MAP_PEER_ID_GET(*msg_word);
vdev_id = HTT_RX_PEER_MAP_VDEV_ID_GET(*msg_word);
peer_mac_addr = htt_t2h_mac_addr_deswizzle(
@ -314,6 +333,13 @@ htt_t2h_lp_msg_handler(void *context, adf_nbuf_t htt_t2h_msg )
case HTT_T2H_MSG_TYPE_PEER_UNMAP:
{
u_int16_t peer_id;
if (adf_nbuf_len(htt_t2h_msg) < HTT_RX_PEER_UNMAP_BYTES) {
adf_print("invalid nbuff len");
WARN_ON(1);
break;
}
peer_id = HTT_RX_PEER_UNMAP_PEER_ID_GET(*msg_word);
if (peer_id > ol_cfg_max_peer_id(pdev->ctrl_pdev)) {
@ -333,6 +359,12 @@ htt_t2h_lp_msg_handler(void *context, adf_nbuf_t htt_t2h_msg )
enum htt_sec_type sec_type;
int is_unicast;
if (adf_nbuf_len(htt_t2h_msg) < HTT_SEC_IND_BYTES) {
adf_print("invalid nbuff len");
WARN_ON(1);
break;
}
peer_id = HTT_SEC_IND_PEER_ID_GET(*msg_word);
sec_type = HTT_SEC_IND_SEC_TYPE_GET(*msg_word);
is_unicast = HTT_SEC_IND_UNICAST_GET(*msg_word);
@ -419,6 +451,12 @@ htt_t2h_lp_msg_handler(void *context, adf_nbuf_t htt_t2h_msg )
int32_t htt_credit_delta;
int sign, old_credit;
if (adf_nbuf_len(htt_t2h_msg) < HTT_TX_CREDIT_MSG_BYTES) {
adf_print("invalid nbuff len");
WARN_ON(1);
break;
}
htt_credit_delta_abs = HTT_TX_CREDIT_DELTA_ABS_GET(*msg_word);
sign = HTT_TX_CREDIT_SIGN_BIT_GET(*msg_word) ? -1 : 1;
htt_credit_delta = sign * htt_credit_delta_abs;
@ -491,7 +529,16 @@ htt_t2h_lp_msg_handler(void *context, adf_nbuf_t htt_t2h_msg )
struct ol_txrx_vdev_t *vdev;
struct ol_txrx_peer_t *peer;
u_int8_t * pn_ptr;
u_int16_t peer_id =
u_int16_t peer_id;
int msg_len = adf_nbuf_len(htt_t2h_msg);
if (msg_len < HTT_RX_OFLD_PKT_ERR_MIC_ERR_BYTES) {
adf_print("invalid nbuff len");
WARN_ON(1);
break;
}
peer_id =
HTT_RX_OFLD_PKT_ERR_MIC_ERR_PEER_ID_GET(*(msg_word + 1));
peer = ol_txrx_peer_find_by_id(pdev->txrx_pdev, peer_id);
@ -777,6 +824,13 @@ if (adf_os_unlikely(pdev->rx_ring.rx_reset)) {
u_int16_t peer_id;
u_int8_t tid, pn_ie_cnt, *pn_ie=NULL;
u_int16_t seq_num_start, seq_num_end;
int msg_len = adf_nbuf_len(htt_t2h_msg);
if (msg_len < HTT_RX_PN_IND_BYTES) {
adf_print("invalid nbuff len");
WARN_ON(1);
break;
}
/*First dword */
peer_id = HTT_RX_PN_IND_PEER_ID_GET(*msg_word);
@ -788,6 +842,13 @@ if (adf_os_unlikely(pdev->rx_ring.rx_reset)) {
seq_num_end = HTT_RX_PN_IND_SEQ_NUM_END_GET(*msg_word);
pn_ie_cnt = HTT_RX_PN_IND_PN_IE_CNT_GET(*msg_word);
if (msg_len - HTT_RX_PN_IND_BYTES <
pn_ie_cnt * sizeof(uint8_t)) {
adf_print("invalid pn_ie len");
WARN_ON(1);
break;
}
msg_word++;
/*Third dword*/
if (pn_ie_cnt) {