| 1 | From 5bc6aa79e53700d56fc1f9f9364573ba4c78da65 Mon Sep 17 00:00:00 2001
|
| 2 | From: Luiz Augusto von Dentz <[email protected]>
|
| 3 | Date: Thu, 2 Jul 2026 11:43:52 -0400
|
| 4 | Subject: adapter: Fix crash on dev_disconnected
|
| 5 |
|
| 6 | Commit 5d836f1c697c ("adapter: Fix failed bonding attempt after LE
|
| 7 | link disconnection") introduces a regression since it attempts to
|
| 8 | call device_is_connected after adapter_remove_connection which may
|
| 9 | free the device causing the following backtrace:
|
| 10 |
|
| 11 | #0 0x5cd6e384262f in btd_device_bearer_is_connected src/device.c:3754
|
| 12 | #1 0x5cd6e384266f in btd_device_is_connected src/device.c:3745
|
| 13 | #2 0x5cd6e37f8614 in dev_disconnected src/adapter.c:8626
|
| 14 |
|
| 15 | Fixes: https://github.com/bluez/bluez/issues/2221
|
| 16 | ---
|
| 17 | src/adapter.c | 25 +++++++++++++++++++++----
|
| 18 | 1 file changed, 21 insertions(+), 4 deletions(-)
|
| 19 |
|
| 20 | diff --git a/src/adapter.c b/src/adapter.c
|
| 21 | index 538f63e0a..210225243 100644
|
| 22 | |
| 23 | |
| 24 | @@ -7612,12 +7612,16 @@ struct agent *adapter_get_agent(struct btd_adapter *adapter)
|
| 25 | static void adapter_remove_connection(struct btd_adapter *adapter,
|
| 26 | struct btd_device *device,
|
| 27 | uint8_t bdaddr_type,
|
| 28 | - uint8_t reason)
|
| 29 | + uint8_t reason,
|
| 30 | + bool *removed)
|
| 31 | {
|
| 32 | bool remove_device = false;
|
| 33 |
|
| 34 | DBG("");
|
| 35 |
|
| 36 | + if (removed)
|
| 37 | + *removed = false;
|
| 38 | +
|
| 39 | if (!g_slist_find(adapter->connections, device)) {
|
| 40 | btd_error(adapter->dev_id, "No matching connection for device");
|
| 41 | return;
|
| 42 | @@ -7638,6 +7642,9 @@ static void adapter_remove_connection(struct btd_adapter *adapter,
|
| 43 |
|
| 44 | DBG("Removing temporary device %s", path);
|
| 45 | btd_adapter_remove_device(adapter, device);
|
| 46 | +
|
| 47 | + if (removed)
|
| 48 | + *removed = true;
|
| 49 | }
|
| 50 | }
|
| 51 |
|
| 52 | @@ -7665,10 +7672,10 @@ static void adapter_stop(struct btd_adapter *adapter)
|
| 53 | uint8_t addr_type = btd_device_get_bdaddr_type(device);
|
| 54 |
|
| 55 | adapter_remove_connection(adapter, device, BDADDR_BREDR,
|
| 56 | - MGMT_DEV_DISCONN_UNKNOWN);
|
| 57 | + MGMT_DEV_DISCONN_UNKNOWN, NULL);
|
| 58 | if (addr_type != BDADDR_BREDR)
|
| 59 | adapter_remove_connection(adapter, device, addr_type,
|
| 60 | - MGMT_DEV_DISCONN_UNKNOWN);
|
| 61 | + MGMT_DEV_DISCONN_UNKNOWN, NULL);
|
| 62 | }
|
| 63 |
|
| 64 | g_dbus_emit_property_changed(dbus_conn, adapter->path,
|
| 65 | @@ -8618,7 +8625,17 @@ static void dev_disconnected(struct btd_adapter *adapter,
|
| 66 |
|
| 67 | device = btd_adapter_find_device(adapter, &addr->bdaddr, addr->type);
|
| 68 | if (device) {
|
| 69 | - adapter_remove_connection(adapter, device, addr->type, reason);
|
| 70 | + bool removed;
|
| 71 | +
|
| 72 | + adapter_remove_connection(adapter, device, addr->type, reason,
|
| 73 | + &removed);
|
| 74 | + /* No need to continue if device was removed from the adapter,
|
| 75 | + * as it will be freed and the disconnect notify will be called
|
| 76 | + * in the device free callback.
|
| 77 | + */
|
| 78 | + if (removed)
|
| 79 | + return;
|
| 80 | +
|
| 81 | disconnect_notify(device, reason);
|
| 82 | }
|
| 83 |
|
| 84 | --
|
| 85 | cgit 1.3-korg
|
| 86 |
|