OSDN Git Service

DO NOT MERGE Fix potential OOB read in sdpu_get_len_from_type
authorTed Wang <tedwang@google.com>
Mon, 29 Apr 2019 02:11:04 +0000 (10:11 +0800)
committerhamzeh <hamzeh@google.com>
Fri, 10 May 2019 21:18:06 +0000 (14:18 -0700)
Add boundary check in sdpu_get_len_from_type to prevent potential OOB read.

Bug: 117105007
Test: Manul
Merged-In: I3755e13ee0a7e22ffd5f48fca909610a26b09d0a
Change-Id: I3755e13ee0a7e22ffd5f48fca909610a26b09d0a
(cherry picked from commit 08202bdcbe5e6cf826926d0995790fcfa309bca8)

stack/sdp/sdp_db.c
stack/sdp/sdp_discovery.c
stack/sdp/sdp_utils.c
stack/sdp/sdpint.h

index 8546536..1c81202 100644 (file)
@@ -129,7 +129,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("%s: bad length", __func__);
+            break;
+        }
         type = type >> 3;
         if (type == UUID_DESC_TYPE)
         {
index 5f1f552..d2bbc58 100644 (file)
@@ -367,6 +367,7 @@ static void sdp_copy_raw_data (tCONN_CB *p_ccb, BOOLEAN offset)
     unsigned int    cpy_len, rem_len;
     UINT32          list_len;
     UINT8           *p;
+    UINT8           *p_end;
     UINT8           type;
 
 #if (SDP_DEBUG_RAW == TRUE)
@@ -385,13 +386,18 @@ 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)
         {
             cpy_len -= 1;
             type = *p++;
             uint8_t* old_p = p;
-            p = sdpu_get_len_from_type (p, type, &list_len);
+            p = sdpu_get_len_from_type (p, p_end, type, &list_len);
+            if (p == NULL || (p + list_len) > p_end) {
+                SDP_TRACE_WARNING("%s: bad length", __func__);
+                return;
+            }
             if ((int)cpy_len < (p - old_p)) {
                 SDP_TRACE_WARNING("%s: no bytes left for data", __func__);
                 return;
@@ -740,7 +746,11 @@ static void process_service_search_attr_rsp(tCONN_CB *p_ccb, UINT8 *p_reply,
         SDP_TRACE_WARNING ("SDP - Wrong type: 0x%02x in attr_rsp", type);
         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_TRACE_WARNING("%s: bad length", __func__);
+        return;
+    }
 
     p_end = &p_ccb->rsp_list[p_ccb->list_len];
 
@@ -789,8 +799,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", seq_len);
         return (NULL);
@@ -810,7 +820,11 @@ static UINT8 *save_attr_seq (tCONN_CB *p_ccb, UINT8 *p, UINT8 *p_msg_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("%s: Bad len in attr_rsp %d", __func__, 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", type, attr_len);
@@ -900,7 +914,11 @@ static UINT8 *add_attr (UINT8 *p, UINT8 *p_end, tSDP_DISCOVERY_DB *p_db, tSDP_DI
     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("%s: bad length in attr_rsp", __func__);
+        return NULL;
+    }
 
     attr_len &= SDP_DISC_ATTR_LEN_MASK;
     attr_type = (type >> 3) & 0x0f;
index 30cdb2c..cbfb874 100644 (file)
@@ -598,7 +598,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;
@@ -622,14 +622,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;
index 71dab92..b0548f5 100644 (file)
@@ -282,7 +282,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);