This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Bluetooth: Crash in bt_gatt_dm_attr_chrc_val when BLE device is disconnected during discovery process (NCSDK-9811)

In certain situation when BLE device is disconnected during service discovery process sw can crash in bt_gatt_dm_char_by_uuid due to BUS FAULT (dereference of pointer showing non accessible memory). Scenario is following,:

  1. scanning is started
  2. connection with BLE device is established during filter match callback.
  3. Gatt discovery is started with bt_gatt_dm_start.
  4. 3 services are discovered correctly
  5. BLE device is disconnected (this is pulse oximeter, it have so good timings that very often disconnect right in this moment)
  6. 4th service is discovered
  7. In "completed" callback for 4th service I'm assigning handlers for one of the characteristics calling bt_gatt_dm_char_by_uuid function.
  8. Crash happen in bt_uuid_cmp function as second argument points to wrong memory

Describe the bug
The bug is that during service discovery none of the characteristics is discovered. discovery_callback with BT_GATT_DISCOVER_CHARACTERISTIC is called only once with attr=NULL, so this basically ends service discovery and cause calling discovery_complete callback. I believe this situation should end with discovery_complete_error. In discovery_complete callback my application tries to assign handlers, but bt_gatt_dm_char_next() is returning pointer to memory that was used for storing characteristic for service 3.

To Reproduce
You need assign handlers during gatt discovery procedure and disconnect device in right moment, which is not easy, when I tried this with different BLE devices I couldn't reproduce issue. One device (pulse oximeter) have so "good" timing that problem can be reproduce in around 50% cases.

Expected behavior
bt_gatt_dm_char_by_uuid should not crash, discovery error callback should be called.

Impact
showstopper

Logs and console output

[17:56:34:142] [00:01:00.593,719] <inf> ble_device: Connected
[17:56:38:919] discovery_process_service cur_service_val->uuid 0x20004f84
[17:56:38:941] discovery_process_attribute cur_attr->uuid 0x20004f90
[17:56:38:941] discovery_process_attribute cur_attr->uuid 0x20004f94
[17:56:38:969] discovery_process_attribute cur_attr->uuid 0x20004fa0
[17:56:38:969] discovery_process_attribute cur_attr->uuid 0x20004fa4
[17:56:38:969] discovery_process_attribute cur_attr->uuid 0x20004fb0
[17:56:38:969] discovery_process_attribute cur_attr->uuid 0x20004fb4
[17:56:38:969] discovery_process_attribute cur_attr->uuid 0x20004fc0
[17:56:38:969] discovery_process_attribute cur_attr->uuid 0x20004fc4
[17:56:38:969] discovery_process_attribute cur_attr->uuid 0x20004fd0
[17:56:38:995] discovery_process_attribute cur_attr->uuid 0x20004fd4
[17:56:38:995] discovery_process_characteristic cur_gatt_chrc->uuid 0x20004fd8
[17:56:39:336] discovery_process_characteristic cur_gatt_chrc->uuid 0x20004fdc
[17:56:39:336] discovery_process_characteristic cur_gatt_chrc->uuid 0x20004fe0
[17:56:39:360] discovery_process_characteristic cur_gatt_chrc->uuid 0x20004fe4
[17:56:39:360] discovery_process_characteristic cur_gatt_chrc->uuid 0x20004fe8
[17:56:39:360] [00:01:06.045,318] <inf> ble_device: Gatt service uuid 1800  -> First service discovery callback
[17:56:39:360] bt_gatt_dm_data_release
[17:56:39:360] svc_attr_memory_release
[17:56:39:385] call bt_gatt_dm_continue
[17:56:39:385] discovery_process_service cur_service_val->uuid 0x20004f84
[17:56:39:385] discovery_process_attribute cur_attr->uuid 0x20004f90
[17:56:39:831] discovery_process_attribute cur_attr->uuid 0x20004f94
[17:56:39:861] discovery_process_attribute cur_attr->uuid 0x20004f98
[17:56:39:861] discovery_process_characteristic cur_gatt_chrc->uuid 0x20004f9c
[17:56:39:861] [00:01:06.445,312] <inf> ble_device: Gatt service uuid 1801 -> Second service discovery callback
[17:56:39:861] bt_gatt_dm_data_release
[17:56:39:861] svc_attr_memory_release
[17:56:39:861] call bt_gatt_dm_continue
[17:56:39:861] discovery_process_service cur_service_val->uuid 0x20004f84
[17:56:39:887] discovery_process_attribute cur_attr->uuid 0x20004f90
[17:56:39:887] discovery_process_attribute cur_attr->uuid 0x20004f94
[17:56:39:887] discovery_process_attribute cur_attr->uuid 0x20004fa0
[17:56:39:887] discovery_process_attribute cur_attr->uuid 0x20004fa4
[17:56:39:887] discovery_process_attribute cur_attr->uuid 0x20004fb0
[17:56:39:887] discovery_process_attribute cur_attr->uuid 0x20004fb4
[17:56:40:042] discovery_process_attribute cur_attr->uuid 0x20004fc0
[17:56:40:042] discovery_process_attribute cur_attr->uuid 0x20004fc4
[17:56:40:042] discovery_process_attribute cur_attr->uuid 0x20004fd0
[17:56:40:042] discovery_process_attribute cur_attr->uuid 0x20004fd4
[17:56:40:076] discovery_process_attribute cur_attr->uuid 0x20004fe0
[17:56:40:076] discovery_process_attribute cur_attr->uuid 0x20004fe4
[17:56:40:076] discovery_process_attribute cur_attr->uuid 0x20005008
[17:56:40:076] discovery_process_attribute cur_attr->uuid 0x2000500c
[17:56:40:076] discovery_process_attribute cur_attr->uuid 0x20005018
[17:56:40:076] discovery_process_attribute cur_attr->uuid 0x2000501c
[17:56:40:939] discovery_process_attribute cur_attr->uuid 0x20005028
[17:56:40:939] discovery_process_attribute cur_attr->uuid 0x2000502c
[17:56:40:939] discovery_process_characteristic cur_gatt_chrc->uuid 0x20005030
[17:56:40:973] discovery_process_characteristic cur_gatt_chrc->uuid 0x20005034
[17:56:40:973] discovery_process_characteristic cur_gatt_chrc->uuid 0x20005038
[17:56:40:973] discovery_process_characteristic cur_gatt_chrc->uuid 0x2000503c
[17:56:40:973] discovery_process_characteristic cur_gatt_chrc->uuid 0x20005040
[17:56:40:973] discovery_process_characteristic cur_gatt_chrc->uuid 0x20005044
[17:56:40:973] discovery_process_characteristic cur_gatt_chrc->uuid 0x20005048
[17:56:40:997] discovery_process_characteristic cur_gatt_chrc->uuid 0x2000504c
[17:56:40:997] discovery_process_characteristic cur_gatt_chrc->uuid 0x20005050
[17:56:40:997] [00:01:08.095,336] <inf> ble_device: Gatt service uuid 180a -> Third service discovery callback
[17:56:42:291] bt_gatt_dm_data_release
[17:56:42:291] svc_attr_memory_release
[17:56:42:291] call bt_gatt_dm_continue
[17:56:42:291] discovery_process_service cur_service_val->uuid 0x20004f84
[17:56:42:329] discovery_process_attribute cur_attr->uuid 0x20004fa0
[17:56:42:329] discovery_process_attribute cur_attr->uuid 0x20004fa4
[17:56:43:506] discovery_process_attribute cur_attr->uuid 0x20004fb8
[17:56:43:528] discovery_process_attribute cur_attr->uuid 0x20004fc4
[17:56:43:528] discovery_process_attribute cur_attr->uuid 0x20004fc8
[17:56:43:528] discovery_process_attribute cur_attr->uuid 0x20004fdc
[17:56:44:555] discovery_process_attribute cur_attr->uuid 0x20004fe8
[17:56:44:584] discovery_process_attribute cur_attr->uuid 0x20005000
[17:56:44:584] discovery_process_attribute cur_attr->uuid 0x20005014
[17:56:44:584] discovery_process_attribute cur_attr->uuid 0x20005020
[17:56:44:584] discovery_process_attribute cur_attr->uuid 0x20005024
[17:56:45:607] discovery_process_attribute cur_attr->uuid 0x20005038
[17:56:45:631] discovery_process_attribute cur_attr->uuid 0x2000503c
[17:56:45:631] [00:01:16.845,458] <inf> ble_device: Gatt service uuid cdeacb80-5235-4c07-8846-93a37ee~ -> Fourth service discovery callback
[17:56:50:040] [00:01:16.845,520] <inf> universal_client: Getting handles from characteristic.
[17:56:50:065] bt_gatt_dm_char_by_uuid chrc->uuid 0x20005034
[17:56:50:065] bt_gatt_dm_char_by_uuid chrc->uuid 0x00020018
[17:56:50:065] bt_gatt_dm_char_by_uuid chrc->uuid 0x28030000
[17:56:50:065] [00:01:16.845,733] <err> os: ***** BUS FAULT *****
[17:56:50:065] [00:01:16.845,733] <err> os:   Precise data bus error
[17:56:50:088] [00:01:16.845,733] <err> os:   BFAR Address: 0x28030000
[17:56:50:088] [00:01:16.845,733] <err> os: r0/a1:  0x20000b12  r1/a2:  0x00000002  r2/a3:  0x20002778
[17:56:50:088] [00:01:16.845,764] <err> os: r3/a4:  0x00000005 r12/ip:  0x00000000 r14/lr:  0x0001c345
[17:56:50:088] [00:01:16.845,764] <err> os:  xpsr:  0x81000000
[17:56:50:112] [00:01:16.845,764] <err> os: Faulting instruction address (r15/pc): 0x0002ecb0
[17:56:50:112] [00:01:16.845,764] <err> os: >>> ZEPHYR FATAL ERROR 0: CPU exception on CPU 0
diff --git a/subsys/bluetooth/gatt_dm.c b/subsys/bluetooth/gatt_dm.c
index 4bbcb590..4b7a96a9 100644
--- a/subsys/bluetooth/gatt_dm.c
+++ b/subsys/bluetooth/gatt_dm.c
@@ -110,6 +110,7 @@ static void svc_attr_memory_release(struct bt_gatt_dm *dm)
 	struct data_chunk_item *item;
 
 	LOG_DBG("Attr memory release");
+	printk("svc_attr_memory_release\n");
 
 	/* Clear attributes */
 	dm->cur_attr_id = 0;
@@ -300,6 +301,7 @@ static uint8_t discovery_process_service(struct bt_gatt_dm *dm,
 		discovery_complete_error(dm, -ENOMEM);
 		return BT_GATT_ITER_STOP;
 	}
+	printk("discovery_process_service cur_service_val->uuid %p\n", cur_service_val->uuid);
 
 	if (cur_attr->handle == cur_service_val->end_handle) {
 		/* No characteristics to discover, go to next service. */
@@ -364,6 +366,7 @@ static uint8_t discovery_process_attribute(struct bt_gatt_dm *dm,
 		return BT_GATT_ITER_STOP;
 	}
 
+	printk("discovery_process_attribute cur_attr->uuid %p\n", cur_attr->uuid);
 	return BT_GATT_ITER_CONTINUE;
 }
 
@@ -381,6 +384,7 @@ static uint8_t discovery_process_characteristic(
 		return BT_GATT_ITER_STOP;
 	}
 
+
 	__ASSERT_NO_MSG(bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CHRC) == 0);
 
 	cur_attr = attr_find_by_handle(dm, attr->handle);
@@ -398,6 +402,7 @@ static uint8_t discovery_process_characteristic(
 		discovery_complete_error(dm, -ENOMEM);
 		return BT_GATT_ITER_STOP;
 	}
+	printk("discovery_process_characteristic cur_gatt_chrc->uuid %p\n", cur_gatt_chrc->uuid);
 
 	return BT_GATT_ITER_CONTINUE;
 }
@@ -505,6 +510,7 @@ const struct bt_gatt_dm_attr *bt_gatt_dm_char_by_uuid(
 		struct bt_gatt_chrc *chrc = bt_gatt_dm_attr_chrc_val(curr);
 
 		__ASSERT_NO_MSG(chrc != NULL);
+		printk("bt_gatt_dm_char_by_uuid chrc->uuid %p\n", chrc->uuid);
 		if (!bt_uuid_cmp(uuid, chrc->uuid)) {
 			return curr;
 		}
@@ -657,6 +663,7 @@ int bt_gatt_dm_continue(struct bt_gatt_dm *dm, void *context)
 
 int bt_gatt_dm_data_release(struct bt_gatt_dm *dm)
 {
+	printk("bt_gatt_dm_data_release\n");
 	if (!atomic_test_and_clear_bit(dm->state_flags,
 				       STATE_ATTRS_RELEASE_PENDING)) {
 		return -EALREADY;

[17:56:50:065] bt_gatt_dm_char_by_uuid chrc->uuid 0x20005034
this is first characteristic checked in bt_gatt_dm_attr_chrc_val function. This address was previously used for storing characteristics from service number 3 (180a), but this memory was released in svc_attr_memory_release

Environment (please complete the following information):

  • OS: Linux
  • Toolchain Zephyr SDK
  • nrf tag: v1.4.2 (a61d43c681eb7e2609a01c1929ae6e2113d7f9a2)

Additional context
I developed workaround for problem. I'm counting discovered characteristics in discovery_process_characteristic - if counter is 0 when att=NULL (in discovery_process_characteristic) I'm calling discovery_error callback. Looks that this works, at least for devices that I'm working with. Not sure it this can be problem with different devices - can we have no characteristics in Service?

Parents Reply Children
No Data
Related