Merge cherrypicks of [2686880, 2686702, 2686703, 2686704, 2686141, 2686142, 2686143, 2686705, 2686706, 2686707, 2686782, 2686783, 2686784, 2686785, 2686786, 2686787, 2686788, 2686708, 2686144, 2686789, 2686709, 2686710, 2686711, 2686712, 2686713, 2686714, 2686715] into oc-r4-release

Change-Id: I2fd6ebabd672dd5a6f898039a6060673798e144d
diff --git a/bta/pan/bta_pan_act.cc b/bta/pan/bta_pan_act.cc
index ecc8212..c559993 100644
--- a/bta/pan/bta_pan_act.cc
+++ b/bta/pan/bta_pan_act.cc
@@ -28,6 +28,8 @@
 
 #include <string.h>
 
+#include <cutils/log.h>
+
 #include "bt_common.h"
 #include "bta_api.h"
 #include "bta_pan_api.h"
@@ -174,6 +176,14 @@
 
   if (sizeof(tBTA_PAN_DATA_PARAMS) > p_buf->offset) {
     /* offset smaller than data structure in front of actual data */
+    if (sizeof(BT_HDR) + sizeof(tBTA_PAN_DATA_PARAMS) + p_buf->len >
+        PAN_BUF_SIZE) {
+      android_errorWriteLog(0x534e4554, "63146237");
+      APPL_TRACE_ERROR("%s: received buffer length too large: %d", __func__,
+                       p_buf->len);
+      osi_free(p_buf);
+      return;
+    }
     p_new_buf = (BT_HDR*)osi_malloc(PAN_BUF_SIZE);
     memcpy((uint8_t*)(p_new_buf + 1) + sizeof(tBTA_PAN_DATA_PARAMS),
            (uint8_t*)(p_buf + 1) + p_buf->offset, p_buf->len);
diff --git a/stack/avdt/avdt_api.cc b/stack/avdt/avdt_api.cc
index 8e6ba92..bf45ad3 100644
--- a/stack/avdt/avdt_api.cc
+++ b/stack/avdt/avdt_api.cc
@@ -1042,7 +1042,7 @@
     /* build SR - assume fit in one packet */
     p_tbl = avdt_ad_tc_tbl_by_type(AVDT_CHAN_REPORT, p_scb->p_ccb, p_scb);
     if (p_tbl->state == AVDT_AD_ST_OPEN) {
-      BT_HDR* p_pkt = (BT_HDR*)osi_malloc(p_tbl->peer_mtu);
+      BT_HDR* p_pkt = (BT_HDR*)osi_malloc(p_tbl->peer_mtu + sizeof(BT_HDR));
 
       p_pkt->offset = L2CAP_MIN_OFFSET;
       p = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
diff --git a/stack/bnep/bnep_main.cc b/stack/bnep/bnep_main.cc
index 4800e78..b0fad6a 100644
--- a/stack/bnep/bnep_main.cc
+++ b/stack/bnep/bnep_main.cc
@@ -525,7 +525,8 @@
       if (ctrl_type == BNEP_SETUP_CONNECTION_REQUEST_MSG &&
           p_bcb->con_state != BNEP_STATE_CONNECTED && extension_present && p &&
           rem_len) {
-        p_bcb->p_pending_data = (BT_HDR*)osi_malloc(rem_len);
+        osi_free(p_bcb->p_pending_data);
+        p_bcb->p_pending_data = (BT_HDR*)osi_malloc(rem_len + sizeof(BT_HDR));
         memcpy((uint8_t*)(p_bcb->p_pending_data + 1), p, rem_len);
         p_bcb->p_pending_data->len = rem_len;
         p_bcb->p_pending_data->offset = 0;
diff --git a/stack/bnep/bnep_utils.cc b/stack/bnep/bnep_utils.cc
index 06a5115..872f4f5 100644
--- a/stack/bnep/bnep_utils.cc
+++ b/stack/bnep/bnep_utils.cc
@@ -144,7 +144,7 @@
 
   /* Drop any response pointer we may be holding */
   p_bcb->con_state = BNEP_STATE_IDLE;
-  p_bcb->p_pending_data = NULL;
+  osi_free_and_reset((void**)&p_bcb->p_pending_data);
 
   /* Free transmit queue */
   while (!fixed_queue_is_empty(p_bcb->xmit_q)) {
@@ -714,25 +714,41 @@
 uint8_t* bnep_process_control_packet(tBNEP_CONN* p_bcb, uint8_t* p,
                                      uint16_t* rem_len, bool is_ext) {
   uint8_t control_type;
-  bool bad_pkt = false;
   uint16_t len, ext_len = 0;
 
+  if (p == NULL || rem_len == NULL) {
+    if (rem_len != NULL) *rem_len = 0;
+    BNEP_TRACE_DEBUG("%s: invalid packet: p = %p rem_len = %p", __func__, p,
+                     rem_len);
+    return NULL;
+  }
+  uint16_t rem_len_orig = *rem_len;
+
   if (is_ext) {
+    if (*rem_len < 1) goto bad_packet_length;
     ext_len = *p++;
     *rem_len = *rem_len - 1;
   }
 
+  if (*rem_len < 1) goto bad_packet_length;
   control_type = *p++;
   *rem_len = *rem_len - 1;
 
   BNEP_TRACE_EVENT(
-      "BNEP processing control packet rem_len %d, is_ext %d, ctrl_type %d",
-      *rem_len, is_ext, control_type);
+      "%s: BNEP processing control packet rem_len %d, is_ext %d, ctrl_type %d",
+      __func__, *rem_len, is_ext, control_type);
 
   switch (control_type) {
     case BNEP_CONTROL_COMMAND_NOT_UNDERSTOOD:
-      BNEP_TRACE_ERROR("BNEP Received Cmd not understood for ctl pkt type: %d",
-                       *p);
+      if (*rem_len < 1) {
+        BNEP_TRACE_ERROR(
+            "%s: Received BNEP_CONTROL_COMMAND_NOT_UNDERSTOOD with bad length",
+            __func__);
+        goto bad_packet_length;
+      }
+      BNEP_TRACE_ERROR(
+          "%s: Received BNEP_CONTROL_COMMAND_NOT_UNDERSTOOD for pkt type: %d",
+          __func__, *p);
       p++;
       *rem_len = *rem_len - 1;
       break;
@@ -740,9 +756,10 @@
     case BNEP_SETUP_CONNECTION_REQUEST_MSG:
       len = *p++;
       if (*rem_len < ((2 * len) + 1)) {
-        bad_pkt = true;
-        BNEP_TRACE_ERROR("BNEP Received Setup message with bad length");
-        break;
+        BNEP_TRACE_ERROR(
+            "%s: Received BNEP_SETUP_CONNECTION_REQUEST_MSG with bad length",
+            __func__);
+        goto bad_packet_length;
       }
       if (!is_ext) bnep_process_setup_conn_req(p_bcb, p, (uint8_t)len);
       p += (2 * len);
@@ -750,6 +767,12 @@
       break;
 
     case BNEP_SETUP_CONNECTION_RESPONSE_MSG:
+      if (*rem_len < 2) {
+        BNEP_TRACE_ERROR(
+            "%s: Received BNEP_SETUP_CONNECTION_RESPONSE_MSG with bad length",
+            __func__);
+        goto bad_packet_length;
+      }
       if (!is_ext) bnep_process_setup_conn_responce(p_bcb, p);
       p += 2;
       *rem_len = *rem_len - 2;
@@ -758,9 +781,10 @@
     case BNEP_FILTER_NET_TYPE_SET_MSG:
       BE_STREAM_TO_UINT16(len, p);
       if (*rem_len < (len + 2)) {
-        bad_pkt = true;
-        BNEP_TRACE_ERROR("BNEP Received Filter set message with bad length");
-        break;
+        BNEP_TRACE_ERROR(
+            "%s: Received BNEP_FILTER_NET_TYPE_SET_MSG with bad length",
+            __func__);
+        goto bad_packet_length;
       }
       bnepu_process_peer_filter_set(p_bcb, p, len);
       p += len;
@@ -768,6 +792,12 @@
       break;
 
     case BNEP_FILTER_NET_TYPE_RESPONSE_MSG:
+      if (*rem_len < 2) {
+        BNEP_TRACE_ERROR(
+            "%s: Received BNEP_FILTER_NET_TYPE_RESPONSE_MSG with bad length",
+            __func__);
+        goto bad_packet_length;
+      }
       bnepu_process_peer_filter_rsp(p_bcb, p);
       p += 2;
       *rem_len = *rem_len - 2;
@@ -776,10 +806,10 @@
     case BNEP_FILTER_MULTI_ADDR_SET_MSG:
       BE_STREAM_TO_UINT16(len, p);
       if (*rem_len < (len + 2)) {
-        bad_pkt = true;
         BNEP_TRACE_ERROR(
-            "BNEP Received Multicast Filter Set message with bad length");
-        break;
+            "%s: Received BNEP_FILTER_MULTI_ADDR_SET_MSG with bad length",
+            __func__);
+        goto bad_packet_length;
       }
       bnepu_process_peer_multicast_filter_set(p_bcb, p, len);
       p += len;
@@ -787,28 +817,37 @@
       break;
 
     case BNEP_FILTER_MULTI_ADDR_RESPONSE_MSG:
+      if (*rem_len < 2) {
+        BNEP_TRACE_ERROR(
+            "%s: Received BNEP_FILTER_MULTI_ADDR_RESPONSE_MSG with bad length",
+            __func__);
+        goto bad_packet_length;
+      }
       bnepu_process_multicast_filter_rsp(p_bcb, p);
       p += 2;
       *rem_len = *rem_len - 2;
       break;
 
     default:
-      BNEP_TRACE_ERROR("BNEP - bad ctl pkt type: %d", control_type);
+      BNEP_TRACE_ERROR("%s: BNEP - bad ctl pkt type: %d", __func__,
+                       control_type);
       bnep_send_command_not_understood(p_bcb, control_type);
-      if (is_ext) {
+      if (is_ext && (ext_len > 0)) {
+        if (*rem_len < (ext_len - 1)) {
+          goto bad_packet_length;
+        }
         p += (ext_len - 1);
         *rem_len -= (ext_len - 1);
       }
       break;
   }
-
-  if (bad_pkt) {
-    BNEP_TRACE_ERROR("BNEP - bad ctl pkt length: %d", *rem_len);
-    *rem_len = 0;
-    return NULL;
-  }
-
   return p;
+
+bad_packet_length:
+  BNEP_TRACE_ERROR("%s: bad control packet length: original=%d remaining=%d",
+                   __func__, rem_len_orig, *rem_len);
+  *rem_len = 0;
+  return NULL;
 }
 
 /*******************************************************************************
diff --git a/stack/l2cap/l2cap_client.cc b/stack/l2cap/l2cap_client.cc
index 2568fc8..8c4eafe 100644
--- a/stack/l2cap/l2cap_client.cc
+++ b/stack/l2cap/l2cap_client.cc
@@ -393,7 +393,7 @@
 
   // TODO(sharvil): eliminate copy into BT_HDR.
   BT_HDR* bt_packet = static_cast<BT_HDR*>(
-      osi_malloc(buffer_length(packet) + L2CAP_MIN_OFFSET));
+      osi_malloc(buffer_length(packet) + L2CAP_MIN_OFFSET + sizeof(BT_HDR)));
   bt_packet->offset = L2CAP_MIN_OFFSET;
   bt_packet->len = buffer_length(packet);
   memcpy(bt_packet->data + bt_packet->offset, buffer_ptr(packet),
@@ -408,8 +408,8 @@
       break;
     }
 
-    BT_HDR* fragment =
-        static_cast<BT_HDR*>(osi_malloc(client->remote_mtu + L2CAP_MIN_OFFSET));
+    BT_HDR* fragment = static_cast<BT_HDR*>(
+        osi_malloc(client->remote_mtu + L2CAP_MIN_OFFSET + sizeof(BT_HDR)));
     fragment->offset = L2CAP_MIN_OFFSET;
     fragment->len = client->remote_mtu;
     memcpy(fragment->data + fragment->offset,
diff --git a/stack/mcap/mca_cact.cc b/stack/mcap/mca_cact.cc
index 72efb85..c39700f 100644
--- a/stack/mcap/mca_cact.cc
+++ b/stack/mcap/mca_cact.cc
@@ -117,7 +117,7 @@
   if ((!p_ccb->p_tx_req) || is_abort) {
     p_ccb->p_tx_req = p_msg;
     if (!p_ccb->cong) {
-      BT_HDR* p_pkt = (BT_HDR*)osi_malloc(MCA_CTRL_MTU);
+      BT_HDR* p_pkt = (BT_HDR*)osi_malloc(MCA_CTRL_MTU + sizeof(BT_HDR));
 
       p_pkt->offset = L2CAP_MIN_OFFSET;
       p = p_start = (uint8_t*)(p_pkt + 1) + L2CAP_MIN_OFFSET;
@@ -154,7 +154,7 @@
 void mca_ccb_snd_rsp(tMCA_CCB* p_ccb, tMCA_CCB_EVT* p_data) {
   tMCA_CCB_MSG* p_msg = (tMCA_CCB_MSG*)p_data;
   uint8_t *p, *p_start;
-  BT_HDR* p_pkt = (BT_HDR*)osi_malloc(MCA_CTRL_MTU);
+  BT_HDR* p_pkt = (BT_HDR*)osi_malloc(MCA_CTRL_MTU + sizeof(BT_HDR));
 
   MCA_TRACE_DEBUG("%s cong=%d req=%d", __func__, p_ccb->cong, p_msg->op_code);
   /* assume that API functions verified the parameters */
@@ -367,7 +367,7 @@
   if (((reject_code != MCA_RSP_SUCCESS) &&
        (evt_data.hdr.op_code != MCA_OP_SYNC_INFO_IND)) ||
       send_rsp) {
-    BT_HDR* p_buf = (BT_HDR*)osi_malloc(MCA_CTRL_MTU);
+    BT_HDR* p_buf = (BT_HDR*)osi_malloc(MCA_CTRL_MTU + sizeof(BT_HDR));
     p_buf->offset = L2CAP_MIN_OFFSET;
     p = p_start = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
     *p++ = reject_opcode;
diff --git a/stack/pan/pan_main.cc b/stack/pan/pan_main.cc
index d89096b..01e1ea4 100644
--- a/stack/pan/pan_main.cc
+++ b/stack/pan/pan_main.cc
@@ -214,6 +214,39 @@
     return;
   }
 
+  /* Check for valid interactions between the three PAN profile roles */
+  /*
+   * For reference, see Table 1 in PAN Profile v1.0 spec.
+   * Note: the remote is the initiator.
+   */
+  bool is_valid_interaction = false;
+  switch (remote_uuid->uu.uuid16) {
+    case UUID_SERVCLASS_NAP:
+    case UUID_SERVCLASS_GN:
+      if (local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU)
+        is_valid_interaction = true;
+      break;
+    case UUID_SERVCLASS_PANU:
+      is_valid_interaction = true;
+      break;
+  }
+  /*
+   * Explicitly disable connections to the local PANU if the remote is
+   * not PANU.
+   */
+  if ((local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU) &&
+      (remote_uuid->uu.uuid16 != UUID_SERVCLASS_PANU)) {
+    is_valid_interaction = false;
+  }
+  if (!is_valid_interaction) {
+    PAN_TRACE_ERROR(
+        "PAN Connection failed because of invalid PAN profile roles "
+        "interaction: Remote UUID 0x%x Local UUID 0x%x",
+        remote_uuid->uu.uuid16, local_uuid->uu.uuid16);
+    BNEP_ConnectResp(handle, BNEP_CONN_FAILED_SRC_UUID);
+    return;
+  }
+
   /* Requested destination role is */
   if (local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU)
     req_role = PAN_ROLE_CLIENT;
diff --git a/stack/sdp/sdp_server.cc b/stack/sdp/sdp_server.cc
index fe67be1..24a168c 100644
--- a/stack/sdp/sdp_server.cc
+++ b/stack/sdp/sdp_server.cc
@@ -218,7 +218,7 @@
     }
     BE_STREAM_TO_UINT16(cont_offset, p_req);
 
-    if (cont_offset != p_ccb->cont_offset) {
+    if (cont_offset != p_ccb->cont_offset || num_rsp_handles < cont_offset) {
       sdpu_build_n_send_error(p_ccb, trans_num, SDP_INVALID_CONT_STATE,
                               SDP_TEXT_BAD_CONT_INX);
       return;