Merge branch 'dev/11/fp3/security-aosp-rvc-release' into int/11/fp3

* dev/11/fp3/security-aosp-rvc-release:
  Revert "Revert "Fix wrong BR/EDR link key downgrades (P_256->P_192)""
  Revert "Revert "[RESTRICT AUTOMERGE] Validate buffer length in sdpu_build_uuid_seq""
  Prevent use-after-free of HID reports

Change-Id: I645864626a54a34766274f65c621c422c07e65e7
diff --git a/btif/src/btif_hh.cc b/btif/src/btif_hh.cc
index 5380fa5..97479e0 100644
--- a/btif/src/btif_hh.cc
+++ b/btif/src/btif_hh.cc
@@ -1095,6 +1095,38 @@
 
 /*******************************************************************************
  *
+ * Function         btif_hh_hsdata_rpt_copy_cb
+ *
+ * Description      Deep copies the tBTA_HH_HSDATA structure
+ *
+ * Returns          void
+ *
+ ******************************************************************************/
+
+static void btif_hh_hsdata_rpt_copy_cb(uint16_t event, char* p_dest,
+                                       char* p_src) {
+  tBTA_HH_HSDATA* p_dst_data = (tBTA_HH_HSDATA*)p_dest;
+  tBTA_HH_HSDATA* p_src_data = (tBTA_HH_HSDATA*)p_src;
+  BT_HDR* hdr;
+
+  if (!p_src) {
+    BTIF_TRACE_ERROR("%s: Nothing to copy", __func__);
+    return;
+  }
+
+  memcpy(p_dst_data, p_src_data, sizeof(tBTA_HH_HSDATA));
+
+  hdr = p_src_data->rsp_data.p_rpt_data;
+  if (hdr != NULL) {
+    uint8_t* p_data = ((uint8_t*)p_dst_data) + sizeof(tBTA_HH_HSDATA);
+    memcpy(p_data, hdr, BT_HDR_SIZE + hdr->offset + hdr->len);
+
+    p_dst_data->rsp_data.p_rpt_data = (BT_HDR*)p_data;
+  }
+}
+
+/*******************************************************************************
+ *
  * Function         bte_hh_evt
  *
  * Description      Switches context from BTE to BTIF for all HH events
@@ -1106,6 +1138,7 @@
 void bte_hh_evt(tBTA_HH_EVT event, tBTA_HH* p_data) {
   bt_status_t status;
   int param_len = 0;
+  tBTIF_COPY_CBACK* p_copy_cback = NULL;
 
   if (BTA_HH_ENABLE_EVT == event)
     param_len = sizeof(tBTA_HH_STATUS);
@@ -1117,11 +1150,18 @@
     param_len = sizeof(tBTA_HH_CBDATA);
   else if (BTA_HH_GET_DSCP_EVT == event)
     param_len = sizeof(tBTA_HH_DEV_DSCP_INFO);
-  else if ((BTA_HH_GET_PROTO_EVT == event) || (BTA_HH_GET_RPT_EVT == event) ||
-           (BTA_HH_GET_IDLE_EVT == event))
+  else if ((BTA_HH_GET_PROTO_EVT == event) || (BTA_HH_GET_IDLE_EVT == event))
     param_len = sizeof(tBTA_HH_HSDATA);
-  else if ((BTA_HH_SET_PROTO_EVT == event) || (BTA_HH_SET_RPT_EVT == event) ||
-           (BTA_HH_VC_UNPLUG_EVT == event) || (BTA_HH_SET_IDLE_EVT == event))
+  else if (BTA_HH_GET_RPT_EVT == event) {
+    BT_HDR* hdr = p_data->hs_data.rsp_data.p_rpt_data;
+    param_len = sizeof(tBTA_HH_HSDATA);
+
+    if (hdr != NULL) {
+      p_copy_cback = btif_hh_hsdata_rpt_copy_cb;
+      param_len += BT_HDR_SIZE + hdr->offset + hdr->len;
+    }
+  } else if ((BTA_HH_SET_PROTO_EVT == event) || (BTA_HH_SET_RPT_EVT == event) ||
+             (BTA_HH_VC_UNPLUG_EVT == event) || (BTA_HH_SET_IDLE_EVT == event))
     param_len = sizeof(tBTA_HH_CBDATA);
   else if ((BTA_HH_ADD_DEV_EVT == event) || (BTA_HH_RMV_DEV_EVT == event))
     param_len = sizeof(tBTA_HH_DEV_INFO);
@@ -1130,7 +1170,7 @@
   /* switch context to btif task context (copy full union size for convenience)
    */
   status = btif_transfer_context(btif_hh_upstreams_evt, (uint16_t)event,
-                                 (char*)p_data, param_len, NULL);
+                                 (char*)p_data, param_len, p_copy_cback);
 
   /* catch any failed context transfers */
   ASSERTC(status == BT_STATUS_SUCCESS, "context transfer failed", status);
diff --git a/stack/btm/btm_sec.cc b/stack/btm/btm_sec.cc
index eecbed5..ec120f6 100644
--- a/stack/btm/btm_sec.cc
+++ b/stack/btm/btm_sec.cc
@@ -3826,22 +3826,6 @@
           SMP_BR_PairWith(p_dev_rec->bd_addr);
         }
       }
-    } else {
-      // BR/EDR is successfully encrypted. Correct LK type if needed
-      // (BR/EDR LK derived from LE LTK was used for encryption)
-      if ((encr_enable == 1) && /* encryption is ON for SSP */
-          /* LK type is for BR/EDR SC */
-          (p_dev_rec->link_key_type == BTM_LKEY_TYPE_UNAUTH_COMB_P_256 ||
-           p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256)) {
-        if (p_dev_rec->link_key_type == BTM_LKEY_TYPE_UNAUTH_COMB_P_256)
-          p_dev_rec->link_key_type = BTM_LKEY_TYPE_UNAUTH_COMB;
-        else /* BTM_LKEY_TYPE_AUTH_COMB_P_256 */
-          p_dev_rec->link_key_type = BTM_LKEY_TYPE_AUTH_COMB;
-
-        BTM_TRACE_DEBUG("updated link key type to %d",
-                        p_dev_rec->link_key_type);
-        btm_send_link_key_notif(p_dev_rec);
-      }
     }
   }
 
diff --git a/stack/sdp/sdp_discovery.cc b/stack/sdp/sdp_discovery.cc
index f5938e4..553e068 100644
--- a/stack/sdp/sdp_discovery.cc
+++ b/stack/sdp/sdp_discovery.cc
@@ -70,10 +70,15 @@
  *
  ******************************************************************************/
 static uint8_t* sdpu_build_uuid_seq(uint8_t* p_out, uint16_t num_uuids,
-                                    Uuid* p_uuid_list) {
+                                    Uuid* p_uuid_list, uint16_t& bytes_left) {
   uint16_t xx;
   uint8_t* p_len;
 
+  if (bytes_left < 2) {
+    DCHECK(0) << "SDP: No space for data element header";
+    return (p_out);
+  }
+
   /* First thing is the data element header */
   UINT8_TO_BE_STREAM(p_out, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
 
@@ -81,9 +86,20 @@
   p_len = p_out;
   p_out += 1;
 
+  /* Account for data element header and length */
+  bytes_left -= 2;
+
   /* Now, loop through and put in all the UUID(s) */
   for (xx = 0; xx < num_uuids; xx++, p_uuid_list++) {
     int len = p_uuid_list->GetShortestRepresentationSize();
+
+    if (len + 1 > bytes_left) {
+      DCHECK(0) << "SDP: Too many UUIDs for internal buffer";
+      break;
+    } else {
+      bytes_left -= (len + 1);
+    }
+
     if (len == Uuid::kNumBytes16) {
       UINT8_TO_BE_STREAM(p_out, (UUID_DESC_TYPE << 3) | SIZE_TWO_BYTES);
       UINT16_TO_BE_STREAM(p_out, p_uuid_list->As16Bit());
@@ -120,6 +136,7 @@
   uint8_t *p, *p_start, *p_param_len;
   BT_HDR* p_cmd = (BT_HDR*)osi_malloc(SDP_DATA_BUF_SIZE);
   uint16_t param_len;
+  uint16_t bytes_left = SDP_DATA_BUF_SIZE;
 
   /* Prepare the buffer for sending the packet to L2CAP */
   p_cmd->offset = L2CAP_MIN_OFFSET;
@@ -134,13 +151,30 @@
   p_param_len = p;
   p += 2;
 
-/* Build the UID sequence. */
+  /* Account for header size, max service record count and
+   * continuation state */
+  const uint16_t base_bytes = (sizeof(BT_HDR) + L2CAP_MIN_OFFSET +
+                               3u + /* service search request header */
+                               2u + /* param len */
+                               3u + ((p_cont) ? cont_len : 0));
+
+  if (base_bytes > bytes_left) {
+    DCHECK(0) << "SDP: Overran SDP data buffer";
+    osi_free(p_cmd);
+    return;
+  }
+
+  bytes_left -= base_bytes;
+
+  /* Build the UID sequence. */
 #if (SDP_BROWSE_PLUS == TRUE)
   p = sdpu_build_uuid_seq(p, 1,
-                          &p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx]);
+                          &p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx],
+                          bytes_left);
 #else
+  /* Build the UID sequence. */
   p = sdpu_build_uuid_seq(p, p_ccb->p_db->num_uuid_filters,
-                          p_ccb->p_db->uuid_filters);
+                          p_ccb->p_db->uuid_filters, bytes_left);
 #endif
 
   /* Set max service record count */
@@ -575,6 +609,7 @@
   if ((cont_request_needed) || (!p_reply)) {
     BT_HDR* p_msg = (BT_HDR*)osi_malloc(SDP_DATA_BUF_SIZE);
     uint8_t* p;
+    uint16_t bytes_left = SDP_DATA_BUF_SIZE;
 
     p_msg->offset = L2CAP_MIN_OFFSET;
     p = p_start = (uint8_t*)(p_msg + 1) + L2CAP_MIN_OFFSET;
@@ -588,13 +623,29 @@
     p_param_len = p;
     p += 2;
 
-/* Build the UID sequence. */
+    /* Account for header size, max service record count and
+     * continuation state */
+    const uint16_t base_bytes = (sizeof(BT_HDR) + L2CAP_MIN_OFFSET +
+                                 3u + /* service search request header */
+                                 2u + /* param len */
+                                 3u + /* max service record count */
+                                 ((p_reply) ? (*p_reply) : 0));
+
+    if (base_bytes > bytes_left) {
+      sdp_disconnect(p_ccb, SDP_INVALID_CONT_STATE);
+      return;
+    }
+
+    bytes_left -= base_bytes;
+
+    /* Build the UID sequence. */
 #if (SDP_BROWSE_PLUS == TRUE)
     p = sdpu_build_uuid_seq(p, 1,
-                            &p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx]);
+                            &p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx],
+                            bytes_left);
 #else
     p = sdpu_build_uuid_seq(p, p_ccb->p_db->num_uuid_filters,
-                            p_ccb->p_db->uuid_filters);
+                            p_ccb->p_db->uuid_filters, bytes_left);
 #endif
 
     /* Max attribute byte count */