2023-03-10 00:04:00

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ 1/2] main: Disable EATT by default

From: Luiz Augusto von Dentz <[email protected]>

EATT is causing some problem with some platforms as they also attempt to
configure it may cause a connection collision which needs to be handled
by the kernel.
---
src/main.c | 2 +-
src/main.conf | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/main.c b/src/main.c
index 2a4d9be05d7a..3198091fc12c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1148,7 +1148,7 @@ static void init_defaults(void)

btd_opts.gatt_cache = BT_GATT_CACHE_ALWAYS;
btd_opts.gatt_mtu = BT_ATT_MAX_LE_MTU;
- btd_opts.gatt_channels = 3;
+ btd_opts.gatt_channels = 1;

btd_opts.avdtp.session_mode = BT_IO_MODE_BASIC;
btd_opts.avdtp.stream_mode = BT_IO_MODE_BASIC;
diff --git a/src/main.conf b/src/main.conf
index 11172c9dd7c6..d108934a8ae9 100644
--- a/src/main.conf
+++ b/src/main.conf
@@ -255,8 +255,8 @@

# Number of ATT channels
# Possible values: 1-5 (1 disables EATT)
-# Default to 3
-#Channels = 3
+# Default to 1
+#Channels = 1

[CSIS]
# SIRK - Set Identification Resolution Key which is common for all the
--
2.39.2



2023-03-10 00:04:02

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ 2/2] gatt: Use DEFER_SETUP for EATT channels

From: Luiz Augusto von Dentz <[email protected]>

This makes use of DEFER_SETUP mechanism to do the following checks
before accepting the connection:

- Checks a valid device object exits
- Checks if initiator/central as if the peripheral start connecting it
may cause collisions.
- Checks if the limit of allowed connections has been reached.
---
src/device.c | 6 ++--
src/device.h | 1 +
src/gatt-database.c | 88 +++++++++++++++++++++++++++++++++++----------
3 files changed, 73 insertions(+), 22 deletions(-)

diff --git a/src/device.c b/src/device.c
index 652c03606b9e..77b38e97a7ea 100644
--- a/src/device.c
+++ b/src/device.c
@@ -310,7 +310,7 @@ static struct bearer_state *get_state(struct btd_device *dev,
return &dev->le_state;
}

-static bool get_initiator(struct btd_device *dev)
+bool btd_device_is_initiator(struct btd_device *dev)
{
if (dev->le_state.connected)
return dev->le_state.initiator;
@@ -3964,7 +3964,7 @@ done:
}

/* Notify driver about the new connection */
- service_accept(service, get_initiator(device));
+ service_accept(service, btd_device_is_initiator(device));
}

static void device_add_gatt_services(struct btd_device *device)
@@ -3984,7 +3984,7 @@ static void device_add_gatt_services(struct btd_device *device)
static void device_accept_gatt_profiles(struct btd_device *device)
{
GSList *l;
- bool initiator = get_initiator(device);
+ bool initiator = btd_device_is_initiator(device);

DBG("initiator %s", initiator ? "true" : "false");

diff --git a/src/device.h b/src/device.h
index 96347ff229cc..3252e14eff84 100644
--- a/src/device.h
+++ b/src/device.h
@@ -67,6 +67,7 @@ GSList *btd_device_get_primaries(struct btd_device *device);
struct gatt_db *btd_device_get_gatt_db(struct btd_device *device);
struct bt_gatt_client *btd_device_get_gatt_client(struct btd_device *device);
struct bt_gatt_server *btd_device_get_gatt_server(struct btd_device *device);
+bool btd_device_is_initiator(struct btd_device *device);
void *btd_device_get_attrib(struct btd_device *device);
void btd_device_gatt_set_service_changed(struct btd_device *device,
uint16_t start, uint16_t end);
diff --git a/src/gatt-database.c b/src/gatt-database.c
index 3b53bf2a3c84..01dd84e8e3f7 100644
--- a/src/gatt-database.c
+++ b/src/gatt-database.c
@@ -632,7 +632,6 @@ static void connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
struct btd_device *device;
uint8_t dst_type;
bdaddr_t src, dst;
- uint16_t cid;

if (gerr) {
error("%s", gerr->message);
@@ -642,7 +641,6 @@ static void connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
bt_io_get(io, &gerr, BT_IO_OPT_SOURCE_BDADDR, &src,
BT_IO_OPT_DEST_BDADDR, &dst,
BT_IO_OPT_DEST_TYPE, &dst_type,
- BT_IO_OPT_CID, &cid,
BT_IO_OPT_INVALID);
if (gerr) {
error("bt_io_get: %s", gerr->message);
@@ -657,21 +655,9 @@ static void connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
if (!adapter)
return;

- /* Check cid before attempting to create device, if the device is using
- * an RPA it could be that the MGMT event has not been processed yet
- * which would lead to create a second copy of the same device using its
- * identity address.
- */
- if (cid == BT_ATT_CID)
- device = btd_adapter_get_device(adapter, &dst, dst_type);
- else
- device = btd_adapter_find_device(adapter, &dst, dst_type);
-
- if (!device) {
- error("Unable to find device, dropping connection attempt");
- g_io_channel_shutdown(io, FALSE, NULL);
+ device = btd_adapter_get_device(adapter, &dst, dst_type);
+ if (!device)
return;
- }

device_attach_att(device, io);
}
@@ -3802,6 +3788,70 @@ static uint8_t server_authorize(struct bt_att *att, uint8_t opcode,
return BT_ATT_ERROR_DB_OUT_OF_SYNC;
}

+static void eatt_confirm_cb(GIOChannel *io, gpointer data)
+{
+ char address[18];
+ uint8_t dst_type;
+ bdaddr_t src, dst;
+ GError *gerr = NULL;
+ struct btd_device *device;
+ struct bt_gatt_server *server;
+ struct bt_att *att;
+
+ bt_io_get(io, &gerr, BT_IO_OPT_SOURCE_BDADDR, &src,
+ BT_IO_OPT_DEST_BDADDR, &dst,
+ BT_IO_OPT_DEST_TYPE, &dst_type,
+ BT_IO_OPT_DEST, address,
+ BT_IO_OPT_INVALID);
+ if (gerr) {
+ error("bt_io_get: %s", gerr->message);
+ g_error_free(gerr);
+ goto drop;
+ }
+
+ DBG("New incoming EATT connection");
+
+ /* Confirm the device exists before accepting the connection, if the
+ * device is using an RPA it could be that the MGMT event has not been
+ * processed yet which would lead to create a second copy of the same
+ * device using its identity address.
+ */
+ device = btd_adapter_find_device(adapter_find(&src), &dst, dst_type);
+ if (!device) {
+ error("Unable to find device: %s", address);
+ goto drop;
+ }
+
+ /* Only allow EATT connection from central */
+ if (btd_device_is_initiator(device)) {
+ warn("EATT connection from peripheral may cause collisions");
+ goto drop;
+ }
+
+ server = btd_device_get_gatt_server(device);
+ if (!server) {
+ error("Unable to resolve bt_server");
+ goto drop;
+ }
+
+ att = bt_gatt_server_get_att(server);
+ if (bt_att_get_channels(att) == btd_opts.gatt_channels) {
+ DBG("EATT channel limit reached");
+ goto drop;
+ }
+
+ if (!bt_io_accept(io, connect_cb, NULL, NULL, &gerr)) {
+ error("bt_io_accept: %s", gerr->message);
+ g_error_free(gerr);
+ goto drop;
+ }
+
+ return;
+
+drop:
+ g_io_channel_shutdown(io, TRUE, NULL);
+}
+
struct btd_gatt_database *btd_gatt_database_new(struct btd_adapter *adapter)
{
struct btd_gatt_database *database;
@@ -3838,14 +3888,14 @@ struct btd_gatt_database *btd_gatt_database_new(struct btd_adapter *adapter)
if (btd_opts.gatt_channels == 1)
goto bredr;

- /* EATT socket */
- database->eatt_io = bt_io_listen(connect_cb, NULL, NULL, NULL,
+ /* EATT socket, encryption is required */
+ database->eatt_io = bt_io_listen(NULL, eatt_confirm_cb, NULL, NULL,
&gerr,
BT_IO_OPT_SOURCE_BDADDR, addr,
BT_IO_OPT_SOURCE_TYPE,
btd_adapter_get_address_type(adapter),
BT_IO_OPT_PSM, BT_ATT_EATT_PSM,
- BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
BT_IO_OPT_MTU, btd_opts.gatt_mtu,
BT_IO_OPT_INVALID);
if (!database->eatt_io) {
--
2.39.2


2023-03-10 01:13:18

by bluez.test.bot

[permalink] [raw]
Subject: RE: [BlueZ,1/2] main: Disable EATT by default

This is an automated email and please do not reply to this email.

Dear Submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
While preparing the CI tests, the patches you submitted couldn't be applied to the current HEAD of the repository.

----- Output -----

error: patch failed: src/main.conf:255
error: src/main.conf: patch does not apply
hint: Use 'git am --show-current-patch' to see the failed patch

Please resolve the issue and submit the patches again.


---
Regards,
Linux Bluetooth