Merge "Fix the test case HCT BV-01-C"
am: e28586ea5b
Change-Id: I1289d8c4802f673bfff967fbd38050ae8fbbd9ed
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 7fb1636..380216c 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -4,3 +4,6 @@
[Builtin Hooks]
clang_format = true
+[Hook Scripts]
+aosp_first = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} ".*$"
+
diff --git a/binder/Android.bp b/binder/Android.bp
index e1f1592..e4beadb 100644
--- a/binder/Android.bp
+++ b/binder/Android.bp
@@ -75,6 +75,9 @@
"-Wextra",
"-Wno-unused-parameter",
],
+ sanitize: {
+ scs: true,
+ },
}
// AIDL interface between libbluetooth-binder and framework.jar
diff --git a/bta/ag/bta_ag_cmd.cc b/bta/ag/bta_ag_cmd.cc
index bec5497..87b2a82 100644
--- a/bta/ag/bta_ag_cmd.cc
+++ b/bta/ag/bta_ag_cmd.cc
@@ -782,9 +782,11 @@
******************************************************************************/
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,
diff --git a/bta/av/bta_av_aact.cc b/bta/av/bta_av_aact.cc
index aa4a1e4..c695c7f 100644
--- a/bta/av/bta_av_aact.cc
+++ b/bta/av/bta_av_aact.cc
@@ -965,7 +965,7 @@
*
******************************************************************************/
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);
diff --git a/bta/gatt/bta_gattc_api.cc b/bta/gatt/bta_gattc_api.cc
index 9b0bd9e..829084c 100644
--- a/bta/gatt/bta_gattc_api.cc
+++ b/bta/gatt/bta_gattc_api.cc
@@ -269,7 +269,7 @@
* Returns returns list of gatt::Service or NULL.
*
******************************************************************************/
-const std::vector<gatt::Service>* BTA_GATTC_GetServices(uint16_t conn_id) {
+const std::list<gatt::Service>* BTA_GATTC_GetServices(uint16_t conn_id) {
return bta_gattc_get_services(conn_id);
}
diff --git a/bta/gatt/bta_gattc_cache.cc b/bta/gatt/bta_gattc_cache.cc
index 25b85ba..eed1d67 100644
--- a/bta/gatt/bta_gattc_cache.cc
+++ b/bta/gatt/bta_gattc_cache.cc
@@ -120,7 +120,7 @@
}
const Service* bta_gattc_find_matching_service(
- const std::vector<Service>& services, uint16_t handle) {
+ const std::list<Service>& services, uint16_t handle) {
for (const Service& service : services) {
if (handle >= service.handle && handle <= service.end_handle)
return &service;
@@ -419,14 +419,13 @@
}
}
-const std::vector<Service>* bta_gattc_get_services_srcb(
- tBTA_GATTC_SERV* p_srcb) {
+const std::list<Service>* bta_gattc_get_services_srcb(tBTA_GATTC_SERV* p_srcb) {
if (!p_srcb || p_srcb->gatt_database.IsEmpty()) return NULL;
return &p_srcb->gatt_database.Services();
}
-const std::vector<Service>* bta_gattc_get_services(uint16_t conn_id) {
+const std::list<Service>* bta_gattc_get_services(uint16_t conn_id) {
tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
if (p_clcb == NULL) return NULL;
@@ -438,14 +437,14 @@
const Service* bta_gattc_get_service_for_handle_srcb(tBTA_GATTC_SERV* p_srcb,
uint16_t handle) {
- const std::vector<Service>* services = bta_gattc_get_services_srcb(p_srcb);
+ const std::list<Service>* services = bta_gattc_get_services_srcb(p_srcb);
if (services == NULL) return NULL;
return bta_gattc_find_matching_service(*services, handle);
}
const Service* bta_gattc_get_service_for_handle(uint16_t conn_id,
uint16_t handle) {
- const std::vector<Service>* services = bta_gattc_get_services(conn_id);
+ const std::list<Service>* services = bta_gattc_get_services(conn_id);
if (services == NULL) return NULL;
return bta_gattc_find_matching_service(*services, handle);
@@ -556,7 +555,7 @@
/*******************************************************************************
* Returns number of elements inside db from start_handle to end_handle
******************************************************************************/
-static size_t bta_gattc_get_db_size(const std::vector<Service>& services,
+static size_t bta_gattc_get_db_size(const std::list<Service>& services,
uint16_t start_handle,
uint16_t end_handle) {
if (services.empty()) return 0;
diff --git a/bta/gatt/bta_gattc_int.h b/bta/gatt/bta_gattc_int.h
index 6ee962d..f0ead49 100644
--- a/bta/gatt/bta_gattc_int.h
+++ b/bta/gatt/bta_gattc_int.h
@@ -426,8 +426,7 @@
uint8_t disc_type);
extern void bta_gattc_search_service(tBTA_GATTC_CLCB* p_clcb,
bluetooth::Uuid* p_uuid);
-extern const std::vector<gatt::Service>* bta_gattc_get_services(
- uint16_t conn_id);
+extern const std::list<gatt::Service>* bta_gattc_get_services(uint16_t conn_id);
extern const gatt::Service* bta_gattc_get_service_for_handle(uint16_t conn_id,
uint16_t handle);
const gatt::Characteristic* bta_gattc_get_characteristic_srcb(
diff --git a/bta/gatt/database.cc b/bta/gatt/database.cc
index 5f99d55..1486b08 100644
--- a/bta/gatt/database.cc
+++ b/bta/gatt/database.cc
@@ -21,6 +21,7 @@
#include "stack/include/gattdefs.h"
#include <base/logging.h>
+#include <list>
#include <memory>
#include <sstream>
@@ -39,7 +40,7 @@
}
} // namespace
-Service* FindService(std::vector<Service>& services, uint16_t handle) {
+Service* FindService(std::list<Service>& services, uint16_t handle) {
for (Service& service : services) {
if (handle >= service.handle && handle <= service.end_handle)
return &service;
@@ -182,4 +183,4 @@
return result;
}
-} // namespace gatt
\ No newline at end of file
+} // namespace gatt
diff --git a/bta/gatt/database.h b/bta/gatt/database.h
index 1e74809..d1ba836 100644
--- a/bta/gatt/database.h
+++ b/bta/gatt/database.h
@@ -18,6 +18,7 @@
#pragma once
+#include <list>
#include <set>
#include <string>
#include <utility>
@@ -101,10 +102,10 @@
/* Clear the GATT database. This method forces relocation to ensure no extra
* space is used unnecesarly */
- void Clear() { std::vector<Service>().swap(services); }
+ void Clear() { std::list<Service>().swap(services); }
/* Return list of services available in this database */
- const std::vector<Service>& Services() const { return services; }
+ const std::list<Service>& Services() const { return services; }
std::string ToString() const;
@@ -116,11 +117,11 @@
friend class DatabaseBuilder;
private:
- std::vector<Service> services;
+ std::list<Service> services;
};
/* Find a service that should contain handle. Helper method for internal use
* inside gatt namespace.*/
-Service* FindService(std::vector<Service>& services, uint16_t handle);
+Service* FindService(std::list<Service>& services, uint16_t handle);
} // namespace gatt
diff --git a/bta/gatt/database_builder.h b/bta/gatt/database_builder.h
index 0913100..d2cc720 100644
--- a/bta/gatt/database_builder.h
+++ b/bta/gatt/database_builder.h
@@ -21,7 +21,6 @@
#include "gatt/database.h"
#include <utility>
-#include <vector>
namespace gatt {
diff --git a/bta/hearing_aid/hearing_aid.cc b/bta/hearing_aid/hearing_aid.cc
index 7463909..75116f4 100644
--- a/bta/hearing_aid/hearing_aid.cc
+++ b/bta/hearing_aid/hearing_aid.cc
@@ -623,7 +623,7 @@
return;
}
- const std::vector<gatt::Service>* services = BTA_GATTC_GetServices(conn_id);
+ const std::list<gatt::Service>* services = BTA_GATTC_GetServices(conn_id);
const gatt::Service* service = nullptr;
for (const gatt::Service& tmp : *services) {
diff --git a/bta/hh/bta_hh_le.cc b/bta/hh/bta_hh_le.cc
index eb87cdf..510e3a4 100644
--- a/bta/hh/bta_hh_le.cc
+++ b/bta/hh/bta_hh_le.cc
@@ -1490,7 +1490,7 @@
return;
}
- const std::vector<gatt::Service>* services =
+ const std::list<gatt::Service>* services =
BTA_GATTC_GetServices(p_data->conn_id);
bool have_hid = false;
diff --git a/bta/include/bta_gatt_api.h b/bta/include/bta_gatt_api.h
index 9176501..41151f8 100644
--- a/bta/include/bta_gatt_api.h
+++ b/bta/include/bta_gatt_api.h
@@ -491,8 +491,7 @@
* Returns returns list of gatt::Service or NULL.
*
******************************************************************************/
-extern const std::vector<gatt::Service>* BTA_GATTC_GetServices(
- uint16_t conn_id);
+extern const std::list<gatt::Service>* BTA_GATTC_GetServices(uint16_t conn_id);
/*******************************************************************************
*
diff --git a/bta/test/gatt/database_builder_sample_device_test.cc b/bta/test/gatt/database_builder_sample_device_test.cc
index bd4dabc..2bfaa04 100644
--- a/bta/test/gatt/database_builder_sample_device_test.cc
+++ b/bta/test/gatt/database_builder_sample_device_test.cc
@@ -19,6 +19,7 @@
#include <gtest/gtest.h>
#include <base/logging.h>
+#include <iterator>
#include <utility>
#include "gatt/database_builder.h"
@@ -223,64 +224,51 @@
EXPECT_FALSE(builder.InProgress());
// verify that the returned database matches what was discovered
- EXPECT_EQ(result.Services()[0].handle, 0x0001);
- EXPECT_EQ(result.Services()[0].uuid, SERVICE_1_UUID);
- EXPECT_EQ(result.Services()[1].uuid, SERVICE_2_UUID);
- EXPECT_EQ(result.Services()[2].uuid, SERVICE_3_UUID);
- EXPECT_EQ(result.Services()[3].uuid, SERVICE_4_UUID);
- EXPECT_EQ(result.Services()[4].uuid, SERVICE_5_UUID);
- EXPECT_EQ(result.Services()[5].uuid, SERVICE_6_UUID);
+ auto service = result.Services().begin();
+ EXPECT_EQ(service->handle, 0x0001);
+ EXPECT_EQ(service->uuid, SERVICE_1_UUID);
- EXPECT_EQ(result.Services()[0].characteristics[0].uuid,
- SERVICE_1_CHAR_1_UUID);
- EXPECT_EQ(result.Services()[0].characteristics[1].uuid,
- SERVICE_1_CHAR_2_UUID);
- EXPECT_EQ(result.Services()[0].characteristics[2].uuid,
- SERVICE_1_CHAR_3_UUID);
+ EXPECT_EQ(service->characteristics[0].uuid, SERVICE_1_CHAR_1_UUID);
+ EXPECT_EQ(service->characteristics[1].uuid, SERVICE_1_CHAR_2_UUID);
+ EXPECT_EQ(service->characteristics[2].uuid, SERVICE_1_CHAR_3_UUID);
- EXPECT_EQ(result.Services()[2].characteristics[0].uuid,
- SERVICE_3_CHAR_1_UUID);
- EXPECT_EQ(result.Services()[2].characteristics[0].descriptors[0].uuid,
+ service++;
+ EXPECT_EQ(service->uuid, SERVICE_2_UUID);
+
+ service++;
+ EXPECT_EQ(service->uuid, SERVICE_3_UUID);
+ EXPECT_EQ(service->characteristics[0].uuid, SERVICE_3_CHAR_1_UUID);
+ EXPECT_EQ(service->characteristics[0].descriptors[0].uuid,
SERVICE_3_CHAR_1_DESC_1_UUID);
- EXPECT_EQ(result.Services()[3].characteristics[0].uuid,
- SERVICE_4_CHAR_1_UUID);
- EXPECT_EQ(result.Services()[3].characteristics[1].uuid,
- SERVICE_4_CHAR_2_UUID);
- EXPECT_EQ(result.Services()[3].characteristics[2].uuid,
- SERVICE_4_CHAR_3_UUID);
- EXPECT_EQ(result.Services()[3].characteristics[3].uuid,
- SERVICE_4_CHAR_4_UUID);
- EXPECT_EQ(result.Services()[3].characteristics[4].uuid,
- SERVICE_4_CHAR_5_UUID);
- EXPECT_EQ(result.Services()[3].characteristics[5].uuid,
- SERVICE_4_CHAR_6_UUID);
- EXPECT_EQ(result.Services()[3].characteristics[5].descriptors[0].uuid,
+ service++;
+ EXPECT_EQ(service->uuid, SERVICE_4_UUID);
+ EXPECT_EQ(service->characteristics[0].uuid, SERVICE_4_CHAR_1_UUID);
+ EXPECT_EQ(service->characteristics[1].uuid, SERVICE_4_CHAR_2_UUID);
+ EXPECT_EQ(service->characteristics[2].uuid, SERVICE_4_CHAR_3_UUID);
+ EXPECT_EQ(service->characteristics[3].uuid, SERVICE_4_CHAR_4_UUID);
+ EXPECT_EQ(service->characteristics[4].uuid, SERVICE_4_CHAR_5_UUID);
+ EXPECT_EQ(service->characteristics[5].uuid, SERVICE_4_CHAR_6_UUID);
+ EXPECT_EQ(service->characteristics[5].descriptors[0].uuid,
SERVICE_4_CHAR_6_DESC_1_UUID);
- EXPECT_EQ(result.Services()[4].characteristics[0].uuid,
- SERVICE_5_CHAR_1_UUID);
- EXPECT_EQ(result.Services()[4].characteristics[1].uuid,
- SERVICE_5_CHAR_2_UUID);
- EXPECT_EQ(result.Services()[4].characteristics[2].uuid,
- SERVICE_5_CHAR_3_UUID);
- EXPECT_EQ(result.Services()[4].characteristics[3].uuid,
- SERVICE_5_CHAR_4_UUID);
- EXPECT_EQ(result.Services()[4].characteristics[4].uuid,
- SERVICE_5_CHAR_5_UUID);
- EXPECT_EQ(result.Services()[4].characteristics[5].uuid,
- SERVICE_5_CHAR_6_UUID);
- EXPECT_EQ(result.Services()[4].characteristics[6].uuid,
- SERVICE_5_CHAR_7_UUID);
+ service++;
+ EXPECT_EQ(service->uuid, SERVICE_5_UUID);
+ EXPECT_EQ(service->characteristics[0].uuid, SERVICE_5_CHAR_1_UUID);
+ EXPECT_EQ(service->characteristics[1].uuid, SERVICE_5_CHAR_2_UUID);
+ EXPECT_EQ(service->characteristics[2].uuid, SERVICE_5_CHAR_3_UUID);
+ EXPECT_EQ(service->characteristics[3].uuid, SERVICE_5_CHAR_4_UUID);
+ EXPECT_EQ(service->characteristics[4].uuid, SERVICE_5_CHAR_5_UUID);
+ EXPECT_EQ(service->characteristics[5].uuid, SERVICE_5_CHAR_6_UUID);
+ EXPECT_EQ(service->characteristics[6].uuid, SERVICE_5_CHAR_7_UUID);
- EXPECT_EQ(result.Services()[5].characteristics[0].uuid,
- SERVICE_6_CHAR_1_UUID);
- EXPECT_EQ(result.Services()[5].characteristics[0].descriptors[0].uuid,
+ service++;
+ EXPECT_EQ(service->uuid, SERVICE_6_UUID);
+ EXPECT_EQ(service->characteristics[0].uuid, SERVICE_6_CHAR_1_UUID);
+ EXPECT_EQ(service->characteristics[0].descriptors[0].uuid,
SERVICE_6_CHAR_1_DESC_1_UUID);
- EXPECT_EQ(result.Services()[5].characteristics[1].uuid,
- SERVICE_6_CHAR_2_UUID);
- EXPECT_EQ(result.Services()[5].characteristics[2].uuid,
- SERVICE_6_CHAR_3_UUID);
+ EXPECT_EQ(service->characteristics[1].uuid, SERVICE_6_CHAR_2_UUID);
+ EXPECT_EQ(service->characteristics[2].uuid, SERVICE_6_CHAR_3_UUID);
}
} // namespace gatt
\ No newline at end of file
diff --git a/bta/test/gatt/database_builder_test.cc b/bta/test/gatt/database_builder_test.cc
index fcafb49..0a7e928 100644
--- a/bta/test/gatt/database_builder_test.cc
+++ b/bta/test/gatt/database_builder_test.cc
@@ -19,6 +19,7 @@
#include <gtest/gtest.h>
#include <base/logging.h>
+#include <iterator>
#include <utility>
#include "gatt/database_builder.h"
@@ -59,10 +60,11 @@
Database result = builder.Build();
// verify that the returned database matches what was discovered
- EXPECT_EQ(result.Services()[0].handle, 0x0001);
- EXPECT_EQ(result.Services()[0].end_handle, 0x0001);
- EXPECT_EQ(result.Services()[0].is_primary, true);
- EXPECT_EQ(result.Services()[0].uuid, SERVICE_1_UUID);
+ auto service = result.Services().begin();
+ EXPECT_EQ(service->handle, 0x0001);
+ EXPECT_EQ(service->end_handle, 0x0001);
+ EXPECT_EQ(service->is_primary, true);
+ EXPECT_EQ(service->uuid, SERVICE_1_UUID);
}
/* Verify adding service, characteristic and descriptor work */
@@ -79,21 +81,20 @@
Database result = builder.Build();
// verify that the returned database matches what was discovered
- EXPECT_EQ(result.Services()[0].handle, 0x0001);
- EXPECT_EQ(result.Services()[0].end_handle, 0x000f);
- EXPECT_EQ(result.Services()[0].is_primary, true);
- EXPECT_EQ(result.Services()[0].uuid, SERVICE_1_UUID);
+ auto service = result.Services().begin();
+ EXPECT_EQ(service->handle, 0x0001);
+ EXPECT_EQ(service->end_handle, 0x000f);
+ EXPECT_EQ(service->is_primary, true);
+ EXPECT_EQ(service->uuid, SERVICE_1_UUID);
- EXPECT_EQ(result.Services()[0].characteristics[0].uuid,
- SERVICE_1_CHAR_1_UUID);
- EXPECT_EQ(result.Services()[0].characteristics[0].declaration_handle, 0x0002);
- EXPECT_EQ(result.Services()[0].characteristics[0].value_handle, 0x0003);
- EXPECT_EQ(result.Services()[0].characteristics[0].properties, 0x02);
+ EXPECT_EQ(service->characteristics[0].uuid, SERVICE_1_CHAR_1_UUID);
+ EXPECT_EQ(service->characteristics[0].declaration_handle, 0x0002);
+ EXPECT_EQ(service->characteristics[0].value_handle, 0x0003);
+ EXPECT_EQ(service->characteristics[0].properties, 0x02);
- EXPECT_EQ(result.Services()[0].characteristics[0].descriptors[0].uuid,
+ EXPECT_EQ(service->characteristics[0].descriptors[0].uuid,
SERVICE_1_CHAR_1_DESC_1_UUID);
- EXPECT_EQ(result.Services()[0].characteristics[0].descriptors[0].handle,
- 0x0004);
+ EXPECT_EQ(service->characteristics[0].descriptors[0].handle, 0x0004);
}
/* This test verifies that DatabaseBuilder properly handle discovery of
@@ -139,27 +140,35 @@
Database result = builder.Build();
// verify that the returned database matches what was discovered
- EXPECT_EQ(result.Services()[0].handle, 0x0001);
- EXPECT_EQ(result.Services()[0].is_primary, true);
- EXPECT_EQ(result.Services()[0].uuid, SERVICE_1_UUID);
+ auto service = result.Services().begin();
+ EXPECT_EQ(service->handle, 0x0001);
+ EXPECT_EQ(service->is_primary, true);
+ EXPECT_EQ(service->uuid, SERVICE_1_UUID);
- EXPECT_EQ(result.Services()[1].handle, 0x0020);
- EXPECT_EQ(result.Services()[1].end_handle, 0x002f);
- EXPECT_EQ(result.Services()[1].uuid, SERVICE_2_UUID);
- EXPECT_EQ(result.Services()[1].is_primary, false);
+ service++;
+ EXPECT_EQ(service->handle, 0x0020);
+ EXPECT_EQ(service->end_handle, 0x002f);
+ EXPECT_EQ(service->uuid, SERVICE_2_UUID);
+ EXPECT_EQ(service->is_primary, false);
- EXPECT_EQ(result.Services()[2].handle, 0x0030);
- EXPECT_EQ(result.Services()[2].end_handle, 0x003f);
- EXPECT_EQ(result.Services()[2].uuid, SERVICE_3_UUID);
- EXPECT_EQ(result.Services()[2].is_primary, true);
+ service++;
+ EXPECT_EQ(service->handle, 0x0030);
+ EXPECT_EQ(service->end_handle, 0x003f);
+ EXPECT_EQ(service->uuid, SERVICE_3_UUID);
+ EXPECT_EQ(service->is_primary, true);
- EXPECT_EQ(result.Services()[3].handle, 0x0040);
- EXPECT_EQ(result.Services()[3].uuid, SERVICE_4_UUID);
- EXPECT_EQ(result.Services()[3].is_primary, false);
+ service++;
+ EXPECT_EQ(service->handle, 0x0040);
+ EXPECT_EQ(service->uuid, SERVICE_4_UUID);
+ EXPECT_EQ(service->is_primary, false);
- EXPECT_EQ(result.Services()[4].handle, 0x0050);
- EXPECT_EQ(result.Services()[4].uuid, SERVICE_5_UUID);
- EXPECT_EQ(result.Services()[4].is_primary, true);
+ service++;
+ EXPECT_EQ(service->handle, 0x0050);
+ EXPECT_EQ(service->uuid, SERVICE_5_UUID);
+ EXPECT_EQ(service->is_primary, true);
+
+ service++;
+ ASSERT_EQ(service, result.Services().end());
}
} // namespace gatt
\ No newline at end of file
diff --git a/btif/Android.bp b/btif/Android.bp
index 814cba7..dd05ead 100644
--- a/btif/Android.bp
+++ b/btif/Android.bp
@@ -24,6 +24,8 @@
"system/bt/utils/include",
"system/bt/include",
"system/libhwbinder/include",
+ "system/security/keystore/include",
+ "hardware/interfaces/keymaster/4.0/support/include",
]
// libbtif static library for target
@@ -71,6 +73,7 @@
"src/btif_hf_client.cc",
"src/btif_hh.cc",
"src/btif_hd.cc",
+ "src/btif_keystore.cc",
"src/btif_mce.cc",
"src/btif_pan.cc",
"src/btif_profile_queue.cc",
@@ -103,6 +106,12 @@
"libhwbinder",
"libutils",
"libcrypto",
+ "android.hardware.keymaster@4.0",
+ "android.hardware.keymaster@3.0",
+ "libkeymaster4support",
+ "libkeystore_aidl",
+ "libkeystore_binder",
+ "libkeystore_parcelables",
],
whole_static_libs: [
"avrcp-target-service",
@@ -124,7 +133,10 @@
defaults: ["fluoride_defaults"],
test_suites: ["device-tests"],
include_dirs: btifCommonIncludes,
- srcs: ["test/btif_storage_test.cc"],
+ srcs: [
+ "test/btif_storage_test.cc",
+ "test/btif_keystore_test.cc"
+ ],
header_libs: ["libbluetooth_headers"],
shared_libs: [
"libaudioclient",
@@ -169,6 +181,9 @@
"libbluetooth-for-tests",
],
cflags: ["-DBUILDCFG"],
+ sanitize: {
+ integer_overflow: true,
+ },
}
// btif profile queue unit tests for target
diff --git a/btif/include/btif_api.h b/btif/include/btif_api.h
index 519fc9c..cef1aad 100644
--- a/btif/include/btif_api.h
+++ b/btif/include/btif_api.h
@@ -105,6 +105,19 @@
/*******************************************************************************
*
+ * Function is_single_user_mode_
+ *
+ * Description Checks if BT was enabled in single user mode. In this
+ * mode, use of keystore for key attestation of LTK is limitee
+ * to this mode defined by UserManager.
+ *
+ * Returns bool
+ *
+ ******************************************************************************/
+bool is_single_user_mode(void);
+
+/*******************************************************************************
+ *
* Function btif_get_adapter_properties
*
* Description Fetches all local adapter properties
diff --git a/btif/include/btif_keystore.h b/btif/include/btif_keystore.h
new file mode 100644
index 0000000..cc06a98
--- /dev/null
+++ b/btif/include/btif_keystore.h
@@ -0,0 +1,78 @@
+/******************************************************************************
+ *
+ * Copyright 2019 Google, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <base/logging.h>
+#include <keystore/keystore_client_impl.h>
+#include <mutex>
+
+#include "osi/include/alarm.h"
+#include "osi/include/allocator.h"
+#include "osi/include/compat.h"
+#include "osi/include/config.h"
+#include "osi/include/log.h"
+#include "osi/include/osi.h"
+#include "osi/include/properties.h"
+
+namespace bluetooth {
+/**
+ * Client wrapper to access AndroidKeystore.
+ *
+ * <p>Use to encrypt/decrypt data and store to disk.
+ */
+class BtifKeystore {
+ public:
+ /**
+ * @param keystore_client injected pre-created client object for keystore
+ */
+ BtifKeystore(keystore::KeystoreClient* keystore_client);
+
+ /**
+ * Encrypts given data
+ *
+ * <p>Returns a string representation of the encrypted data
+ *
+ * @param data to be encrypted
+ * @param flags for keystore
+ */
+ std::string Encrypt(const std::string& data, int32_t flags);
+
+ /**
+ * Returns a decrypted string representation of the encrypted data or empty
+ * string on error.
+ *
+ * @param input encrypted data
+ */
+ std::string Decrypt(const std::string& input_filename);
+
+ /**
+ * Check for existence of keystore key.
+ *
+ * This key can be cleared if a user manually wipes bluetooth storage data
+ * b/133214365
+ */
+ bool DoesKeyExist();
+
+ private:
+ std::unique_ptr<keystore::KeystoreClient> keystore_client_;
+ std::mutex api_mutex_;
+ keystore::KeyStoreNativeReturnCode GenerateKey(const std::string& name,
+ int32_t flags,
+ bool auth_bound);
+};
+
+} // namespace bluetooth
diff --git a/btif/src/bluetooth.cc b/btif/src/bluetooth.cc
index 1faca2d..9dd4908 100644
--- a/btif/src/bluetooth.cc
+++ b/btif/src/bluetooth.cc
@@ -81,6 +81,7 @@
bt_callbacks_t* bt_hal_cbacks = NULL;
bool restricted_mode = false;
+bool single_user_mode = false;
/*******************************************************************************
* Externs
@@ -132,8 +133,10 @@
*
****************************************************************************/
-static int init(bt_callbacks_t* callbacks) {
- LOG_INFO(LOG_TAG, "%s", __func__);
+static int init(bt_callbacks_t* callbacks, bool start_restricted,
+ bool is_single_user_mode) {
+ LOG_INFO(LOG_TAG, "%s: start restricted = %d ; single user = %d", __func__,
+ start_restricted, is_single_user_mode);
if (interface_ready()) return BT_STATUS_DONE;
@@ -142,16 +145,14 @@
#endif
bt_hal_cbacks = callbacks;
+ restricted_mode = start_restricted;
+ single_user_mode = is_single_user_mode;
stack_manager_get_interface()->init_stack();
btif_debug_init();
return BT_STATUS_SUCCESS;
}
-static int enable(bool start_restricted) {
- LOG_INFO(LOG_TAG, "%s: start restricted = %d", __func__, start_restricted);
-
- restricted_mode = start_restricted;
-
+static int enable() {
if (!interface_ready()) return BT_STATUS_NOT_READY;
stack_manager_get_interface()->start_up_stack_async();
@@ -168,6 +169,7 @@
static void cleanup(void) { stack_manager_get_interface()->clean_up_stack(); }
bool is_restricted_mode() { return restricted_mode; }
+bool is_single_user_mode() { return single_user_mode; }
static int get_adapter_properties(void) {
/* sanity check */
diff --git a/btif/src/btif_config.cc b/btif/src/btif_config.cc
index c017c0f..ed24d7d 100644
--- a/btif/src/btif_config.cc
+++ b/btif/src/btif_config.cc
@@ -23,19 +23,22 @@
#include <base/logging.h>
#include <ctype.h>
#include <openssl/rand.h>
+#include <openssl/sha.h>
+#include <private/android_filesystem_config.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
-#include <string>
-
#include <mutex>
+#include <sstream>
+#include <string>
#include "bt_types.h"
#include "btcore/include/module.h"
#include "btif_api.h"
#include "btif_common.h"
#include "btif_config_transcode.h"
+#include "btif_keystore.h"
#include "btif_util.h"
#include "common/address_obfuscator.h"
#include "osi/include/alarm.h"
@@ -52,10 +55,18 @@
#define FILE_TIMESTAMP "TimeCreated"
#define FILE_SOURCE "FileSource"
#define TIME_STRING_LENGTH sizeof("YYYY-MM-DD HH:MM:SS")
+#define DISABLED "disabled"
static const char* TIME_STRING_FORMAT = "%Y-%m-%d %H:%M:%S";
+constexpr int kBufferSize = 400 * 10; // initial file is ~400B
+
+static bool use_key_attestation() {
+ return getuid() == AID_BLUETOOTH && is_single_user_mode();
+}
+
#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.
@@ -66,6 +77,8 @@
#else // !defined(OS_GENERIC)
static const char* CONFIG_FILE_PATH = "/data/misc/bluedroid/bt_config.conf";
static const char* CONFIG_BACKUP_PATH = "/data/misc/bluedroid/bt_config.bak";
+static const char* CONFIG_FILE_CHECKSUM_PATH = "/data/misc/bluedroid/bt_config.conf.encrypted-checksum";
+static const char* CONFIG_BACKUP_CHECKSUM_PATH = "/data/misc/bluedroid/bt_config.bak.encrypted-checksum";
static const char* CONFIG_LEGACY_FILE_PATH =
"/data/misc/bluedroid/bt_config.xml";
#endif // defined(OS_GENERIC)
@@ -77,7 +90,12 @@
static void delete_config_files(void);
static void btif_config_remove_unpaired(config_t* config);
static void btif_config_remove_restricted(config_t* config);
-static std::unique_ptr<config_t> btif_config_open(const char* filename);
+static std::unique_ptr<config_t> btif_config_open(const char* filename, const char* checksum_filename);
+
+// Key attestation
+static std::string hash_file(const char* filename);
+static std::string read_checksum_file(const char* filename);
+static void write_checksum_file(const char* filename, const std::string& hash);
static enum ConfigSource {
NOT_LOADED,
@@ -158,21 +176,26 @@
static std::unique_ptr<config_t> config;
static alarm_t* config_timer;
+static BtifKeystore btif_keystore(new keystore::KeystoreClientImpl);
+
// Module lifecycle functions
static future_t* init(void) {
std::unique_lock<std::recursive_mutex> lock(config_lock);
- if (is_factory_reset()) delete_config_files();
+ if (is_factory_reset() ||
+ (use_key_attestation() && !btif_keystore.DoesKeyExist()))
+ delete_config_files();
std::string file_source;
- config = btif_config_open(CONFIG_FILE_PATH);
+ config = btif_config_open(CONFIG_FILE_PATH, CONFIG_FILE_CHECKSUM_PATH);
btif_config_source = ORIGINAL;
if (!config) {
LOG_WARN(LOG_TAG, "%s unable to load config file: %s; using backup.",
__func__, CONFIG_FILE_PATH);
- config = btif_config_open(CONFIG_BACKUP_PATH);
+ remove(CONFIG_FILE_CHECKSUM_PATH);
+ config = btif_config_open(CONFIG_BACKUP_PATH, CONFIG_BACKUP_CHECKSUM_PATH);
btif_config_source = BACKUP;
file_source = "Backup";
}
@@ -180,6 +203,7 @@
LOG_WARN(LOG_TAG,
"%s unable to load backup; attempting to transcode legacy file.",
__func__);
+ remove(CONFIG_BACKUP_CHECKSUM_PATH);
config = btif_config_transcode(CONFIG_LEGACY_FILE_PATH);
btif_config_source = LEGACY;
file_source = "Legacy";
@@ -239,7 +263,25 @@
return future_new_immediate(FUTURE_FAIL);
}
-static std::unique_ptr<config_t> btif_config_open(const char* filename) {
+static std::unique_ptr<config_t> btif_config_open(const char* filename, const char* checksum_filename) {
+ // START KEY ATTESTATION
+ // Get hash of current file
+ std::string current_hash = hash_file(filename);
+ // Get stored hash
+ std::string stored_hash = read_checksum_file(checksum_filename);
+ if (stored_hash.empty()) {
+ LOG(ERROR) << __func__ << ": stored_hash=<empty>";
+ if (!current_hash.empty()) {
+ write_checksum_file(checksum_filename, current_hash);
+ stored_hash = read_checksum_file(checksum_filename);
+ }
+ }
+ // Compare hashes
+ if (current_hash != stored_hash) {
+ return nullptr;
+ }
+ // END KEY ATTESTATION
+
std::unique_ptr<config_t> config = config_new(filename);
if (!config) return nullptr;
@@ -413,6 +455,12 @@
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) {
@@ -465,6 +513,13 @@
bool ret = config_save(*config, CONFIG_FILE_PATH);
btif_config_source = RESET;
+
+ // Save encrypted hash
+ std::string current_hash = hash_file(CONFIG_FILE_PATH);
+ if (!current_hash.empty()) {
+ write_checksum_file(CONFIG_FILE_CHECKSUM_PATH, current_hash);
+ }
+
return ret;
}
@@ -482,9 +537,15 @@
std::unique_lock<std::recursive_mutex> lock(config_lock);
rename(CONFIG_FILE_PATH, CONFIG_BACKUP_PATH);
+ rename(CONFIG_FILE_CHECKSUM_PATH, CONFIG_BACKUP_CHECKSUM_PATH);
std::unique_ptr<config_t> config_paired = config_new_clone(*config);
btif_config_remove_unpaired(config_paired.get());
config_save(*config_paired, CONFIG_FILE_PATH);
+ // Save hash
+ std::string current_hash = hash_file(CONFIG_FILE_PATH);
+ if (!current_hash.empty()) {
+ write_checksum_file(CONFIG_FILE_CHECKSUM_PATH, current_hash);
+ }
}
static void btif_config_remove_unpaired(config_t* conf) {
@@ -576,5 +637,65 @@
static void delete_config_files(void) {
remove(CONFIG_FILE_PATH);
remove(CONFIG_BACKUP_PATH);
+ remove(CONFIG_FILE_CHECKSUM_PATH);
+ remove(CONFIG_BACKUP_CHECKSUM_PATH);
osi_property_set("persist.bluetooth.factoryreset", "false");
}
+
+static std::string hash_file(const char* filename) {
+ if (!use_key_attestation()) {
+ LOG(INFO) << __func__ << ": Disabled for multi-user";
+ return DISABLED;
+ }
+ FILE* fp = fopen(filename, "rb");
+ if (!fp) {
+ LOG(ERROR) << __func__ << ": unable to open config file: '" << filename
+ << "': " << strerror(errno);
+ return "";
+ }
+ uint8_t hash[SHA256_DIGEST_LENGTH];
+ SHA256_CTX sha256;
+ SHA256_Init(&sha256);
+ 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);
+ }
+ SHA256_Final(hash, &sha256);
+ std::stringstream ss;
+ for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
+ ss << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
+ }
+ fclose(fp);
+ return ss.str();
+}
+
+static std::string read_checksum_file(const char* checksum_filename) {
+ if (!use_key_attestation()) {
+ LOG(INFO) << __func__ << ": Disabled for multi-user";
+ return DISABLED;
+ }
+ std::string encrypted_hash = checksum_read(checksum_filename);
+ if (encrypted_hash.empty()) {
+ LOG(INFO) << __func__ << ": read empty hash.";
+ return "";
+ }
+ return btif_keystore.Decrypt(encrypted_hash);
+}
+
+static void write_checksum_file(const char* checksum_filename,
+ const std::string& hash) {
+ if (!use_key_attestation()) {
+ LOG(INFO) << __func__
+ << ": Disabled for multi-user, since config changed removing "
+ "checksums.";
+ remove(CONFIG_FILE_CHECKSUM_PATH);
+ remove(CONFIG_BACKUP_CHECKSUM_PATH);
+ return;
+ }
+ std::string encrypted_checksum = btif_keystore.Encrypt(hash, 0);
+ CHECK(!encrypted_checksum.empty())
+ << __func__ << ": Failed encrypting checksum";
+ CHECK(checksum_save(encrypted_checksum, checksum_filename))
+ << __func__ << ": Failed to save checksum!";
+}
diff --git a/btif/src/btif_dm.cc b/btif/src/btif_dm.cc
index 683834a..1f5cb82 100644
--- a/btif/src/btif_dm.cc
+++ b/btif/src/btif_dm.cc
@@ -260,6 +260,11 @@
return !memcmp(zero, data, sizeof(zero));
}
+static bool is_bonding_or_sdp() {
+ return pairing_cb.state == BT_BOND_STATE_BONDING ||
+ (pairing_cb.state == BT_BOND_STATE_BONDED && pairing_cb.sdp_attempts);
+}
+
static void btif_dm_data_copy(uint16_t event, char* dst, char* src) {
tBTA_DM_SEC* dst_dm_sec = (tBTA_DM_SEC*)dst;
tBTA_DM_SEC* src_dm_sec = (tBTA_DM_SEC*)src;
@@ -486,8 +491,6 @@
bt_bond_state_t state) {
btif_stats_add_bond_event(bd_addr, BTIF_DM_FUNC_BOND_STATE_CHANGED, state);
- // Send bonding state only once - based on outgoing/incoming we may receive
- // duplicates
if ((pairing_cb.state == state) && (state == BT_BOND_STATE_BONDING)) {
// Cross key pairing so send callback for static address
if (!pairing_cb.static_bdaddr.IsEmpty()) {
@@ -505,14 +508,18 @@
auto tmp = bd_addr;
HAL_CBACK(bt_hal_cbacks, bond_state_changed_cb, status, &tmp, state);
- if (state == BT_BOND_STATE_BONDING) {
+ int dev_type;
+ if (!btif_get_device_type(bd_addr, &dev_type)) {
+ dev_type = BT_DEVICE_TYPE_BREDR;
+ }
+
+ if (state == BT_BOND_STATE_BONDING ||
+ (state == BT_BOND_STATE_BONDED && pairing_cb.sdp_attempts > 0)) {
+ // Save state for the device is bonding or SDP.
pairing_cb.state = state;
pairing_cb.bd_addr = bd_addr;
} else {
- if (!pairing_cb.sdp_attempts)
- memset(&pairing_cb, 0, sizeof(pairing_cb));
- else
- BTIF_TRACE_DEBUG("%s: BR-EDR service discovery active", __func__);
+ pairing_cb = {};
}
}
@@ -1138,6 +1145,17 @@
/* Trigger SDP on the device */
pairing_cb.sdp_attempts = 1;
+
+ if (is_crosskey) {
+ // If bonding occurred due to cross-key pairing, send bonding callback
+ // for static address now
+ LOG_INFO(LOG_TAG,
+ "%s: send bonding state update for static address %s",
+ __func__, bd_addr.ToString().c_str());
+ bond_state_changed(BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_BONDING);
+ }
+ bond_state_changed(BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_BONDED);
+
btif_dm_get_remote_services(bd_addr);
}
}
@@ -1395,9 +1413,9 @@
BTIF_TRACE_DEBUG("%s:(result=0x%x, services 0x%x)", __func__,
p_data->disc_res.result, p_data->disc_res.services);
- if ((p_data->disc_res.result != BTA_SUCCESS) &&
- (pairing_cb.state == BT_BOND_STATE_BONDING) &&
- (pairing_cb.sdp_attempts < BTIF_DM_MAX_SDP_ATTEMPTS_AFTER_PAIRING)) {
+ if (p_data->disc_res.result != BTA_SUCCESS &&
+ pairing_cb.state == BT_BOND_STATE_BONDED &&
+ pairing_cb.sdp_attempts < BTIF_DM_MAX_SDP_ATTEMPTS_AFTER_PAIRING) {
if (pairing_cb.sdp_attempts) {
BTIF_TRACE_WARNING("%s: SDP failed after bonding re-attempting",
__func__);
@@ -1424,21 +1442,36 @@
/* onUuidChanged requires getBondedDevices to be populated.
** bond_state_changed needs to be sent prior to remote_device_property
*/
- if ((pairing_cb.state == BT_BOND_STATE_BONDING) &&
+ if (pairing_cb.state == BT_BOND_STATE_BONDED && pairing_cb.sdp_attempts &&
(p_data->disc_res.bd_addr == pairing_cb.bd_addr ||
- p_data->disc_res.bd_addr == pairing_cb.static_bdaddr) &&
- pairing_cb.sdp_attempts > 0) {
- BTIF_TRACE_DEBUG(
- "%s Remote Service SDP done. Call bond_state_changed_cb BONDED",
- __func__);
+ p_data->disc_res.bd_addr == pairing_cb.static_bdaddr)) {
+ LOG_INFO(LOG_TAG, "%s: SDP search done for %s", __func__,
+ bd_addr.ToString().c_str());
pairing_cb.sdp_attempts = 0;
- // If bonding occured due to cross-key pairing, send bonding callback
- // for static address now
- if (p_data->disc_res.bd_addr == pairing_cb.static_bdaddr)
- bond_state_changed(BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_BONDING);
+ // Both SDP and bonding are done, clear pairing control block in case
+ // it is not already cleared
+ pairing_cb = {};
- bond_state_changed(BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_BONDED);
+ // Send one empty UUID to Java to unblock pairing intent when SDP failed
+ // or no UUID is discovered
+ if (p_data->disc_res.result != BTA_SUCCESS ||
+ p_data->disc_res.num_uuids == 0) {
+ LOG_INFO(LOG_TAG,
+ "%s: SDP failed, send empty UUID to unblock bonding %s",
+ __func__, bd_addr.ToString().c_str());
+ bt_property_t prop;
+ Uuid uuid = {};
+
+ prop.type = BT_PROPERTY_UUIDS;
+ prop.val = &uuid;
+ prop.len = Uuid::kNumBytes128;
+
+ /* Send the event to the BTIF */
+ HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb,
+ BT_STATUS_SUCCESS, &bd_addr, 1, &prop);
+ break;
+ }
}
if (p_data->disc_res.num_uuids != 0) {
@@ -1634,7 +1667,7 @@
break;
case BTA_DM_BOND_CANCEL_CMPL_EVT:
- if (pairing_cb.state == BT_BOND_STATE_BONDING) {
+ if (is_bonding_or_sdp()) {
bd_addr = pairing_cb.bd_addr;
btm_set_bond_type_dev(pairing_cb.bd_addr, BOND_TYPE_UNKNOWN);
bond_state_changed((bt_status_t)p_data->bond_cancel_cmpl.result,
@@ -2274,7 +2307,7 @@
** 1. Restore scan modes
** 2. special handling for HID devices
*/
- if (pairing_cb.state == BT_BOND_STATE_BONDING) {
+ if (is_bonding_or_sdp()) {
if (pairing_cb.is_ssp) {
if (pairing_cb.is_le_only) {
BTA_DmBleSecurityGrant(*bd_addr, BTA_DM_SEC_PAIR_NOT_SPT);
@@ -2486,7 +2519,7 @@
/*******************************************************************************
*
- * Function btif_dm_get_remote_services_transport
+ * Function btif_dm_get_remote_services_by_transport
*
* Description Start SDP to get remote services by transport
*
@@ -2885,6 +2918,10 @@
break;
}
}
+ if (state == BT_BOND_STATE_BONDED && bd_addr != pairing_cb.static_bdaddr) {
+ // Report RPA bonding state to Java in crosskey paring
+ bond_state_changed(status, bd_addr, BT_BOND_STATE_BONDING);
+ }
bond_state_changed(status, bd_addr, state);
}
@@ -3191,7 +3228,7 @@
void btif_dm_on_disable() {
/* cancel any pending pairing requests */
- if (pairing_cb.state == BT_BOND_STATE_BONDING) {
+ if (is_bonding_or_sdp()) {
BTIF_TRACE_DEBUG("%s: Cancel pending pairing request", __func__);
btif_dm_cancel_bond(&pairing_cb.bd_addr);
}
diff --git a/btif/src/btif_hf.cc b/btif/src/btif_hf.cc
index e0e9515..04ad011 100644
--- a/btif/src/btif_hf.cc
+++ b/btif/src/btif_hf.cc
@@ -412,7 +412,7 @@
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;
diff --git a/btif/src/btif_hf_client.cc b/btif/src/btif_hf_client.cc
index e40975e..c999885 100644
--- a/btif/src/btif_hf_client.cc
+++ b/btif/src/btif_hf_client.cc
@@ -949,7 +949,7 @@
(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:
diff --git a/btif/src/btif_keystore.cc b/btif/src/btif_keystore.cc
new file mode 100644
index 0000000..0af03e1
--- /dev/null
+++ b/btif/src/btif_keystore.cc
@@ -0,0 +1,105 @@
+/******************************************************************************
+ *
+ * Copyright 2019 Google, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "btif_keystore.h"
+
+#include <base/files/file_util.h>
+#include <base/logging.h>
+#include <base/strings/string_number_conversions.h>
+#include <base/strings/string_split.h>
+#include <base/strings/string_util.h>
+#include <base/strings/utf_string_conversions.h>
+#include <sys/stat.h>
+
+using namespace keystore;
+using namespace bluetooth;
+
+constexpr char kKeyStore[] = "AndroidKeystore";
+
+namespace bluetooth {
+
+BtifKeystore::BtifKeystore(keystore::KeystoreClient* keystore_client)
+ : keystore_client_(keystore_client) {}
+
+std::string BtifKeystore::Encrypt(const std::string& data, int32_t flags) {
+ std::lock_guard<std::mutex> lock(api_mutex_);
+ std::string output;
+ if (data.empty()) {
+ LOG(ERROR) << __func__ << ": empty data";
+ return output;
+ }
+ if (!keystore_client_->doesKeyExist(kKeyStore)) {
+ auto gen_result = GenerateKey(kKeyStore, 0, false);
+ if (!gen_result.isOk()) {
+ LOG(FATAL) << "EncryptWithAuthentication Failed: generateKey response="
+ << gen_result;
+ return output;
+ }
+ }
+ if (!keystore_client_->encryptWithAuthentication(kKeyStore, data, flags,
+ &output)) {
+ LOG(FATAL) << "EncryptWithAuthentication failed.";
+ return output;
+ }
+ return output;
+}
+
+std::string BtifKeystore::Decrypt(const std::string& input) {
+ std::lock_guard<std::mutex> lock(api_mutex_);
+ if (input.empty()) {
+ LOG(ERROR) << __func__ << ": empty input data";
+ return "";
+ }
+ std::string output;
+ if (!keystore_client_->decryptWithAuthentication(kKeyStore, input, &output)) {
+ LOG(FATAL) << "DecryptWithAuthentication failed.\n";
+ }
+ return output;
+}
+
+// Note: auth_bound keys created with this tool will not be usable.
+KeyStoreNativeReturnCode BtifKeystore::GenerateKey(const std::string& name,
+ int32_t flags,
+ bool auth_bound) {
+ AuthorizationSetBuilder params;
+ params.RsaSigningKey(2048, 65537)
+ .Digest(Digest::SHA_2_224)
+ .Digest(Digest::SHA_2_256)
+ .Digest(Digest::SHA_2_384)
+ .Digest(Digest::SHA_2_512)
+ .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
+ .Padding(PaddingMode::RSA_PSS);
+ if (auth_bound) {
+ // Gatekeeper normally generates the secure user id.
+ // Using zero allows the key to be created, but it will not be usuable.
+ params.Authorization(TAG_USER_SECURE_ID, 0);
+ } else {
+ params.Authorization(TAG_NO_AUTH_REQUIRED);
+ }
+ AuthorizationSet hardware_enforced_characteristics;
+ AuthorizationSet software_enforced_characteristics;
+ return keystore_client_->generateKey(name, params, flags,
+ &hardware_enforced_characteristics,
+ &software_enforced_characteristics);
+}
+
+bool BtifKeystore::DoesKeyExist() {
+ return keystore_client_->doesKeyExist(kKeyStore);
+}
+
+} // namespace bluetooth
diff --git a/btif/src/btif_storage.cc b/btif/src/btif_storage.cc
index b6ffcda..2427493 100644
--- a/btif/src/btif_storage.cc
+++ b/btif/src/btif_storage.cc
@@ -889,9 +889,8 @@
tBTA_LE_KEY_VALUE key;
memset(&key, 0, sizeof(key));
- if (btif_storage_get_ble_bonding_key(
- &bd_addr, BTIF_DM_LE_KEY_PENC, (uint8_t*)&key,
- sizeof(tBTM_LE_PENC_KEYS)) == BT_STATUS_SUCCESS) {
+ if (btif_storage_get_ble_bonding_key(&bd_addr, BTIF_DM_LE_KEY_PENC, (uint8_t*)&key, sizeof(tBTM_LE_PENC_KEYS)) ==
+ BT_STATUS_SUCCESS) {
if (is_sample_ltk(key.penc_key.ltk)) {
bad_ltk.push_back(bd_addr);
}
@@ -900,8 +899,7 @@
for (RawAddress address : bad_ltk) {
android_errorWriteLog(0x534e4554, "128437297");
- LOG(ERROR) << __func__
- << ": removing bond to device using test TLK: " << address;
+ LOG(ERROR) << __func__ << ": removing bond to device using test TLK: " << address;
btif_storage_remove_bonded_device(&address);
}
diff --git a/btif/test/btif_keystore_test.cc b/btif/test/btif_keystore_test.cc
new file mode 100644
index 0000000..4cabbad
--- /dev/null
+++ b/btif/test/btif_keystore_test.cc
@@ -0,0 +1,64 @@
+/******************************************************************************
+ *
+ * Copyright 2019 Google, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <base/logging.h>
+#include <binder/ProcessState.h>
+#include <gtest/gtest.h>
+#include <fstream>
+
+#include "btif/include/btif_keystore.h"
+
+using namespace bluetooth;
+
+class BtifKeystoreTest : public ::testing::Test {
+ protected:
+ std::unique_ptr<BtifKeystore> btif_keystore_;
+ void SetUp() override {
+ android::ProcessState::self()->startThreadPool();
+ btif_keystore_ =
+ std::make_unique<BtifKeystore>(static_cast<keystore::KeystoreClient*>(
+ new keystore::KeystoreClientImpl));
+ };
+ void TearDown() override { btif_keystore_ = nullptr; };
+};
+
+TEST_F(BtifKeystoreTest, test_encrypt_decrypt) {
+ std::string hash = "test";
+
+ std::string encrypted_hash = btif_keystore_->Encrypt(hash, 0);
+ std::string decrypted_hash = btif_keystore_->Decrypt(encrypted_hash);
+
+ EXPECT_FALSE(encrypted_hash.empty());
+ EXPECT_EQ(hash, decrypted_hash);
+}
+
+TEST_F(BtifKeystoreTest, test_encrypt_empty_hash) {
+ std::string hash = "";
+
+ std::string encrypted_hash = btif_keystore_->Encrypt(hash, 0);
+
+ EXPECT_TRUE(encrypted_hash.empty());
+}
+
+TEST_F(BtifKeystoreTest, test_decrypt_empty_hash) {
+ std::string hash = "";
+
+ std::string decrypted_hash = btif_keystore_->Decrypt(hash);
+
+ EXPECT_TRUE(decrypted_hash.empty());
+}
diff --git a/common/scoped_scs_exit.h b/common/scoped_scs_exit.h
deleted file mode 100644
index ad4a8d6..0000000
--- a/common/scoped_scs_exit.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-// Prevent x18 (shadow call stack address) from being clobbered by functions
-// called by a function that declares a variable of this type by temporarily
-// storing the value on the stack. This is used only when calling out to certain
-// vendor libraries.
-struct ScopedSCSExit {
-#ifdef __aarch64__
- void* scs;
-
- __attribute__((always_inline, no_sanitize("shadow-call-stack"))) ScopedSCSExit() {
- __asm__ __volatile__("str x18, [%0]" ::"r"(&scs));
- }
-
- __attribute__((always_inline, no_sanitize("shadow-call-stack"))) ~ScopedSCSExit() {
- __asm__ __volatile__("ldr x18, [%0]; str xzr, [%0]" ::"r"(&scs));
- }
-#else
- // Silence unused variable warnings in non-SCS builds.
- __attribute__((no_sanitize("shadow-call-stack"))) ScopedSCSExit() {}
- __attribute__((no_sanitize("shadow-call-stack"))) ~ScopedSCSExit() {}
-#endif
-};
diff --git a/hci/include/btsnoop.h b/hci/include/btsnoop.h
index e897a96..476c62d 100644
--- a/hci/include/btsnoop.h
+++ b/hci/include/btsnoop.h
@@ -29,6 +29,28 @@
// 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);
diff --git a/hci/src/btsnoop.cc b/hci/src/btsnoop.cc
index 6938725..ad06ac7 100644
--- a/hci/src/btsnoop.cc
+++ b/hci/src/btsnoop.cc
@@ -21,6 +21,7 @@
#include <mutex>
#include <arpa/inet.h>
+#include <base/logging.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
@@ -34,14 +35,21 @@
#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
@@ -50,7 +58,14 @@
// 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 @@
// 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* 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 @@
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 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 @@
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 @@
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 @@
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);
diff --git a/hci/src/packet_fragmenter.cc b/hci/src/packet_fragmenter.cc
index c1c61df..f688982 100644
--- a/hci/src/packet_fragmenter.cc
+++ b/hci/src/packet_fragmenter.cc
@@ -123,12 +123,10 @@
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 @@
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,
diff --git a/include/hardware/bluetooth.h b/include/hardware/bluetooth.h
index f97e116..063abf9 100644
--- a/include/hardware/bluetooth.h
+++ b/include/hardware/bluetooth.h
@@ -466,11 +466,16 @@
/**
* Opens the interface and provides the callback routines
* to the implemenation of this interface.
+ * The |start_restricted| flag inits the adapter in restricted mode. In
+ * restricted mode, bonds that are created are marked as restricted in the
+ * config file. These devices are deleted upon leaving restricted mode.
+ * The |is_single_user_mode| flag inits the adapter in NIAP mode.
*/
- int (*init)(bt_callbacks_t* callbacks);
+ int (*init)(bt_callbacks_t* callbacks, bool guest_mode,
+ bool is_single_user_mode);
/** Enable Bluetooth. */
- int (*enable)(bool guest_mode);
+ int (*enable)();
/** Disable Bluetooth. */
int (*disable)(void);
diff --git a/main/Android.bp b/main/Android.bp
index 3efd993..cb300a4 100644
--- a/main/Android.bp
+++ b/main/Android.bp
@@ -34,6 +34,8 @@
"system/bt/embdrv/sbc/encoder/include",
"system/bt/embdrv/sbc/decoder/include",
"system/bt/utils/include",
+ "system/security/keystore/include",
+ "hardware/interfaces/keymaster/4.0/support/include",
],
logtags: ["../EventLogTags.logtags"],
shared_libs: [
@@ -95,6 +97,9 @@
cflags: [
"-DBUILDCFG",
],
+ sanitize: {
+ scs: true,
+ },
}
cc_library_static {
diff --git a/osi/include/config.h b/osi/include/config.h
index 55adecb..47c3a3e 100644
--- a/osi/include/config.h
+++ b/osi/include/config.h
@@ -49,6 +49,9 @@
// file on the filesystem.
std::unique_ptr<config_t> config_new(const char* filename);
+// Read the checksum from the |filename|
+std::string checksum_read(const char* filename);
+
// Clones |src|, including all of it's sections, keys, and values.
// Returns a new config which is a copy and separated from the original;
// changes to the new config are not reflected in any way in the original.
@@ -133,3 +136,8 @@
// |config_save|, all comments and special formatting in the original file will
// be lost. Neither |config| nor |filename| may be NULL.
bool config_save(const config_t& config, const std::string& filename);
+
+// Saves the encrypted |checksum| of config file to a given |filename| Note
+// that this could be a destructive operation: if |filename| already exists,
+// it will be overwritten.
+bool checksum_save(const std::string& checksum, const std::string& filename);
diff --git a/osi/src/alarm.cc b/osi/src/alarm.cc
index 30e4ed8..bc1eee5 100644
--- a/osi/src/alarm.cc
+++ b/osi/src/alarm.cc
@@ -246,7 +246,7 @@
CHECK(alarms != NULL);
if (!alarm) return;
- std::shared_ptr<std::recursive_mutex> local_mutex_ref = alarm->callback_mutex;
+ std::shared_ptr<std::recursive_mutex> local_mutex_ref;
{
std::lock_guard<std::mutex> lock(alarms_mutex);
local_mutex_ref = alarm->callback_mutex;
diff --git a/osi/src/config.cc b/osi/src/config.cc
index e937959..de7e6e6 100644
--- a/osi/src/config.cc
+++ b/osi/src/config.cc
@@ -18,7 +18,7 @@
#include "osi/include/config.h"
-#include <base/files/file_path.h>
+#include <base/files/file_util.h>
#include <base/logging.h>
#include <ctype.h>
#include <errno.h>
@@ -84,6 +84,19 @@
return config;
}
+std::string checksum_read(const char* filename) {
+ base::FilePath path(filename);
+ if (!base::PathExists(path)) {
+ LOG(ERROR) << __func__ << ": unable to locate file '" << filename << "'";
+ return "";
+ }
+ std::string encrypted_hash;
+ if (!base::ReadFileToString(path, &encrypted_hash)) {
+ LOG(ERROR) << __func__ << ": unable to read file '" << filename << "'";
+ }
+ return encrypted_hash;
+}
+
std::unique_ptr<config_t> config_new_clone(const config_t& src) {
std::unique_ptr<config_t> ret = config_new_empty();
@@ -332,6 +345,107 @@
return false;
}
+bool checksum_save(const std::string& checksum, const std::string& filename) {
+ CHECK(!checksum.empty()) << __func__ << ": checksum cannot be empty";
+ CHECK(!filename.empty()) << __func__ << ": filename cannot be empty";
+
+ // Steps to ensure content of config checksum file gets to disk:
+ //
+ // 1) Open and write to temp file (e.g.
+ // bt_config.conf.encrypted-checksum.new). 2) Sync the temp file to disk with
+ // fsync(). 3) Rename temp file to actual config checksum file (e.g.
+ // bt_config.conf.encrypted-checksum).
+ // This ensures atomic update.
+ // 4) Sync directory that has the conf file with fsync().
+ // This ensures directory entries are up-to-date.
+ FILE* fp = nullptr;
+ int dir_fd = -1;
+
+ // Build temp config checksum file based on config checksum file (e.g.
+ // bt_config.conf.encrypted-checksum.new).
+ const std::string temp_filename = filename + ".new";
+ base::FilePath path(temp_filename);
+
+ // Extract directory from file path (e.g. /data/misc/bluedroid).
+ const std::string directoryname = base::FilePath(filename).DirName().value();
+ if (directoryname.empty()) {
+ LOG(ERROR) << __func__ << ": error extracting directory from '" << filename
+ << "': " << strerror(errno);
+ goto error2;
+ }
+
+ dir_fd = open(directoryname.c_str(), O_RDONLY);
+ if (dir_fd < 0) {
+ LOG(ERROR) << __func__ << ": unable to open dir '" << directoryname
+ << "': " << strerror(errno);
+ goto error2;
+ }
+
+ if (base::WriteFile(path, checksum.data(), checksum.size()) !=
+ (int)checksum.size()) {
+ LOG(ERROR) << __func__ << ": unable to write file '" << filename.c_str();
+ goto error2;
+ }
+
+ fp = fopen(temp_filename.c_str(), "rb");
+ if (!fp) {
+ LOG(ERROR) << __func__ << ": unable to write to file '" << temp_filename
+ << "': " << strerror(errno);
+ goto error2;
+ }
+
+ // Sync written temp file out to disk. fsync() is blocking until data makes it
+ // to disk.
+ if (fsync(fileno(fp)) < 0) {
+ LOG(WARNING) << __func__ << ": unable to fsync file '" << temp_filename
+ << "': " << strerror(errno);
+ }
+
+ if (fclose(fp) == EOF) {
+ LOG(ERROR) << __func__ << ": unable to close file '" << temp_filename
+ << "': " << strerror(errno);
+ goto error2;
+ }
+ fp = nullptr;
+
+ // Change the file's permissions to Read/Write by User and Group
+ if (chmod(temp_filename.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) ==
+ -1) {
+ LOG(ERROR) << __func__ << ": unable to change file permissions '"
+ << filename << "': " << strerror(errno);
+ goto error2;
+ }
+
+ // Rename written temp file to the actual config file.
+ if (rename(temp_filename.c_str(), filename.c_str()) == -1) {
+ LOG(ERROR) << __func__ << ": unable to commit file '" << filename
+ << "': " << strerror(errno);
+ goto error2;
+ }
+
+ // This should ensure the directory is updated as well.
+ if (fsync(dir_fd) < 0) {
+ LOG(WARNING) << __func__ << ": unable to fsync dir '" << directoryname
+ << "': " << strerror(errno);
+ }
+
+ if (close(dir_fd) < 0) {
+ LOG(ERROR) << __func__ << ": unable to close dir '" << directoryname
+ << "': " << strerror(errno);
+ goto error2;
+ }
+
+ return true;
+
+error2:
+ // This indicates there is a write issue. Unlink as partial data is not
+ // acceptable.
+ unlink(temp_filename.c_str());
+ if (fp) fclose(fp);
+ if (dir_fd != -1) close(dir_fd);
+ return false;
+}
+
static char* trim(char* str) {
while (isspace(*str)) ++str;
diff --git a/osi/test/config_test.cc b/osi/test/config_test.cc
index 7c689c9..32858fd 100644
--- a/osi/test/config_test.cc
+++ b/osi/test/config_test.cc
@@ -1,3 +1,4 @@
+#include <base/files/file_util.h>
#include <gtest/gtest.h>
#include "AllocationTestHarness.h"
@@ -173,3 +174,24 @@
std::unique_ptr<config_t> config = config_new(CONFIG_FILE);
EXPECT_TRUE(config_save(*config, CONFIG_FILE));
}
+
+TEST_F(ConfigTest, checksum_read) {
+ std::string filename = "/data/misc/bluedroid/test.checksum";
+ std::string checksum = "0x1234";
+ base::FilePath file_path(filename);
+
+ EXPECT_EQ(base::WriteFile(file_path, checksum.data(), checksum.size()),
+ (int)checksum.size());
+
+ EXPECT_EQ(checksum_read(filename.c_str()), checksum.c_str());
+}
+
+TEST_F(ConfigTest, checksum_save) {
+ std::string filename = "/data/misc/bluedroid/test.checksum";
+ std::string checksum = "0x1234";
+ base::FilePath file_path(filename);
+
+ EXPECT_TRUE(checksum_save(checksum, filename));
+
+ EXPECT_TRUE(base::PathExists(file_path));
+}
diff --git a/packet/avrcp/general_reject_packet.cc b/packet/avrcp/general_reject_packet.cc
index cde0031..db3d31a 100644
--- a/packet/avrcp/general_reject_packet.cc
+++ b/packet/avrcp/general_reject_packet.cc
@@ -19,11 +19,9 @@
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;
}
diff --git a/packet/avrcp/general_reject_packet.h b/packet/avrcp/general_reject_packet.h
index 4058fd4..b3fb2fe 100644
--- a/packet/avrcp/general_reject_packet.h
+++ b/packet/avrcp/general_reject_packet.h
@@ -25,8 +25,7 @@
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 @@
protected:
Status reason_;
- GeneralRejectBuilder(BrowsePdu pdu, Status reason)
- : BrowsePacketBuilder(pdu), reason_(reason){};
+ GeneralRejectBuilder(Status reason) : BrowsePacketBuilder(BrowsePdu::GENERAL_REJECT), reason_(reason){};
};
} // namespace avrcp
diff --git a/packet/avrcp/register_notification_packet.cc b/packet/avrcp/register_notification_packet.cc
index adb5e59..6bbd16a 100644
--- a/packet/avrcp/register_notification_packet.cc
+++ b/packet/avrcp/register_notification_packet.cc
@@ -39,8 +39,9 @@
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:
diff --git a/packet/tests/avrcp/avrcp_test_packets.h b/packet/tests/avrcp/avrcp_test_packets.h
index 13994d0..14e30e7 100644
--- a/packet/tests/avrcp/avrcp_test_packets.h
+++ b/packet/tests/avrcp/avrcp_test_packets.h
@@ -106,8 +106,8 @@
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 @@
// 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_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
diff --git a/packet/tests/avrcp/general_reject_packet_test.cc b/packet/tests/avrcp/general_reject_packet_test.cc
index e27d0b7..4d73dba 100644
--- a/packet/tests/avrcp/general_reject_packet_test.cc
+++ b/packet/tests/avrcp/general_reject_packet_test.cc
@@ -26,8 +26,7 @@
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());
diff --git a/profile/avrcp/device.cc b/profile/avrcp/device.cc
index cf94cfc..4ca624b 100644
--- a/profile/avrcp/device.cc
+++ b/profile/avrcp/device.cc
@@ -80,6 +80,13 @@
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 @@
} 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 @@
// 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 @@
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::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::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 @@
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::MessageReceived(uint8_t label, std::shared_ptr<Packet> pkt) {
+ 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 @@
} 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 @@
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::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 @@
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::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 @@
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::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::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 @@
send_message(label, true, std::move(builder));
return;
}
+
switch (pkt->GetScope()) {
case Scope::NOW_PLAYING: {
media_interface_->GetNowPlayingList(
@@ -1121,6 +1220,13 @@
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(),
diff --git a/profile/avrcp/tests/avrcp_device_test.cc b/profile/avrcp/tests/avrcp_device_test.cc
index 206e7e2..d221e1b 100644
--- a/profile/avrcp/tests/avrcp_device_test.cc
+++ b/profile/avrcp/tests/avrcp_device_test.cc
@@ -1358,6 +1358,126 @@
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
diff --git a/service/adapter.cc b/service/adapter.cc
index 669aeff..4d414dd 100644
--- a/service/adapter.cc
+++ b/service/adapter.cc
@@ -230,7 +230,7 @@
bool IsEnabled() const override { return state_.load() == ADAPTER_STATE_ON; }
- bool Enable(bool start_restricted) override {
+ bool Enable() override {
AdapterState current_state = GetState();
if (current_state != ADAPTER_STATE_OFF) {
LOG(INFO) << "Adapter not disabled - state: "
@@ -243,8 +243,7 @@
state_ = ADAPTER_STATE_TURNING_ON;
NotifyAdapterStateChanged(current_state, state_);
- int status = hal::BluetoothInterface::Get()->GetHALInterface()->enable(
- start_restricted);
+ int status = hal::BluetoothInterface::Get()->GetHALInterface()->enable();
if (status != BT_STATUS_SUCCESS) {
LOG(ERROR) << "Failed to enable Bluetooth - status: "
<< BtStatusText((const bt_status_t)status);
diff --git a/service/adapter.h b/service/adapter.h
index edb8afe..a4e517c 100644
--- a/service/adapter.h
+++ b/service/adapter.h
@@ -119,10 +119,7 @@
// to the controller, otherwise returns false. A successful call to this
// method only means that the enable request has been sent to the Bluetooth
// controller and does not imply that the operation itself succeeded.
- // The |start_restricted| flag enables the adapter in restricted mode. In
- // restricted mode, bonds that are created are marked as restricted in the
- // config file. These devices are deleted upon leaving restricted mode.
- virtual bool Enable(bool start_restricted) = 0;
+ virtual bool Enable() = 0;
// Powers off the Bluetooth radio. Returns true, if the disable request was
// successfully sent to the Bluetooth controller.
diff --git a/service/client/main.cc b/service/client/main.cc
index 43228a4..6458b2d 100644
--- a/service/client/main.cc
+++ b/service/client/main.cc
@@ -389,25 +389,8 @@
}
void HandleEnable(IBluetooth* bt_iface, const vector<string>& args) {
- bool is_restricted_mode = false;
-
- for (const auto& iter : args) {
- const std::string& arg = iter;
- if (arg == "-h") {
- static const char kUsage[] =
- "Usage: start-adv [flags]\n"
- "\n"
- "Flags:\n"
- "\t--restricted|-r\tStart in restricted mode\n";
- cout << kUsage << endl;
- return;
- } else if (arg == "--restricted" || arg == "-r") {
- is_restricted_mode = true;
- }
- }
-
bool status;
- bt_iface->Enable(is_restricted_mode, &status);
+ bt_iface->Enable(&status);
PrintCommandStatus(status);
}
diff --git a/service/common/android/bluetooth/IBluetooth.aidl b/service/common/android/bluetooth/IBluetooth.aidl
index 3986ad7..46c7654 100644
--- a/service/common/android/bluetooth/IBluetooth.aidl
+++ b/service/common/android/bluetooth/IBluetooth.aidl
@@ -32,7 +32,7 @@
interface IBluetooth {
boolean IsEnabled();
int GetState();
- boolean Enable(boolean startRestricted);
+ boolean Enable();
boolean EnableNoAutoConnect();
boolean Disable();
diff --git a/service/daemon.cc b/service/daemon.cc
index a64c2d8..439c2c2 100644
--- a/service/daemon.cc
+++ b/service/daemon.cc
@@ -59,7 +59,7 @@
// ipc::IPCManager::Delegate implementation:
void OnIPCHandlerStarted(ipc::IPCManager::Type /* type */) override {
if (!settings_->EnableOnStart()) return;
- adapter_->Enable(false /* start_restricted */);
+ adapter_->Enable();
}
void OnIPCHandlerStopped(ipc::IPCManager::Type /* type */) override {
diff --git a/service/hal/bluetooth_interface.cc b/service/hal/bluetooth_interface.cc
index a08fb7b..5ca220c 100644
--- a/service/hal/bluetooth_interface.cc
+++ b/service/hal/bluetooth_interface.cc
@@ -254,7 +254,7 @@
// Initialize the Bluetooth interface. Set up the adapter (Bluetooth DM) API
// callbacks.
- status = hal_iface_->init(&bt_callbacks);
+ status = hal_iface_->init(&bt_callbacks, false, false);
if (status != BT_STATUS_SUCCESS) {
LOG(ERROR) << "Failed to initialize Bluetooth stack";
return false;
diff --git a/service/hal/fake_bluetooth_interface.cc b/service/hal/fake_bluetooth_interface.cc
index 7979155..f1d03ad 100644
--- a/service/hal/fake_bluetooth_interface.cc
+++ b/service/hal/fake_bluetooth_interface.cc
@@ -23,7 +23,7 @@
FakeBluetoothInterface::Manager g_hal_manager;
-int FakeHALEnable(bool start_restricted) {
+int FakeHALEnable() {
return g_hal_manager.enable_succeed ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
}
diff --git a/service/ipc/binder/bluetooth_binder_server.cc b/service/ipc/binder/bluetooth_binder_server.cc
index ca36019..097abb7 100644
--- a/service/ipc/binder/bluetooth_binder_server.cc
+++ b/service/ipc/binder/bluetooth_binder_server.cc
@@ -64,10 +64,9 @@
return Status::ok();
}
-Status BluetoothBinderServer::Enable(bool start_restricted,
- bool* _aidl_return) {
+Status BluetoothBinderServer::Enable(bool* _aidl_return) {
VLOG(2) << __func__;
- *_aidl_return = adapter_->Enable(start_restricted);
+ *_aidl_return = adapter_->Enable();
return Status::ok();
}
diff --git a/service/ipc/binder/bluetooth_binder_server.h b/service/ipc/binder/bluetooth_binder_server.h
index bfeb589..7131e8b 100644
--- a/service/ipc/binder/bluetooth_binder_server.h
+++ b/service/ipc/binder/bluetooth_binder_server.h
@@ -71,7 +71,7 @@
// IBluetooth overrides:
Status IsEnabled(bool* _aidl_return) override;
Status GetState(int32_t* _aidl_return) override;
- Status Enable(bool start_restricted, bool* _aidl_return) override;
+ Status Enable(bool* _aidl_return) override;
Status EnableNoAutoConnect(bool* _aidl_return) override;
Status Disable(bool* _aidl_return) override;
diff --git a/service/test/adapter_unittest.cc b/service/test/adapter_unittest.cc
index e6f5d10..b1cedc1 100644
--- a/service/test/adapter_unittest.cc
+++ b/service/test/adapter_unittest.cc
@@ -124,12 +124,12 @@
EXPECT_EQ(bluetooth::ADAPTER_STATE_OFF, adapter_->GetState());
// Enable fails at HAL level
- EXPECT_FALSE(adapter_->Enable(false));
+ EXPECT_FALSE(adapter_->Enable());
EXPECT_EQ(bluetooth::ADAPTER_STATE_OFF, adapter_->GetState());
// Enable success
fake_hal_manager_->enable_succeed = true;
- EXPECT_TRUE(adapter_->Enable(false));
+ EXPECT_TRUE(adapter_->Enable());
// Should have received a state update.
EXPECT_EQ(bluetooth::ADAPTER_STATE_OFF, observer.prev_state());
@@ -137,7 +137,7 @@
// Enable fails because not disabled
EXPECT_EQ(bluetooth::ADAPTER_STATE_TURNING_ON, adapter_->GetState());
- EXPECT_FALSE(adapter_->Enable(false));
+ EXPECT_FALSE(adapter_->Enable());
// Adapter state updates properly
fake_hal_iface_->NotifyAdapterStateChanged(BT_STATE_ON);
@@ -148,7 +148,7 @@
EXPECT_EQ(bluetooth::ADAPTER_STATE_ON, observer.cur_state());
// Enable fails because already enabled
- EXPECT_FALSE(adapter_->Enable(false));
+ EXPECT_FALSE(adapter_->Enable());
}
TEST_F(AdapterTest, Disable) {
diff --git a/service/test/mock_adapter.h b/service/test/mock_adapter.h
index 2c496b1..b652026 100644
--- a/service/test/mock_adapter.h
+++ b/service/test/mock_adapter.h
@@ -32,7 +32,7 @@
MOCK_METHOD1(RemoveObserver, void(Observer*));
MOCK_CONST_METHOD0(GetState, AdapterState());
MOCK_CONST_METHOD0(IsEnabled, bool());
- MOCK_METHOD1(Enable, bool(bool));
+ MOCK_METHOD0(Enable, bool());
MOCK_METHOD0(Disable, bool());
MOCK_CONST_METHOD0(GetName, std::string());
MOCK_METHOD1(SetName, bool(const std::string&));
diff --git a/stack/Android.bp b/stack/Android.bp
index 03f93a5..d90d6b8 100644
--- a/stack/Android.bp
+++ b/stack/Android.bp
@@ -178,7 +178,6 @@
shared_libs: [
"libcutils",
"liblog",
- "libstatslog",
],
required: [
"libldacBT_enc",
@@ -281,6 +280,7 @@
"rfcomm/rfc_ts_frames.cc",
"rfcomm/rfc_utils.cc",
"test/common/mock_btm_layer.cc",
+ "test/common/mock_btsnoop_module.cc",
"test/common/mock_btu_layer.cc",
"test/common/mock_l2cap_layer.cc",
"test/common/stack_test_packet_utils.cc",
diff --git a/stack/a2dp/a2dp_vendor_aptx_encoder.cc b/stack/a2dp/a2dp_vendor_aptx_encoder.cc
index e7d0145..0d605c0 100644
--- a/stack/a2dp/a2dp_vendor_aptx_encoder.cc
+++ b/stack/a2dp/a2dp_vendor_aptx_encoder.cc
@@ -26,7 +26,6 @@
#include "a2dp_vendor.h"
#include "a2dp_vendor_aptx.h"
#include "bt_common.h"
-#include "common/scoped_scs_exit.h"
#include "common/time_util.h"
#include "osi/include/log.h"
#include "osi/include/osi.h"
@@ -55,25 +54,6 @@
static tAPTX_ENCODER_ENCODE_STEREO aptx_encoder_encode_stereo_func;
static tAPTX_ENCODER_SIZEOF_PARAMS aptx_encoder_sizeof_params_func;
-__attribute__((no_sanitize("shadow-call-stack")))
-static int aptx_encoder_init(void* state, short endian) {
- ScopedSCSExit x;
- return aptx_encoder_init_func(state, endian);
-}
-
-__attribute__((no_sanitize("shadow-call-stack")))
-static int aptx_encoder_encode_stereo(void* state, void* pcmL, void* pcmR,
- void* buffer) {
- ScopedSCSExit x;
- return aptx_encoder_encode_stereo_func(state, pcmL, pcmR, buffer);
-}
-
-__attribute__((no_sanitize("shadow-call-stack")))
-static int aptx_encoder_sizeof_params() {
- ScopedSCSExit x;
- return aptx_encoder_sizeof_params_func();
-}
-
// offset
#if (BTA_AV_CO_CP_SCMS_T == TRUE)
#define A2DP_APTX_OFFSET (AVDT_MEDIA_OFFSET + 1)
@@ -212,9 +192,9 @@
#endif
a2dp_aptx_encoder_cb.aptx_encoder_state =
- osi_malloc(aptx_encoder_sizeof_params());
+ osi_malloc(aptx_encoder_sizeof_params_func());
if (a2dp_aptx_encoder_cb.aptx_encoder_state != NULL) {
- aptx_encoder_init(a2dp_aptx_encoder_cb.aptx_encoder_state, 0);
+ aptx_encoder_init_func(a2dp_aptx_encoder_cb.aptx_encoder_state, 0);
} else {
LOG_ERROR(LOG_TAG, "%s: Cannot allocate aptX encoder state", __func__);
// TODO: Return an error?
@@ -486,8 +466,8 @@
pcmR[i] = (uint16_t) * (data16_in + ((2 * j) + 1));
}
- aptx_encoder_encode_stereo(a2dp_aptx_encoder_cb.aptx_encoder_state, &pcmL,
- &pcmR, &encoded_sample);
+ aptx_encoder_encode_stereo_func(a2dp_aptx_encoder_cb.aptx_encoder_state,
+ &pcmL, &pcmR, &encoded_sample);
data_out[*data_out_index + 0] = (uint8_t)((encoded_sample[0] >> 8) & 0xff);
data_out[*data_out_index + 1] = (uint8_t)((encoded_sample[0] >> 0) & 0xff);
diff --git a/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc b/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc
index d271e0d..fb782dd 100644
--- a/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc
+++ b/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc
@@ -26,7 +26,6 @@
#include "a2dp_vendor.h"
#include "a2dp_vendor_aptx_hd.h"
#include "bt_common.h"
-#include "common/scoped_scs_exit.h"
#include "common/time_util.h"
#include "osi/include/log.h"
#include "osi/include/osi.h"
@@ -56,25 +55,6 @@
static tAPTX_HD_ENCODER_ENCODE_STEREO aptx_hd_encoder_encode_stereo_func;
static tAPTX_HD_ENCODER_SIZEOF_PARAMS aptx_hd_encoder_sizeof_params_func;
-__attribute__((no_sanitize("shadow-call-stack")))
-static int aptx_hd_encoder_init(void* state, short endian) {
- ScopedSCSExit x;
- return aptx_hd_encoder_init_func(state, endian);
-}
-
-__attribute__((no_sanitize("shadow-call-stack")))
-static int aptx_hd_encoder_encode_stereo(void* state, void* pcmL, void* pcmR,
- void* buffer) {
- ScopedSCSExit x;
- return aptx_hd_encoder_encode_stereo_func(state, pcmL, pcmR, buffer);
-}
-
-__attribute__((no_sanitize("shadow-call-stack")))
-static int aptx_hd_encoder_sizeof_params() {
- ScopedSCSExit x;
- return aptx_hd_encoder_sizeof_params_func();
-}
-
// offset
#if (BTA_AV_CO_CP_SCMS_T == TRUE)
#define A2DP_APTX_HD_OFFSET (AVDT_MEDIA_OFFSET + 1)
@@ -213,9 +193,9 @@
#endif
a2dp_aptx_hd_encoder_cb.aptx_hd_encoder_state =
- osi_malloc(aptx_hd_encoder_sizeof_params());
+ osi_malloc(aptx_hd_encoder_sizeof_params_func());
if (a2dp_aptx_hd_encoder_cb.aptx_hd_encoder_state != NULL) {
- aptx_hd_encoder_init(a2dp_aptx_hd_encoder_cb.aptx_hd_encoder_state, 0);
+ aptx_hd_encoder_init_func(a2dp_aptx_hd_encoder_cb.aptx_hd_encoder_state, 0);
} else {
LOG_ERROR(LOG_TAG, "%s: Cannot allocate aptX-HD encoder state", __func__);
// TODO: Return an error?
@@ -480,7 +460,7 @@
p += 3;
}
- aptx_hd_encoder_encode_stereo(
+ aptx_hd_encoder_encode_stereo_func(
a2dp_aptx_hd_encoder_cb.aptx_hd_encoder_state, &pcmL, &pcmR,
&encoded_sample);
diff --git a/stack/avct/avct_api.cc b/stack/avct/avct_api.cc
index 5ced71f..51e2daf 100644
--- a/stack/avct/avct_api.cc
+++ b/stack/avct/avct_api.cc
@@ -56,7 +56,8 @@
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 @@
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 */
diff --git a/stack/avct/avct_lcb_act.cc b/stack/avct/avct_lcb_act.cc
index faa098b..eec049d 100644
--- a/stack/avct/avct_lcb_act.cc
+++ b/stack/avct/avct_lcb_act.cc
@@ -53,6 +53,12 @@
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);
diff --git a/stack/avdt/avdt_api.cc b/stack/avdt/avdt_api.cc
index 903862e..9350c31 100644
--- a/stack/avdt/avdt_api.cc
+++ b/stack/avdt/avdt_api.cc
@@ -90,7 +90,8 @@
******************************************************************************/
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,
diff --git a/stack/avdt/avdt_msg.cc b/stack/avdt/avdt_msg.cc
index 0ac9b64..853f369 100644
--- a/stack/avdt/avdt_msg.cc
+++ b/stack/avdt/avdt_msg.cc
@@ -586,6 +586,10 @@
/* 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 @@
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 @@
/* 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 @@
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;
diff --git a/stack/avrc/avrc_pars_tg.cc b/stack/avrc/avrc_pars_tg.cc
index c0504ee..22471bd 100644
--- a/stack/avrc/avrc_pars_tg.cc
+++ b/stack/avrc/avrc_pars_tg.cc
@@ -135,15 +135,16 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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;
diff --git a/stack/bnep/bnep_api.cc b/stack/bnep/bnep_api.cc
index 0e7b692..809d0b2 100644
--- a/stack/bnep/bnep_api.cc
+++ b/stack/bnep/bnep_api.cc
@@ -340,7 +340,7 @@
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 @@
/* 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 @@
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 @@
/* 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 @@
/* 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 @@
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;
diff --git a/stack/bnep/bnep_int.h b/stack/bnep/bnep_int.h
index 2587147..5bba15d 100644
--- a/stack/bnep/bnep_int.h
+++ b/stack/bnep/bnep_int.h
@@ -229,7 +229,7 @@
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
diff --git a/stack/bnep/bnep_main.cc b/stack/bnep/bnep_main.cc
index ae6c51b..265ec79 100644
--- a/stack/bnep/bnep_main.cc
+++ b/stack/bnep/bnep_main.cc
@@ -94,7 +94,8 @@
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;
}
diff --git a/stack/bnep/bnep_utils.cc b/stack/bnep/bnep_utils.cc
index 6d6d709..ac74ce0 100644
--- a/stack/bnep/bnep_utils.cc
+++ b/stack/bnep/bnep_utils.cc
@@ -1259,23 +1259,33 @@
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);
}
diff --git a/stack/btm/btm_ble_gap.cc b/stack/btm/btm_ble_gap.cc
index ca40a2b..c46acf0 100644
--- a/stack/btm/btm_ble_gap.cc
+++ b/stack/btm/btm_ble_gap.cc
@@ -58,7 +58,10 @@
#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 @@
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 @@
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 @@
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 @@
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()) {
diff --git a/stack/btm/btm_sec.cc b/stack/btm/btm_sec.cc
index 4db757e..4df0974 100644
--- a/stack/btm/btm_sec.cc
+++ b/stack/btm/btm_sec.cc
@@ -4552,8 +4552,7 @@
*/
if (is_sample_ltk(p_dev_rec->ble.keys.pltk)) {
android_errorWriteLog(0x534e4554, "128437297");
- LOG(INFO) << __func__ << " removing bond to device that used sample LTK: "
- << p_dev_rec->bd_addr;
+ LOG(INFO) << __func__ << " removing bond to device that used sample LTK: " << p_dev_rec->bd_addr;
bta_dm_remove_device(p_dev_rec->bd_addr);
}
diff --git a/stack/btu/btu_hcif.cc b/stack/btu/btu_hcif.cc
index b9543fd..4612422 100644
--- a/stack/btu/btu_hcif.cc
+++ b/stack/btu/btu_hcif.cc
@@ -1129,8 +1129,16 @@
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_ERR_INSUFFCIENT_SECURITY) {
+ /* If remote device stop the encryption before we call "Read Encryption Key
+ * Size", we might receive Insufficient Security, which means that link is
+ * no longer encrypted. */
+ LOG(INFO) << __func__ << ": encryption stopped on link: " << loghex(handle);
+ return;
+ }
+
if (status != HCI_SUCCESS) {
LOG(INFO) << __func__ << ": disconnecting, status: " << loghex(status);
btsnd_hcic_disconnect(handle, HCI_ERR_PEER_USER);
@@ -1139,9 +1147,8 @@
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 +1176,16 @@
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 +2058,15 @@
* 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_ERR_INSUFFCIENT_SECURITY) {
+ /* If remote device stop the encryption before we call "Read Encryption Key
+ * Size", we might receive Insufficient Security, which means that link is
+ * no longer encrypted. */
+ LOG(INFO) << __func__ << ": encryption stopped on link: " << loghex(handle);
+ return;
+ }
+
if (status != HCI_SUCCESS) {
LOG(INFO) << __func__ << ": disconnecting, status: " << loghex(status);
btsnd_hcic_disconnect(handle, HCI_ERR_PEER_USER);
@@ -2059,9 +2075,8 @@
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 +2095,7 @@
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));
}
}
diff --git a/stack/gap/gap_conn.cc b/stack/gap/gap_conn.cc
index 72183bb..15d3ddb 100644
--- a/stack/gap/gap_conn.cc
+++ b/stack/gap/gap_conn.cc
@@ -235,8 +235,7 @@
/* 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);
diff --git a/stack/gatt/gatt_api.cc b/stack/gatt/gatt_api.cc
index 4195548..37bc614 100644
--- a/stack/gatt/gatt_api.cc
+++ b/stack/gatt/gatt_api.cc
@@ -382,6 +382,7 @@
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) {
diff --git a/stack/gatt/gatt_cl.cc b/stack/gatt/gatt_cl.cc
index 2650a30..27a4f4f 100644
--- a/stack/gatt/gatt_cl.cc
+++ b/stack/gatt/gatt_cl.cc
@@ -627,6 +627,10 @@
memset(&value, 0, sizeof(value));
STREAM_TO_UINT16(value.handle, p);
value.len = len - 2;
+ if (value.len > GATT_MAX_ATTR_LEN) {
+ LOG(ERROR) << "value.len larger than GATT_MAX_ATTR_LEN, discard";
+ return;
+ }
memcpy(value.value, p, value.len);
if (!GATT_HANDLE_IS_VALID(value.handle)) {
diff --git a/stack/gatt/gatt_main.cc b/stack/gatt/gatt_main.cc
index b332496..87f9c87 100644
--- a/stack/gatt/gatt_main.cc
+++ b/stack/gatt/gatt_main.cc
@@ -124,7 +124,8 @@
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";
}
diff --git a/stack/hcic/hcicmds.cc b/stack/hcic/hcicmds.cc
index 2e849a4..23a8648 100644
--- a/stack/hcic/hcicmds.cc
+++ b/stack/hcic/hcicmds.cc
@@ -1309,9 +1309,8 @@
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 @@
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) {
diff --git a/stack/hid/hidd_api.cc b/stack/hid/hidd_api.cc
index f93511e..cd40c2c 100644
--- a/stack/hid/hidd_api.cc
+++ b/stack/hid/hidd_api.cc
@@ -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 @@
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);
diff --git a/stack/hid/hidd_conn.cc b/stack/hid/hidd_conn.cc
index e4525f9..55ec3b2 100644
--- a/stack/hid/hidd_conn.cc
+++ b/stack/hid/hidd_conn.cc
@@ -614,6 +614,12 @@
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 @@
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);
diff --git a/stack/hid/hidh_conn.cc b/stack/hid/hidh_conn.cc
index 6b729e5..3c694f0 100644
--- a/stack/hid/hidh_conn.cc
+++ b/stack/hid/hidh_conn.cc
@@ -97,11 +97,13 @@
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);
diff --git a/stack/include/advertise_data_parser.h b/stack/include/advertise_data_parser.h
index b62dbb3..a1ac17b 100644
--- a/stack/include/advertise_data_parser.h
+++ b/stack/include/advertise_data_parser.h
@@ -34,7 +34,8 @@
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;
diff --git a/stack/include/bt_types.h b/stack/include/bt_types.h
index 4121a19..7804328 100644
--- a/stack/include/bt_types.h
+++ b/stack/include/bt_types.h
@@ -21,7 +21,6 @@
#include <stdbool.h>
#include <stdint.h>
-#include <string.h>
#ifndef FALSE
#define FALSE false
@@ -581,7 +580,9 @@
* 0x4C68384139F574D836BCF34E9DFB01BF */
constexpr Octet16 SAMPLE_LTK = {0xbf, 0x01, 0xfb, 0x9d, 0x4e, 0xf3, 0xbc, 0x36,
0xd8, 0x74, 0xf5, 0x39, 0x41, 0x38, 0x68, 0x4c};
-inline bool is_sample_ltk(const Octet16& ltk) { return ltk == SAMPLE_LTK; }
+inline bool is_sample_ltk(const Octet16& ltk) {
+ return ltk == SAMPLE_LTK;
+}
#endif
diff --git a/stack/include/hcimsgs.h b/stack/include/hcimsgs.h
index 5682a5c..285ae41 100644
--- a/stack/include/hcimsgs.h
+++ b/stack/include/hcimsgs.h
@@ -611,8 +611,7 @@
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(
diff --git a/stack/include/l2c_api.h b/stack/include/l2c_api.h
index 88121af..8f364e7 100644
--- a/stack/include/l2c_api.h
+++ b/stack/include/l2c_api.h
@@ -328,7 +328,7 @@
} 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 @@
* 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);
/*******************************************************************************
*
diff --git a/stack/l2cap/l2c_api.cc b/stack/l2cap/l2c_api.cc
index 6dc41de..b5a9564 100644
--- a/stack/l2cap/l2c_api.cc
+++ b/stack/l2cap/l2c_api.cc
@@ -58,7 +58,8 @@
* 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 @@
}
}
+ p_rcb->log_packets = enable_snoop;
p_rcb->api = *p_cb_info;
p_rcb->real_psm = psm;
diff --git a/stack/l2cap/l2c_int.h b/stack/l2cap/l2c_int.h
index 0b71a19..53b6f32 100644
--- a/stack/l2cap/l2c_int.h
+++ b/stack/l2cap/l2c_int.h
@@ -241,6 +241,7 @@
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 */
diff --git a/stack/l2cap/l2c_main.cc b/stack/l2cap/l2c_main.cc
index 74e7135..128f60e 100644
--- a/stack/l2cap/l2c_main.cc
+++ b/stack/l2cap/l2c_main.cc
@@ -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 @@
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 @@
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 @@
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 @@
#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);
}
diff --git a/stack/l2cap/l2c_utils.cc b/stack/l2cap/l2c_utils.cc
index 448acaa..593f12f 100644
--- a/stack/l2cap/l2c_utils.cc
+++ b/stack/l2cap/l2c_utils.cc
@@ -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 @@
/* 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);
}
diff --git a/stack/rfcomm/rfc_l2cap_if.cc b/stack/rfcomm/rfc_l2cap_if.cc
index 3275d77..3dc4ec2 100644
--- a/stack/rfcomm/rfc_l2cap_if.cc
+++ b/stack/rfcomm/rfc_l2cap_if.cc
@@ -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 @@
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 */);
}
/*******************************************************************************
diff --git a/stack/rfcomm/rfc_port_fsm.cc b/stack/rfcomm/rfc_port_fsm.cc
index f486bdd..1b82ddf 100644
--- a/stack/rfcomm/rfc_port_fsm.cc
+++ b/stack/rfcomm/rfc_port_fsm.cc
@@ -34,6 +34,14 @@
#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 @@
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 @@
} 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;
}
diff --git a/stack/rfcomm/rfc_ts_frames.cc b/stack/rfcomm/rfc_ts_frames.cc
index d253b40..7bc98a2 100644
--- a/stack/rfcomm/rfc_ts_frames.cc
+++ b/stack/rfcomm/rfc_ts_frames.cc
@@ -533,12 +533,21 @@
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++;
diff --git a/stack/sdp/sdp_discovery.cc b/stack/sdp/sdp_discovery.cc
index e7fe979..55259ca 100644
--- a/stack/sdp/sdp_discovery.cc
+++ b/stack/sdp/sdp_discovery.cc
@@ -217,6 +217,12 @@
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--;
@@ -368,11 +374,6 @@
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;
}
@@ -397,6 +398,12 @@
/* 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;
diff --git a/stack/sdp/sdp_main.cc b/stack/sdp/sdp_main.cc
index 3df37c5..2211c39 100644
--- a/stack/sdp/sdp_main.cc
+++ b/stack/sdp/sdp_main.cc
@@ -121,7 +121,7 @@
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");
}
}
diff --git a/stack/smp/smp_act.cc b/stack/smp/smp_act.cc
index db6ed66..21b960b 100644
--- a/stack/smp/smp_act.cc
+++ b/stack/smp/smp_act.cc
@@ -16,6 +16,7 @@
*
******************************************************************************/
+#include <cutils/log.h>
#include <log/log.h>
#include <string.h>
#include "btif_common.h"
@@ -488,7 +489,15 @@
******************************************************************************/
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);
@@ -511,6 +520,14 @@
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);
@@ -779,6 +796,14 @@
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);
@@ -942,7 +967,7 @@
STREAM_TO_ARRAY(le_key.penc_key.rand, p, BT_OCTET8_LEN);
/* store the encryption keys from peer device */
- le_key.lenc_key.ltk = p_cb->ltk;
+ 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;
@@ -977,6 +1002,15 @@
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.pid_key.identity_addr_type, p);
@@ -1000,6 +1034,15 @@
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 */
diff --git a/stack/smp/smp_int.h b/stack/smp/smp_int.h
index 9886d4f..72fdf55 100644
--- a/stack/smp/smp_int.h
+++ b/stack/smp/smp_int.h
@@ -450,6 +450,7 @@
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);
diff --git a/stack/smp/smp_l2c.cc b/stack/smp/smp_l2c.cc
index b6881e6..2daeb21 100644
--- a/stack/smp/smp_l2c.cc
+++ b/stack/smp/smp_l2c.cc
@@ -22,6 +22,7 @@
*
******************************************************************************/
+#include <cutils/log.h>
#include "bt_target.h"
#include <string.h>
@@ -142,6 +143,14 @@
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 @@
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 */
diff --git a/stack/smp/smp_utils.cc b/stack/smp/smp_utils.cc
index f81e21d..b5da5ba 100644
--- a/stack/smp/smp_utils.cc
+++ b/stack/smp/smp_utils.cc
@@ -955,6 +955,33 @@
/*******************************************************************************
*
+ * 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
diff --git a/stack/test/common/mock_btsnoop_module.cc b/stack/test/common/mock_btsnoop_module.cc
new file mode 100644
index 0000000..7a5c5ae
--- /dev/null
+++ b/stack/test/common/mock_btsnoop_module.cc
@@ -0,0 +1,42 @@
+/******************************************************************************
+ *
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "hci/include/btsnoop.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; }
diff --git a/stack/test/common/mock_l2cap_layer.cc b/stack/test/common/mock_l2cap_layer.cc
index 9f08d56..4756f17 100644
--- a/stack/test/common/mock_l2cap_layer.cc
+++ b/stack/test/common/mock_l2cap_layer.cc
@@ -24,9 +24,11 @@
l2cap_interface = mock_l2cap_interface;
}
-uint16_t L2CA_Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info) {
- VLOG(1) << __func__ << ": psm=" << psm << ", p_cb_info=" << p_cb_info;
- return l2cap_interface->Register(psm, p_cb_info);
+uint16_t L2CA_Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info,
+ bool enable_snoop) {
+ VLOG(1) << __func__ << ": psm=" << psm << ", p_cb_info=" << p_cb_info
+ << ", enable_snoop=" << enable_snoop;
+ return l2cap_interface->Register(psm, p_cb_info, enable_snoop);
}
uint16_t L2CA_ConnectReq(uint16_t psm, const RawAddress& bd_addr) {
diff --git a/stack/test/common/mock_l2cap_layer.h b/stack/test/common/mock_l2cap_layer.h
index 78c8a9c..ade7585 100644
--- a/stack/test/common/mock_l2cap_layer.h
+++ b/stack/test/common/mock_l2cap_layer.h
@@ -26,7 +26,8 @@
class L2capInterface {
public:
- virtual uint16_t Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info) = 0;
+ virtual uint16_t Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info,
+ bool enable_snoop) = 0;
virtual uint16_t ConnectRequest(uint16_t psm, const RawAddress& bd_addr) = 0;
virtual bool ConnectResponse(const RawAddress& bd_addr, uint8_t id,
uint16_t lcid, uint16_t result,
@@ -41,7 +42,8 @@
class MockL2capInterface : public L2capInterface {
public:
- MOCK_METHOD2(Register, uint16_t(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info));
+ MOCK_METHOD3(Register, uint16_t(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info,
+ bool enable_snoop));
MOCK_METHOD2(ConnectRequest,
uint16_t(uint16_t psm, const RawAddress& bd_addr));
MOCK_METHOD5(ConnectResponse,
diff --git a/stack/test/rfcomm/stack_rfcomm_test.cc b/stack/test/rfcomm/stack_rfcomm_test.cc
index 3d9da3f..52e1170 100644
--- a/stack/test/rfcomm/stack_rfcomm_test.cc
+++ b/stack/test/rfcomm/stack_rfcomm_test.cc
@@ -453,7 +453,7 @@
&btm_security_internal_interface_);
bluetooth::l2cap::SetMockInterface(&l2cap_interface_);
rfcomm_callback = &rfcomm_callback_;
- EXPECT_CALL(l2cap_interface_, Register(BT_PSM_RFCOMM, _))
+ EXPECT_CALL(l2cap_interface_, Register(BT_PSM_RFCOMM, _, _))
.WillOnce(
DoAll(SaveArgPointee<1>(&l2cap_appl_info_), Return(BT_PSM_RFCOMM)));
RFCOMM_Init();
diff --git a/test/suite/Android.bp b/test/suite/Android.bp
index 85b46fa..1d919ed 100644
--- a/test/suite/Android.bp
+++ b/test/suite/Android.bp
@@ -15,6 +15,8 @@
shared_libs: [
"liblog",
"libcutils",
+ "libbinder",
+ "libutils",
],
static_libs: [
"libbtcore",
@@ -40,6 +42,8 @@
shared_libs: [
"liblog",
"libcutils",
+ "libbinder",
+ "libutils",
],
static_libs: [
"libbtcore",
diff --git a/test/suite/adapter/adapter_unittest.cc b/test/suite/adapter/adapter_unittest.cc
index 24ca3e5..7a26e28 100644
--- a/test/suite/adapter/adapter_unittest.cc
+++ b/test/suite/adapter/adapter_unittest.cc
@@ -35,7 +35,7 @@
EXPECT_EQ(GetState(), BT_STATE_OFF)
<< "Test should be run with Adapter disabled";
- EXPECT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS);
+ EXPECT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS);
semaphore_wait(adapter_state_changed_callback_sem_);
EXPECT_EQ(GetState(), BT_STATE_ON) << "Adapter did not turn on.";
@@ -49,7 +49,7 @@
<< "Test should be run with Adapter disabled";
for (int i = 0; i < kTestRepeatCount; ++i) {
- EXPECT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS);
+ EXPECT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS);
semaphore_wait(adapter_state_changed_callback_sem_);
EXPECT_EQ(GetState(), BT_STATE_ON) << "Adapter did not turn on.";
@@ -62,7 +62,7 @@
TEST_F(BluetoothTest, AdapterSetGetName) {
bt_property_t* new_name = property_new_name("BluetoothTestName1");
- EXPECT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS);
+ EXPECT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS);
semaphore_wait(adapter_state_changed_callback_sem_);
EXPECT_EQ(GetState(), BT_STATE_ON)
<< "Test should be run with Adapter enabled";
@@ -114,7 +114,7 @@
}
TEST_F(BluetoothTest, AdapterStartDiscovery) {
- EXPECT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS);
+ EXPECT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS);
semaphore_wait(adapter_state_changed_callback_sem_);
EXPECT_EQ(GetState(), BT_STATE_ON)
<< "Test should be run with Adapter enabled";
@@ -130,7 +130,7 @@
}
TEST_F(BluetoothTest, AdapterCancelDiscovery) {
- EXPECT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS);
+ EXPECT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS);
semaphore_wait(adapter_state_changed_callback_sem_);
EXPECT_EQ(GetState(), BT_STATE_ON)
<< "Test should be run with Adapter enabled";
@@ -155,7 +155,7 @@
RawAddress bdaddr = {{0x22, 0x22, 0x22, 0x22, 0x22, 0x22}};
for (int i = 0; i < kTestRepeatCount; ++i) {
- EXPECT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS);
+ EXPECT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS);
semaphore_wait(adapter_state_changed_callback_sem_);
EXPECT_EQ(GetState(), BT_STATE_ON) << "Adapter did not turn on.";
@@ -179,8 +179,8 @@
ASSERT_TRUE(bt_callbacks != nullptr);
for (int i = 0; i < kTestRepeatCount; ++i) {
- bt_interface()->init(bt_callbacks);
- EXPECT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS);
+ bt_interface()->init(bt_callbacks, false, false);
+ EXPECT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS);
semaphore_wait(adapter_state_changed_callback_sem_);
EXPECT_EQ(GetState(), BT_STATE_ON) << "Adapter did not turn on.";
diff --git a/test/suite/adapter/bluetooth_test.cc b/test/suite/adapter/bluetooth_test.cc
index 02132f1..626ac42 100644
--- a/test/suite/adapter/bluetooth_test.cc
+++ b/test/suite/adapter/bluetooth_test.cc
@@ -17,6 +17,8 @@
******************************************************************************/
#include "adapter/bluetooth_test.h"
+#include <binder/ProcessState.h>
+#include <stdio.h>
#include <mutex>
#include "btcore/include/property.h"
@@ -31,6 +33,7 @@
namespace bttest {
void BluetoothTest::SetUp() {
+ android::ProcessState::self()->startThreadPool();
bt_interface_ = nullptr;
state_ = BT_STATE_OFF;
properties_changed_count_ = 0;
@@ -46,6 +49,9 @@
adapter_state_changed_callback_sem_ = semaphore_new(0);
discovery_state_changed_callback_sem_ = semaphore_new(0);
+ remove("/data/misc/bluedroid/bt_config.conf.encrypted-checksum");
+ remove("/data/misc/bluedroid/bt_config.bak.encrypted-checksum");
+
bluetooth::hal::BluetoothInterface::Initialize();
ASSERT_TRUE(bluetooth::hal::BluetoothInterface::IsInitialized());
auto bt_hal_interface = bluetooth::hal::BluetoothInterface::Get();
diff --git a/test/suite/gatt/gatt_test.cc b/test/suite/gatt/gatt_test.cc
index e3546d3..8c8f1ab 100644
--- a/test/suite/gatt/gatt_test.cc
+++ b/test/suite/gatt/gatt_test.cc
@@ -33,7 +33,7 @@
status_ = 0;
BluetoothTest::SetUp();
- ASSERT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS);
+ ASSERT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS);
semaphore_wait(adapter_state_changed_callback_sem_);
EXPECT_TRUE(GetState() == BT_STATE_ON);
diff --git a/test/suite/rfcomm/rfcomm_test.cc b/test/suite/rfcomm/rfcomm_test.cc
index 01d9fed..d5baf35 100644
--- a/test/suite/rfcomm/rfcomm_test.cc
+++ b/test/suite/rfcomm/rfcomm_test.cc
@@ -28,7 +28,7 @@
void RFCommTest::SetUp() {
BluetoothTest::SetUp();
- ASSERT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS);
+ ASSERT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS);
semaphore_wait(adapter_state_changed_callback_sem_);
ASSERT_TRUE(GetState() == BT_STATE_ON);
socket_interface_ =
diff --git a/udrv/ulinux/uipc.cc b/udrv/ulinux/uipc.cc
index e2f2950..24fa711 100644
--- a/udrv/ulinux/uipc.cc
+++ b/udrv/ulinux/uipc.cc
@@ -621,15 +621,15 @@
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;