OSDN Git Service

Merge "packet: Add Packet classes and tests" am: a275910a49 am: 257ed53ca9
authorMyles Watson <mylesgw@google.com>
Wed, 3 Apr 2019 02:51:27 +0000 (19:51 -0700)
committerandroid-build-merger <android-build-merger@google.com>
Wed, 3 Apr 2019 02:51:27 +0000 (19:51 -0700)
am: 995361568d

Change-Id: I9f2f7b7b8bc14b80f7306ad2eb6cc5907d39c440

55 files changed:
PREUPLOAD.cfg
binder/Android.bp
bta/ag/bta_ag_cmd.cc
bta/av/bta_av_aact.cc
btif/src/btif_config.cc
btif/src/btif_hf.cc
btif/src/btif_hf_client.cc
hci/include/btsnoop.h
hci/src/btsnoop.cc
hci/src/packet_fragmenter.cc
main/Android.bp
packet/avrcp/general_reject_packet.cc
packet/avrcp/general_reject_packet.h
packet/avrcp/register_notification_packet.cc
packet/tests/avrcp/avrcp_test_packets.h
packet/tests/avrcp/general_reject_packet_test.cc
profile/avrcp/device.cc
profile/avrcp/tests/avrcp_device_test.cc
stack/avct/avct_api.cc
stack/avct/avct_lcb_act.cc
stack/avdt/avdt_api.cc
stack/avdt/avdt_msg.cc
stack/avrc/avrc_pars_tg.cc
stack/bnep/bnep_api.cc
stack/bnep/bnep_int.h
stack/bnep/bnep_main.cc
stack/bnep/bnep_utils.cc
stack/btm/btm_ble_gap.cc
stack/btu/btu_hcif.cc
stack/gap/gap_conn.cc
stack/gatt/gatt_api.cc
stack/gatt/gatt_main.cc
stack/hcic/hcicmds.cc
stack/hid/hidd_api.cc
stack/hid/hidd_conn.cc
stack/hid/hidh_conn.cc
stack/include/advertise_data_parser.h
stack/include/hcimsgs.h
stack/include/l2c_api.h
stack/l2cap/l2c_api.cc
stack/l2cap/l2c_int.h
stack/l2cap/l2c_main.cc
stack/l2cap/l2c_utils.cc
stack/rfcomm/rfc_l2cap_if.cc
stack/rfcomm/rfc_port_fsm.cc
stack/rfcomm/rfc_ts_frames.cc
stack/sdp/sdp_discovery.cc
stack/sdp/sdp_main.cc
stack/smp/smp_act.cc
stack/smp/smp_int.h
stack/smp/smp_l2c.cc
stack/smp/smp_utils.cc
stack/test/rfcomm/stack_rfcomm_test.cc
test/suite/adapter/bluetooth_test.cc
udrv/ulinux/uipc.cc

index 7fb1636..380216c 100644 (file)
@@ -4,3 +4,6 @@ ignore_merged_commits = true
 [Builtin Hooks]
 clang_format = true
 
+[Hook Scripts]
+aosp_first = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} ".*$"
+
index cff166b..650906c 100644 (file)
@@ -76,6 +76,9 @@ cc_library_shared {
         "-Wextra",
         "-Wno-unused-parameter",
     ],
+    sanitize: {
+        scs: true,
+    },
 }
 
 // AIDL interface between libbluetooth-binder and framework.jar
index bec5497..87b2a82 100644 (file)
@@ -782,9 +782,11 @@ static void bta_ag_bind_response(tBTA_AG_SCB* p_scb, uint8_t arg_type) {
  ******************************************************************************/
 static bool bta_ag_parse_biev_response(tBTA_AG_SCB* p_scb, tBTA_AG_VAL* val) {
   char* p_token = strtok(val->str, ",");
+  if (p_token == nullptr) return false;
   uint16_t rcv_ind_id = atoi(p_token);
 
   p_token = strtok(nullptr, ",");
+  if (p_token == nullptr) return false;
   uint16_t rcv_ind_val = atoi(p_token);
 
   APPL_TRACE_DEBUG("%s BIEV indicator id %d, value %d", __func__, rcv_ind_id,
index 7342b61..7833dc7 100644 (file)
@@ -965,7 +965,7 @@ void bta_av_free_sdb(tBTA_AV_SCB* p_scb, UNUSED_ATTR tBTA_AV_DATA* p_data) {
  *
  ******************************************************************************/
 void bta_av_config_ind(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
-  tBTA_AV_CI_SETCONFIG setconfig;
+  tBTA_AV_CI_SETCONFIG setconfig{};
   tAVDT_SEP_INFO* p_info;
   const AvdtpSepConfig* p_evt_cfg = &p_data->str_msg.cfg;
   uint8_t psc_mask = (p_evt_cfg->psc_mask | p_scb->cfg.psc_mask);
index 9b80868..7d23e34 100644 (file)
 #define DISABLED "disabled"
 static const char* TIME_STRING_FORMAT = "%Y-%m-%d %H:%M:%S";
 
-#define BT_CONFIG_METRICS_SECTION "Metrics"
-#define BT_CONFIG_METRICS_SALT_256BIT "Salt256Bit"
-using bluetooth::common::AddressObfuscator;
 constexpr int kBufferSize = 400 * 10;  // initial file is ~400B
 
 static bool use_key_attestation() { return getuid() == AID_BLUETOOTH; }
 
+#define BT_CONFIG_METRICS_SECTION "Metrics"
+#define BT_CONFIG_METRICS_SALT_256BIT "Salt256Bit"
 using bluetooth::BtifKeystore;
+using bluetooth::common::AddressObfuscator;
 
 // TODO(armansito): Find a better way than searching by a hardcoded path.
 #if defined(OS_GENERIC)
@@ -451,6 +451,12 @@ bool btif_config_set_bin(const std::string& section, const std::string& key,
 
   if (length > 0) CHECK(value != NULL);
 
+  size_t max_value = ((size_t)-1);
+  if (((max_value - 1) / 2) < length) {
+    LOG(ERROR) << __func__ << ": length too long";
+    return false;
+  }
+
   char* str = (char*)osi_calloc(length * 2 + 1);
 
   for (size_t i = 0; i < length; ++i) {
@@ -646,7 +652,7 @@ static std::string hash_file(const char* filename) {
   uint8_t hash[SHA256_DIGEST_LENGTH];
   SHA256_CTX sha256;
   SHA256_Init(&sha256);
-  std::array<unsigned char, kBufferSize> buffer;
+  std::array<std::byte, kBufferSize> buffer;
   int bytes_read = 0;
   while ((bytes_read = fread(buffer.data(), 1, buffer.size(), fp))) {
     SHA256_Update(&sha256, buffer.data(), bytes_read);
index e0e9515..04ad011 100644 (file)
@@ -412,7 +412,7 @@ static void btif_hf_upstreams_evt(uint16_t event, char* p_param) {
     case BTA_AG_AT_BLDN_EVT:
     case BTA_AG_AT_D_EVT:
       bt_hf_callbacks->DialCallCallback(
-          (event == BTA_AG_AT_D_EVT) ? p_data->val.str : nullptr,
+          (event == BTA_AG_AT_D_EVT) ? p_data->val.str : (char*)"",
           &btif_hf_cb[idx].connected_bda);
       break;
 
index 7c65bf7..e84291d 100644 (file)
@@ -949,7 +949,7 @@ static void btif_hf_client_upstreams_evt(uint16_t event, char* p_param) {
                 (bthf_client_call_state_t)p_data->clcc.status,
                 p_data->clcc.mpty ? BTHF_CLIENT_CALL_MPTY_TYPE_MULTI
                                   : BTHF_CLIENT_CALL_MPTY_TYPE_SINGLE,
-                p_data->clcc.number_present ? p_data->clcc.number : NULL);
+                p_data->clcc.number_present ? p_data->clcc.number : "");
       break;
 
     case BTA_HF_CLIENT_CNUM_EVT:
index e897a96..476c62d 100644 (file)
@@ -29,6 +29,28 @@ typedef struct btsnoop_t {
   // true, the packet is marked as incoming. Otherwise, the packet is marked
   // as outgoing.
   void (*capture)(const BT_HDR* packet, bool is_received);
+
+  // Set a L2CAP channel as whitelisted, allowing packets with that L2CAP CID
+  // to show up in the snoop logs.
+  void (*whitelist_l2c_channel)(uint16_t conn_handle, uint16_t local_cid,
+                                uint16_t remote_cid);
+
+  // Set a RFCOMM dlci as whitelisted, allowing packets with that RFCOMM CID
+  // to show up in the snoop logs. The local_cid is used to associate it with
+  // its corrisponding ACL connection. The dlci is the channel with direction
+  // so there is no chance of a collision if two services are using the same
+  // channel but in different directions.
+  void (*whitelist_rfc_dlci)(uint16_t local_cid, uint8_t dlci);
+
+  // Indicate that the provided L2CAP channel is being used for RFCOMM.
+  // If packets with the provided L2CAP CID are encountered, they will be
+  // filtered on RFCOMM based on channels provided to |filter_rfc_channel|.
+  void (*add_rfc_l2c_channel)(uint16_t conn_handle, uint16_t local_cid,
+                              uint16_t remote_cid);
+
+  // Clear an L2CAP channel from being filtered.
+  void (*clear_l2cap_whitelist)(uint16_t conn_handle, uint16_t local_cid,
+                                uint16_t remote_cid);
 } btsnoop_t;
 
 const btsnoop_t* btsnoop_get_interface(void);
index 6938725..ad06ac7 100644 (file)
@@ -21,6 +21,7 @@
 #include <mutex>
 
 #include <arpa/inet.h>
+#include <base/logging.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
 #include <sys/time.h>
 #include <sys/uio.h>
 #include <unistd.h>
+#include <mutex>
+#include <unordered_map>
+#include <unordered_set>
 
 #include "bt_types.h"
 #include "common/time_util.h"
 #include "hci/include/btsnoop.h"
 #include "hci/include/btsnoop_mem.h"
 #include "hci_layer.h"
+#include "internal_include/bt_trace.h"
 #include "osi/include/log.h"
 #include "osi/include/properties.h"
+#include "stack/include/hcimsgs.h"
+#include "stack/include/rfcdefs.h"
+#include "stack/l2cap/l2c_int.h"
 #include "stack_config.h"
 
 // The number of of packets per btsnoop file before we rotate to the next
 // property
 #define DEFAULT_BTSNOOP_SIZE 0xffff
 
-#define BTSNOOP_ENABLE_PROPERTY "persist.bluetooth.btsnoopenable"
+#define IS_DEBUGGABLE_PROPERTY "ro.debuggable"
+
+#define BTSNOOP_LOG_MODE_PROPERTY "persist.bluetooth.btsnooplogmode"
+#define BTSNOOP_DEFAULT_MODE_PROPERTY "persist.bluetooth.btsnoopdefaultmode"
+#define BTSNOOP_MODE_DISABLED "disabled"
+#define BTSNOOP_MODE_FILTERED "filtered"
+#define BTSNOOP_MODE_FULL "full"
+
 #define BTSNOOP_PATH_PROPERTY "persist.bluetooth.btsnooppath"
 #define DEFAULT_BTSNOOP_PATH "/data/misc/bluetooth/logs/btsnoop_hci.log"
 #define BTSNOOP_MAX_PACKETS_PROPERTY "persist.bluetooth.btsnoopsize"
@@ -65,33 +80,138 @@ typedef enum {
 // Epoch in microseconds since 01/01/0000.
 static const uint64_t BTSNOOP_EPOCH_DELTA = 0x00dcddb30f2f8000ULL;
 
+// Number of bytes into a packet where you can find the value for a channel.
+static const size_t ACL_CHANNEL_OFFSET = 0;
+static const size_t L2C_CHANNEL_OFFSET = 6;
+static const size_t RFC_CHANNEL_OFFSET = 8;
+static const size_t RFC_EVENT_OFFSET = 9;
+
+// The size of the L2CAP header. All information past this point is removed from
+// a filtered packet.
+static const uint32_t L2C_HEADER_SIZE = 9;
+
 static int logfile_fd = INVALID_FD;
 static std::mutex btsnoop_mutex;
 
 static int32_t packets_per_file;
 static int32_t packet_counter;
 
+// Channel tracking variables for filtering.
+
+// Keeps track of L2CAP channels that need to be filtered out of the snoop
+// logs.
+class FilterTracker {
+ public:
+  // NOTE: 1 is used as a static CID for L2CAP signaling
+  std::unordered_set<uint16_t> l2c_local_cid = {1};
+  std::unordered_set<uint16_t> l2c_remote_cid = {1};
+  uint16_t rfc_local_cid = 0;
+  uint16_t rfc_remote_cid = 0;
+  std::unordered_set<uint16_t> rfc_channels = {0};
+
+  // Adds L2C channel to whitelist.
+  void addL2cCid(uint16_t local_cid, uint16_t remote_cid) {
+    l2c_local_cid.insert(local_cid);
+    l2c_remote_cid.insert(remote_cid);
+  }
+
+  // Sets L2CAP channel that RFCOMM uses.
+  void setRfcCid(uint16_t local_cid, uint16_t remote_cid) {
+    rfc_local_cid = local_cid;
+    rfc_remote_cid = remote_cid;
+  }
+
+  // Remove L2C channel from whitelist.
+  void removeL2cCid(uint16_t local_cid, uint16_t remote_cid) {
+    if (rfc_local_cid == local_cid) {
+      rfc_channels.clear();
+      rfc_channels.insert(0);
+      rfc_local_cid = 0;
+      rfc_remote_cid = 0;
+    }
+
+    l2c_local_cid.erase(local_cid);
+    l2c_remote_cid.erase(remote_cid);
+  }
+
+  void addRfcDlci(uint8_t channel) { rfc_channels.insert(channel); }
+
+  bool isWhitelistedL2c(bool local, uint16_t cid) {
+    const auto& set = local ? l2c_local_cid : l2c_remote_cid;
+    return (set.find(cid) != set.end());
+  }
+
+  bool isRfcChannel(bool local, uint16_t cid) {
+    const auto& channel = local ? rfc_local_cid : rfc_remote_cid;
+    return cid == channel;
+  }
+
+  bool isWhitelistedDlci(uint8_t dlci) {
+    return rfc_channels.find(dlci) != rfc_channels.end();
+  }
+};
+
+std::mutex filter_list_mutex;
+std::unordered_map<uint16_t, FilterTracker> filter_list;
+std::unordered_map<uint16_t, uint16_t> local_cid_to_acl;
+
+// Cached value for whether full snoop logs are enabled. So the property isn't
+// checked for every packet.
+static bool is_btsnoop_enabled;
+static bool is_btsnoop_filtered;
+
 // TODO(zachoverflow): merge btsnoop and btsnoop_net together
 void btsnoop_net_open();
 void btsnoop_net_close();
 void btsnoop_net_write(const void* data, size_t length);
 
-static void delete_btsnoop_files();
-static bool is_btsnoop_enabled();
-static char* get_btsnoop_log_path(char* log_path);
-static char* get_btsnoop_last_log_path(char* last_log_path, char* log_path);
+static void delete_btsnoop_files(bool filtered);
+static std::string get_btsnoop_log_path(bool filtered);
+static std::string get_btsnoop_last_log_path(std::string log_path);
 static void open_next_snoop_file();
 static void btsnoop_write_packet(packet_type_t type, uint8_t* packet,
                                  bool is_received, uint64_t timestamp_us);
 
 // Module lifecycle functions
 
-static future_t* start_up(void) {
+static future_t* start_up() {
+  std::array<char, PROPERTY_VALUE_MAX> property = {};
   std::lock_guard<std::mutex> lock(btsnoop_mutex);
 
-  if (!is_btsnoop_enabled()) {
-    delete_btsnoop_files();
+  // Default mode is FILTERED on userdebug/eng build, DISABLED on user build.
+  // It can also be overwritten by modifying the global setting.
+  int is_debuggable = osi_property_get_int32(IS_DEBUGGABLE_PROPERTY, 0);
+  std::string default_mode = BTSNOOP_MODE_DISABLED;
+  if (is_debuggable) {
+    int len = osi_property_get(BTSNOOP_DEFAULT_MODE_PROPERTY, property.data(),
+                               BTSNOOP_MODE_DISABLED);
+    default_mode = std::string(property.data(), len);
+  }
+
+  // Get the actual mode
+  int len = osi_property_get(BTSNOOP_LOG_MODE_PROPERTY, property.data(),
+                             default_mode.c_str());
+  std::string btsnoop_mode(property.data(), len);
+
+  if (btsnoop_mode == BTSNOOP_MODE_FILTERED) {
+    LOG(INFO) << __func__ << ": Filtered Snoop Logs enabled";
+    is_btsnoop_enabled = true;
+    is_btsnoop_filtered = true;
+    delete_btsnoop_files(false);
+  } else if (btsnoop_mode == BTSNOOP_MODE_FULL) {
+    LOG(INFO) << __func__ << ": Snoop Logs fully enabled";
+    is_btsnoop_enabled = true;
+    is_btsnoop_filtered = false;
+    delete_btsnoop_files(true);
   } else {
+    LOG(INFO) << __func__ << ": Snoop Logs disabled";
+    is_btsnoop_enabled = false;
+    is_btsnoop_filtered = false;
+    delete_btsnoop_files(true);
+    delete_btsnoop_files(false);
+  }
+
+  if (is_btsnoop_enabled) {
     open_next_snoop_file();
     packets_per_file = osi_property_get_int32(BTSNOOP_MAX_PACKETS_PROPERTY,
                                               DEFAULT_BTSNOOP_SIZE);
@@ -104,14 +224,21 @@ static future_t* start_up(void) {
 static future_t* shut_down(void) {
   std::lock_guard<std::mutex> lock(btsnoop_mutex);
 
-  if (!is_btsnoop_enabled()) {
-    delete_btsnoop_files();
+  if (is_btsnoop_enabled) {
+    if (is_btsnoop_filtered) {
+      delete_btsnoop_files(false);
+    } else {
+      delete_btsnoop_files(true);
+    }
+  } else {
+    delete_btsnoop_files(true);
+    delete_btsnoop_files(false);
   }
 
   if (logfile_fd != INVALID_FD) close(logfile_fd);
   logfile_fd = INVALID_FD;
 
-  btsnoop_net_close();
+  if (is_btsnoop_enabled) btsnoop_net_close();
 
   return NULL;
 }
@@ -129,7 +256,12 @@ static void capture(const BT_HDR* buffer, bool is_received) {
   uint8_t* p = const_cast<uint8_t*>(buffer->data + buffer->offset);
 
   std::lock_guard<std::mutex> lock(btsnoop_mutex);
-  uint64_t timestamp_us = bluetooth::common::time_gettimeofday_us();
+
+  struct timespec ts_now = {};
+  clock_gettime(CLOCK_REALTIME, &ts_now);
+  uint64_t timestamp_us =
+      ((uint64_t)ts_now.tv_sec * 1000000L) + ((uint64_t)ts_now.tv_nsec / 1000);
+
   btsnoop_mem_capture(buffer, timestamp_us);
 
   if (logfile_fd == INVALID_FD) return;
@@ -152,39 +284,75 @@ static void capture(const BT_HDR* buffer, bool is_received) {
   }
 }
 
-static const btsnoop_t interface = {capture};
+static void whitelist_l2c_channel(uint16_t conn_handle, uint16_t local_cid,
+                                  uint16_t remote_cid) {
+  LOG(INFO) << __func__
+            << ": Whitelisting l2cap channel. conn_handle=" << conn_handle
+            << " cid=" << loghex(local_cid) << ":" << loghex(remote_cid);
+  std::lock_guard lock(filter_list_mutex);
 
-const btsnoop_t* btsnoop_get_interface() {
-  return &interface;
+  // This will create the entry if there is no associated filter with the
+  // connection.
+  filter_list[conn_handle].addL2cCid(local_cid, remote_cid);
 }
 
-// Internal functions
-static void delete_btsnoop_files() {
-  LOG_VERBOSE(LOG_TAG, "Deleting snoop log if it exists");
-  char log_path[PROPERTY_VALUE_MAX];
-  char last_log_path[PROPERTY_VALUE_MAX + sizeof(".last")];
-  get_btsnoop_log_path(log_path);
-  get_btsnoop_last_log_path(last_log_path, log_path);
-  remove(log_path);
-  remove(last_log_path);
+static void whitelist_rfc_dlci(uint16_t local_cid, uint8_t dlci) {
+  LOG(INFO) << __func__
+            << ": Whitelisting rfcomm channel. L2CAP CID=" << loghex(local_cid)
+            << " DLCI=" << loghex(dlci);
+  std::lock_guard lock(filter_list_mutex);
+
+  tL2C_CCB* p_ccb = l2cu_find_ccb_by_cid(nullptr, local_cid);
+  filter_list[p_ccb->p_lcb->handle].addRfcDlci(dlci);
 }
 
-static bool is_btsnoop_enabled() {
-  char btsnoop_enabled[PROPERTY_VALUE_MAX] = {0};
-  osi_property_get(BTSNOOP_ENABLE_PROPERTY, btsnoop_enabled, "false");
-  return strncmp(btsnoop_enabled, "true", 4) == 0;
+static void add_rfc_l2c_channel(uint16_t conn_handle, uint16_t local_cid,
+                                uint16_t remote_cid) {
+  LOG(INFO) << __func__
+            << ": rfcomm data going over l2cap channel. conn_handle="
+            << conn_handle << " cid=" << loghex(local_cid) << ":"
+            << loghex(remote_cid);
+  std::lock_guard lock(filter_list_mutex);
+
+  filter_list[conn_handle].setRfcCid(local_cid, remote_cid);
+  local_cid_to_acl.insert({local_cid, conn_handle});
 }
 
-static char* get_btsnoop_log_path(char* btsnoop_path) {
+static void clear_l2cap_whitelist(uint16_t conn_handle, uint16_t local_cid,
+                                  uint16_t remote_cid) {
+  LOG(INFO) << __func__
+            << ": Clearing whitelist from l2cap channel. conn_handle="
+            << conn_handle << " cid=" << local_cid << ":" << remote_cid;
+
+  std::lock_guard lock(filter_list_mutex);
+  filter_list[conn_handle].removeL2cCid(local_cid, remote_cid);
+}
+
+static const btsnoop_t interface = {capture, whitelist_l2c_channel,
+                                    whitelist_rfc_dlci, add_rfc_l2c_channel,
+                                    clear_l2cap_whitelist};
+
+const btsnoop_t* btsnoop_get_interface() { return &interface; }
+
+static void delete_btsnoop_files(bool filtered) {
+  LOG(INFO) << __func__
+            << ": Deleting snoop logs if they exist. filtered = " << filtered;
+  auto log_path = get_btsnoop_log_path(filtered);
+  remove(log_path.c_str());
+  remove(get_btsnoop_last_log_path(log_path).c_str());
+}
+
+std::string get_btsnoop_log_path(bool filtered) {
+  char btsnoop_path[PROPERTY_VALUE_MAX];
   osi_property_get(BTSNOOP_PATH_PROPERTY, btsnoop_path, DEFAULT_BTSNOOP_PATH);
-  return btsnoop_path;
+  std::string result(btsnoop_path);
+  if (filtered) result = result.append(".filtered");
+
+  return result;
 }
 
-static char* get_btsnoop_last_log_path(char* last_log_path,
-                                       char* btsnoop_path) {
-  snprintf(last_log_path, PROPERTY_VALUE_MAX + sizeof(".last"), "%s.last",
-           btsnoop_path);
-  return last_log_path;
+std::string get_btsnoop_last_log_path(std::string btsnoop_path) {
+  return btsnoop_path.append(".last");
 }
 
 static void open_next_snoop_file() {
@@ -195,22 +363,20 @@ static void open_next_snoop_file() {
     logfile_fd = INVALID_FD;
   }
 
-  char log_path[PROPERTY_VALUE_MAX];
-  char last_log_path[PROPERTY_VALUE_MAX + sizeof(".last")];
-  get_btsnoop_log_path(log_path);
-  get_btsnoop_last_log_path(last_log_path, log_path);
+  auto log_path = get_btsnoop_log_path(is_btsnoop_filtered);
+  auto last_log_path = get_btsnoop_last_log_path(log_path);
 
-  if (rename(log_path, last_log_path) != 0 && errno != ENOENT)
-    LOG_ERROR(LOG_TAG, "%s unable to rename '%s' to '%s': %s", __func__,
-              log_path, last_log_path, strerror(errno));
+  if (rename(log_path.c_str(), last_log_path.c_str()) != 0 && errno != ENOENT)
+    LOG(ERROR) << __func__ << ": unable to rename '" << log_path << "' to '"
+               << last_log_path << "' : " << strerror(errno);
 
   mode_t prevmask = umask(0);
-  logfile_fd = open(log_path, O_WRONLY | O_CREAT | O_TRUNC,
+  logfile_fd = open(log_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC,
                     S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
   umask(prevmask);
   if (logfile_fd == INVALID_FD) {
-    LOG_ERROR(LOG_TAG, "%s unable to open '%s': %s", __func__, log_path,
-              strerror(errno));
+    LOG(ERROR) << __func__ << ": unable to open '" << log_path
+               << "' : " << strerror(errno);
     return;
   }
 
@@ -235,6 +401,32 @@ static uint64_t htonll(uint64_t ll) {
   return ll;
 }
 
+static bool should_filter_log(bool is_received, uint8_t* packet) {
+  uint16_t acl_handle =
+      HCID_GET_HANDLE((((uint16_t)packet[ACL_CHANNEL_OFFSET + 1]) << 8) +
+                      packet[ACL_CHANNEL_OFFSET]);
+
+  std::lock_guard lock(filter_list_mutex);
+  auto& filters = filter_list[acl_handle];
+  uint16_t l2c_channel =
+      (packet[L2C_CHANNEL_OFFSET + 1] << 8) + packet[L2C_CHANNEL_OFFSET];
+  if (filters.isRfcChannel(is_received, l2c_channel)) {
+    uint8_t rfc_event = packet[RFC_EVENT_OFFSET] & 0b11101111;
+    if (rfc_event == RFCOMM_SABME || rfc_event == RFCOMM_UA) {
+      return false;
+    }
+
+    uint8_t rfc_dlci = packet[RFC_CHANNEL_OFFSET] >> 2;
+    if (!filters.isWhitelistedDlci(rfc_dlci)) {
+      return true;
+    }
+  } else if (!filters.isWhitelistedL2c(is_received, l2c_channel)) {
+    return true;
+  }
+
+  return false;
+}
+
 static void btsnoop_write_packet(packet_type_t type, uint8_t* packet,
                                  bool is_received, uint64_t timestamp_us) {
   uint32_t length_he = 0;
@@ -261,7 +453,15 @@ static void btsnoop_write_packet(packet_type_t type, uint8_t* packet,
 
   btsnoop_header_t header;
   header.length_original = htonl(length_he);
-  header.length_captured = header.length_original;
+
+  bool blacklisted = false;
+  if (is_btsnoop_filtered && type == kAclPacket) {
+    blacklisted = should_filter_log(is_received, packet);
+  }
+
+  header.length_captured =
+      blacklisted ? htonl(L2C_HEADER_SIZE) : header.length_original;
+  if (blacklisted) length_he = L2C_HEADER_SIZE;
   header.flags = htonl(flags);
   header.dropped_packets = 0;
   header.timestamp = htonll(timestamp_us + BTSNOOP_EPOCH_DELTA);
index 921ac82..5036ed5 100644 (file)
@@ -123,12 +123,10 @@ static void reassemble_and_dispatch(UNUSED_ATTR BT_HDR* packet) {
   if ((packet->event & MSG_EVT_MASK) == MSG_HC_TO_STACK_HCI_ACL) {
     uint8_t* stream = packet->data;
     uint16_t handle;
-    uint16_t l2cap_length;
     uint16_t acl_length;
 
     STREAM_TO_UINT16(handle, stream);
     STREAM_TO_UINT16(acl_length, stream);
-    STREAM_TO_UINT16(l2cap_length, stream);
 
     CHECK(acl_length == packet->len - HCI_ACL_PREAMBLE_SIZE);
 
@@ -136,6 +134,13 @@ static void reassemble_and_dispatch(UNUSED_ATTR BT_HDR* packet) {
     handle = handle & HANDLE_MASK;
 
     if (boundary_flag == START_PACKET_BOUNDARY) {
+      if (acl_length < 2) {
+        LOG_WARN(LOG_TAG, "%s invalid acl_length %d", __func__, acl_length);
+        buffer_allocator->free(packet);
+        return;
+      }
+      uint16_t l2cap_length;
+      STREAM_TO_UINT16(l2cap_length, stream);
       auto map_iter = partial_packets.find(handle);
       if (map_iter != partial_packets.end()) {
         LOG_WARN(LOG_TAG,
index 8b32562..f787e9e 100644 (file)
@@ -98,6 +98,9 @@ cc_library_shared {
     cflags: [
         "-DBUILDCFG",
     ],
+    sanitize: {
+        scs: true,
+    },
 }
 
 cc_library_static {
index cde0031..db3d31a 100644 (file)
 namespace bluetooth {
 namespace avrcp {
 
-std::unique_ptr<GeneralRejectBuilder> GeneralRejectBuilder::MakeBuilder(
-    BrowsePdu pdu, Status reason) {
+std::unique_ptr<GeneralRejectBuilder> GeneralRejectBuilder::MakeBuilder(Status reason) {
   std::unique_ptr<GeneralRejectBuilder> builder =
-      std::unique_ptr<GeneralRejectBuilder>(
-          new GeneralRejectBuilder(pdu, reason));
+      std::unique_ptr<GeneralRejectBuilder>(new GeneralRejectBuilder(reason));
 
   return builder;
 }
index 4058fd4..b3fb2fe 100644 (file)
@@ -25,8 +25,7 @@ class GeneralRejectBuilder : public BrowsePacketBuilder {
  public:
   virtual ~GeneralRejectBuilder() = default;
 
-  static std::unique_ptr<GeneralRejectBuilder> MakeBuilder(BrowsePdu pdu,
-                                                           Status reason);
+  static std::unique_ptr<GeneralRejectBuilder> MakeBuilder(Status reason);
 
   virtual size_t size() const override;
   virtual bool Serialize(
@@ -35,8 +34,7 @@ class GeneralRejectBuilder : public BrowsePacketBuilder {
  protected:
   Status reason_;
 
-  GeneralRejectBuilder(BrowsePdu pdu, Status reason)
-      : BrowsePacketBuilder(pdu), reason_(reason){};
+  GeneralRejectBuilder(Status reason) : BrowsePacketBuilder(BrowsePdu::GENERAL_REJECT), reason_(reason){};
 };
 
 }  // namespace avrcp
index adb5e59..6bbd16a 100644 (file)
@@ -39,8 +39,9 @@ uint8_t RegisterNotificationResponse::GetVolume() const {
 bool RegisterNotificationResponse::IsValid() const {
   if (!VendorPacket::IsValid()) return false;
   if (size() < kMinSize()) return false;
-  if (GetCType() != CType::INTERIM && GetCType() != CType::CHANGED)
+  if (GetCType() != CType::INTERIM && GetCType() != CType::CHANGED && GetCType() != CType::REJECTED) {
     return false;
+  }
 
   switch (GetEvent()) {
     case Event::VOLUME_CHANGED:
index 13994d0..14e30e7 100644 (file)
@@ -106,8 +106,8 @@ std::vector<uint8_t> register_volume_changed_notification = {
     0x00, 0x05, 0x0d, 0x00, 0x00, 0x00, 0x00};
 
 // AVRCP Register Notification without any parameter
-std::vector<uint8_t> register_notification_invalid = {
-    0x03, 0x48, 0x00, 0x00, 0x19, 0x58, 0x31, 0x00, 0x00, 0x05};
+std::vector<uint8_t> register_notification_invalid = {0x03, 0x48, 0x00, 0x00, 0x19, 0x58, 0x31,
+                                                      0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00};
 
 // AVRCP Interim Playback Status Notification
 std::vector<uint8_t> interim_play_status_notification = {
@@ -208,9 +208,8 @@ std::vector<uint8_t> get_folder_items_request_vfs = {
 //    start_item = 0x00
 //    end_item = 0x05
 //    attributes_requested: All Items
-std::vector<uint8_t> get_folder_items_request_now_playing = {
-    0x71, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x05, 0x00};
+std::vector<uint8_t> get_folder_items_request_now_playing = {0x71, 0x00, 0x0a, 0x03, 0x00, 0x00, 0x00,
+                                                             0x00, 0x00, 0x00, 0x00, 0x05, 0x00};
 
 // AVRCP Browse Get Folder Items Response packet with range out of bounds error
 std::vector<uint8_t> get_folder_items_error_response = {0x71, 0x00, 0x01, 0x0b};
@@ -356,4 +355,36 @@ std::vector<uint8_t> set_absolute_volume_request = {
 std::vector<uint8_t> set_absolute_volume_response = {
     0x09, 0x48, 0x00, 0x00, 0x19, 0x58, 0x50, 0x00, 0x00, 0x01, 0x43};
 
+// Invalid Packets
+// Short Vendor Packet
+std::vector<uint8_t> short_vendor_packet = {0x01, 0x48, 0x00, 0x00, 0x19, 0x58, 0x10, 0x00, 0x00, 0x01};
+
+// Short Get Capabilities Request Packet
+std::vector<uint8_t> short_get_capabilities_request = {0x01, 0x48, 0x00, 0x00, 0x19, 0x58, 0x10, 0x00, 0x00, 0x00};
+
+// Short Get Element Attributes Request Packet
+std::vector<uint8_t> short_get_element_attributes_request = {0x01, 0x48, 0x00, 0x00, 0x19,
+                                                             0x58, 0x20, 0x00, 0x00, 0x00};
+
+// Short Play Item Request Packet
+std::vector<uint8_t> short_play_item_request = {0x00, 0x48, 0x00, 0x00, 0x19, 0x58, 0x74, 0x00, 0x00, 0x00};
+
+// Short Set Addressed Player Request Packet
+std::vector<uint8_t> short_set_addressed_player_request = {0x00, 0x48, 0x00, 0x00, 0x19, 0x58, 0x60, 0x00, 0x00, 0x00};
+
+// Short Browse Packet
+std::vector<uint8_t> short_browse_packet = {0x71, 0x00, 0x0a};
+
+// Short Get Folder Items Request Packet
+std::vector<uint8_t> short_get_folder_items_request = {0x71, 0x00, 0x00};
+
+// Short Get Total Number of Items Request Packet
+std::vector<uint8_t> short_get_total_number_of_items_request = {0x75, 0x00, 0x00};
+
+// Short Change Path Request Packet
+std::vector<uint8_t> short_change_path_request = {0x72, 0x00, 0x00};
+
+// Short Get Item Attributes Request Packet
+std::vector<uint8_t> short_get_item_attributes_request = {0x73, 0x00, 0x00};
+
 }  // namespace
index e27d0b7..4d73dba 100644 (file)
@@ -26,8 +26,7 @@ namespace avrcp {
 using TestGeneralRejectPacket = TestPacketType<BrowsePacket>;
 
 TEST(GeneralRejectPacketBuilderTest, buildPacketTest) {
-  auto builder = GeneralRejectBuilder::MakeBuilder(BrowsePdu::GENERAL_REJECT,
-                                                   Status::INVALID_COMMAND);
+  auto builder = GeneralRejectBuilder::MakeBuilder(Status::INVALID_COMMAND);
 
   ASSERT_EQ(builder->size(), general_reject_invalid_command_packet.size());
 
index cf94cfc..4ca624b 100644 (file)
@@ -80,6 +80,13 @@ void Device::VendorPacketHandler(uint8_t label,
   CHECK(media_interface_);
   DEVICE_VLOG(3) << __func__ << ": pdu=" << pkt->GetCommandPdu();
 
+  if (!pkt->IsValid()) {
+    DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+    auto response = RejectBuilder::MakeBuilder(static_cast<CommandPdu>(0), Status::INVALID_COMMAND);
+    send_message(label, false, std::move(response));
+    return;
+  }
+
   // All CTypes at and above NOT_IMPLEMENTED are all response types.
   if (pkt->GetCType() == CType::NOT_IMPLEMENTED) {
     return;
@@ -125,9 +132,15 @@ void Device::VendorPacketHandler(uint8_t label,
     } break;
 
     case CommandPdu::GET_ELEMENT_ATTRIBUTES: {
-      media_interface_->GetSongInfo(base::Bind(
-          &Device::GetElementAttributesResponse, weak_ptr_factory_.GetWeakPtr(),
-          label, Packet::Specialize<GetElementAttributesRequest>(pkt)));
+      auto get_element_attributes_request_pkt = Packet::Specialize<GetElementAttributesRequest>(pkt);
+
+      if (!get_element_attributes_request_pkt->IsValid()) {
+        DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+        auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(), Status::INVALID_PARAMETER);
+        send_message(label, false, std::move(response));
+      }
+      media_interface_->GetSongInfo(base::Bind(&Device::GetElementAttributesResponse, weak_ptr_factory_.GetWeakPtr(),
+                                               label, get_element_attributes_request_pkt));
     } break;
 
     case CommandPdu::GET_PLAY_STATUS: {
@@ -145,9 +158,17 @@ void Device::VendorPacketHandler(uint8_t label,
       // this currently since the current implementation only has one
       // player and the player will never change, but we need it for a
       // more complete implementation.
-      media_interface_->GetMediaPlayerList(base::Bind(
-          &Device::HandleSetAddressedPlayer, weak_ptr_factory_.GetWeakPtr(),
-          label, Packet::Specialize<SetAddressedPlayerRequest>(pkt)));
+      auto set_addressed_player_request = Packet::Specialize<SetAddressedPlayerRequest>(pkt);
+
+      if (!set_addressed_player_request->IsValid()) {
+        DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+        auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(), Status::INVALID_PARAMETER);
+        send_message(label, false, std::move(response));
+        return;
+      }
+
+      media_interface_->GetMediaPlayerList(base::Bind(&Device::HandleSetAddressedPlayer, weak_ptr_factory_.GetWeakPtr(),
+                                                      label, set_addressed_player_request));
     } break;
 
     default: {
@@ -164,6 +185,13 @@ void Device::HandleGetCapabilities(
   DEVICE_VLOG(4) << __func__
                  << ": capability=" << pkt->GetCapabilityRequested();
 
+  if (!pkt->IsValid()) {
+    DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+    auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(), Status::INVALID_PARAMETER);
+    send_message(label, false, std::move(response));
+    return;
+  }
+
   switch (pkt->GetCapabilityRequested()) {
     case Capability::COMPANY_ID: {
       auto response =
@@ -202,7 +230,7 @@ void Device::HandleGetCapabilities(
 void Device::HandleNotification(
     uint8_t label, const std::shared_ptr<RegisterNotificationRequest>& pkt) {
   if (!pkt->IsValid()) {
-    DEVICE_LOG(ERROR) << __func__ << ": Request packet is not valid";
+    DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
     auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(),
                                                Status::INVALID_PARAMETER);
     send_message(label, false, std::move(response));
@@ -307,6 +335,17 @@ void Device::RegisterVolumeChanged() {
 void Device::HandleVolumeChanged(
     uint8_t label, const std::shared_ptr<RegisterNotificationResponse>& pkt) {
   DEVICE_VLOG(1) << __func__ << ": interim=" << pkt->IsInterim();
+
+  if (!pkt->IsValid()) {
+    DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+    auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(), Status::INVALID_PARAMETER);
+    send_message(label, false, std::move(response));
+    active_labels_.erase(label);
+    volume_interface_ = nullptr;
+    volume_ = VOL_REGISTRATION_FAILED;
+    return;
+  }
+
   if (volume_interface_ == nullptr) return;
 
   if (pkt->GetCType() == CType::REJECTED) {
@@ -546,6 +585,7 @@ void Device::GetElementAttributesResponse(
     uint8_t label, std::shared_ptr<GetElementAttributesRequest> pkt,
     SongInfo info) {
   DEVICE_VLOG(2) << __func__;
+
   auto get_element_attributes_pkt = pkt;
   auto attributes_requested =
       get_element_attributes_pkt->GetAttributesRequested();
@@ -570,10 +610,15 @@ void Device::GetElementAttributesResponse(
 }
 
 void Device::MessageReceived(uint8_t label, std::shared_ptr<Packet> pkt) {
-  DEVICE_VLOG(4) << __func__ << ": opcode=" << pkt->GetOpcode();
+  if (!pkt->IsValid()) {
+    DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+    auto response = RejectBuilder::MakeBuilder(static_cast<CommandPdu>(0), Status::INVALID_COMMAND);
+    send_message(label, false, std::move(response));
+    return;
+  }
 
+  DEVICE_VLOG(4) << __func__ << ": opcode=" << pkt->GetOpcode();
   active_labels_.insert(label);
-
   switch (pkt->GetOpcode()) {
     // TODO (apanicke): Remove handling of UNIT_INFO and SUBUNIT_INFO from
     // the AVRC_API and instead handle it here to reduce fragmentation.
@@ -583,6 +628,14 @@ void Device::MessageReceived(uint8_t label, std::shared_ptr<Packet> pkt) {
     } break;
     case Opcode::PASS_THROUGH: {
       auto pass_through_packet = Packet::Specialize<PassThroughPacket>(pkt);
+
+      if (!pass_through_packet->IsValid()) {
+        DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+        auto response = RejectBuilder::MakeBuilder(static_cast<CommandPdu>(0), Status::INVALID_COMMAND);
+        send_message(label, false, std::move(response));
+        return;
+      }
+
       auto response = PassThroughPacketBuilder::MakeBuilder(
           true, pass_through_packet->GetKeyState() == KeyState::PUSHED,
           pass_through_packet->GetOperationId());
@@ -633,6 +686,13 @@ void Device::HandlePlayItem(uint8_t label,
   DEVICE_VLOG(2) << __func__ << ": scope=" << pkt->GetScope()
                  << " uid=" << pkt->GetUid();
 
+  if (!pkt->IsValid()) {
+    DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+    auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(), Status::INVALID_PARAMETER);
+    send_message(label, false, std::move(response));
+    return;
+  }
+
   std::string media_id = "";
   switch (pkt->GetScope()) {
     case Scope::NOW_PLAYING:
@@ -680,6 +740,13 @@ void Device::HandleSetAddressedPlayer(
 
 void Device::BrowseMessageReceived(uint8_t label,
                                    std::shared_ptr<BrowsePacket> pkt) {
+  if (!pkt->IsValid()) {
+    DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+    auto response = GeneralRejectBuilder::MakeBuilder(Status::INVALID_COMMAND);
+    send_message(label, false, std::move(response));
+    return;
+  }
+
   DEVICE_VLOG(1) << __func__ << ": pdu=" << pkt->GetPdu();
 
   switch (pkt->GetPdu()) {
@@ -704,8 +771,7 @@ void Device::BrowseMessageReceived(uint8_t label,
       break;
     default:
       DEVICE_LOG(WARNING) << __func__ << ": " << pkt->GetPdu();
-      auto response = GeneralRejectBuilder::MakeBuilder(
-          BrowsePdu::GENERAL_REJECT, Status::INVALID_COMMAND);
+      auto response = GeneralRejectBuilder::MakeBuilder(Status::INVALID_COMMAND);
       send_message(label, true, std::move(response));
 
       break;
@@ -714,6 +780,15 @@ void Device::BrowseMessageReceived(uint8_t label,
 
 void Device::HandleGetFolderItems(uint8_t label,
                                   std::shared_ptr<GetFolderItemsRequest> pkt) {
+  if (!pkt->IsValid()) {
+    // The specific get folder items builder is unimportant on failure.
+    DEVICE_LOG(WARNING) << __func__ << ": Get folder items request packet is not valid";
+    auto response =
+        GetFolderItemsResponseBuilder::MakePlayerListBuilder(Status::INVALID_PARAMETER, 0x0000, browse_mtu_);
+    send_message(label, true, std::move(response));
+    return;
+  }
+
   DEVICE_VLOG(2) << __func__ << ": scope=" << pkt->GetScope();
 
   switch (pkt->GetScope()) {
@@ -735,12 +810,21 @@ void Device::HandleGetFolderItems(uint8_t label,
       break;
     default:
       DEVICE_LOG(ERROR) << __func__ << ": " << pkt->GetScope();
+      auto response = GetFolderItemsResponseBuilder::MakePlayerListBuilder(Status::INVALID_PARAMETER, 0, browse_mtu_);
+      send_message(label, true, std::move(response));
       break;
   }
 }
 
 void Device::HandleGetTotalNumberOfItems(
     uint8_t label, std::shared_ptr<GetTotalNumberOfItemsRequest> pkt) {
+  if (!pkt->IsValid()) {
+    DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+    auto response = GetTotalNumberOfItemsResponseBuilder::MakeBuilder(Status::INVALID_PARAMETER, 0x0000, 0);
+    send_message(label, true, std::move(response));
+    return;
+  }
+
   DEVICE_VLOG(2) << __func__ << ": scope=" << pkt->GetScope();
 
   switch (pkt->GetScope()) {
@@ -796,6 +880,13 @@ void Device::GetTotalNumberOfItemsNowPlayingResponse(
 
 void Device::HandleChangePath(uint8_t label,
                               std::shared_ptr<ChangePathRequest> pkt) {
+  if (!pkt->IsValid()) {
+    DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+    auto response = ChangePathResponseBuilder::MakeBuilder(Status::INVALID_PARAMETER, 0);
+    send_message(label, true, std::move(response));
+    return;
+  }
+
   DEVICE_VLOG(2) << __func__ << ": direction=" << pkt->GetDirection()
                  << " uid=" << loghex(pkt->GetUid());
 
@@ -846,6 +937,13 @@ void Device::ChangePathResponse(uint8_t label,
 
 void Device::HandleGetItemAttributes(
     uint8_t label, std::shared_ptr<GetItemAttributesRequest> pkt) {
+  if (!pkt->IsValid()) {
+    DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+    auto builder = GetItemAttributesResponseBuilder::MakeBuilder(Status::INVALID_PARAMETER, browse_mtu_);
+    send_message(label, true, std::move(builder));
+    return;
+  }
+
   DEVICE_VLOG(2) << __func__ << ": scope=" << pkt->GetScope()
                  << " uid=" << loghex(pkt->GetUid())
                  << " uid counter=" << loghex(pkt->GetUidCounter());
@@ -856,6 +954,7 @@ void Device::HandleGetItemAttributes(
     send_message(label, true, std::move(builder));
     return;
   }
+
   switch (pkt->GetScope()) {
     case Scope::NOW_PLAYING: {
       media_interface_->GetNowPlayingList(
@@ -1121,6 +1220,13 @@ void Device::GetNowPlayingListResponse(
 
 void Device::HandleSetBrowsedPlayer(
     uint8_t label, std::shared_ptr<SetBrowsedPlayerRequest> pkt) {
+  if (!pkt->IsValid()) {
+    DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+    auto response = SetBrowsedPlayerResponseBuilder::MakeBuilder(Status::INVALID_PARAMETER, 0x0000, 0, 0, "");
+    send_message(label, true, std::move(response));
+    return;
+  }
+
   DEVICE_VLOG(2) << __func__ << ": player_id=" << pkt->GetPlayerId();
   media_interface_->SetBrowsedPlayer(
       pkt->GetPlayerId(),
index 83c6a13..c608da6 100644 (file)
@@ -1358,6 +1358,126 @@ TEST_F(AvrcpDeviceTest, invalidRegisterNotificationTest) {
   SendMessage(1, reg_notif_request);
 }
 
+TEST_F(AvrcpDeviceTest, invalidVendorPacketTest) {
+  MockMediaInterface interface;
+  NiceMock<MockA2dpInterface> a2dp_interface;
+
+  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+  auto rsp = RejectBuilder::MakeBuilder(static_cast<CommandPdu>(0), Status::INVALID_COMMAND);
+  EXPECT_CALL(response_cb, Call(1, false, matchPacket(std::move(rsp)))).Times(1);
+  auto short_packet = TestAvrcpPacket::Make(short_vendor_packet);
+  SendMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidCapabilitiesPacketTest) {
+  MockMediaInterface interface;
+  NiceMock<MockA2dpInterface> a2dp_interface;
+
+  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+  auto rsp = RejectBuilder::MakeBuilder(CommandPdu::GET_CAPABILITIES, Status::INVALID_PARAMETER);
+  EXPECT_CALL(response_cb, Call(1, false, matchPacket(std::move(rsp)))).Times(1);
+  auto short_packet = TestAvrcpPacket::Make(short_get_capabilities_request);
+  SendMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidGetElementAttributesPacketTest) {
+  MockMediaInterface interface;
+  NiceMock<MockA2dpInterface> a2dp_interface;
+
+  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+  auto rsp = RejectBuilder::MakeBuilder(CommandPdu::GET_ELEMENT_ATTRIBUTES, Status::INVALID_PARAMETER);
+  EXPECT_CALL(response_cb, Call(1, false, matchPacket(std::move(rsp)))).Times(1);
+  auto short_packet = TestAvrcpPacket::Make(short_get_element_attributes_request);
+  SendMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidPlayItemPacketTest) {
+  MockMediaInterface interface;
+  NiceMock<MockA2dpInterface> a2dp_interface;
+
+  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+  auto rsp = RejectBuilder::MakeBuilder(CommandPdu::PLAY_ITEM, Status::INVALID_PARAMETER);
+  EXPECT_CALL(response_cb, Call(1, false, matchPacket(std::move(rsp)))).Times(1);
+  auto short_packet = TestAvrcpPacket::Make(short_play_item_request);
+  SendMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidSetAddressedPlayerPacketTest) {
+  MockMediaInterface interface;
+  NiceMock<MockA2dpInterface> a2dp_interface;
+
+  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+  auto rsp = RejectBuilder::MakeBuilder(CommandPdu::SET_ADDRESSED_PLAYER, Status::INVALID_PARAMETER);
+  EXPECT_CALL(response_cb, Call(1, false, matchPacket(std::move(rsp)))).Times(1);
+  auto short_packet = TestAvrcpPacket::Make(short_set_addressed_player_request);
+  SendMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidBrowsePacketTest) {
+  MockMediaInterface interface;
+  NiceMock<MockA2dpInterface> a2dp_interface;
+
+  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+  auto rsp = GeneralRejectBuilder::MakeBuilder(Status::INVALID_COMMAND);
+  EXPECT_CALL(response_cb, Call(1, false, matchPacket(std::move(rsp)))).Times(1);
+  auto short_packet = TestBrowsePacket::Make(short_browse_packet);
+  SendBrowseMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidGetFolderItemsPacketTest) {
+  MockMediaInterface interface;
+  NiceMock<MockA2dpInterface> a2dp_interface;
+
+  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+  auto rsp = GetFolderItemsResponseBuilder::MakePlayerListBuilder(Status::INVALID_PARAMETER, 0x0000, 0xFFFF);
+  EXPECT_CALL(response_cb, Call(1, true, matchPacket(std::move(rsp)))).Times(1);
+  auto short_packet = TestBrowsePacket::Make(short_get_folder_items_request);
+  SendBrowseMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidGetTotalNumberOfItemsPacketTest) {
+  MockMediaInterface interface;
+  NiceMock<MockA2dpInterface> a2dp_interface;
+
+  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+  auto rsp = GetTotalNumberOfItemsResponseBuilder::MakeBuilder(Status::INVALID_PARAMETER, 0x0000, 0xFFFF);
+  EXPECT_CALL(response_cb, Call(1, true, matchPacket(std::move(rsp)))).Times(1);
+  auto short_packet = TestBrowsePacket::Make(short_get_total_number_of_items_request);
+  SendBrowseMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidChangePathPacketTest) {
+  MockMediaInterface interface;
+  NiceMock<MockA2dpInterface> a2dp_interface;
+
+  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+  auto rsp = ChangePathResponseBuilder::MakeBuilder(Status::INVALID_PARAMETER, 0);
+  EXPECT_CALL(response_cb, Call(1, true, matchPacket(std::move(rsp)))).Times(1);
+  auto short_packet = TestBrowsePacket::Make(short_change_path_request);
+  SendBrowseMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidGetItemAttributesPacketTest) {
+  MockMediaInterface interface;
+  NiceMock<MockA2dpInterface> a2dp_interface;
+
+  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+  auto rsp = GetItemAttributesResponseBuilder::MakeBuilder(Status::INVALID_PARAMETER, 0xFFFF);
+  EXPECT_CALL(response_cb, Call(1, true, matchPacket(std::move(rsp)))).Times(1);
+  auto short_packet = TestBrowsePacket::Make(short_get_item_attributes_request);
+  SendBrowseMessage(1, short_packet);
+}
+
 }  // namespace avrcp
 }  // namespace bluetooth
 
index 5ced71f..51e2daf 100644 (file)
@@ -56,7 +56,8 @@ void AVCT_Register(uint16_t mtu, UNUSED_ATTR uint16_t mtu_br,
   AVCT_TRACE_API("AVCT_Register");
 
   /* register PSM with L2CAP */
-  L2CA_Register(AVCT_PSM, (tL2CAP_APPL_INFO*)&avct_l2c_appl);
+  L2CA_Register(AVCT_PSM, (tL2CAP_APPL_INFO*)&avct_l2c_appl,
+                true /* enable_snoop */);
 
   /* set security level */
   BTM_SetSecurityLevel(true, "", BTM_SEC_SERVICE_AVCTP, sec_mask, AVCT_PSM, 0,
@@ -68,7 +69,8 @@ void AVCT_Register(uint16_t mtu, UNUSED_ATTR uint16_t mtu_br,
   memset(&avct_cb, 0, sizeof(tAVCT_CB));
 
   /* Include the browsing channel which uses eFCR */
-  L2CA_Register(AVCT_BR_PSM, (tL2CAP_APPL_INFO*)&avct_l2c_br_appl);
+  L2CA_Register(AVCT_BR_PSM, (tL2CAP_APPL_INFO*)&avct_l2c_br_appl,
+                true /*enable_snoop*/);
 
   /* AVCTP browsing channel uses the same security service as AVCTP control
    * channel */
index faa098b..eec049d 100644 (file)
@@ -53,6 +53,12 @@ static BT_HDR* avct_lcb_msg_asmbl(tAVCT_LCB* p_lcb, BT_HDR* p_buf) {
   uint8_t pkt_type;
   BT_HDR* p_ret;
 
+  if (p_buf->len < 1) {
+    osi_free(p_buf);
+    p_ret = NULL;
+    return p_ret;
+  }
+
   /* parse the message header */
   p = (uint8_t*)(p_buf + 1) + p_buf->offset;
   pkt_type = AVCT_PKT_TYPE(p);
index 903862e..9350c31 100644 (file)
@@ -90,7 +90,8 @@ void avdt_scb_transport_channel_timer_timeout(void* data) {
  ******************************************************************************/
 void AVDT_Register(AvdtpRcb* p_reg, tAVDT_CTRL_CBACK* p_cback) {
   /* register PSM with L2CAP */
-  L2CA_Register(AVDT_PSM, (tL2CAP_APPL_INFO*)&avdt_l2c_appl);
+  L2CA_Register(AVDT_PSM, (tL2CAP_APPL_INFO*)&avdt_l2c_appl,
+                true /* enable_snoop */);
 
   /* set security level */
   BTM_SetSecurityLevel(true, "", BTM_SEC_SERVICE_AVDTP, p_reg->sec_mask,
index 0ac9b64..853f369 100644 (file)
@@ -586,6 +586,10 @@ static uint8_t avdt_msg_prs_cfg(AvdtpSepConfig* p_cfg, uint8_t* p, uint16_t len,
     /* parse individual information elements with additional parameters */
     switch (elem) {
       case AVDT_CAT_RECOV:
+        if ((p_end - p) < 3) {
+          err = AVDT_ERR_PAYLOAD;
+          break;
+        }
         p_cfg->recov_type = *p++;
         p_cfg->recov_mrws = *p++;
         p_cfg->recov_mnmp = *p++;
@@ -617,6 +621,10 @@ static uint8_t avdt_msg_prs_cfg(AvdtpSepConfig* p_cfg, uint8_t* p, uint16_t len,
         break;
 
       case AVDT_CAT_HDRCMP:
+        if ((p_end - p) < 1) {
+          err = AVDT_ERR_PAYLOAD;
+          break;
+        }
         p_cfg->hdrcmp_mask = *p++;
         break;
 
@@ -1191,6 +1199,14 @@ BT_HDR* avdt_msg_asmbl(AvdtpCcb* p_ccb, BT_HDR* p_buf) {
 
   /* parse the message header */
   p = (uint8_t*)(p_buf + 1) + p_buf->offset;
+
+  /* Check if is valid length */
+  if (p_buf->len < 1) {
+    android_errorWriteLog(0x534e4554, "78287084");
+    osi_free(p_buf);
+    p_ret = NULL;
+    return p_ret;
+  }
   AVDT_MSG_PRS_PKT_TYPE(p, pkt_type);
 
   /* quick sanity check on length */
@@ -1499,8 +1515,8 @@ void avdt_msg_ind(AvdtpCcb* p_ccb, BT_HDR* p_buf) {
   uint8_t pkt_type;
   uint8_t msg_type;
   uint8_t sig = 0;
-  tAVDT_MSG msg;
-  AvdtpSepConfig cfg;
+  tAVDT_MSG msg{};
+  AvdtpSepConfig cfg{};
   uint8_t err;
   uint8_t evt = 0;
   uint8_t scb_hdl;
index c0504ee..22471bd 100644 (file)
@@ -135,15 +135,16 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR* p_msg,
       if (!AVRC_IS_VALID_CAP_ID(p_result->get_caps.capability_id))
         status = AVRC_STS_BAD_PARAM;
       else if (len != 1)
-        status = AVRC_STS_INTERNAL_ERR;
+        return AVRC_STS_INTERNAL_ERR;
       break;
 
     case AVRC_PDU_LIST_PLAYER_APP_ATTR: /* 0x11 */
       /* no additional parameters */
-      if (len != 0) status = AVRC_STS_INTERNAL_ERR;
+      if (len != 0) return AVRC_STS_INTERNAL_ERR;
       break;
 
     case AVRC_PDU_LIST_PLAYER_APP_VALUES: /* 0x12 */
+      if (len == 0) return AVRC_STS_INTERNAL_ERR;
       p_result->list_app_values.attr_id = *p++;
       if (!AVRC_IS_VALID_ATTRIBUTE(p_result->list_app_values.attr_id))
         status = AVRC_STS_BAD_PARAM;
@@ -153,6 +154,7 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR* p_msg,
 
     case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE: /* 0x13 */
     case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT: /* 0x15 */
+      if (len == 0) return AVRC_STS_INTERNAL_ERR;
       BE_STREAM_TO_UINT8(p_result->get_cur_app_val.num_attr, p);
       if (len != (p_result->get_cur_app_val.num_attr + 1)) {
         status = AVRC_STS_INTERNAL_ERR;
@@ -177,6 +179,7 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR* p_msg,
       break;
 
     case AVRC_PDU_SET_PLAYER_APP_VALUE: /* 0x14 */
+      if (len == 0) return AVRC_STS_INTERNAL_ERR;
       BE_STREAM_TO_UINT8(p_result->set_app_val.num_val, p);
       size_needed = sizeof(tAVRC_APP_SETTING);
       if (p_buf && (len == ((p_result->set_app_val.num_val << 1) + 1))) {
@@ -208,7 +211,7 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR* p_msg,
 
     case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT: /* 0x16 */
       if (len < 3)
-        status = AVRC_STS_INTERNAL_ERR;
+        return AVRC_STS_INTERNAL_ERR;
       else {
         BE_STREAM_TO_UINT8(p_result->get_app_val_txt.attr_id, p);
         if (!AVRC_IS_VALID_ATTRIBUTE(p_result->get_app_val_txt.attr_id))
@@ -240,7 +243,7 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR* p_msg,
 
     case AVRC_PDU_INFORM_DISPLAY_CHARSET: /* 0x17 */
       if (len < 3)
-        status = AVRC_STS_INTERNAL_ERR;
+        return AVRC_STS_INTERNAL_ERR;
       else {
         BE_STREAM_TO_UINT8(p_result->inform_charset.num_id, p);
         if ((len - 1 /* num_id */) != p_result->inform_charset.num_id * 2)
@@ -258,7 +261,7 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR* p_msg,
 
     case AVRC_PDU_INFORM_BATTERY_STAT_OF_CT: /* 0x18 */
       if (len != 1)
-        status = AVRC_STS_INTERNAL_ERR;
+        return AVRC_STS_INTERNAL_ERR;
       else {
         p_result->inform_battery_status.battery_status = *p++;
         if (!AVRC_IS_VALID_BATTERY_STATUS(
@@ -269,7 +272,7 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR* p_msg,
 
     case AVRC_PDU_GET_ELEMENT_ATTR: /* 0x20 */
       if (len < 9)                  /* UID/8 and num_attr/1 */
-        status = AVRC_STS_INTERNAL_ERR;
+        return AVRC_STS_INTERNAL_ERR;
       else {
         BE_STREAM_TO_UINT32(u32, p);
         BE_STREAM_TO_UINT32(u32_2, p);
@@ -293,12 +296,12 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR* p_msg,
 
     case AVRC_PDU_GET_PLAY_STATUS: /* 0x30 */
       /* no additional parameters */
-      if (len != 0) status = AVRC_STS_INTERNAL_ERR;
+      if (len != 0) return AVRC_STS_INTERNAL_ERR;
       break;
 
     case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */
       if (len != 5)
-        status = AVRC_STS_INTERNAL_ERR;
+        return AVRC_STS_INTERNAL_ERR;
       else {
         BE_STREAM_TO_UINT8(p_result->reg_notif.event_id, p);
         BE_STREAM_TO_UINT32(p_result->reg_notif.param, p);
@@ -307,21 +310,21 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR* p_msg,
 
     case AVRC_PDU_SET_ABSOLUTE_VOLUME: /* 0x50 */
       if (len != 1)
-        status = AVRC_STS_INTERNAL_ERR;
+        return AVRC_STS_INTERNAL_ERR;
       else
         p_result->volume.volume = *p++;
       break;
 
     case AVRC_PDU_REQUEST_CONTINUATION_RSP: /* 0x40 */
       if (len != 1) {
-        status = AVRC_STS_INTERNAL_ERR;
+        return AVRC_STS_INTERNAL_ERR;
       }
       BE_STREAM_TO_UINT8(p_result->continu.target_pdu, p);
       break;
 
     case AVRC_PDU_ABORT_CONTINUATION_RSP: /* 0x41 */
       if (len != 1) {
-        status = AVRC_STS_INTERNAL_ERR;
+        return AVRC_STS_INTERNAL_ERR;
       }
       BE_STREAM_TO_UINT8(p_result->abort.target_pdu, p);
       break;
@@ -330,14 +333,14 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR* p_msg,
       if (len != 2) {
         AVRC_TRACE_ERROR("AVRC_PDU_SET_ADDRESSED_PLAYER length is incorrect:%d",
                          len);
-        status = AVRC_STS_INTERNAL_ERR;
+        return AVRC_STS_INTERNAL_ERR;
       }
       BE_STREAM_TO_UINT16(p_result->addr_player.player_id, p);
       break;
 
     case AVRC_PDU_PLAY_ITEM:          /* 0x74 */
     case AVRC_PDU_ADD_TO_NOW_PLAYING: /* 0x90 */
-      if (len != (AVRC_UID_SIZE + 3)) status = AVRC_STS_INTERNAL_ERR;
+      if (len != (AVRC_UID_SIZE + 3)) return AVRC_STS_INTERNAL_ERR;
       BE_STREAM_TO_UINT8(p_result->play_item.scope, p);
       if (p_result->play_item.scope > AVRC_SCOPE_NOW_PLAYING) {
         status = AVRC_STS_BAD_SCOPE;
index 0e7b692..809d0b2 100644 (file)
@@ -340,7 +340,7 @@ tBNEP_RESULT BNEP_WriteBuf(uint16_t handle, const RawAddress& p_dest_addr,
   p_bcb = &(bnep_cb.bcb[handle - 1]);
   /* Check MTU size */
   if (p_buf->len > BNEP_MTU_SIZE) {
-    BNEP_TRACE_ERROR("BNEP_Write() length %d exceeded MTU %d", p_buf->len,
+    BNEP_TRACE_ERROR("%s length %d exceeded MTU %d", __func__, p_buf->len,
                      BNEP_MTU_SIZE);
     osi_free(p_buf);
     return (BNEP_MTU_EXCEDED);
@@ -349,7 +349,7 @@ tBNEP_RESULT BNEP_WriteBuf(uint16_t handle, const RawAddress& p_dest_addr,
   /* Check if the packet should be filtered out */
   p_data = (uint8_t*)(p_buf + 1) + p_buf->offset;
   if (bnep_is_packet_allowed(p_bcb, p_dest_addr, protocol, fw_ext_present,
-                             p_data) != BNEP_SUCCESS) {
+                             p_data, p_buf->len) != BNEP_SUCCESS) {
     /*
     ** If packet is filtered and ext headers are present
     ** drop the data and forward the ext headers
@@ -361,6 +361,11 @@ tBNEP_RESULT BNEP_WriteBuf(uint16_t handle, const RawAddress& p_dest_addr,
       org_len = p_buf->len;
       new_len = 0;
       do {
+        if ((new_len + 2) > org_len) {
+          osi_free(p_buf);
+          return BNEP_IGNORE_CMD;
+        }
+
         ext = *p_data++;
         length = *p_data++;
         p_data += length;
@@ -437,7 +442,7 @@ tBNEP_RESULT BNEP_Write(uint16_t handle, const RawAddress& p_dest_addr,
 
   /* Check MTU size. Consider the possibility of having extension headers */
   if (len > BNEP_MTU_SIZE) {
-    BNEP_TRACE_ERROR("BNEP_Write() length %d exceeded MTU %d", len,
+    BNEP_TRACE_ERROR("%s length %d exceeded MTU %d", __func__, len,
                      BNEP_MTU_SIZE);
     return (BNEP_MTU_EXCEDED);
   }
@@ -448,7 +453,7 @@ tBNEP_RESULT BNEP_Write(uint16_t handle, const RawAddress& p_dest_addr,
 
   /* Check if the packet should be filtered out */
   if (bnep_is_packet_allowed(p_bcb, p_dest_addr, protocol, fw_ext_present,
-                             p_data) != BNEP_SUCCESS) {
+                             p_data, len) != BNEP_SUCCESS) {
     /*
     ** If packet is filtered and ext headers are present
     ** drop the data and forward the ext headers
@@ -461,6 +466,10 @@ tBNEP_RESULT BNEP_Write(uint16_t handle, const RawAddress& p_dest_addr,
       new_len = 0;
       p = p_data;
       do {
+        if ((new_len + 2) > org_len) {
+          return BNEP_IGNORE_CMD;
+        }
+
         ext = *p_data++;
         length = *p_data++;
         p_data += length;
index 2587147..5bba15d 100644 (file)
@@ -229,7 +229,7 @@ extern void bnep_sec_check_complete(const RawAddress* bd_addr,
 extern tBNEP_RESULT bnep_is_packet_allowed(tBNEP_CONN* p_bcb,
                                            const RawAddress& p_dest_addr,
                                            uint16_t protocol,
-                                           bool fw_ext_present,
-                                           uint8_t* p_data);
+                                           bool fw_ext_present, uint8_t* p_data,
+                                           uint16_t org_len);
 
 #endif
index ae6c51b..265ec79 100644 (file)
@@ -94,7 +94,8 @@ tBNEP_RESULT bnep_register_with_l2cap(void) {
   bnep_cb.reg_info.pL2CA_CongestionStatus_Cb = bnep_congestion_ind;
 
   /* Now, register with L2CAP */
-  if (!L2CA_Register(BT_PSM_BNEP, &bnep_cb.reg_info)) {
+  if (!L2CA_Register(BT_PSM_BNEP, &bnep_cb.reg_info,
+                     false /* enable_snoop */)) {
     BNEP_TRACE_ERROR("BNEP - Registration failed");
     return BNEP_SECURITY_FAIL;
   }
index 6d6d709..ac74ce0 100644 (file)
@@ -1259,23 +1259,33 @@ void bnep_sec_check_complete(UNUSED_ATTR const RawAddress* bd_addr,
 tBNEP_RESULT bnep_is_packet_allowed(tBNEP_CONN* p_bcb,
                                     const RawAddress& p_dest_addr,
                                     uint16_t protocol, bool fw_ext_present,
-                                    uint8_t* p_data) {
+                                    uint8_t* p_data, uint16_t org_len) {
   if (p_bcb->rcvd_num_filters) {
     uint16_t i, proto;
 
     /* Findout the actual protocol to check for the filtering */
     proto = protocol;
     if (proto == BNEP_802_1_P_PROTOCOL) {
+      uint16_t new_len = 0;
       if (fw_ext_present) {
         uint8_t len, ext;
         /* parse the extension headers and findout actual protocol */
         do {
+          if ((new_len + 2) > org_len) {
+            return BNEP_IGNORE_CMD;
+          }
+
           ext = *p_data++;
           len = *p_data++;
           p_data += len;
 
+          new_len += (len + 2);
+
         } while (ext & 0x80);
       }
+      if ((new_len + 4) > org_len) {
+        return BNEP_IGNORE_CMD;
+      }
       p_data += 2;
       BE_STREAM_TO_UINT16(proto, p_data);
     }
index ca40a2b..c46acf0 100644 (file)
 
 #define BTM_EXT_BLE_RMT_NAME_TIMEOUT_MS (30 * 1000)
 #define MIN_ADV_LENGTH 2
-#define BTM_VSC_CHIP_CAPABILITY_RSP_LEN_L_RELEASE 9
+#define BTM_VSC_CHIP_CAPABILITY_RSP_LEN 9
+#define BTM_VSC_CHIP_CAPABILITY_RSP_LEN_L_RELEASE \
+  BTM_VSC_CHIP_CAPABILITY_RSP_LEN
+#define BTM_VSC_CHIP_CAPABILITY_RSP_LEN_M_RELEASE 15
 
 namespace {
 
@@ -495,6 +498,7 @@ static void btm_ble_vendor_capability_vsc_cmpl_cback(
     BTM_TRACE_DEBUG("%s: Status = 0x%02x (0 is success)", __func__, status);
     return;
   }
+  CHECK(p_vcs_cplt_params->param_len > BTM_VSC_CHIP_CAPABILITY_RSP_LEN);
   STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.adv_inst_max, p);
   STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.rpa_offloading, p);
   STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.tot_scan_results_strg, p);
@@ -512,6 +516,7 @@ static void btm_ble_vendor_capability_vsc_cmpl_cback(
 
   if (btm_cb.cmn_ble_vsc_cb.version_supported >=
       BTM_VSC_CHIP_CAPABILITY_M_VERSION) {
+    CHECK(p_vcs_cplt_params->param_len >= BTM_VSC_CHIP_CAPABILITY_RSP_LEN_M_RELEASE);
     STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.total_trackable_advertisers, p);
     STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.extended_scan_support, p);
     STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.debug_logging_supported, p);
@@ -1473,7 +1478,7 @@ uint8_t btm_ble_is_discoverable(const RawAddress& bda,
   if (!adv_data.empty()) {
     const uint8_t* p_flag = AdvertiseDataParser::GetFieldByType(
         adv_data, BTM_BLE_AD_TYPE_FLAG, &data_len);
-    if (p_flag != NULL) {
+    if (p_flag != NULL && data_len != 0) {
       flag = *p_flag;
 
       if ((btm_cb.btm_inq_vars.inq_active & BTM_BLE_GENERAL_INQUIRY) &&
@@ -1659,7 +1664,7 @@ void btm_ble_update_inq_result(tINQ_DB_ENT* p_i, uint8_t addr_type,
   if (!data.empty()) {
     const uint8_t* p_flag =
         AdvertiseDataParser::GetFieldByType(data, BTM_BLE_AD_TYPE_FLAG, &len);
-    if (p_flag != NULL) p_cur->flag = *p_flag;
+    if (p_flag != NULL && len != 0) p_cur->flag = *p_flag;
   }
 
   if (!data.empty()) {
index b9543fd..987d173 100644 (file)
@@ -1129,8 +1129,8 @@ static void btu_hcif_rmt_name_request_comp_evt(uint8_t* p, uint16_t evt_len) {
 
 constexpr uint8_t MIN_KEY_SIZE = 7;
 
-static void read_encryption_key_size_complete_after_encryption_change(
-    uint8_t status, uint16_t handle, uint8_t key_size) {
+static void read_encryption_key_size_complete_after_encryption_change(uint8_t status, uint16_t handle,
+                                                                      uint8_t key_size) {
   if (status != HCI_SUCCESS) {
     LOG(INFO) << __func__ << ": disconnecting, status: " << loghex(status);
     btsnd_hcic_disconnect(handle, HCI_ERR_PEER_USER);
@@ -1139,9 +1139,8 @@ static void read_encryption_key_size_complete_after_encryption_change(
 
   if (key_size < MIN_KEY_SIZE) {
     android_errorWriteLog(0x534e4554, "124301137");
-    LOG(ERROR) << __func__
-               << " encryption key too short, disconnecting. handle: "
-               << loghex(handle) << " key_size: " << +key_size;
+    LOG(ERROR) << __func__ << " encryption key too short, disconnecting. handle: " << loghex(handle)
+               << " key_size: " << +key_size;
 
     btsnd_hcic_disconnect(handle, HCI_ERR_HOST_REJECT_SECURITY);
     return;
@@ -1169,14 +1168,16 @@ static void btu_hcif_encryption_change_evt(uint8_t* p) {
   STREAM_TO_UINT16(handle, p);
   STREAM_TO_UINT8(encr_enable, p);
 
-  if (status != HCI_SUCCESS || encr_enable == 0 ||
-      BTM_IsBleConnection(handle)) {
+  if (status != HCI_SUCCESS || encr_enable == 0 || BTM_IsBleConnection(handle)) {
+    if (status == HCI_ERR_CONNECTION_TOUT) {
+      smp_cancel_start_encryption_attempt();
+      return;
+    }
+
     btm_acl_encrypt_change(handle, status, encr_enable);
     btm_sec_encrypt_change(handle, status, encr_enable);
   } else {
-    btsnd_hcic_read_encryption_key_size(
-        handle,
-        base::Bind(&read_encryption_key_size_complete_after_encryption_change));
+    btsnd_hcic_read_encryption_key_size(handle, base::Bind(&read_encryption_key_size_complete_after_encryption_change));
   }
 }
 
@@ -2049,8 +2050,7 @@ static void btu_hcif_enhanced_flush_complete_evt(void) {
  * End of Simple Pairing Events
  **********************************************/
 
-static void read_encryption_key_size_complete_after_key_refresh(
-    uint8_t status, uint16_t handle, uint8_t key_size) {
+static void read_encryption_key_size_complete_after_key_refresh(uint8_t status, uint16_t handle, uint8_t key_size) {
   if (status != HCI_SUCCESS) {
     LOG(INFO) << __func__ << ": disconnecting, status: " << loghex(status);
     btsnd_hcic_disconnect(handle, HCI_ERR_PEER_USER);
@@ -2059,9 +2059,8 @@ static void read_encryption_key_size_complete_after_key_refresh(
 
   if (key_size < MIN_KEY_SIZE) {
     android_errorWriteLog(0x534e4554, "124301137");
-    LOG(ERROR) << __func__
-               << " encryption key too short, disconnecting. handle: "
-               << loghex(handle) << " key_size: " << +key_size;
+    LOG(ERROR) << __func__ << " encryption key too short, disconnecting. handle: " << loghex(handle)
+               << " key_size: " << +key_size;
 
     btsnd_hcic_disconnect(handle, HCI_ERR_HOST_REJECT_SECURITY);
     return;
@@ -2080,9 +2079,7 @@ static void btu_hcif_encryption_key_refresh_cmpl_evt(uint8_t* p) {
   if (status != HCI_SUCCESS || BTM_IsBleConnection(handle)) {
     btm_sec_encrypt_change(handle, status, (status == HCI_SUCCESS) ? 1 : 0);
   } else {
-    btsnd_hcic_read_encryption_key_size(
-        handle,
-        base::Bind(&read_encryption_key_size_complete_after_key_refresh));
+    btsnd_hcic_read_encryption_key_size(handle, base::Bind(&read_encryption_key_size_complete_after_key_refresh));
   }
 }
 
index 72183bb..15d3ddb 100644 (file)
@@ -235,8 +235,7 @@ uint16_t GAP_ConnOpen(const char* p_serv_name, uint8_t service_id,
 
   /* Register the PSM with L2CAP */
   if (transport == BT_TRANSPORT_BR_EDR) {
-    p_ccb->psm = L2CA_REGISTER(
-        psm, &conn.reg_info, AMP_AUTOSWITCH_ALLOWED | AMP_USE_AMP_IF_POSSIBLE);
+    p_ccb->psm = L2CA_REGISTER(psm, &conn.reg_info, false /* enable_snoop */);
     if (p_ccb->psm == 0) {
       LOG(ERROR) << StringPrintf("%s: Failure registering PSM 0x%04x", __func__,
                                  psm);
index 4195548..37bc614 100644 (file)
@@ -382,6 +382,7 @@ void GATTS_StopService(uint16_t service_handle) {
   if (it == gatt_cb.srv_list_info->end()) {
     LOG(ERROR) << __func__ << ": service_handle=" << loghex(service_handle)
                << " is not in use";
+    return;
   }
 
   if (it->sdp_handle) {
index 49e7da9..6a00750 100644 (file)
@@ -124,7 +124,8 @@ void gatt_init(void) {
   L2CA_RegisterFixedChannel(L2CAP_ATT_CID, &fixed_reg);
 
   /* Now, register with L2CAP for ATT PSM over BR/EDR */
-  if (!L2CA_Register(BT_PSM_ATT, (tL2CAP_APPL_INFO*)&dyn_info)) {
+  if (!L2CA_Register(BT_PSM_ATT, (tL2CAP_APPL_INFO*)&dyn_info,
+                     false /* enable_snoop */)) {
     LOG(ERROR) << "ATT Dynamic Registration failed";
   }
 
index 2e849a4..23a8648 100644 (file)
@@ -1309,9 +1309,8 @@ void btsnd_hcic_read_rssi(uint16_t handle) {
   btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
 }
 
-static void read_encryption_key_size_complete(
-    ReadEncKeySizeCb cb, uint8_t* return_parameters,
-    uint16_t return_parameters_length) {
+static void read_encryption_key_size_complete(ReadEncKeySizeCb cb, uint8_t* return_parameters,
+                                              uint16_t return_parameters_length) {
   uint8_t status;
   uint16_t handle;
   uint8_t key_size;
@@ -1330,9 +1329,8 @@ void btsnd_hcic_read_encryption_key_size(uint16_t handle, ReadEncKeySizeCb cb) {
   uint8_t* p = param;
   UINT16_TO_STREAM(p, handle);
 
-  btu_hcif_send_cmd_with_cb(
-      FROM_HERE, HCI_READ_ENCR_KEY_SIZE, param, len,
-      base::Bind(&read_encryption_key_size_complete, base::Passed(&cb)));
+  btu_hcif_send_cmd_with_cb(FROM_HERE, HCI_READ_ENCR_KEY_SIZE, param, len,
+                            base::Bind(&read_encryption_key_size_complete, base::Passed(&cb)));
 }
 
 void btsnd_hcic_read_failed_contact_counter(uint16_t handle) {
index f93511e..cd40c2c 100644 (file)
@@ -33,7 +33,6 @@
 #include "hidd_api.h"
 #include "hidd_int.h"
 #include "hiddefs.h"
-#include "log/log.h"
 
 tHID_DEV_CTB hd_cb;
 
@@ -321,10 +320,6 @@ tHID_STATUS HID_DevAddRecord(uint32_t handle, char* p_name, char* p_description,
       UINT8_TO_BE_STREAM(p, desc_len);
       ARRAY_TO_BE_STREAM(p, p_desc_data, (int)desc_len);
 
-      if (desc_len > HIDD_APP_DESCRIPTOR_LEN - 6) {
-        android_errorWriteLog(0x534e4554, "113572366");
-      }
-
       result &= SDP_AddAttribute(handle, ATTR_ID_HID_DESCRIPTOR_LIST,
                                  DATA_ELE_SEQ_DESC_TYPE, p - p_buf, p_buf);
 
index e4525f9..55ec3b2 100644 (file)
@@ -614,6 +614,12 @@ static void hidd_l2cif_data_ind(uint16_t cid, BT_HDR* p_msg) {
 
   HIDD_TRACE_EVENT("%s: cid=%04x", __func__, cid);
 
+  if (p_msg->len < 1) {
+    HIDD_TRACE_ERROR("Invalid data length, ignore");
+    osi_free(p_msg);
+    return;
+  }
+
   p_hcon = &hd_cb.device.conn;
 
   if (p_hcon->conn_state == HID_CONN_STATE_UNUSED ||
@@ -756,12 +762,14 @@ tHID_STATUS hidd_conn_reg(void) {
   hd_cb.l2cap_intr_cfg.flush_to_present = TRUE;
   hd_cb.l2cap_intr_cfg.flush_to = HID_DEV_FLUSH_TO;
 
-  if (!L2CA_Register(HID_PSM_CONTROL, (tL2CAP_APPL_INFO*)&dev_reg_info)) {
+  if (!L2CA_Register(HID_PSM_CONTROL, (tL2CAP_APPL_INFO*)&dev_reg_info,
+                     false /* enable_snoop */)) {
     HIDD_TRACE_ERROR("HID Control (device) registration failed");
     return (HID_ERR_L2CAP_FAILED);
   }
 
-  if (!L2CA_Register(HID_PSM_INTERRUPT, (tL2CAP_APPL_INFO*)&dev_reg_info)) {
+  if (!L2CA_Register(HID_PSM_INTERRUPT, (tL2CAP_APPL_INFO*)&dev_reg_info,
+                     false /* enable_snoop */)) {
     L2CA_Deregister(HID_PSM_CONTROL);
     HIDD_TRACE_ERROR("HID Interrupt (device) registration failed");
     return (HID_ERR_L2CAP_FAILED);
index 6b729e5..3c694f0 100644 (file)
@@ -97,11 +97,13 @@ tHID_STATUS hidh_conn_reg(void) {
   hh_cb.l2cap_cfg.flush_to = HID_HOST_FLUSH_TO;
 
   /* Now, register with L2CAP */
-  if (!L2CA_Register(HID_PSM_CONTROL, (tL2CAP_APPL_INFO*)&hst_reg_info)) {
+  if (!L2CA_Register(HID_PSM_CONTROL, (tL2CAP_APPL_INFO*)&hst_reg_info,
+                     false /* enable_snoop */)) {
     HIDH_TRACE_ERROR("HID-Host Control Registration failed");
     return (HID_ERR_L2CAP_FAILED);
   }
-  if (!L2CA_Register(HID_PSM_INTERRUPT, (tL2CAP_APPL_INFO*)&hst_reg_info)) {
+  if (!L2CA_Register(HID_PSM_INTERRUPT, (tL2CAP_APPL_INFO*)&hst_reg_info,
+                     false /* enable_snoop */)) {
     L2CA_Deregister(HID_PSM_CONTROL);
     HIDH_TRACE_ERROR("HID-Host Interrupt Registration failed");
     return (HID_ERR_L2CAP_FAILED);
index b62dbb3..a1ac17b 100644 (file)
@@ -34,7 +34,8 @@ class AdvertiseDataParser {
     auto data_start = ad.begin() + position;
 
     // Traxxas - bad name length
-    if (std::equal(data_start, data_start + 3, trx_quirk.begin()) &&
+    if ((ad.size() - position) >= 18 &&
+        std::equal(data_start, data_start + 3, trx_quirk.begin()) &&
         std::equal(data_start + 5, data_start + 11, trx_quirk.begin() + 5) &&
         std::equal(data_start + 12, data_start + 18, trx_quirk.begin() + 12)) {
       return true;
index 5682a5c..285ae41 100644 (file)
@@ -611,8 +611,7 @@ extern void btsnd_hcic_write_cur_iac_lap(
 extern void btsnd_hcic_get_link_quality(uint16_t handle); /* Get Link Quality */
 extern void btsnd_hcic_read_rssi(uint16_t handle);        /* Read RSSI */
 using ReadEncKeySizeCb = base::OnceCallback<void(uint8_t, uint16_t, uint8_t)>;
-extern void btsnd_hcic_read_encryption_key_size(uint16_t handle,
-                                                ReadEncKeySizeCb cb);
+extern void btsnd_hcic_read_encryption_key_size(uint16_t handle, ReadEncKeySizeCb cb);
 extern void btsnd_hcic_read_failed_contact_counter(uint16_t handle);
 extern void btsnd_hcic_read_automatic_flush_timeout(uint16_t handle);
 extern void btsnd_hcic_enable_test_mode(
index 88121af..8f364e7 100644 (file)
@@ -328,7 +328,7 @@ typedef struct {
 
 } tL2CAP_ERTM_INFO;
 
-#define L2CA_REGISTER(a, b, c) L2CA_Register(a, (tL2CAP_APPL_INFO*)(b))
+#define L2CA_REGISTER(a, b, c) L2CA_Register(a, (tL2CAP_APPL_INFO*)(b), c)
 #define L2CA_DEREGISTER(a) L2CA_Deregister(a)
 #define L2CA_CONNECT_REQ(a, b, c) L2CA_ErtmConnectReq(a, b, c)
 #define L2CA_CONNECT_RSP(a, b, c, d, e, f) L2CA_ErtmConnectRsp(a, b, c, d, e, f)
@@ -362,7 +362,8 @@ typedef struct {
  *                  BTM_SetSecurityLevel().
  *
  ******************************************************************************/
-extern uint16_t L2CA_Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info);
+extern uint16_t L2CA_Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info,
+                              bool enable_snoop);
 
 /*******************************************************************************
  *
index 6dc41de..b5a9564 100644 (file)
@@ -58,7 +58,8 @@ using base::StringPrintf;
  *                  L2CA_ErtmConnectReq() and L2CA_Deregister()
  *
  ******************************************************************************/
-uint16_t L2CA_Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info) {
+uint16_t L2CA_Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info,
+                       bool enable_snoop) {
   tL2C_RCB* p_rcb;
   uint16_t vpsm = psm;
 
@@ -104,6 +105,7 @@ uint16_t L2CA_Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info) {
     }
   }
 
+  p_rcb->log_packets = enable_snoop;
   p_rcb->api = *p_cb_info;
   p_rcb->real_psm = psm;
 
index 0b71a19..53b6f32 100644 (file)
@@ -241,6 +241,7 @@ typedef struct {
 
 typedef struct {
   bool in_use;
+  bool log_packets;
   uint16_t psm;
   uint16_t real_psm; /* This may be a dummy RCB for an o/b connection but */
                      /* this is the real PSM that we need to connect to */
index 74e7135..128f60e 100644 (file)
@@ -33,6 +33,7 @@
 #include "btm_int.h"
 #include "btu.h"
 #include "device/include/controller.h"
+#include "hci/include/btsnoop.h"
 #include "hcimsgs.h"
 #include "l2c_api.h"
 #include "l2c_int.h"
@@ -79,8 +80,8 @@ void l2c_rcv_acl_data(BT_HDR* p_msg) {
 
   uint16_t hci_len;
   STREAM_TO_UINT16(hci_len, p);
-  if (hci_len < L2CAP_PKT_OVERHEAD) {
-    /* Must receive at least the L2CAP length and CID */
+  if (hci_len < L2CAP_PKT_OVERHEAD || hci_len != p_msg->len - 4) {
+    /* Remote-declared packet size must match HCI_ACL size - ACL header (4) */
     L2CAP_TRACE_WARNING("L2CAP - got incorrect hci header");
     osi_free(p_msg);
     return;
@@ -396,6 +397,14 @@ static void process_l2cap_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
         p_ccb->p_rcb = p_rcb;
         p_ccb->remote_cid = rcid;
 
+        if (p_rcb->psm == BT_PSM_RFCOMM) {
+          btsnoop_get_interface()->add_rfc_l2c_channel(
+              p_lcb->handle, p_ccb->local_cid, p_ccb->remote_cid);
+        } else if (p_rcb->log_packets) {
+          btsnoop_get_interface()->whitelist_l2c_channel(
+              p_lcb->handle, p_ccb->local_cid, p_ccb->remote_cid);
+        }
+
         l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_REQ, &con_info);
         break;
       }
@@ -427,6 +436,15 @@ static void process_l2cap_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
         else
           l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
 
+        tL2C_RCB* p_rcb = p_ccb->p_rcb;
+        if (p_rcb->psm == BT_PSM_RFCOMM) {
+          btsnoop_get_interface()->add_rfc_l2c_channel(
+              p_lcb->handle, p_ccb->local_cid, p_ccb->remote_cid);
+        } else if (p_rcb->log_packets) {
+          btsnoop_get_interface()->whitelist_l2c_channel(
+              p_lcb->handle, p_ccb->local_cid, p_ccb->remote_cid);
+        }
+
         break;
       }
 
@@ -763,6 +781,10 @@ static void process_l2cap_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
 #if (L2CAP_NUM_FIXED_CHNLS > 0)
         if (info_type == L2CAP_FIXED_CHANNELS_INFO_TYPE) {
           if (result == L2CAP_INFO_RESP_RESULT_SUCCESS) {
+            if (p + L2CAP_FIXED_CHNL_ARRAY_SIZE > p_next_cmd) {
+              android_errorWriteLog(0x534e4554, "111215173");
+              return;
+            }
             memcpy(p_lcb->peer_chnl_mask, p, L2CAP_FIXED_CHNL_ARRAY_SIZE);
           }
 
index 448acaa..593f12f 100644 (file)
@@ -33,6 +33,7 @@
 #include "btm_int.h"
 #include "btu.h"
 #include "device/include/controller.h"
+#include "hci/include/btsnoop.h"
 #include "hcidefs.h"
 #include "hcimsgs.h"
 #include "l2c_int.h"
@@ -1569,6 +1570,9 @@ void l2cu_release_ccb(tL2C_CCB* p_ccb) {
   /* If already released, could be race condition */
   if (!p_ccb->in_use) return;
 
+  btsnoop_get_interface()->clear_l2cap_whitelist(
+      p_lcb->handle, p_ccb->local_cid, p_ccb->remote_cid);
+
   if (p_rcb && (p_rcb->psm != p_rcb->real_psm)) {
     btm_sec_clr_service_by_psm(p_rcb->psm);
   }
index 3275d77..3dc4ec2 100644 (file)
@@ -30,6 +30,7 @@
 #include "osi/include/osi.h"
 
 #include "bt_utils.h"
+#include "hci/include/btsnoop.h"
 #include "l2c_api.h"
 #include "l2cdefs.h"
 #include "port_api.h"
@@ -73,7 +74,7 @@ void rfcomm_l2cap_if_init(void) {
   p_l2c->pL2CA_CongestionStatus_Cb = RFCOMM_CongestionStatusInd;
   p_l2c->pL2CA_TxComplete_Cb = NULL;
 
-  L2CA_Register(BT_PSM_RFCOMM, p_l2c);
+  L2CA_Register(BT_PSM_RFCOMM, p_l2c, true /* enable_snoop */);
 }
 
 /*******************************************************************************
index f486bdd..1b82ddf 100644 (file)
 #include "rfc_int.h"
 #include "rfcdefs.h"
 
+#include <set>
+#include "hci/include/btsnoop.h"
+
+static const std::set<uint16_t> uuid_logging_whitelist = {
+    UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY,
+    UUID_SERVCLASS_AG_HANDSFREE,
+};
+
 /******************************************************************************/
 /*            L O C A L    F U N C T I O N     P R O T O T Y P E S            */
 /******************************************************************************/
@@ -206,6 +214,13 @@ void rfc_port_sm_sabme_wait_ua(tPORT* p_port, uint16_t event, void* p_data) {
     case RFC_EVENT_UA:
       rfc_port_timer_stop(p_port);
       p_port->rfc.state = RFC_STATE_OPENED;
+
+      if (uuid_logging_whitelist.find(p_port->uuid) !=
+          uuid_logging_whitelist.end()) {
+        btsnoop_get_interface()->whitelist_rfc_dlci(p_port->rfc.p_mcb->lcid,
+                                                    p_port->dlci);
+      }
+
       PORT_DlcEstablishCnf(p_port->rfc.p_mcb, p_port->dlci,
                            p_port->rfc.p_mcb->peer_l2cap_mtu, RFCOMM_SUCCESS);
       return;
@@ -317,6 +332,12 @@ void rfc_port_sm_term_wait_sec_check(tPORT* p_port, uint16_t event,
       } else {
         rfc_send_ua(p_port->rfc.p_mcb, p_port->dlci);
         p_port->rfc.state = RFC_STATE_OPENED;
+
+        if (uuid_logging_whitelist.find(p_port->uuid) !=
+            uuid_logging_whitelist.end()) {
+          btsnoop_get_interface()->whitelist_rfc_dlci(p_port->rfc.p_mcb->lcid,
+                                                      p_port->dlci);
+        }
       }
       return;
   }
index d253b40..7bc98a2 100644 (file)
@@ -533,12 +533,21 @@ uint8_t rfc_parse_data(tRFC_MCB* p_mcb, MX_FRAME* p_frame, BT_HDR* p_buf) {
     return RFC_EVENT_BAD_FRAME;
   }
 
+  if (p_buf->len < (3 + !ead + !eal + 1)) {
+    android_errorWriteLog(0x534e4554, "120255805");
+    RFCOMM_TRACE_ERROR("Bad Length: %d", p_buf->len);
+    return RFC_EVENT_BAD_FRAME;
+  }
   p_buf->len -= (3 + !ead + !eal + 1); /* Additional 1 for FCS */
   p_buf->offset += (3 + !ead + !eal);
 
   /* handle credit if credit based flow control */
   if ((p_mcb->flow == PORT_FC_CREDIT) && (p_frame->type == RFCOMM_UIH) &&
       (p_frame->dlci != RFCOMM_MX_DLCI) && (p_frame->pf == 1)) {
+    if (p_buf->len < sizeof(uint8_t)) {
+      RFCOMM_TRACE_ERROR("Bad Length in flow control: %d", p_buf->len);
+      return RFC_EVENT_BAD_FRAME;
+    }
     p_frame->credit = *p_data++;
     p_buf->len--;
     p_buf->offset++;
index 29377b0..6c504af 100644 (file)
@@ -217,6 +217,12 @@ void sdp_disc_server_rsp(tCONN_CB* p_ccb, BT_HDR* p_msg) {
   p = (uint8_t*)(p_msg + 1) + p_msg->offset;
   uint8_t* p_end = p + p_msg->len;
 
+  if (p_msg->len < 1) {
+    android_errorWriteLog(0x534e4554, "79883568");
+    sdp_disconnect(p_ccb, SDP_GENERIC_ERROR);
+    return;
+  }
+
   BE_STREAM_TO_UINT8(rsp_pdu, p);
 
   p_msg->len--;
@@ -362,11 +368,6 @@ static void sdp_copy_raw_data(tCONN_CB* p_ccb, bool offset) {
       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;
   }
@@ -391,6 +392,12 @@ static void process_service_attr_rsp(tCONN_CB* p_ccb, uint8_t* p_reply,
 
   /* If p_reply is NULL, we were called after the records handles were read */
   if (p_reply) {
+    if (p_reply + 4 /* transaction ID and length */ + sizeof(list_byte_count) >
+        p_reply_end) {
+      sdp_disconnect(p_ccb, SDP_INVALID_PDU_SIZE);
+      return;
+    }
+
     /* Skip transaction ID and length */
     p_reply += 4;
 
index 3df37c5..2211c39 100644 (file)
@@ -121,7 +121,7 @@ void sdp_init(void) {
   sdp_cb.reg_info.pL2CA_TxComplete_Cb = NULL;
 
   /* Now, register with L2CAP */
-  if (!L2CA_Register(SDP_PSM, &sdp_cb.reg_info)) {
+  if (!L2CA_Register(SDP_PSM, &sdp_cb.reg_info, true /* enable_snoop */)) {
     SDP_TRACE_ERROR("SDP Registration failed");
   }
 }
index ef88cd8..21b960b 100644 (file)
@@ -16,6 +16,7 @@
  *
  ******************************************************************************/
 
+#include <cutils/log.h>
 #include <log/log.h>
 #include <string.h>
 #include "btif_common.h"
@@ -343,7 +344,7 @@ void smp_send_keypress_notification(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
  * Description  send encryption information command.
  ******************************************************************************/
 void smp_send_enc_info(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
-  tBTM_LE_LENC_KEYS le_key;
+  tBTM_LE_KEY_VALUE le_key;
 
   SMP_TRACE_DEBUG("%s: p_cb->loc_enc_size = %d", __func__, p_cb->loc_enc_size);
   smp_update_key_mask(p_cb, SMP_SEC_KEY_TYPE_ENC, false);
@@ -352,15 +353,14 @@ void smp_send_enc_info(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
   smp_send_cmd(SMP_OPCODE_MASTER_ID, p_cb);
 
   /* save the DIV and key size information when acting as slave device */
-  le_key.ltk = p_cb->ltk;
-  le_key.div = p_cb->div;
-  le_key.key_size = p_cb->loc_enc_size;
-  le_key.sec_level = p_cb->sec_level;
+  le_key.lenc_key.ltk = p_cb->ltk;
+  le_key.lenc_key.div = p_cb->div;
+  le_key.lenc_key.key_size = p_cb->loc_enc_size;
+  le_key.lenc_key.sec_level = p_cb->sec_level;
 
   if ((p_cb->peer_auth_req & SMP_AUTH_BOND) &&
       (p_cb->loc_auth_req & SMP_AUTH_BOND))
-    btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LENC,
-                        (tBTM_LE_KEY_VALUE*)&le_key, true);
+    btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LENC, &le_key, true);
 
   SMP_TRACE_WARNING("%s", __func__);
 
@@ -389,17 +389,16 @@ void smp_send_id_info(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 
 /**  send CSRK command. */
 void smp_send_csrk_info(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
-  tBTM_LE_LCSRK_KEYS key;
+  tBTM_LE_KEY_VALUE key;
   SMP_TRACE_DEBUG("%s", __func__);
   smp_update_key_mask(p_cb, SMP_SEC_KEY_TYPE_CSRK, false);
 
   if (smp_send_cmd(SMP_OPCODE_SIGN_INFO, p_cb)) {
-    key.div = p_cb->div;
-    key.sec_level = p_cb->sec_level;
-    key.counter = 0; /* initialize the local counter */
-    key.csrk = p_cb->csrk;
-    btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LCSRK,
-                        (tBTM_LE_KEY_VALUE*)&key, true);
+    key.lcsrk_key.div = p_cb->div;
+    key.lcsrk_key.sec_level = p_cb->sec_level;
+    key.lcsrk_key.counter = 0; /* initialize the local counter */
+    key.lcsrk_key.csrk = p_cb->csrk;
+    btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LCSRK, &key, true);
   }
 
   smp_key_distribution_by_transport(p_cb, NULL);
@@ -490,7 +489,15 @@ void smp_proc_sec_grant(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
  ******************************************************************************/
 void smp_proc_pair_fail(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
   SMP_TRACE_DEBUG("%s", __func__);
-  p_cb->status = p_data->status;
+
+  if (p_cb->rcvd_cmd_len < 2) {
+    android_errorWriteLog(0x534e4554, "111214739");
+    SMP_TRACE_WARNING("%s: rcvd_cmd_len %d too short: must be at least 2",
+                      __func__, p_cb->rcvd_cmd_len);
+    p_cb->status = SMP_INVALID_PARAMETERS;
+  } else {
+    p_cb->status = p_data->status;
+  }
 
   /* Cancel pending auth complete timer if set */
   alarm_cancel(p_cb->delayed_auth_timer_ent);
@@ -513,6 +520,14 @@ void smp_proc_pair_cmd(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 
   p_cb->flags |= SMP_PAIR_FLAG_ENC_AFTER_PAIR;
 
+  if (smp_command_has_invalid_length(p_cb)) {
+    tSMP_INT_DATA smp_int_data;
+    smp_int_data.status = SMP_INVALID_PARAMETERS;
+    android_errorWriteLog(0x534e4554, "111850706");
+    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
+    return;
+  }
+
   STREAM_TO_UINT8(p_cb->peer_io_caps, p);
   STREAM_TO_UINT8(p_cb->peer_oob_flag, p);
   STREAM_TO_UINT8(p_cb->peer_auth_req, p);
@@ -781,6 +796,14 @@ void smp_br_process_pairing_command(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 
   p_cb->flags |= SMP_PAIR_FLAG_ENC_AFTER_PAIR;
 
+  if (smp_command_has_invalid_length(p_cb)) {
+    tSMP_INT_DATA smp_int_data;
+    smp_int_data.status = SMP_INVALID_PARAMETERS;
+    android_errorWriteLog(0x534e4554, "111213909");
+    smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &smp_int_data);
+    return;
+  }
+
   STREAM_TO_UINT8(p_cb->peer_io_caps, p);
   STREAM_TO_UINT8(p_cb->peer_oob_flag, p);
   STREAM_TO_UINT8(p_cb->peer_auth_req, p);
@@ -927,7 +950,7 @@ void smp_proc_enc_info(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 /** process master ID from slave device */
 void smp_proc_master_id(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
   uint8_t* p = p_data->p_data;
-  tBTM_LE_PENC_KEYS le_key;
+  tBTM_LE_KEY_VALUE le_key;
 
   SMP_TRACE_DEBUG("%s", __func__);
 
@@ -940,18 +963,17 @@ void smp_proc_master_id(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 
   smp_update_key_mask(p_cb, SMP_SEC_KEY_TYPE_ENC, true);
 
-  STREAM_TO_UINT16(le_key.ediv, p);
-  STREAM_TO_ARRAY(le_key.rand, p, BT_OCTET8_LEN);
+  STREAM_TO_UINT16(le_key.penc_key.ediv, p);
+  STREAM_TO_ARRAY(le_key.penc_key.rand, p, BT_OCTET8_LEN);
 
   /* store the encryption keys from peer device */
-  le_key.ltk = p_cb->ltk;
-  le_key.sec_level = p_cb->sec_level;
-  le_key.key_size = p_cb->loc_enc_size;
+  le_key.penc_key.ltk = p_cb->ltk;
+  le_key.penc_key.sec_level = p_cb->sec_level;
+  le_key.penc_key.key_size = p_cb->loc_enc_size;
 
   if ((p_cb->peer_auth_req & SMP_AUTH_BOND) &&
       (p_cb->loc_auth_req & SMP_AUTH_BOND))
-    btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PENC,
-                        (tBTM_LE_KEY_VALUE*)&le_key, true);
+    btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PENC, &le_key, true);
 
   smp_key_distribution(p_cb, NULL);
 }
@@ -977,48 +999,65 @@ void smp_proc_id_info(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 /** process identity address from peer device */
 void smp_proc_id_addr(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
   uint8_t* p = p_data->p_data;
-  tBTM_LE_PID_KEYS pid_key;
+  tBTM_LE_KEY_VALUE pid_key;
 
   SMP_TRACE_DEBUG("%s", __func__);
+
+  if (smp_command_has_invalid_parameters(p_cb)) {
+    tSMP_INT_DATA smp_int_data;
+    smp_int_data.status = SMP_INVALID_PARAMETERS;
+    android_errorWriteLog(0x534e4554, "111214770");
+    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
+    return;
+  }
+
   smp_update_key_mask(p_cb, SMP_SEC_KEY_TYPE_ID, true);
 
-  STREAM_TO_UINT8(pid_key.identity_addr_type, p);
-  STREAM_TO_BDADDR(pid_key.identity_addr, p);
-  pid_key.irk = p_cb->tk;
+  STREAM_TO_UINT8(pid_key.pid_key.identity_addr_type, p);
+  STREAM_TO_BDADDR(pid_key.pid_key.identity_addr, p);
+  pid_key.pid_key.irk = p_cb->tk;
 
   /* to use as BD_ADDR for lk derived from ltk */
   p_cb->id_addr_rcvd = true;
-  p_cb->id_addr_type = pid_key.identity_addr_type;
-  p_cb->id_addr = pid_key.identity_addr;
+  p_cb->id_addr_type = pid_key.pid_key.identity_addr_type;
+  p_cb->id_addr = pid_key.pid_key.identity_addr;
 
   /* store the ID key from peer device */
   if ((p_cb->peer_auth_req & SMP_AUTH_BOND) &&
       (p_cb->loc_auth_req & SMP_AUTH_BOND))
-    btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PID,
-                        (tBTM_LE_KEY_VALUE*)&pid_key, true);
+    btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PID, &pid_key, true);
   smp_key_distribution_by_transport(p_cb, NULL);
 }
 
 /* process security information from peer device */
 void smp_proc_srk_info(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
-  tBTM_LE_PCSRK_KEYS le_key;
+  tBTM_LE_KEY_VALUE le_key;
 
   SMP_TRACE_DEBUG("%s", __func__);
+
+  if (smp_command_has_invalid_parameters(p_cb)) {
+    tSMP_INT_DATA smp_int_data;
+    smp_int_data.status = SMP_INVALID_PARAMETERS;
+    android_errorWriteLog(0x534e4554, "111214470");
+    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
+    return;
+  }
+
   smp_update_key_mask(p_cb, SMP_SEC_KEY_TYPE_CSRK, true);
 
   /* save CSRK to security record */
-  le_key.sec_level = p_cb->sec_level;
+  le_key.pcsrk_key.sec_level = p_cb->sec_level;
 
   /* get peer CSRK */
-  maybe_non_aligned_memcpy(le_key.csrk.data(), p_data->p_data, OCTET16_LEN);
+  maybe_non_aligned_memcpy(le_key.pcsrk_key.csrk.data(), p_data->p_data,
+                           OCTET16_LEN);
 
   /* initialize the peer counter */
-  le_key.counter = 0;
+  le_key.pcsrk_key.counter = 0;
 
   if ((p_cb->peer_auth_req & SMP_AUTH_BOND) &&
       (p_cb->loc_auth_req & SMP_AUTH_BOND))
-    btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PCSRK,
-                        (tBTM_LE_KEY_VALUE*)&le_key, true);
+    btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PCSRK, &le_key, true);
   smp_key_distribution_by_transport(p_cb, NULL);
 }
 
index 9886d4f..72fdf55 100644 (file)
@@ -450,6 +450,7 @@ extern void smp_convert_string_to_tk(Octet16* tk, uint32_t passkey);
 extern void smp_mask_enc_key(uint8_t loc_enc_size, Octet16* p_data);
 extern void smp_rsp_timeout(void* data);
 extern void smp_delayed_auth_complete_timeout(void* data);
+extern bool smp_command_has_invalid_length(tSMP_CB* p_cb);
 extern bool smp_command_has_invalid_parameters(tSMP_CB* p_cb);
 extern void smp_reject_unexpected_pairing_command(const RawAddress& bd_addr);
 extern tSMP_ASSO_MODEL smp_select_association_model(tSMP_CB* p_cb);
index b6881e6..2daeb21 100644 (file)
@@ -22,6 +22,7 @@
  *
  ******************************************************************************/
 
+#include <cutils/log.h>
 #include "bt_target.h"
 
 #include <string.h>
@@ -142,6 +143,14 @@ static void smp_data_received(uint16_t channel, const RawAddress& bd_addr,
   uint8_t* p = (uint8_t*)(p_buf + 1) + p_buf->offset;
   uint8_t cmd;
 
+  if (p_buf->len < 1) {
+    android_errorWriteLog(0x534e4554, "111215315");
+    SMP_TRACE_WARNING("%s: smp packet length %d too short: must be at least 1",
+                      __func__, p_buf->len);
+    osi_free(p_buf);
+    return;
+  }
+
   STREAM_TO_UINT8(cmd, p);
 
   SMP_TRACE_EVENT("%s: SMDBG l2c, cmd=0x%x", __func__, cmd);
@@ -286,6 +295,14 @@ static void smp_br_data_received(uint16_t channel, const RawAddress& bd_addr,
   uint8_t cmd;
   SMP_TRACE_EVENT("SMDBG l2c %s", __func__);
 
+  if (p_buf->len < 1) {
+    android_errorWriteLog(0x534e4554, "111215315");
+    SMP_TRACE_WARNING("%s: smp packet length %d too short: must be at least 1",
+                      __func__, p_buf->len);
+    osi_free(p_buf);
+    return;
+  }
+
   STREAM_TO_UINT8(cmd, p);
 
   /* sanity check */
index 98d9394..b5da5ba 100644 (file)
@@ -955,6 +955,33 @@ void smp_proc_pairing_cmpl(tSMP_CB* p_cb) {
 
 /*******************************************************************************
  *
+ * Function         smp_command_has_invalid_length
+ *
+ * Description      Checks if the received SMP command has invalid length
+ *                  It returns true if the command has invalid length.
+ *
+ * Returns          true if the command has invalid length, false otherwise.
+ *
+ ******************************************************************************/
+bool smp_command_has_invalid_length(tSMP_CB* p_cb) {
+  uint8_t cmd_code = p_cb->rcvd_cmd_code;
+
+  if ((cmd_code > (SMP_OPCODE_MAX + 1 /* for SMP_OPCODE_PAIR_COMMITM */)) ||
+      (cmd_code < SMP_OPCODE_MIN)) {
+    SMP_TRACE_WARNING("%s: Received command with RESERVED code 0x%02x",
+                      __func__, cmd_code);
+    return true;
+  }
+
+  if (!smp_command_has_valid_fixed_length(p_cb)) {
+    return true;
+  }
+
+  return false;
+}
+
+/*******************************************************************************
+ *
  * Function         smp_command_has_invalid_parameters
  *
  * Description      Checks if the received SMP command has invalid parameters
@@ -1443,25 +1470,23 @@ bool smp_check_commitment(tSMP_CB* p_cb) {
  *
  ******************************************************************************/
 void smp_save_secure_connections_long_term_key(tSMP_CB* p_cb) {
-  tBTM_LE_LENC_KEYS lle_key;
-  tBTM_LE_PENC_KEYS ple_key;
+  tBTM_LE_KEY_VALUE lle_key;
+  tBTM_LE_KEY_VALUE ple_key;
 
   SMP_TRACE_DEBUG("%s-Save LTK as local LTK key", __func__);
-  lle_key.ltk = p_cb->ltk;
-  lle_key.div = 0;
-  lle_key.key_size = p_cb->loc_enc_size;
-  lle_key.sec_level = p_cb->sec_level;
-  btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LENC,
-                      (tBTM_LE_KEY_VALUE*)&lle_key, true);
+  lle_key.lenc_key.ltk = p_cb->ltk;
+  lle_key.lenc_key.div = 0;
+  lle_key.lenc_key.key_size = p_cb->loc_enc_size;
+  lle_key.lenc_key.sec_level = p_cb->sec_level;
+  btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LENC, &lle_key, true);
 
   SMP_TRACE_DEBUG("%s-Save LTK as peer LTK key", __func__);
-  ple_key.ediv = 0;
-  memset(ple_key.rand, 0, BT_OCTET8_LEN);
-  ple_key.ltk = p_cb->ltk;
-  ple_key.sec_level = p_cb->sec_level;
-  ple_key.key_size = p_cb->loc_enc_size;
-  btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PENC,
-                      (tBTM_LE_KEY_VALUE*)&ple_key, true);
+  ple_key.penc_key.ediv = 0;
+  memset(ple_key.penc_key.rand, 0, BT_OCTET8_LEN);
+  ple_key.penc_key.ltk = p_cb->ltk;
+  ple_key.penc_key.sec_level = p_cb->sec_level;
+  ple_key.penc_key.key_size = p_cb->loc_enc_size;
+  btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PENC, &ple_key, true);
 }
 
 /** The function calculates MacKey and LTK and saves them in CB. To calculate
index 3d9da3f..0d27e5d 100644 (file)
@@ -27,6 +27,7 @@
 #include "port_api.h"
 
 #include "btm_int.h"
+#include "hci/include/btsnoop.h"
 #include "rfc_int.h"
 
 #include "mock_btm_layer.h"
 #include "stack_rfcomm_test_utils.h"
 #include "stack_test_packet_utils.h"
 
+static void capture(const BT_HDR*, bool) { /* do nothing */
+}
+static void whitelist_l2c_channel(uint16_t, uint16_t,
+                                  uint16_t) { /* do nothing */
+}
+static void whitelist_rfc_dlci(uint16_t, uint8_t) { /* do nothing */
+}
+static void add_rfc_l2c_channel(uint16_t, uint16_t, uint16_t) { /* do nothing */
+}
+static void clear_l2cap_whitelist(uint16_t, uint16_t,
+                                  uint16_t) { /* do nothing */
+}
+static const btsnoop_t fake_snoop = {capture, whitelist_l2c_channel,
+                                     whitelist_rfc_dlci, add_rfc_l2c_channel,
+                                     clear_l2cap_whitelist};
+const btsnoop_t* btsnoop_get_interface() { return &fake_snoop; }
+
 std::string DumpByteBufferToString(uint8_t* p_data, size_t len) {
   std::stringstream str;
   str.setf(std::ios_base::hex, std::ios::basefield);
@@ -46,6 +64,8 @@ std::string DumpByteBufferToString(uint8_t* p_data, size_t len) {
   return str.str();
 }
 
+uint16_t L2CA_Register(unsigned short, tL2CAP_APPL_INFO*, bool) { return 0; }
+
 std::string DumpBtHdrToString(BT_HDR* p_hdr) {
   uint8_t* p_hdr_data = p_hdr->data + p_hdr->offset;
   return DumpByteBufferToString(p_hdr_data, p_hdr->len);
index fdf4a9d..626ac42 100644 (file)
@@ -21,7 +21,6 @@
 #include <stdio.h>
 #include <mutex>
 #include "btcore/include/property.h"
-#include "osi/include/properties.h"
 
 namespace {
 
@@ -71,8 +70,6 @@ void BluetoothTest::TearDown() {
   bt_hal_interface->RemoveObserver(this);
   bt_hal_interface->CleanUp();
   ASSERT_FALSE(bt_hal_interface->IsInitialized());
-
-  osi_property_set("debug.bluetooth.unittest", "false");
 }
 
 void BluetoothTest::ClearSemaphore(semaphore_t* sem) {
index e2f2950..24fa711 100644 (file)
@@ -621,15 +621,15 @@ bool UIPC_Send(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id,
 uint32_t UIPC_Read(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id,
                    UNUSED_ATTR uint16_t* p_msg_evt, uint8_t* p_buf,
                    uint32_t len) {
-  int n_read = 0;
-  int fd = uipc.ch[ch_id].fd;
-  struct pollfd pfd;
-
   if (ch_id >= UIPC_CH_NUM) {
     BTIF_TRACE_ERROR("UIPC_Read : invalid ch id %d", ch_id);
     return 0;
   }
 
+  int n_read = 0;
+  int fd = uipc.ch[ch_id].fd;
+  struct pollfd pfd;
+
   if (fd == UIPC_DISCONNECTED) {
     BTIF_TRACE_ERROR("UIPC_Read : channel %d closed", ch_id);
     return 0;