Merge tag 'android-security-13.0.0_r13' into staging/lineage-20.0_merge-android-security-13.0.0_r13

Android security 13.0.0 release 13

# -----BEGIN PGP SIGNATURE-----
#
# iF0EABECAB0WIQRDQNE1cO+UXoOBCWTorT+BmrEOeAUCZZWxiwAKCRDorT+BmrEO
# eEsCAKCIhbDOn3n9433Ky8Wt+JVu9pW/hwCdH6OZVIWPvDY0ki/lb/0r24B4c4Q=
# =mV7Z
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed Jan  3 21:12:11 2024 EET
# gpg:                using DSA key 4340D13570EF945E83810964E8AD3F819AB10E78
# gpg: Good signature from "The Android Open Source Project <initial-contribution@android.com>" [marginal]
# gpg: initial-contribution@android.com: Verified 2237 signatures in the past
#      2 years.  Encrypted 4 messages in the past 24 months.
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 4340 D135 70EF 945E 8381  0964 E8AD 3F81 9AB1 0E78

# By Brian Delwiche
# Via Android Build Coastguard Worker
* tag 'android-security-13.0.0_r13':
  Fix some OOB errors in BTM parsing

Change-Id: I6cc2374030f1a8b19ad71ecc4bb045385a8aeae5
diff --git a/system/stack/btm/btm_ble_gap.cc b/system/stack/btm/btm_ble_gap.cc
index 84ff981..3d334a0 100644
--- a/system/stack/btm/btm_ble_gap.cc
+++ b/system/stack/btm/btm_ble_gap.cc
@@ -1437,6 +1437,16 @@
   uint16_t sync_handle, iso_interval, max_pdu, max_sdu;
   uint8_t num_bises, nse, bn, pto, irc, phy, framing, encryption;
   uint32_t sdu_interval;
+
+  // 2 bytes for sync handle, 1 byte for num_bises, 1 byte for nse, 2 bytes for
+  // iso_interval, 1 byte each for bn, pto, irc, 2 bytes for max_pdu, 3 bytes
+  // for sdu_interval, 2 bytes for max_sdu, 1 byte each for phy, framing,
+  // encryption
+  if (param_len < 19) {
+    LOG_ERROR("Insufficient data");
+    return;
+  }
+
   STREAM_TO_UINT16(sync_handle, p);
   STREAM_TO_UINT8(num_bises, p);
   STREAM_TO_UINT8(nse, p);
@@ -2566,20 +2576,27 @@
       advertising_sid;
   int8_t rssi, tx_power;
   uint16_t event_type, periodic_adv_int, direct_address_type;
+  size_t bytes_to_process;
 
   /* Only process the results if the inquiry is still active */
   if (!btm_cb.ble_ctr_cb.is_ble_scan_active()) return;
 
+  bytes_to_process = 1;
+
+  if (data_len < bytes_to_process) {
+    LOG(ERROR) << "Malformed LE extended advertising packet: not enough room "
+                  "for num reports";
+    return;
+  }
+
   /* Extract the number of reports in this event. */
   STREAM_TO_UINT8(num_reports, p);
 
-  constexpr int extended_report_header_size = 24;
   while (num_reports--) {
-    if (p + extended_report_header_size > data + data_len) {
-      // TODO(jpawlowski): we should crash the stack here
-      BTM_TRACE_ERROR(
-          "Malformed LE Extended Advertising Report Event from controller - "
-          "can't loop the data");
+    bytes_to_process += 24;
+    if (data_len < bytes_to_process) {
+      LOG(ERROR) << "Malformed LE extended advertising packet: not enough room "
+                    "for metadata";
       return;
     }
 
@@ -2599,8 +2616,11 @@
 
     const uint8_t* pkt_data = p;
     p += pkt_data_len; /* Advance to the the next packet*/
-    if (p > data + data_len) {
-      LOG(ERROR) << "Invalid pkt_data_len: " << +pkt_data_len;
+
+    bytes_to_process += pkt_data_len;
+    if (data_len < bytes_to_process) {
+      LOG(ERROR) << "Malformed LE extended advertising packet: not enough room "
+                    "for packet data";
       return;
     }
 
@@ -2633,18 +2653,28 @@
   const uint8_t* p = data;
   uint8_t legacy_evt_type, addr_type, num_reports, pkt_data_len;
   int8_t rssi;
+  size_t bytes_to_process;
 
   /* Only process the results if the inquiry is still active */
   if (!btm_cb.ble_ctr_cb.is_ble_scan_active()) return;
 
+  bytes_to_process = 1;
+
+  if (data_len < bytes_to_process) {
+    LOG(ERROR)
+        << "Malformed LE advertising packet: not enough room for num reports";
+    return;
+  }
+
   /* Extract the number of reports in this event. */
   STREAM_TO_UINT8(num_reports, p);
 
-  constexpr int report_header_size = 10;
   while (num_reports--) {
-    if (p + report_header_size > data + data_len) {
-      // TODO(jpawlowski): we should crash the stack here
-      BTM_TRACE_ERROR("Malformed LE Advertising Report Event from controller");
+    bytes_to_process += 9;
+
+    if (data_len < bytes_to_process) {
+      LOG(ERROR)
+          << "Malformed LE advertising packet: not enough room for metadata";
       return;
     }
 
@@ -2656,8 +2686,12 @@
 
     const uint8_t* pkt_data = p;
     p += pkt_data_len; /* Advance to the the rssi byte */
-    if (p > data + data_len - sizeof(rssi)) {
-      LOG(ERROR) << "Invalid pkt_data_len: " << +pkt_data_len;
+
+    // include rssi for this check
+    bytes_to_process += pkt_data_len + 1;
+    if (data_len < bytes_to_process) {
+      LOG(ERROR) << "Malformed LE advertising packet: not enough room for "
+                    "packet data and/or RSSI";
       return;
     }
 
diff --git a/system/stack/btu/btu_hcif.cc b/system/stack/btu/btu_hcif.cc
index ec05df2..f00effe 100644
--- a/system/stack/btu/btu_hcif.cc
+++ b/system/stack/btu/btu_hcif.cc
@@ -1693,6 +1693,12 @@
     return;
   }
 
+  // 2 bytes each for handle, tx_data_len, TxTimer, rx_data_len
+  if (evt_len < 8) {
+    LOG_ERROR("Event packet too short");
+    return;
+  }
+
   STREAM_TO_UINT16(handle, p);
   STREAM_TO_UINT16(tx_data_len, p);
   p += 2; /* Skip the TxTimer */