Skip to content

Commit 80ebd9d

Browse files
committed
fw/services/bluetooth: do not choke on gap_bondings of the wrong version
snowy uses v1 of bluetooth_persistent_storage, which NimBLE does not support. As it turns out, we are generally not very robust against gap_bondings that we don't know how to deal with, and we can crash the system if they happen! Let's rather ignore them, in case a future PebbleOS version extends the gap_bonding structure in a way that we don't know how to read and someone tries to downgrade. Signed-off-by: Joshua Wise <[email protected]>
1 parent 8e3ab60 commit 80ebd9d

File tree

1 file changed

+36
-21
lines changed

1 file changed

+36
-21
lines changed

src/fw/services/normal/bluetooth/bluetooth_persistent_storage.c

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,13 @@
5050
// Let the unittest define this using a header override:
5151
# include "services/normal/bluetooth/bluetooth_persistent_storage_unittest_impl.h"
5252
#else
53-
// TODO: perhaps revert this back to v1 for cc2564x if we can figure out how to handle the old format
54-
// right now, you have to make sure you've erased all bondings before upgrading else you'll crash
55-
// because the v2 code chokes on the v1 format
5653
# if BT_CONTROLLER_DA14681 || BT_CONTROLLER_QEMU || BT_CONTROLLER_NRF52 || BT_CONTROLLER_CC2564X
5754
# include "services/normal/bluetooth/bluetooth_persistent_storage_v2_impl.h"
5855
# else
5956
# error "Unknown BT_CONTROLLER_... define?"
6057
# endif
6158
#endif
6259

63-
//! The BtPersistBonding*Data structs can never shrink, only grow
64-
6560
//! Stores data about a remote BT classic device
6661
typedef struct PACKED {
6762
BTDeviceAddress addr;
@@ -126,6 +121,26 @@ static PebbleMutex *s_db_mutex = NULL;
126121
//! @note prv_lock() must be held when accessing this variable.
127122
static PebbleProtocolCapabilities s_cached_system_capabilities;
128123

124+
// TODO: extend these to be able to load a legacy BtPersistBondingData from
125+
// v1 and migrate it, if we wish to. The old format requires regenerating
126+
// CSRK / LTK from div/ediv directly, which seems not to be an API that's
127+
// readily exposed from NimBLE. For now, we throw away old pairings.
128+
129+
//! Is this val_len any kind of BtPersistBondingData that we support loading?
130+
static bool prv_val_len_is_bonding(size_t val_len) {
131+
// In theory, it was permissible on old PebbleOS to have a smaller
132+
// BtPersistBondingData v2 that needed to get zero-padded out to a larger
133+
// one, and that was the "versioning"; this check does not check for that.
134+
// In practice, this never happened, so we are OK!
135+
return val_len == sizeof(BtPersistBondingData);
136+
}
137+
138+
//! Load whatever is in this SettingsRecordInfo into a modern BtPersistBondingData structure.
139+
static void prv_load_pairing_data_from_val(SettingsFile *file, SettingsRecordInfo *info, BtPersistBondingData *data) {
140+
PBL_ASSERTN(info->val_len == sizeof(BtPersistBondingData));
141+
info->get_val(file, (uint8_t *)data, info->val_len);
142+
}
143+
129144
static void prv_lock(void) {
130145
mutex_lock(s_db_mutex);
131146
}
@@ -320,12 +335,12 @@ static bool prv_any_pinned_ble_pairings_itr(SettingsFile *file,
320335
if (info->key_len != sizeof(BTBondingID)) {
321336
return true;
322337
}
323-
if (info->val_len == 0) {
338+
if (!prv_val_len_is_bonding(info->val_len)) {
324339
return true;
325340
}
326341

327342
BtPersistBondingData data;
328-
info->get_val(file, &data, sizeof(data));
343+
prv_load_pairing_data_from_val(file, info, &data);
329344
if (data.ble_data.requires_address_pinning) {
330345
bool *has_pinned_ble_pairings = context;
331346
*has_pinned_ble_pairings = true;
@@ -518,14 +533,14 @@ typedef struct {
518533
static bool prv_get_num_pairings_by_type_itr(SettingsFile *file,
519534
SettingsRecordInfo *info, void *context) {
520535
// check entry is valid
521-
if (info->val_len == 0 || info->key_len != sizeof(BTBondingID)) {
536+
if (!prv_val_len_is_bonding(info->val_len) || info->key_len != sizeof(BTBondingID)) {
522537
return true; // continue iterating
523538
}
524539

525540
PairingCountItrData *itr_data = (PairingCountItrData *)context;
526541

527542
BtPersistBondingData stored_data;
528-
info->get_val(file, (uint8_t*) &stored_data, MIN((unsigned)info->val_len, sizeof(stored_data)));
543+
prv_load_pairing_data_from_val(file, info, &stored_data);
529544

530545
if (stored_data.type == itr_data->type) {
531546
itr_data->count++;
@@ -577,7 +592,7 @@ static bool prv_is_pairing_info_equal_identity(const BtPersistLEPairingInfo *a,
577592
static bool prv_get_key_for_sm_pairing_info_itr(SettingsFile *file,
578593
SettingsRecordInfo *info, void *context) {
579594
// check entry is valid
580-
if (info->val_len == 0 || info->key_len != sizeof(BTBondingID)) {
595+
if (!prv_val_len_is_bonding(info->val_len) || info->key_len != sizeof(BTBondingID)) {
581596
return true; // continue iterating
582597
}
583598

@@ -586,7 +601,7 @@ static bool prv_get_key_for_sm_pairing_info_itr(SettingsFile *file,
586601
BTBondingID key;
587602
BtPersistBondingData stored_data;
588603
info->get_key(file, (uint8_t*) &key, info->key_len);
589-
info->get_val(file, (uint8_t*) &stored_data, MIN((unsigned)info->val_len, sizeof(stored_data)));
604+
prv_load_pairing_data_from_val(file, info, &stored_data);
590605

591606
if (stored_data.type == BtPersistBondingTypeBLE &&
592607
prv_is_pairing_info_equal_identity(&stored_data.ble_data.pairing_info,
@@ -752,7 +767,7 @@ typedef struct {
752767
static bool prv_find_by_addr_itr(SettingsFile *file,
753768
SettingsRecordInfo *info, void *context) {
754769
// check entry is valid
755-
if (info->val_len == 0 || info->key_len != sizeof(BTBondingID)) {
770+
if (!prv_val_len_is_bonding(info->val_len) || info->key_len != sizeof(BTBondingID)) {
756771
return true; // continue iterating
757772
}
758773

@@ -761,7 +776,7 @@ static bool prv_find_by_addr_itr(SettingsFile *file,
761776
BTBondingID key;
762777
BtPersistBondingData stored_data;
763778
info->get_key(file, (uint8_t*) &key, info->key_len);
764-
info->get_val(file, (uint8_t*) &stored_data, MIN((unsigned)info->val_len, sizeof(stored_data)));
779+
prv_load_pairing_data_from_val(file, info, &stored_data);
765780

766781
if (stored_data.type == BtPersistBondingTypeBLE &&
767782
bt_device_equal(&itr_data->device.opaque,
@@ -889,14 +904,14 @@ bool bt_persistent_storage_get_ble_pinned_address(BTDeviceAddress *address_out)
889904
static bool prv_get_first_ancs_bonding_itr(SettingsFile *file,
890905
SettingsRecordInfo *info, void *context) {
891906
// check entry is valid
892-
if (info->val_len == 0 || info->key_len != sizeof(BTBondingID)) {
907+
if (!prv_val_len_is_bonding(info->val_len) || info->key_len != sizeof(BTBondingID)) {
893908
return true; // continue iterating
894909
}
895910

896911
BTBondingID *first_ancs_supported_bonding_found = (BTBondingID *) context;
897912

898913
BtPersistBondingData stored_data;
899-
info->get_val(file, (uint8_t*) &stored_data, MIN((unsigned)info->val_len, sizeof(stored_data)));
914+
prv_load_pairing_data_from_val(file, info, &stored_data);
900915

901916

902917
if (stored_data.type == BtPersistBondingTypeBLE && stored_data.ble_data.supports_ancs) {
@@ -957,7 +972,7 @@ static void prv_public_for_each_ble_cb(BTBondingID key,
957972
static bool prv_ble_pairing_internal_for_each_itr(SettingsFile *file,
958973
SettingsRecordInfo *info, void *context) {
959974
// check entry is valid
960-
if (info->val_len == 0 || info->key_len != sizeof(BTBondingID)) {
975+
if (!prv_val_len_is_bonding(info->val_len) || info->key_len != sizeof(BTBondingID)) {
961976
return true; // continue iterating
962977
}
963978

@@ -966,7 +981,7 @@ static bool prv_ble_pairing_internal_for_each_itr(SettingsFile *file,
966981
BTBondingID key;
967982
BtPersistBondingData stored_data;
968983
info->get_key(file, (uint8_t*) &key, info->key_len);
969-
info->get_val(file, (uint8_t*) &stored_data, MIN((unsigned)info->val_len, sizeof(stored_data)));
984+
prv_load_pairing_data_from_val(file, info, &stored_data);
970985

971986
if (stored_data.type == BtPersistBondingTypeBLE) {
972987
internal_itr_data->cb(key, &stored_data, internal_itr_data->cb_data);
@@ -1037,7 +1052,7 @@ typedef struct {
10371052
static bool prv_get_key_for_bt_classic_addr_itr(SettingsFile *file,
10381053
SettingsRecordInfo *info, void *context) {
10391054
// check entry is valid
1040-
if (info->val_len == 0 || info->key_len != sizeof(BTBondingID)) {
1055+
if (!prv_val_len_is_bonding(info->val_len) || info->key_len != sizeof(BTBondingID)) {
10411056
return true; // continue iterating
10421057
}
10431058

@@ -1046,7 +1061,7 @@ static bool prv_get_key_for_bt_classic_addr_itr(SettingsFile *file,
10461061
BTBondingID key;
10471062
BtPersistBondingData stored_data;
10481063
info->get_key(file, (uint8_t*) &key, info->key_len);
1049-
info->get_val(file, (uint8_t*) &stored_data, MIN((unsigned)info->val_len, sizeof(stored_data)));
1064+
prv_load_pairing_data_from_val(file, info, &stored_data);
10501065

10511066
if (stored_data.type == BtPersistBondingTypeBTClassic &&
10521067
!memcmp(&itr_data->address, &stored_data.bt_classic_data.addr, sizeof(itr_data->address))) {
@@ -1222,7 +1237,7 @@ typedef struct {
12221237
static bool bt_persistent_storage_bt_classic_pairing_for_each_itr(SettingsFile *file,
12231238
SettingsRecordInfo *info, void *context) {
12241239
// check entry is valid
1225-
if (info->val_len == 0 || info->key_len != sizeof(BTBondingID)) {
1240+
if (!prv_val_len_is_bonding(info->val_len) || info->key_len != sizeof(BTBondingID)) {
12261241
return true; // continue iterating
12271242
}
12281243

@@ -1231,7 +1246,7 @@ static bool bt_persistent_storage_bt_classic_pairing_for_each_itr(SettingsFile *
12311246
BTBondingID key;
12321247
BtPersistBondingData stored_data;
12331248
info->get_key(file, (uint8_t*) &key, info->key_len);
1234-
info->get_val(file, (uint8_t*) &stored_data, MIN((unsigned)info->val_len, sizeof(stored_data)));
1249+
prv_load_pairing_data_from_val(file, info, &stored_data);
12351250

12361251
if (stored_data.type == BtPersistBondingTypeBTClassic) {
12371252
itr_data->cb(&stored_data.bt_classic_data.addr, &stored_data.bt_classic_data.link_key,

0 commit comments

Comments
 (0)