OSDN Git Service

RESTRICT AUTOMERGE: Fixes two bluetooth causing remote overreads (2/2)
[android-x86/system-bt.git] / stack / sdp / sdp_discovery.c
index 067d066..b01d834 100644 (file)
@@ -31,6 +31,7 @@
 #include "l2cdefs.h"
 #include "hcidefs.h"
 #include "hcimsgs.h"
+#include "log/log.h"
 #include "sdp_api.h"
 #include "sdpint.h"
 #include "btu.h"
 /*              L O C A L    F U N C T I O N     P R O T O T Y P E S            */
 /********************************************************************************/
 #if SDP_CLIENT_ENABLED == TRUE
-static void          process_service_search_rsp (tCONN_CB *p_ccb, UINT8 *p_reply);
-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 void process_service_search_rsp(tCONN_CB* p_ccb, uint8_t* p_reply,
+                                       uint8_t* p_reply_end);
+static void process_service_attr_rsp(tCONN_CB* p_ccb, uint8_t* p_reply,
+                                     uint8_t* p_reply_end);
+static void process_service_search_attr_rsp(tCONN_CB* p_ccb, uint8_t* p_reply,
+                                            uint8_t* p_reply_end);
 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,
@@ -120,16 +124,10 @@ static UINT8 *sdpu_build_uuid_seq (UINT8 *p_out, UINT16 num_uuids, tSDP_UUID *p_
 static void sdp_snd_service_search_req(tCONN_CB *p_ccb, UINT8 cont_len, UINT8 * p_cont)
 {
     UINT8           *p, *p_start, *p_param_len;
-    BT_HDR          *p_cmd = (BT_HDR *) osi_getbuf(SDP_DATA_BUF_SIZE);
+    BT_HDR          *p_cmd = (BT_HDR *) osi_malloc(SDP_DATA_BUF_SIZE);
     UINT16          param_len;
 
-    /* Check the buffer for sending the packet to L2CAP */
-    if (p_cmd == NULL)
-    {
-        sdp_disconnect (p_ccb, SDP_NO_RESOURCES);
-        return;
-    }
-
+    /* Prepare the buffer for sending the packet to L2CAP */
     p_cmd->offset = L2CAP_MIN_OFFSET;
     p = p_start = (UINT8 *)(p_cmd + 1) + L2CAP_MIN_OFFSET;
 
@@ -199,7 +197,7 @@ void sdp_disc_connected (tCONN_CB *p_ccb)
     {
         p_ccb->disc_state = SDP_DISC_WAIT_SEARCH_ATTR;
 
-        process_service_search_attr_rsp (p_ccb, NULL);
+        process_service_search_attr_rsp(p_ccb, NULL, NULL);
     }
     else
     {
@@ -237,6 +235,7 @@ void sdp_disc_server_rsp (tCONN_CB *p_ccb, BT_HDR *p_msg)
 
     /* Got a reply!! Check what we got back */
     p = (UINT8 *)(p_msg + 1) + p_msg->offset;
+    uint8_t* p_end = p + p_msg->len;
 
     BE_STREAM_TO_UINT8 (rsp_pdu, p);
 
@@ -247,7 +246,7 @@ void sdp_disc_server_rsp (tCONN_CB *p_ccb, BT_HDR *p_msg)
     case SDP_PDU_SERVICE_SEARCH_RSP:
         if (p_ccb->disc_state == SDP_DISC_WAIT_HANDLES)
         {
-            process_service_search_rsp (p_ccb, p);
+            process_service_search_rsp(p_ccb, p, p_end);
             invalid_pdu = FALSE;
         }
         break;
@@ -255,7 +254,7 @@ void sdp_disc_server_rsp (tCONN_CB *p_ccb, BT_HDR *p_msg)
     case SDP_PDU_SERVICE_ATTR_RSP:
         if (p_ccb->disc_state == SDP_DISC_WAIT_ATTR)
         {
-            process_service_attr_rsp (p_ccb, p);
+            process_service_attr_rsp(p_ccb, p, p_end);
             invalid_pdu = FALSE;
         }
         break;
@@ -263,7 +262,7 @@ void sdp_disc_server_rsp (tCONN_CB *p_ccb, BT_HDR *p_msg)
     case SDP_PDU_SERVICE_SEARCH_ATTR_RSP:
         if (p_ccb->disc_state == SDP_DISC_WAIT_SEARCH_ATTR)
         {
-            process_service_search_attr_rsp (p_ccb, p);
+            process_service_search_attr_rsp(p_ccb, p, p_end);
             invalid_pdu = FALSE;
         }
         break;
@@ -286,8 +285,8 @@ void sdp_disc_server_rsp (tCONN_CB *p_ccb, BT_HDR *p_msg)
 ** Returns          void
 **
 *******************************************************************************/
-static void process_service_search_rsp (tCONN_CB *p_ccb, UINT8 *p_reply)
-{
+static void process_service_search_rsp(tCONN_CB *p_ccb, UINT8 *p_reply,
+                                       uint8_t* p_reply_end) {
     UINT16      xx;
     UINT16      total, cur_handles, orig;
     UINT8       cont_len;
@@ -323,6 +322,11 @@ static void process_service_search_rsp (tCONN_CB *p_ccb, UINT8 *p_reply)
             sdp_disconnect (p_ccb, SDP_INVALID_CONT_STATE);
             return;
         }
+        if (p_reply + cont_len > p_reply_end) {
+            android_errorWriteLog(0x534e4554, "68161546");
+            sdp_disconnect(p_ccb, SDP_INVALID_CONT_STATE);
+            return;
+        }
         /* stay in the same state */
         sdp_snd_service_search_req(p_ccb, cont_len, p_reply);
     }
@@ -332,7 +336,7 @@ static void process_service_search_rsp (tCONN_CB *p_ccb, UINT8 *p_reply)
         p_ccb->disc_state = SDP_DISC_WAIT_ATTR;
 
         /* Kick off the first attribute request */
-        process_service_attr_rsp (p_ccb, NULL);
+        process_service_attr_rsp(p_ccb, NULL, NULL);
     }
 }
 
@@ -349,7 +353,7 @@ static void process_service_search_rsp (tCONN_CB *p_ccb, UINT8 *p_reply)
 #if (SDP_RAW_DATA_INCLUDED == TRUE)
 static void sdp_copy_raw_data (tCONN_CB *p_ccb, BOOLEAN offset)
 {
-    unsigned int    cpy_len;
+    unsigned int    cpy_len, rem_len;
     UINT32          list_len;
     UINT8           *p;
     UINT8           type;
@@ -376,14 +380,20 @@ static void sdp_copy_raw_data (tCONN_CB *p_ccb, BOOLEAN offset)
             type = *p++;
             p = sdpu_get_len_from_type (p, type, &list_len);
         }
-        if(list_len && list_len < cpy_len )
+        if(list_len < cpy_len )
         {
             cpy_len = list_len;
         }
-#if (SDP_DEBUG_RAW == TRUE)
-        SDP_TRACE_WARNING("list_len :%d cpy_len:%d raw_size:%d raw_used:%d",
-            list_len, cpy_len, p_ccb->p_db->raw_size, p_ccb->p_db->raw_used);
-#endif
+        rem_len = SDP_MAX_LIST_BYTE_COUNT - (unsigned int)(p - &p_ccb->rsp_list[0]);
+        if (cpy_len > rem_len) {
+            SDP_TRACE_WARNING("rem_len :%d less than cpy_len:%d", rem_len, cpy_len);
+            cpy_len = rem_len;
+        }
+        SDP_TRACE_WARNING(
+          "%s: list_len:%d cpy_len:%d p:%p p_ccb:%p p_db:%p raw_size:%d "
+          "raw_used:%d raw_data:%p",
+          __func__, list_len, cpy_len, p, p_ccb, p_ccb->p_db,
+          p_ccb->p_db->raw_size, p_ccb->p_db->raw_used, p_ccb->p_db->raw_data);
         memcpy (&p_ccb->p_db->raw_data[p_ccb->p_db->raw_used], p, cpy_len);
         p_ccb->p_db->raw_used += cpy_len;
     }
@@ -400,8 +410,8 @@ static void sdp_copy_raw_data (tCONN_CB *p_ccb, BOOLEAN offset)
 ** Returns          void
 **
 *******************************************************************************/
-static void process_service_attr_rsp (tCONN_CB *p_ccb, UINT8 *p_reply)
-{
+static void process_service_attr_rsp(tCONN_CB *p_ccb, UINT8 *p_reply,
+                                     uint8_t* p_reply_end) {
     UINT8           *p_start, *p_param_len;
     UINT16          param_len, list_byte_count;
     BOOLEAN         cont_request_needed = FALSE;
@@ -437,16 +447,8 @@ static void process_service_attr_rsp (tCONN_CB *p_ccb, UINT8 *p_reply)
             p_ccb->list_len, list_byte_count);
 #endif
         if (p_ccb->rsp_list == NULL)
-        {
-            p_ccb->rsp_list = (UINT8 *)osi_getbuf (SDP_MAX_LIST_BYTE_COUNT);
-            if (p_ccb->rsp_list == NULL)
-            {
-                SDP_TRACE_ERROR ("SDP - no buf to save rsp");
-                sdp_disconnect (p_ccb, SDP_NO_RESOURCES);
-                return;
-            }
-        }
-        memcpy (&p_ccb->rsp_list[p_ccb->list_len], p_reply, list_byte_count);
+            p_ccb->rsp_list = (UINT8 *)osi_malloc(SDP_MAX_LIST_BYTE_COUNT);
+        memcpy(&p_ccb->rsp_list[p_ccb->list_len], p_reply, list_byte_count);
         p_ccb->list_len += list_byte_count;
         p_reply         += list_byte_count;
 #if (SDP_DEBUG_RAW == TRUE)
@@ -486,15 +488,9 @@ static void process_service_attr_rsp (tCONN_CB *p_ccb, UINT8 *p_reply)
     /* Now, ask for the next handle. Re-use the buffer we just got. */
     if (p_ccb->cur_handle < p_ccb->num_handles)
     {
-        BT_HDR  *p_msg = (BT_HDR *) osi_getbuf(SDP_DATA_BUF_SIZE);
+        BT_HDR  *p_msg = (BT_HDR *)osi_malloc(SDP_DATA_BUF_SIZE);
         UINT8   *p;
 
-        if (!p_msg)
-        {
-            sdp_disconnect (p_ccb, SDP_NO_RESOURCES);
-            return;
-        }
-
         p_msg->offset = L2CAP_MIN_OFFSET;
         p = p_start = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
 
@@ -521,8 +517,12 @@ static void process_service_attr_rsp (tCONN_CB *p_ccb, UINT8 *p_reply)
         /* Was this a continuation request ? */
         if (cont_request_needed)
         {
-            memcpy (p, p_reply, *p_reply + 1);
-            p += *p_reply + 1;
+            if ((p_reply + *p_reply + 1) <= p_reply_end) {
+                memcpy(p, p_reply, *p_reply + 1);
+                p += *p_reply + 1;
+            } else {
+                android_errorWriteLog(0x534e4554, "68161546");
+            }
         }
         else
             UINT8_TO_BE_STREAM (p, 0);
@@ -560,8 +560,8 @@ static void process_service_attr_rsp (tCONN_CB *p_ccb, UINT8 *p_reply)
 ** Returns          void
 **
 *******************************************************************************/
-static void process_service_search_attr_rsp (tCONN_CB *p_ccb, UINT8 *p_reply)
-{
+static void process_service_search_attr_rsp(tCONN_CB *p_ccb, UINT8 *p_reply,
+                                            uint8_t* p_reply_end) {
     UINT8           *p, *p_start, *p_end, *p_param_len;
     UINT8           type;
     UINT32          seq_len;
@@ -598,15 +598,7 @@ static void process_service_search_attr_rsp (tCONN_CB *p_ccb, UINT8 *p_reply)
             p_ccb->list_len, lists_byte_count);
 #endif
         if (p_ccb->rsp_list == NULL)
-        {
-            p_ccb->rsp_list = (UINT8 *)osi_getbuf (SDP_MAX_LIST_BYTE_COUNT);
-            if (p_ccb->rsp_list == NULL)
-            {
-                SDP_TRACE_ERROR ("SDP - no buf to save rsp");
-                sdp_disconnect (p_ccb, SDP_NO_RESOURCES);
-                return;
-            }
-        }
+            p_ccb->rsp_list = (UINT8 *)osi_malloc(SDP_MAX_LIST_BYTE_COUNT);
         memcpy (&p_ccb->rsp_list[p_ccb->list_len], p_reply, lists_byte_count);
         p_ccb->list_len += lists_byte_count;
         p_reply         += lists_byte_count;
@@ -634,15 +626,9 @@ static void process_service_search_attr_rsp (tCONN_CB *p_ccb, UINT8 *p_reply)
     /* If continuation request (or first time request) */
     if ((cont_request_needed) || (!p_reply))
     {
-        BT_HDR  *p_msg = (BT_HDR *) osi_getbuf(SDP_DATA_BUF_SIZE);
+        BT_HDR  *p_msg = (BT_HDR *)osi_malloc(SDP_DATA_BUF_SIZE);
         UINT8   *p;
 
-        if (!p_msg)
-        {
-            sdp_disconnect (p_ccb, SDP_NO_RESOURCES);
-            return;
-        }
-
         p_msg->offset = L2CAP_MIN_OFFSET;
         p = p_start = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
 
@@ -674,8 +660,12 @@ static void process_service_search_attr_rsp (tCONN_CB *p_ccb, UINT8 *p_reply)
         /* No continuation for first request */
         if (p_reply)
         {
-            memcpy (p, p_reply, *p_reply + 1);
-            p += *p_reply + 1;
+            if ((p_reply + *p_reply + 1) <= p_reply_end) {
+                memcpy(p, p_reply, *p_reply + 1);
+                p += *p_reply + 1;
+            } else {
+                android_errorWriteLog(0x534e4554, "68161546");
+            }
         }
         else
             UINT8_TO_BE_STREAM (p, 0);