BtifConfig: Prevent unprotected access to btif config cache
* btif_config_sections() used to allow unprotected access to internals
of btif config cache that is normally protected by a mutex
* Changing that function to btif_config_get_paired_devices() as all
users of that API only require paired devices
* Instead of returning a reference to the underlying list, the new API
returns a copy of all paired devices, thus preventing any race
conditon from happening when iterating through this vector
Bug: 67595284
Test: manual pairing test
Tag: #stability
Change-Id: If20db2c94cebb538f7c8d5c7c4b4c463dcfc1988
diff --git a/system/btif/include/btif_config.h b/system/btif/include/btif_config.h
index d1678cd..da1d75f 100644
--- a/system/btif/include/btif_config.h
+++ b/system/btif/include/btif_config.h
@@ -64,7 +64,7 @@
size_t btif_config_get_bin_length(const std::string& section,
const std::string& key);
-const std::list<section_t>& btif_config_sections();
+std::vector<RawAddress> btif_config_get_paired_devices();
void btif_config_save(void);
void btif_config_flush(void);
diff --git a/system/btif/include/btif_config_cache.h b/system/btif/include/btif_config_cache.h
index aedcd4e..61406f9 100644
--- a/system/btif/include/btif_config_cache.h
+++ b/system/btif/include/btif_config_cache.h
@@ -31,7 +31,7 @@
void Clear();
void Init(std::unique_ptr<config_t> source);
- const std::list<section_t>& GetPersistentSections();
+ std::vector<std::string> GetPersistentSectionNames();
config_t PersistentSectionCopy();
bool HasSection(const std::string& section_name);
bool HasUnpairedSection(const std::string& section_name);
diff --git a/system/btif/include/btif_storage.h b/system/btif/include/btif_storage.h
index 1c1163d..b1d8d3b 100644
--- a/system/btif/include/btif_storage.h
+++ b/system/btif/include/btif_storage.h
@@ -219,7 +219,7 @@
* BT_STATUS_FAIL otherwise
*
******************************************************************************/
-bt_status_t btif_storage_remove_hid_info(RawAddress* remote_bd_addr);
+bt_status_t btif_storage_remove_hid_info(const RawAddress& remote_bd_addr);
/** Loads information about bonded hearing aid devices */
void btif_storage_load_bonded_hearing_aids();
@@ -255,7 +255,7 @@
const uint8_t* key,
uint8_t key_type,
uint8_t key_length);
-bt_status_t btif_storage_get_ble_bonding_key(RawAddress* remote_bd_addr,
+bt_status_t btif_storage_get_ble_bonding_key(const RawAddress& remote_bd_addr,
uint8_t key_type,
uint8_t* key_value,
int key_length);
@@ -294,7 +294,7 @@
*
******************************************************************************/
-bt_status_t btif_storage_set_hidd(RawAddress* remote_bd_addr);
+bt_status_t btif_storage_set_hidd(const RawAddress& remote_bd_addr);
/*******************************************************************************
*
diff --git a/system/btif/src/btif_config.cc b/system/btif/src/btif_config.cc
index d95aa55..b79b805 100644
--- a/system/btif/src/btif_config.cc
+++ b/system/btif/src/btif_config.cc
@@ -218,18 +218,14 @@
// version of android without a metric id.
std::vector<RawAddress> addresses_without_id;
- for (auto& section : btif_config_sections()) {
- auto& section_name = section.name;
- RawAddress mac_address;
- if (!RawAddress::FromString(section_name, mac_address)) {
- continue;
- }
+ for (const auto& mac_address : btif_config_get_paired_devices()) {
+ auto addr_str = mac_address.ToString();
// if the section name is a mac address
bool is_valid_id_found = false;
- if (btif_config_exist(section_name, BT_CONFIG_METRICS_ID_KEY)) {
+ if (btif_config_exist(addr_str, BT_CONFIG_METRICS_ID_KEY)) {
// there is one metric id under this mac_address
int id = 0;
- btif_config_get_int(section_name, BT_CONFIG_METRICS_ID_KEY, &id);
+ btif_config_get_int(addr_str, BT_CONFIG_METRICS_ID_KEY, &id);
if (MetricIdAllocator::IsValidId(id)) {
paired_device_map[mac_address] = id;
is_valid_id_found = true;
@@ -581,8 +577,23 @@
return true;
}
-const std::list<section_t>& btif_config_sections() {
- return btif_config_cache.GetPersistentSections();
+std::vector<RawAddress> btif_config_get_paired_devices() {
+ std::vector<std::string> names;
+ {
+ std::unique_lock<std::recursive_mutex> lock(config_lock);
+ names = btif_config_cache.GetPersistentSectionNames();
+ }
+ std::vector<RawAddress> result;
+ result.reserve(names.size());
+ for (const auto& name : names) {
+ RawAddress addr = {};
+ if (!RawAddress::FromString(name, addr)) {
+ LOG(WARNING) << __func__ << ": " << name << " is not a valid address";
+ continue;
+ }
+ result.emplace_back(addr);
+ }
+ return result;
}
bool btif_config_remove(const std::string& section, const std::string& key) {
@@ -672,9 +683,8 @@
if (!file_source) {
file_source.emplace("Original");
}
-
- dprintf(fd, " Devices loaded: %zu\n",
- btif_config_cache.GetPersistentSections().size());
+ auto devices = btif_config_cache.GetPersistentSectionNames();
+ dprintf(fd, " Devices loaded: %zu\n", devices.size());
dprintf(fd, " File created/tagged: %s\n", btif_config_time_created);
dprintf(fd, " File source: %s\n", file_source->c_str());
}
diff --git a/system/btif/src/btif_config_cache.cc b/system/btif/src/btif_config_cache.cc
index c5562aa..dc4ae4d 100644
--- a/system/btif/src/btif_config_cache.cc
+++ b/system/btif/src/btif_config_cache.cc
@@ -148,16 +148,21 @@
}
}
+std::vector<std::string> BtifConfigCache::GetPersistentSectionNames() {
+ std::vector<std::string> result;
+ result.reserve(paired_devices_list_.sections.size());
+ for (const auto& section : paired_devices_list_.sections) {
+ result.emplace_back(section.name);
+ }
+ return result;
+}
+
/* clone persistent sections (Local Adapter sections, remote paired devices
* section,..) */
config_t BtifConfigCache::PersistentSectionCopy() {
return paired_devices_list_;
}
-const std::list<section_t>& BtifConfigCache::GetPersistentSections() {
- return paired_devices_list_.sections;
-}
-
void BtifConfigCache::SetString(std::string section_name, std::string key,
std::string value) {
if (trim_new_line(section_name) || trim_new_line(key) ||
diff --git a/system/btif/src/btif_gatt_util.cc b/system/btif/src/btif_gatt_util.cc
index 16f2275..2f2df59 100644
--- a/system/btif/src/btif_gatt_util.cc
+++ b/system/btif/src/btif_gatt_util.cc
@@ -76,7 +76,7 @@
tGATT_TRANSPORT transport_link) {
tBTM_LE_PENC_KEYS key;
if ((btif_storage_get_ble_bonding_key(
- &bd_addr, BTIF_DM_LE_KEY_PENC, (uint8_t*)&key,
+ bd_addr, BTIF_DM_LE_KEY_PENC, (uint8_t*)&key,
sizeof(tBTM_LE_PENC_KEYS)) == BT_STATUS_SUCCESS) &&
!btif_gatt_is_link_encrypted(bd_addr)) {
BTIF_TRACE_DEBUG("%s: transport = %d", __func__, transport_link);
diff --git a/system/btif/src/btif_hd.cc b/system/btif/src/btif_hd.cc
index d580a19..7942693 100644
--- a/system/btif/src/btif_hd.cc
+++ b/system/btif/src/btif_hd.cc
@@ -211,7 +211,7 @@
BTA_HdDisconnect();
break;
}
- btif_storage_set_hidd((RawAddress*)&p_data->conn.bda);
+ btif_storage_set_hidd(p_data->conn.bda);
HAL_CBACK(bt_hd_callbacks, connection_state_cb,
(RawAddress*)&p_data->conn.bda, BTHD_CONN_STATE_CONNECTED);
diff --git a/system/btif/src/btif_hh.cc b/system/btif/src/btif_hh.cc
index b89e6d9..5f1e5a8 100644
--- a/system/btif/src/btif_hh.cc
+++ b/system/btif/src/btif_hh.cc
@@ -460,7 +460,7 @@
p_added_dev = &btif_hh_cb.added_devices[i];
if (p_added_dev->bd_addr == bd_addr) {
BTA_HhRemoveDev(p_added_dev->dev_handle);
- btif_storage_remove_hid_info(&(p_added_dev->bd_addr));
+ btif_storage_remove_hid_info(p_added_dev->bd_addr);
memset(&(p_added_dev->bd_addr), 0, 6);
p_added_dev->dev_handle = BTA_HH_INVALID_HANDLE;
break;
diff --git a/system/btif/src/btif_storage.cc b/system/btif/src/btif_storage.cc
index 4c3f5f0..257c110 100644
--- a/system/btif/src/btif_storage.cc
+++ b/system/btif/src/btif_storage.cc
@@ -448,11 +448,8 @@
bool bt_linkkey_file_found = false;
int device_type;
- // TODO: this code is not thread safe, it can corrupt config content.
- // b/67595284
- for (const section_t& section : btif_config_sections()) {
- const std::string& name = section.name;
- if (!RawAddress::IsValidAddress(name)) continue;
+ for (const auto& bd_addr : btif_config_get_paired_devices()) {
+ auto name = bd_addr.ToString();
BTIF_TRACE_DEBUG("Remote device:%s", name.c_str());
LinkKey link_key;
@@ -460,8 +457,6 @@
if (btif_config_get_bin(name, "LinkKey", link_key.data(), &size)) {
int linkkey_type;
if (btif_config_get_int(name, "LinkKeyType", &linkkey_type)) {
- RawAddress bd_addr;
- RawAddress::FromString(name, bd_addr);
if (add) {
DEV_CLASS dev_class = {0, 0, 0};
int cod;
@@ -501,7 +496,7 @@
tBTA_LE_KEY_VALUE key;
memset(&key, 0, sizeof(key));
- if (btif_storage_get_ble_bonding_key(&bd_addr, key_type, (uint8_t*)&key,
+ if (btif_storage_get_ble_bonding_key(bd_addr, key_type, (uint8_t*)&key,
key_len) == BT_STATUS_SUCCESS) {
if (add_key) {
if (!*device_added) {
@@ -872,20 +867,14 @@
*/
static void remove_devices_with_sample_ltk() {
std::vector<RawAddress> bad_ltk;
- for (const section_t& section : btif_config_sections()) {
- const std::string& name = section.name;
- if (!RawAddress::IsValidAddress(name)) {
- continue;
- }
-
- RawAddress bd_addr;
- RawAddress::FromString(name, bd_addr);
+ for (const auto& bd_addr : btif_config_get_paired_devices()) {
+ auto name = bd_addr.ToString();
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,
+ 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);
@@ -1093,7 +1082,7 @@
* BT_STATUS_FAIL otherwise
*
******************************************************************************/
-bt_status_t btif_storage_get_ble_bonding_key(RawAddress* remote_bd_addr,
+bt_status_t btif_storage_get_ble_bonding_key(const RawAddress& remote_bd_addr,
uint8_t key_type,
uint8_t* key_value,
int key_length) {
@@ -1122,7 +1111,7 @@
}
size_t length = key_length;
int ret =
- btif_config_get_bin(remote_bd_addr->ToString(), name, key_value, &length);
+ btif_config_get_bin(remote_bd_addr.ToString(), name, key_value, &length);
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
}
@@ -1366,11 +1355,8 @@
*
******************************************************************************/
bt_status_t btif_storage_load_bonded_hid_info(void) {
- // TODO: this code is not thread safe, it can corrupt config content.
- // b/67595284
- for (const section_t& section : btif_config_sections()) {
- const std::string& name = section.name;
- if (!RawAddress::IsValidAddress(name)) continue;
+ for (const auto& bd_addr : btif_config_get_paired_devices()) {
+ auto name = bd_addr.ToString();
BTIF_TRACE_DEBUG("Remote device:%s", name.c_str());
@@ -1379,9 +1365,7 @@
uint16_t attr_mask = (uint16_t)value;
if (btif_in_fetch_bonded_device(name) != BT_STATUS_SUCCESS) {
- RawAddress bd_addr;
- RawAddress::FromString(name, bd_addr);
- btif_storage_remove_hid_info(&bd_addr);
+ btif_storage_remove_hid_info(bd_addr);
continue;
}
@@ -1422,8 +1406,6 @@
(uint8_t*)dscp_info.descriptor.dsc_list, &len);
}
- RawAddress bd_addr;
- RawAddress::FromString(name, bd_addr);
// add extracted information to BTA HH
if (btif_hh_add_added_dev(bd_addr, attr_mask)) {
BTA_HhAddDev(bd_addr, attr_mask, sub_class, app_id, dscp_info);
@@ -1444,8 +1426,8 @@
* BT_STATUS_FAIL otherwise
*
******************************************************************************/
-bt_status_t btif_storage_remove_hid_info(RawAddress* remote_bd_addr) {
- std::string bdstr = remote_bd_addr->ToString();
+bt_status_t btif_storage_remove_hid_info(const RawAddress& remote_bd_addr) {
+ std::string bdstr = remote_bd_addr.ToString();
btif_config_remove(bdstr, "HidAttrMask");
btif_config_remove(bdstr, "HidSubClass");
@@ -1514,11 +1496,8 @@
/** Loads information about bonded hearing aid devices */
void btif_storage_load_bonded_hearing_aids() {
- // TODO: this code is not thread safe, it can corrupt config content.
- // b/67595284
- for (const section_t& section : btif_config_sections()) {
- const std::string& name = section.name;
- if (!RawAddress::IsValidAddress(name)) continue;
+ for (const auto& bd_addr : btif_config_get_paired_devices()) {
+ const std::string& name = bd_addr.ToString();
int size = STORAGE_UUID_STRING_SIZE * HEARINGAID_MAX_NUM_UUIDS;
char uuid_str[size];
@@ -1542,8 +1521,6 @@
BTIF_TRACE_DEBUG("Remote device:%s", name.c_str());
if (btif_in_fetch_bonded_device(name) != BT_STATUS_SUCCESS) {
- RawAddress bd_addr;
- RawAddress::FromString(name, bd_addr);
btif_storage_remove_hearing_aid(bd_addr);
continue;
}
@@ -1598,9 +1575,6 @@
if (btif_config_get_int(name, HEARING_AID_IS_WHITE_LISTED, &value))
is_white_listed = value;
- RawAddress bd_addr;
- RawAddress::FromString(name, bd_addr);
-
// add extracted information to BTA Hearing Aid
do_in_main_thread(
FROM_HERE,
@@ -1712,18 +1686,13 @@
*
******************************************************************************/
bt_status_t btif_storage_load_hidd(void) {
- // TODO: this code is not thread safe, it can corrupt config content.
- // b/67595284
- for (const section_t& section : btif_config_sections()) {
- const std::string& name = section.name;
- if (!RawAddress::IsValidAddress(name)) continue;
+ for (const auto& bd_addr : btif_config_get_paired_devices()) {
+ auto name = bd_addr.ToString();
BTIF_TRACE_DEBUG("Remote device:%s", name.c_str());
int value;
if (btif_in_fetch_bonded_device(name) == BT_STATUS_SUCCESS) {
if (btif_config_get_int(name, "HidDeviceCabled", &value)) {
- RawAddress bd_addr;
- RawAddress::FromString(name, bd_addr);
BTA_HdAddDevice(bd_addr);
break;
}
@@ -1743,13 +1712,13 @@
* Returns BT_STATUS_SUCCESS
*
******************************************************************************/
-bt_status_t btif_storage_set_hidd(RawAddress* remote_bd_addr) {
- std::string remote_device_address_string = remote_bd_addr->ToString();
- for (const section_t& section : btif_config_sections()) {
- if (!RawAddress::IsValidAddress(section.name)) continue;
- if (section.name == remote_device_address_string) continue;
- if (btif_in_fetch_bonded_device(section.name) == BT_STATUS_SUCCESS) {
- btif_config_remove(section.name, "HidDeviceCabled");
+bt_status_t btif_storage_set_hidd(const RawAddress& remote_bd_addr) {
+ std::string remote_device_address_string = remote_bd_addr.ToString();
+ for (const auto& bd_addr : btif_config_get_paired_devices()) {
+ auto name = bd_addr.ToString();
+ if (bd_addr == remote_bd_addr) continue;
+ if (btif_in_fetch_bonded_device(name) == BT_STATUS_SUCCESS) {
+ btif_config_remove(name, "HidDeviceCabled");
}
}
diff --git a/system/btif/test/btif_config_cache_test.cc b/system/btif/test/btif_config_cache_test.cc
index aaccf8c..b7c0e9b 100644
--- a/system/btif/test/btif_config_cache_test.cc
+++ b/system/btif/test/btif_config_cache_test.cc
@@ -483,8 +483,9 @@
// check GetPersistentSections
int num_of_paired_devices = 0;
- for (const section_t& sec : test_btif_config_cache.GetPersistentSections()) {
- EXPECT_TRUE(test_btif_config_cache.HasPersistentSection(sec.name));
+ for (const auto& sec_name :
+ test_btif_config_cache.GetPersistentSectionNames()) {
+ EXPECT_TRUE(test_btif_config_cache.HasPersistentSection(sec_name));
num_of_paired_devices++;
}
EXPECT_EQ(num_of_paired_devices, 3);