qcacmn: Add sanity check for wmi TLV length
Add sanity check for wmi TLV header length before padding/shrinking elements in a wmi which has a variable length for its TLV structure. Currently, the TLV length is not checked so its maximum value could be 65535 which results in a hugh count for elements. Number of elements is used to terminate the loop for padding/shrinking. If the number was too large, there would be memory overflow. Change-Id: Iea0615fc511696c6cc5dcc48a9dfff225256a52b CRs-Fixed: 2181685
This commit is contained in:

committed by
snandini

父節點
8cdcf67521
當前提交
1075366660
@@ -507,6 +507,7 @@ wmitlv_check_and_pad_tlvs(void *os_handle, void *param_struc_ptr,
|
|||||||
wmitlv_cmd_param_info *cmd_param_tlvs_ptr = NULL;
|
wmitlv_cmd_param_info *cmd_param_tlvs_ptr = NULL;
|
||||||
A_UINT32 remaining_expected_tlvs = 0xFFFFFFFF;
|
A_UINT32 remaining_expected_tlvs = 0xFFFFFFFF;
|
||||||
A_UINT32 len_wmi_cmd_struct_buf;
|
A_UINT32 len_wmi_cmd_struct_buf;
|
||||||
|
A_UINT32 free_buf_len;
|
||||||
A_INT32 error = -1;
|
A_INT32 error = -1;
|
||||||
|
|
||||||
/* Get the number of TLVs for this command/event */
|
/* Get the number of TLVs for this command/event */
|
||||||
@@ -569,6 +570,13 @@ wmitlv_check_and_pad_tlvs(void *os_handle, void *param_struc_ptr,
|
|||||||
WMITLV_GET_TLVLEN(WMITLV_GET_HDR(buf_ptr));
|
WMITLV_GET_TLVLEN(WMITLV_GET_HDR(buf_ptr));
|
||||||
int num_padding_bytes = 0;
|
int num_padding_bytes = 0;
|
||||||
|
|
||||||
|
free_buf_len = param_buf_len - (buf_idx + WMI_TLV_HDR_SIZE);
|
||||||
|
if (curr_tlv_len > free_buf_len) {
|
||||||
|
wmi_tlv_print_error("%s: TLV length overflow",
|
||||||
|
__func__);
|
||||||
|
goto Error_wmitlv_check_and_pad_tlvs;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the attributes of the TLV with the given order in "tlv_index" */
|
/* Get the attributes of the TLV with the given order in "tlv_index" */
|
||||||
wmi_tlv_OS_MEMZERO(&attr_struct_ptr,
|
wmi_tlv_OS_MEMZERO(&attr_struct_ptr,
|
||||||
sizeof(wmitlv_attributes_struc));
|
sizeof(wmitlv_attributes_struc));
|
||||||
@@ -632,6 +640,13 @@ wmitlv_check_and_pad_tlvs(void *os_handle, void *param_struc_ptr,
|
|||||||
WMITLV_GET_TLVLEN(WMITLV_GET_HDR
|
WMITLV_GET_TLVLEN(WMITLV_GET_HDR
|
||||||
(buf_ptr));
|
(buf_ptr));
|
||||||
in_tlv_len += WMI_TLV_HDR_SIZE;
|
in_tlv_len += WMI_TLV_HDR_SIZE;
|
||||||
|
if (in_tlv_len > curr_tlv_len) {
|
||||||
|
wmi_tlv_print_error("%s: Invalid in_tlv_len=%d",
|
||||||
|
__func__,
|
||||||
|
in_tlv_len);
|
||||||
|
goto
|
||||||
|
Error_wmitlv_check_and_pad_tlvs;
|
||||||
|
}
|
||||||
tlv_size_diff =
|
tlv_size_diff =
|
||||||
in_tlv_len -
|
in_tlv_len -
|
||||||
attr_struct_ptr.tag_struct_size;
|
attr_struct_ptr.tag_struct_size;
|
||||||
@@ -751,8 +766,17 @@ wmitlv_check_and_pad_tlvs(void *os_handle, void *param_struc_ptr,
|
|||||||
|
|
||||||
/* Move subsequent TLVs by number of bytes to be padded
|
/* Move subsequent TLVs by number of bytes to be padded
|
||||||
* for all elements */
|
* for all elements */
|
||||||
if (param_buf_len >
|
if ((free_buf_len <
|
||||||
(buf_idx + curr_tlv_len)) {
|
attr_struct_ptr.tag_struct_size *
|
||||||
|
num_of_elems) ||
|
||||||
|
(param_buf_len <
|
||||||
|
buf_idx + curr_tlv_len +
|
||||||
|
num_padding_bytes * num_of_elems)) {
|
||||||
|
wmi_tlv_print_error("%s: Insufficent buffer\n",
|
||||||
|
__func__);
|
||||||
|
goto
|
||||||
|
Error_wmitlv_check_and_pad_tlvs;
|
||||||
|
} else {
|
||||||
src_addr =
|
src_addr =
|
||||||
buf_ptr + curr_tlv_len;
|
buf_ptr + curr_tlv_len;
|
||||||
dst_addr =
|
dst_addr =
|
||||||
@@ -772,12 +796,10 @@ wmitlv_check_and_pad_tlvs(void *os_handle, void *param_struc_ptr,
|
|||||||
* bytes to be padded for one element and alse set
|
* bytes to be padded for one element and alse set
|
||||||
* padding bytes to zero */
|
* padding bytes to zero */
|
||||||
tlv_buf_ptr = buf_ptr;
|
tlv_buf_ptr = buf_ptr;
|
||||||
for (i = 0; i < num_of_elems; i++) {
|
for (i = 0; i < num_of_elems - 1; i++) {
|
||||||
src_addr =
|
src_addr =
|
||||||
tlv_buf_ptr + in_tlv_len;
|
tlv_buf_ptr + in_tlv_len;
|
||||||
if (i != (num_of_elems - 1)) {
|
if (i != (num_of_elems - 1)) {
|
||||||
/* Need not move anything for last element
|
|
||||||
* in the array */
|
|
||||||
dst_addr =
|
dst_addr =
|
||||||
tlv_buf_ptr +
|
tlv_buf_ptr +
|
||||||
in_tlv_len +
|
in_tlv_len +
|
||||||
@@ -800,6 +822,9 @@ wmitlv_check_and_pad_tlvs(void *os_handle, void *param_struc_ptr,
|
|||||||
attr_struct_ptr.
|
attr_struct_ptr.
|
||||||
tag_struct_size;
|
tag_struct_size;
|
||||||
}
|
}
|
||||||
|
src_addr = tlv_buf_ptr + in_tlv_len;
|
||||||
|
wmi_tlv_OS_MEMZERO(src_addr,
|
||||||
|
num_padding_bytes);
|
||||||
|
|
||||||
/* Update the number of padding bytes to total number
|
/* Update the number of padding bytes to total number
|
||||||
* of bytes padded for all elements in the array */
|
* of bytes padded for all elements in the array */
|
||||||
|
Reference in New Issue
Block a user