mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-03 03:31:41 +03:00
fix(bt/bluedroid): fixed potential OOB in Bluedroid
This commit is contained in:
@@ -276,7 +276,7 @@ extern void sdpu_build_n_send_error (tCONN_CB *p_ccb, UINT16 trans_num, UIN
|
||||
extern UINT8 *sdpu_extract_attr_seq (UINT8 *p, UINT16 param_len, tSDP_ATTR_SEQ *p_seq);
|
||||
extern UINT8 *sdpu_extract_uid_seq (UINT8 *p, UINT16 param_len, tSDP_UUID_SEQ *p_seq);
|
||||
|
||||
extern UINT8 *sdpu_get_len_from_type (UINT8 *p, UINT8 type, UINT32 *p_len);
|
||||
extern UINT8 *sdpu_get_len_from_type (UINT8 *p, UINT8 *p_end, UINT8 type, UINT32 *p_len);
|
||||
extern BOOLEAN sdpu_is_base_uuid (UINT8 *p_uuid);
|
||||
extern BOOLEAN sdpu_compare_uuid_arrays (UINT8 *p_uuid1, UINT32 len1, UINT8 *p_uuid2, UINT16 len2);
|
||||
extern BOOLEAN sdpu_compare_bt_uuids (tBT_UUID *p_uuid1, tBT_UUID *p_uuid2);
|
||||
|
||||
@@ -139,7 +139,11 @@ static BOOLEAN find_uuid_in_seq (UINT8 *p , UINT32 seq_len, UINT8 *p_uuid,
|
||||
|
||||
while (p < p_end) {
|
||||
type = *p++;
|
||||
p = sdpu_get_len_from_type (p, type, &len);
|
||||
p = sdpu_get_len_from_type (p, p_end, type, &len);
|
||||
if ((p == NULL) || (p + len) > p_end) {
|
||||
SDP_TRACE_WARNING("bad length\n");
|
||||
return (FALSE);
|
||||
}
|
||||
type = type >> 3;
|
||||
if (type == UUID_DESC_TYPE) {
|
||||
if (sdpu_compare_uuid_arrays (p, len, p_uuid, uuid_len)) {
|
||||
|
||||
@@ -50,7 +50,7 @@ static void process_service_attr_rsp (tCONN_CB *p_ccb, UINT8 *p_reply);
|
||||
static void process_service_search_attr_rsp (tCONN_CB *p_ccb, UINT8 *p_reply);
|
||||
static UINT8 *save_attr_seq (tCONN_CB *p_ccb, UINT8 *p, UINT8 *p_msg_end);
|
||||
static tSDP_DISC_REC *add_record (tSDP_DISCOVERY_DB *p_db, BD_ADDR p_bda);
|
||||
static UINT8 *add_attr (UINT8 *p, tSDP_DISCOVERY_DB *p_db, tSDP_DISC_REC *p_rec,
|
||||
static UINT8 *add_attr (UINT8 *p, UINT8 *p_end, tSDP_DISCOVERY_DB *p_db, tSDP_DISC_REC *p_rec,
|
||||
UINT16 attr_id, tSDP_DISC_ATTR *p_parent_attr, UINT8 nest_level);
|
||||
|
||||
/* Safety check in case we go crazy */
|
||||
@@ -333,6 +333,7 @@ static void sdp_copy_raw_data (tCONN_CB *p_ccb, BOOLEAN offset)
|
||||
unsigned int cpy_len;
|
||||
UINT32 list_len;
|
||||
UINT8 *p;
|
||||
UINT8 *p_end;
|
||||
UINT8 type;
|
||||
|
||||
#if (SDP_DEBUG_RAW == TRUE)
|
||||
@@ -349,10 +350,22 @@ static void sdp_copy_raw_data (tCONN_CB *p_ccb, BOOLEAN offset)
|
||||
cpy_len = p_ccb->p_db->raw_size - p_ccb->p_db->raw_used;
|
||||
list_len = p_ccb->list_len;
|
||||
p = &p_ccb->rsp_list[0];
|
||||
p_end = &p_ccb->rsp_list[0] + list_len;
|
||||
|
||||
if (offset) {
|
||||
type = *p++;
|
||||
p = sdpu_get_len_from_type (p, type, &list_len);
|
||||
cpy_len--;
|
||||
uint8_t *p_old = p;
|
||||
p = sdpu_get_len_from_type (p, p_end, type, &list_len);
|
||||
if ((p == NULL) || (p + list_len) > p_end) {
|
||||
SDP_TRACE_WARNING("bad length\n");
|
||||
return;
|
||||
}
|
||||
if ((int)cpy_len < (p - p_old)) {
|
||||
SDP_TRACE_WARNING("no bytes left for data\n");
|
||||
return;
|
||||
}
|
||||
cpy_len -= (p - p_old);
|
||||
}
|
||||
if (list_len < cpy_len ) {
|
||||
cpy_len = list_len;
|
||||
@@ -672,7 +685,11 @@ static void process_service_search_attr_rsp (tCONN_CB *p_ccb, UINT8 *p_reply)
|
||||
sdp_disconnect (p_ccb, SDP_ILLEGAL_PARAMETER);
|
||||
return;
|
||||
}
|
||||
p = sdpu_get_len_from_type (p, type, &seq_len);
|
||||
p = sdpu_get_len_from_type (p, p + p_ccb->list_len, type, &seq_len);
|
||||
if (p == NULL || (p + seq_len) > (p + p_ccb->list_len)) {
|
||||
sdp_disconnect(p_ccb, SDP_ILLEGAL_PARAMETER);
|
||||
return;
|
||||
}
|
||||
|
||||
p_end = &p_ccb->rsp_list[p_ccb->list_len];
|
||||
|
||||
@@ -717,8 +734,8 @@ static UINT8 *save_attr_seq (tCONN_CB *p_ccb, UINT8 *p, UINT8 *p_msg_end)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
p = sdpu_get_len_from_type (p, type, &seq_len);
|
||||
if ((p + seq_len) > p_msg_end) {
|
||||
p = sdpu_get_len_from_type (p, p_msg_end, type, &seq_len);
|
||||
if ((p == NULL) || (p + seq_len) > p_msg_end) {
|
||||
SDP_TRACE_WARNING ("SDP - Bad len in attr_rsp %d\n", seq_len);
|
||||
return (NULL);
|
||||
}
|
||||
@@ -735,7 +752,11 @@ static UINT8 *save_attr_seq (tCONN_CB *p_ccb, UINT8 *p, UINT8 *p_msg_end)
|
||||
while (p < p_seq_end) {
|
||||
/* First get the attribute ID */
|
||||
type = *p++;
|
||||
p = sdpu_get_len_from_type (p, type, &attr_len);
|
||||
p = sdpu_get_len_from_type (p, p_msg_end, type, &attr_len);
|
||||
if ((p == NULL) || (p + attr_len) > p_seq_end) {
|
||||
SDP_TRACE_WARNING ("SDP - Bad len in attr_rsp %d\n", attr_len);
|
||||
return (NULL);
|
||||
}
|
||||
if (((type >> 3) != UINT_DESC_TYPE) || (attr_len != 2)) {
|
||||
SDP_TRACE_WARNING ("SDP - Bad type: 0x%02x or len: %d in attr_rsp\n", type, attr_len);
|
||||
return (NULL);
|
||||
@@ -743,7 +764,7 @@ static UINT8 *save_attr_seq (tCONN_CB *p_ccb, UINT8 *p, UINT8 *p_msg_end)
|
||||
BE_STREAM_TO_UINT16 (attr_id, p);
|
||||
|
||||
/* Now, add the attribute value */
|
||||
p = add_attr (p, p_ccb->p_db, p_rec, attr_id, NULL, 0);
|
||||
p = add_attr (p, p_seq_end, p_ccb->p_db, p_rec, attr_id, NULL, 0);
|
||||
|
||||
if (!p) {
|
||||
SDP_TRACE_WARNING ("SDP - DB full add_attr\n");
|
||||
@@ -809,7 +830,7 @@ tSDP_DISC_REC *add_record (tSDP_DISCOVERY_DB *p_db, BD_ADDR p_bda)
|
||||
** Returns pointer to next byte in data stream
|
||||
**
|
||||
*******************************************************************************/
|
||||
static UINT8 *add_attr (UINT8 *p, tSDP_DISCOVERY_DB *p_db, tSDP_DISC_REC *p_rec,
|
||||
static UINT8 *add_attr (UINT8 *p, UINT8 *p_end, tSDP_DISCOVERY_DB *p_db, tSDP_DISC_REC *p_rec,
|
||||
UINT16 attr_id, tSDP_DISC_ATTR *p_parent_attr, UINT8 nest_level)
|
||||
{
|
||||
tSDP_DISC_ATTR *p_attr;
|
||||
@@ -818,14 +839,19 @@ static UINT8 *add_attr (UINT8 *p, tSDP_DISCOVERY_DB *p_db, tSDP_DISC_REC *p_rec,
|
||||
UINT16 attr_type;
|
||||
UINT16 id;
|
||||
UINT8 type;
|
||||
UINT8 *p_end;
|
||||
UINT8 *p_attr_end;
|
||||
UINT8 is_additional_list = nest_level & SDP_ADDITIONAL_LIST_MASK;
|
||||
|
||||
nest_level &= ~(SDP_ADDITIONAL_LIST_MASK);
|
||||
|
||||
type = *p++;
|
||||
p = sdpu_get_len_from_type (p, type, &attr_len);
|
||||
p = sdpu_get_len_from_type (p, p_end, type, &attr_len);
|
||||
if ((p == NULL) || (p + attr_len > p_end)) {
|
||||
SDP_TRACE_WARNING ("SDP - Bad len in attr_rsp %d\n", attr_len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p_attr_end = p + attr_len;
|
||||
attr_len &= SDP_DISC_ATTR_LEN_MASK;
|
||||
attr_type = (type >> 3) & 0x0f;
|
||||
|
||||
@@ -860,17 +886,16 @@ static UINT8 *add_attr (UINT8 *p, tSDP_DISCOVERY_DB *p_db, tSDP_DISC_REC *p_rec,
|
||||
/* Reserve the memory for the attribute now, as we need to add sub-attributes */
|
||||
p_db->p_free_mem += sizeof (tSDP_DISC_ATTR);
|
||||
p_db->mem_free -= sizeof (tSDP_DISC_ATTR);
|
||||
p_end = p + attr_len;
|
||||
total_len = 0;
|
||||
|
||||
/* SDP_TRACE_DEBUG ("SDP - attr nest level:%d(list)", nest_level); */
|
||||
if (nest_level >= MAX_NEST_LEVELS) {
|
||||
SDP_TRACE_ERROR ("SDP - attr nesting too deep\n");
|
||||
return (p_end);
|
||||
return (p_attr_end);
|
||||
}
|
||||
|
||||
/* Now, add the list entry */
|
||||
p = add_attr (p, p_db, p_rec, ATTR_ID_PROTOCOL_DESC_LIST, p_attr, (UINT8)(nest_level + 1));
|
||||
p = add_attr (p, p_end, p_db, p_rec, ATTR_ID_PROTOCOL_DESC_LIST, p_attr, (UINT8)(nest_level + 1));
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -943,22 +968,21 @@ static UINT8 *add_attr (UINT8 *p, tSDP_DISCOVERY_DB *p_db, tSDP_DISC_REC *p_rec,
|
||||
/* Reserve the memory for the attribute now, as we need to add sub-attributes */
|
||||
p_db->p_free_mem += sizeof (tSDP_DISC_ATTR);
|
||||
p_db->mem_free -= sizeof (tSDP_DISC_ATTR);
|
||||
p_end = p + attr_len;
|
||||
total_len = 0;
|
||||
|
||||
/* SDP_TRACE_DEBUG ("SDP - attr nest level:%d", nest_level); */
|
||||
if (nest_level >= MAX_NEST_LEVELS) {
|
||||
SDP_TRACE_ERROR ("SDP - attr nesting too deep\n");
|
||||
return (p_end);
|
||||
return (p_attr_end);
|
||||
}
|
||||
if (is_additional_list != 0 || attr_id == ATTR_ID_ADDITION_PROTO_DESC_LISTS) {
|
||||
nest_level |= SDP_ADDITIONAL_LIST_MASK;
|
||||
}
|
||||
/* SDP_TRACE_DEBUG ("SDP - attr nest level:0x%x(finish)", nest_level); */
|
||||
|
||||
while (p < p_end) {
|
||||
while (p < p_attr_end) {
|
||||
/* Now, add the list entry */
|
||||
p = add_attr (p, p_db, p_rec, 0, p_attr, (UINT8)(nest_level + 1));
|
||||
p = add_attr (p, p_end, p_db, p_rec, 0, p_attr, (UINT8)(nest_level + 1));
|
||||
|
||||
if (!p) {
|
||||
return (NULL);
|
||||
@@ -978,7 +1002,7 @@ static UINT8 *add_attr (UINT8 *p, tSDP_DISCOVERY_DB *p_db, tSDP_DISC_REC *p_rec,
|
||||
break;
|
||||
default:
|
||||
SDP_TRACE_WARNING ("SDP - bad len in boolean attr: %d\n", attr_len);
|
||||
return (p + attr_len);
|
||||
return (p_attr_end);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -355,6 +355,7 @@ static void process_service_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
|
||||
/* Free and reallocate buffer */
|
||||
if (p_ccb->rsp_list) {
|
||||
osi_free(p_ccb->rsp_list);
|
||||
p_ccb->rsp_list = NULL;
|
||||
}
|
||||
|
||||
p_ccb->rsp_list = (UINT8 *)osi_malloc(max_list_len);
|
||||
@@ -457,7 +458,7 @@ static void process_service_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
|
||||
}
|
||||
}
|
||||
}
|
||||
/* If all the attributes have been accomodated in p_rsp,
|
||||
/* If all the attributes have been accommodated in p_rsp,
|
||||
reset next_attr_index */
|
||||
if (xx == attr_seq.num_attr) {
|
||||
p_ccb->cont_info.next_attr_index = 0;
|
||||
@@ -590,6 +591,7 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
|
||||
/* Free and reallocate buffer */
|
||||
if (p_ccb->rsp_list) {
|
||||
osi_free (p_ccb->rsp_list);
|
||||
p_ccb->rsp_list = NULL;
|
||||
}
|
||||
|
||||
p_ccb->rsp_list = (UINT8 *)osi_malloc (max_list_len);
|
||||
@@ -623,6 +625,7 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
|
||||
/* Free and reallocate if the earlier allocated buffer is small */
|
||||
if (p_ccb->rsp_list) {
|
||||
osi_free (p_ccb->rsp_list);
|
||||
p_ccb->rsp_list = NULL;
|
||||
}
|
||||
|
||||
p_ccb->rsp_list = (UINT8 *)osi_malloc (max_list_len);
|
||||
|
||||
@@ -575,7 +575,7 @@ UINT8 *sdpu_extract_attr_seq (UINT8 *p, UINT16 param_len, tSDP_ATTR_SEQ *p_seq)
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
UINT8 *sdpu_get_len_from_type (UINT8 *p, UINT8 type, UINT32 *p_len)
|
||||
UINT8 *sdpu_get_len_from_type (UINT8 *p, UINT8 *p_end, UINT8 type, UINT32 *p_len)
|
||||
{
|
||||
UINT8 u8;
|
||||
UINT16 u16;
|
||||
@@ -598,14 +598,26 @@ UINT8 *sdpu_get_len_from_type (UINT8 *p, UINT8 type, UINT32 *p_len)
|
||||
*p_len = 16;
|
||||
break;
|
||||
case SIZE_IN_NEXT_BYTE:
|
||||
if (p + 1 > p_end) {
|
||||
*p_len = 0;
|
||||
return NULL;
|
||||
}
|
||||
BE_STREAM_TO_UINT8 (u8, p);
|
||||
*p_len = u8;
|
||||
break;
|
||||
case SIZE_IN_NEXT_WORD:
|
||||
if (p + 2 > p_end) {
|
||||
*p_len = 0;
|
||||
return NULL;
|
||||
}
|
||||
BE_STREAM_TO_UINT16 (u16, p);
|
||||
*p_len = u16;
|
||||
break;
|
||||
case SIZE_IN_NEXT_LONG:
|
||||
if (p + 4 > p_end) {
|
||||
*p_len = 0;
|
||||
return NULL;
|
||||
}
|
||||
BE_STREAM_TO_UINT32 (u32, p);
|
||||
*p_len = (UINT16) u32;
|
||||
break;
|
||||
@@ -753,7 +765,7 @@ BOOLEAN sdpu_compare_bt_uuids (tBT_UUID *p_uuid1, tBT_UUID *p_uuid2)
|
||||
**
|
||||
** NOTE - it is assumed that BT UUID structures are compressed to the
|
||||
** smallest possible UUIDs (by removing the base SDP UUID).
|
||||
** - it is also assumed that the discovery atribute is compressed
|
||||
** - it is also assumed that the discovery attribute is compressed
|
||||
** to the smallest possible
|
||||
**
|
||||
** Returns TRUE if matched, else FALSE
|
||||
@@ -768,21 +780,13 @@ BOOLEAN sdpu_compare_uuid_with_attr (tBT_UUID *p_btuuid, tSDP_DISC_ATTR *p_attr)
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if (p_btuuid->len == 2) {
|
||||
if (p_btuuid->len == LEN_UUID_16) {
|
||||
return (BOOLEAN)(p_btuuid->uu.uuid16 == p_attr->attr_value.v.u16);
|
||||
} else if (p_btuuid->len == 4) {
|
||||
} else if (p_btuuid->len == LEN_UUID_32) {
|
||||
return (BOOLEAN)(p_btuuid->uu.uuid32 == p_attr->attr_value.v.u32);
|
||||
}
|
||||
/* coverity[overrun-buffer-arg] */
|
||||
/*
|
||||
Event overrun-buffer-arg: Overrun of static array "&p_attr->attr_value.v.array" of size 4 bytes by passing it to a function which indexes it with argument "16U" at byte position 15
|
||||
FALSE-POSITIVE error from Coverity test tool. Please do NOT remove following comment.
|
||||
False-positive: SDP uses scratch buffer to hold the attribute value.
|
||||
The actual size of tSDP_DISC_ATVAL does not matter.
|
||||
If the array size in tSDP_DISC_ATVAL is increase, we would increase the system RAM usage unnecessarily
|
||||
*/
|
||||
else if (!memcmp (p_btuuid->uu.uuid128, (void *) p_attr->attr_value.v.array, MAX_UUID_SIZE)) {
|
||||
return (TRUE);
|
||||
else if (p_btuuid->len == LEN_UUID_128) {
|
||||
return (BOOLEAN)(!memcmp(p_btuuid->uu.uuid128, (void *) p_attr->attr_value.v.array, LEN_UUID_128));
|
||||
}
|
||||
|
||||
return (FALSE);
|
||||
|
||||
Reference in New Issue
Block a user