summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMyles Watson <mylesgw@google.com>2018-01-11 17:43:40 -0800
committerAndreas Blaesius <andi@unlegacy-android.org>2018-04-14 14:02:06 +0200
commita490759d3569efe6e94bef306865a4f8e01b3656 (patch)
treec8f04ee2d54f94c547538eca2f4b3665242b4dda
parent178c0ff3a46a9a633822414ddeaed6aa0e536ba9 (diff)
downloadandroid_system_bt-a490759d3569efe6e94bef306865a4f8e01b3656.tar.gz
android_system_bt-a490759d3569efe6e94bef306865a4f8e01b3656.tar.bz2
android_system_bt-a490759d3569efe6e94bef306865a4f8e01b3656.zip
SDP: Check p_req_end before reading from p_req
Bug: 69384124 Test: Connect a headset Change-Id: Ia30c58ed39977552e5ddc21cc3c1b54c6b1d8abe Merged-In: Ia30c58ed39977552e5ddc21cc3c1b54c6b1d8abe (cherry picked from commit dd856fbc4ade8f7d78873db3533b4c9fd7c6d612)
-rw-r--r--stack/sdp/sdp_server.c56
-rw-r--r--stack/sdp/sdp_utils.c38
2 files changed, 68 insertions, 26 deletions
diff --git a/stack/sdp/sdp_server.c b/stack/sdp/sdp_server.c
index c9a214fc0..b7ef7ee99 100644
--- a/stack/sdp/sdp_server.c
+++ b/stack/sdp/sdp_server.c
@@ -23,7 +23,6 @@
*
******************************************************************************/
#include <cutils/log.h>
-
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@@ -360,11 +359,25 @@ void sdp_server_handle_client_req (tCONN_CB *p_ccb, BT_HDR *p_msg)
/* Start inactivity timer */
btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_SDP, SDP_INACT_TIMEOUT);
+ if (p_req + sizeof(pdu_id) + sizeof(trans_num) > p_req_end) {
+ android_errorWriteLog(0x534e4554, "69384124");
+ trans_num = 0;
+ sdpu_build_n_send_error(p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX,
+ SDP_TEXT_BAD_HEADER);
+ }
+
/* The first byte in the message is the pdu type */
pdu_id = *p_req++;
/* Extract the transaction number and parameter length */
BE_STREAM_TO_UINT16 (trans_num, p_req);
+
+ if (p_req + sizeof(param_len) > p_req_end) {
+ android_errorWriteLog(0x534e4554, "69384124");
+ sdpu_build_n_send_error(p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX,
+ SDP_TEXT_BAD_HEADER);
+ }
+
BE_STREAM_TO_UINT16 (param_len, p_req);
if ((p_req + param_len) != p_req_end)
@@ -429,19 +442,17 @@ static void process_service_search (tCONN_CB *p_ccb, UINT16 trans_num,
return;
}
- /* Get the max replies we can send. Cap it at our max anyways. */
- BE_STREAM_TO_UINT16 (max_replies, p_req);
-
- if (max_replies > SDP_MAX_RECORDS)
- max_replies = SDP_MAX_RECORDS;
-
-
- if ((!p_req) || (p_req > p_req_end))
+ if (p_req + sizeof(max_replies) + sizeof(uint8_t) > p_req_end)
{
+ android_errorWriteLog(0x534e4554, "69384124");
sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX, SDP_TEXT_BAD_MAX_RECORDS_LIST);
return;
}
+ /* Get the max replies we can send. Cap it at our max anyways. */
+ BE_STREAM_TO_UINT16 (max_replies, p_req);
+ if (max_replies > SDP_MAX_RECORDS)
+ max_replies = SDP_MAX_RECORDS;
/* Get a list of handles that match the UUIDs given to us */
for (num_rsp_handles = 0; num_rsp_handles < max_replies; )
@@ -457,7 +468,8 @@ static void process_service_search (tCONN_CB *p_ccb, UINT16 trans_num,
/* Check if this is a continuation request */
if (*p_req)
{
- if (*p_req++ != SDP_CONTINUATION_LEN || (p_req >= p_req_end))
+ if (*p_req++ != SDP_CONTINUATION_LEN ||
+ (p_req + sizeof(cont_offset) > p_req_end))
{
sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_CONT_STATE,
SDP_TEXT_BAD_CONT_LEN);
@@ -580,15 +592,16 @@ static void process_service_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
BOOLEAN is_hfp_fallback = FALSE;
UINT16 attr_len;
- /* Extract the record handle */
- BE_STREAM_TO_UINT32 (rec_handle, p_req);
-
- if (p_req > p_req_end)
+ if (p_req + sizeof(rec_handle) + sizeof(max_list_len) > p_req_end)
{
+ android_errorWriteLog(0x534e4554, "69384124");
sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_SERV_REC_HDL, SDP_TEXT_BAD_HANDLE);
return;
}
+ /* Extract the record handle */
+ BE_STREAM_TO_UINT32 (rec_handle, p_req);
+
/* Get the max list length we can send. Cap it at MTU size minus overhead */
BE_STREAM_TO_UINT16 (max_list_len, p_req);
@@ -597,7 +610,8 @@ static void process_service_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
p_req = sdpu_extract_attr_seq (p_req, param_len, &attr_seq);
- if ((!p_req) || (!attr_seq.num_attr) || (p_req > p_req_end))
+ if ((!p_req) || (!attr_seq.num_attr) ||
+ (p_req + sizeof(uint8_t) > p_req_end))
{
sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX, SDP_TEXT_BAD_ATTR_LIST);
return;
@@ -634,7 +648,8 @@ static void process_service_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
return;
}
- if (*p_req++ != SDP_CONTINUATION_LEN)
+ if (*p_req++ != SDP_CONTINUATION_LEN ||
+ (p_req + sizeof(cont_offset) > p_req_end))
{
sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_CONT_STATE, SDP_TEXT_BAD_CONT_LEN);
return;
@@ -922,7 +937,8 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
/* Extract the UUID sequence to search for */
p_req = sdpu_extract_uid_seq (p_req, param_len, &uid_seq);
- if ((!p_req) || (!uid_seq.num_uids))
+ if ((!p_req) || (!uid_seq.num_uids) ||
+ (p_req + sizeof(uint16_t) > p_req_end))
{
sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX, SDP_TEXT_BAD_UUID_LIST);
return;
@@ -936,7 +952,8 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
p_req = sdpu_extract_attr_seq (p_req, param_len, &attr_seq);
- if ((!p_req) || (!attr_seq.num_attr))
+ if ((!p_req) || (!attr_seq.num_attr) ||
+ (p_req + sizeof(uint8_t) > p_req_end))
{
sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX, SDP_TEXT_BAD_ATTR_LIST);
return;
@@ -967,7 +984,8 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
return;
}
- if (*p_req++ != SDP_CONTINUATION_LEN)
+ if (*p_req++ != SDP_CONTINUATION_LEN ||
+ (p_req + sizeof(uint16_t) > p_req_end))
{
sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_CONT_STATE, SDP_TEXT_BAD_CONT_LEN);
return;
diff --git a/stack/sdp/sdp_utils.c b/stack/sdp/sdp_utils.c
index d9b1ea7ef..02af9f971 100644
--- a/stack/sdp/sdp_utils.c
+++ b/stack/sdp/sdp_utils.c
@@ -382,6 +382,8 @@ UINT8 *sdpu_extract_uid_seq (UINT8 *p, UINT16 param_len, tSDP_UUID_SEQ *p_seq)
p_seq->num_uids = 0;
/* A UID sequence is composed of a bunch of UIDs. */
+ if (sizeof(descr) > param_len) return (NULL);
+ param_len -= sizeof(descr);
BE_STREAM_TO_UINT8 (descr, p);
type = descr >> 3;
@@ -402,19 +404,25 @@ UINT8 *sdpu_extract_uid_seq (UINT8 *p, UINT16 param_len, tSDP_UUID_SEQ *p_seq)
seq_len = 16;
break;
case SIZE_IN_NEXT_BYTE:
+ if (sizeof(uint8_t) > param_len) return (NULL);
+ param_len -= sizeof(uint8_t);
BE_STREAM_TO_UINT8 (seq_len, p);
break;
case SIZE_IN_NEXT_WORD:
+ if (sizeof(uint16_t) > param_len) return (NULL);
+ param_len -= sizeof(uint16_t);
BE_STREAM_TO_UINT16 (seq_len, p);
break;
case SIZE_IN_NEXT_LONG:
+ if (sizeof(uint32_t) > param_len) return (NULL);
+ param_len -= sizeof(uint32_t);
BE_STREAM_TO_UINT32 (seq_len, p);
break;
default:
return (NULL);
}
- if (seq_len >= param_len)
+ if (seq_len > param_len)
return (NULL);
p_seq_end = p + seq_len;
@@ -441,12 +449,15 @@ UINT8 *sdpu_extract_uid_seq (UINT8 *p, UINT16 param_len, tSDP_UUID_SEQ *p_seq)
uuid_len = 16;
break;
case SIZE_IN_NEXT_BYTE:
+ if (p + sizeof(uint8_t) > p_seq_end) return NULL;
BE_STREAM_TO_UINT8 (uuid_len, p);
break;
case SIZE_IN_NEXT_WORD:
+ if (p + sizeof(uint16_t) > p_seq_end) return NULL;
BE_STREAM_TO_UINT16 (uuid_len, p);
break;
case SIZE_IN_NEXT_LONG:
+ if (p + sizeof(uint32_t) > p_seq_end) return NULL;
BE_STREAM_TO_UINT32 (uuid_len, p);
break;
default:
@@ -454,7 +465,8 @@ UINT8 *sdpu_extract_uid_seq (UINT8 *p, UINT16 param_len, tSDP_UUID_SEQ *p_seq)
}
/* If UUID length is valid, copy it across */
- if ((uuid_len == 2) || (uuid_len == 4) || (uuid_len == 16))
+ if (((uuid_len == 2) || (uuid_len == 4) || (uuid_len == 16)) &&
+ (p + uuid_len <= p_seq_end))
{
p_seq->uuid_entry[p_seq->num_uids].len = (UINT16) uuid_len;
BE_STREAM_TO_ARRAY (p, p_seq->uuid_entry[p_seq->num_uids].value, (int)uuid_len);
@@ -496,33 +508,41 @@ UINT8 *sdpu_extract_attr_seq (UINT8 *p, UINT16 param_len, tSDP_ATTR_SEQ *p_seq)
p_seq->num_attr = 0;
/* Get attribute sequence info */
+ if (param_len < sizeof(descr)) return NULL;
+ param_len -= sizeof(descr);
BE_STREAM_TO_UINT8 (descr, p);
type = descr >> 3;
size = descr & 7;
if (type != DATA_ELE_SEQ_DESC_TYPE)
- return (p);
+ return NULL;
switch (size)
{
case SIZE_IN_NEXT_BYTE:
+ if (param_len < sizeof(uint8_t)) return NULL;
+ param_len -= sizeof(uint8_t);
BE_STREAM_TO_UINT8 (list_len, p);
break;
case SIZE_IN_NEXT_WORD:
+ if (param_len < sizeof(uint16_t)) return NULL;
+ param_len -= sizeof(uint16_t);
BE_STREAM_TO_UINT16 (list_len, p);
break;
case SIZE_IN_NEXT_LONG:
+ if (param_len < sizeof(uint32_t)) return NULL;
+ param_len -= sizeof(uint32_t);
BE_STREAM_TO_UINT32 (list_len, p);
break;
default:
- return (p);
+ return NULL;
}
if (list_len > param_len)
- return (p);
+ return NULL;
p_end_list = p + list_len;
@@ -534,7 +554,7 @@ UINT8 *sdpu_extract_attr_seq (UINT8 *p, UINT16 param_len, tSDP_ATTR_SEQ *p_seq)
size = descr & 7;
if (type != UINT_DESC_TYPE)
- return (p);
+ return NULL;
switch (size)
{
@@ -545,20 +565,24 @@ UINT8 *sdpu_extract_attr_seq (UINT8 *p, UINT16 param_len, tSDP_ATTR_SEQ *p_seq)
attr_len = 4;
break;
case SIZE_IN_NEXT_BYTE:
+ if (p + sizeof(uint8_t) > p_end_list) return NULL;
BE_STREAM_TO_UINT8 (attr_len, p);
break;
case SIZE_IN_NEXT_WORD:
+ if (p + sizeof(uint16_t) > p_end_list) return NULL;
BE_STREAM_TO_UINT16 (attr_len, p);
break;
case SIZE_IN_NEXT_LONG:
+ if (p + sizeof(uint32_t) > p_end_list) return NULL;
BE_STREAM_TO_UINT32 (attr_len, p);
break;
default:
- return (NULL);
+ return NULL;
break;
}
/* Attribute length must be 2-bytes or 4-bytes for a paired entry. */
+ if (p + attr_len > p_end_list) return NULL;
if (attr_len == 2)
{
BE_STREAM_TO_UINT16 (p_seq->attr_entry[p_seq->num_attr].start, p);