All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH BlueZ v1 1/4] gatt-server: Check prepare write length before reallocating
@ 2026-09-10 18:42 Luiz Augusto von Dentz
  2026-09-10 18:42 ` [PATCH BlueZ v1 2/4] adapter: Unify the A2DP admin allowlist UUID mapping Luiz Augusto von Dentz
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Luiz Augusto von Dentz @ 2026-09-10 18:42 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

append_prep_data() grew the buffer and copied the new fragment into it
before rejecting a total length above UINT16_MAX. On overflow the
allocation had already been enlarged and written while prep_data->length
was left at its previous value, desynchronising the buffer from its
tracked size.

Move the bound check ahead of the realloc() so an oversized prepare
write queue is rejected without touching the buffer.

Assisted-by: opencode:claude-opus-5
---
 src/shared/gatt-server.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/shared/gatt-server.c b/src/shared/gatt-server.c
index 516fceb8ed00..fde791aae867 100644
--- a/src/shared/gatt-server.c
+++ b/src/shared/gatt-server.c
@@ -1207,6 +1207,8 @@ static bool append_prep_data(struct prep_write_data *prep_data, uint16_t handle,
 		return true;
 
 	len = (size_t)prep_data->length + (size_t)length;
+	if (len > UINT16_MAX)
+		return false;
 
 	val = realloc(prep_data->value, len);
 	if (!val)
@@ -1215,9 +1217,6 @@ static bool append_prep_data(struct prep_write_data *prep_data, uint16_t handle,
 	memcpy(val + prep_data->length, value, length);
 
 	prep_data->value = val;
-
-	if (len > UINT16_MAX)
-		return false;
 	prep_data->length = (uint16_t)len;
 
 	return true;
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH BlueZ v1 2/4] adapter: Unify the A2DP admin allowlist UUID mapping
  2026-09-10 18:42 [PATCH BlueZ v1 1/4] gatt-server: Check prepare write length before reallocating Luiz Augusto von Dentz
@ 2026-09-10 18:42 ` Luiz Augusto von Dentz
  2026-09-10 18:42 ` [PATCH BlueZ v1 3/4] battery: Document the unknown sentinels and fix a stale name Luiz Augusto von Dentz
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Luiz Augusto von Dentz @ 2026-09-10 18:42 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

The allowlist enforcement added across the adapter, device and A2DP
layers ended up using three different UUIDs for the same two profiles:
adapter.c mapped both a2dp-source and a2dp-sink to ADVANCED_AUDIO_UUID
(0x110d), while device.c and a2dp.c mapped them to the local role UUIDs
0x110a and 0x110b. An allowlist containing only 0x110a therefore blocked
the a2dp-sink adapter probe outright, so the finer grained SEP checks in
a2dp.c never ran.

Add btd_profile_get_policy_uuid() as the single place resolving a
profile to the UUID of the local service it provides. btd_profile names
and remote_uuid describe the remote role, so the A2DP profiles are
inverted there: "a2dp-source" registers the local Sink server and
"a2dp-sink" registers the local Source server. This matches what
device.c and a2dp.c already do.

Note that allowlisting 0x110d alone no longer enables A2DP; the local
role UUIDs 0x110a and/or 0x110b have to be listed.

This also drops the hardcoded profile name table in adapter.c. Every
entry but the two A2DP ones just returned profile->remote_uuid, and any
profile without a local_uuid that was missing from the table resolved to
NULL, i.e. was allowed unconditionally regardless of the allowlist.

Assisted-by: opencode:claude-opus-5
---
 src/adapter.c | 49 +------------------------------------------------
 src/device.c  | 25 ++-----------------------
 src/profile.c | 24 ++++++++++++++++++++++++
 src/profile.h |  7 +++++++
 4 files changed, 34 insertions(+), 71 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 157d7392d32c..fc734424be07 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -5353,59 +5353,12 @@ static void load_drivers(struct btd_adapter *adapter)
 		probe_driver(adapter, l->data);
 }
 
-struct profile_allowlist_map {
-	const char *name;
-	const char *uuid;
-	bool use_remote_uuid;
-};
-
-/*
- * Adapter server policy UUID defaults to local_uuid when available.
- * Profiles listed below are exceptions.
- *
- * A2DP profiles map to ADVANCED_AUDIO_UUID so profile probe gating matches
- * the A2DP profile class (0x110d), while adapter service registration/removal
- * still filters specific Source/Sink records by their own UUIDs.
- */
-static const struct profile_allowlist_map profile_allowlist_map[] = {
-	{ "a2dp-source", ADVANCED_AUDIO_UUID, false },
-	{ "a2dp-sink", ADVANCED_AUDIO_UUID, false },
-	{ "audio-avrcp-target", NULL, true },
-	{ "avrcp-controller", NULL, true },
-	{ "vcp", NULL, true },
-	{ "micp", NULL, true },
-	{ "ccp", NULL, true },
-	{ "gmap", NULL, true },
-	{ "tmap", NULL, true },
-	{ "bass", NULL, true },
-	{ "bap", NULL, true },
-	{ "mcp-gmcs", NULL, true },
-};
-
 static const char *profile_allowlist_uuid(const struct btd_profile *profile)
 {
-	size_t i;
-
 	if (profile->local_uuid)
 		return profile->local_uuid;
 
-	if (!profile->name)
-		return NULL;
-
-	for (i = 0; i < ARRAY_SIZE(profile_allowlist_map); i++) {
-		const struct profile_allowlist_map *entry =
-						&profile_allowlist_map[i];
-
-		if (strcmp(profile->name, entry->name))
-			continue;
-
-		if (entry->use_remote_uuid)
-			return profile->remote_uuid;
-
-		return entry->uuid;
-	}
-
-	return NULL;
+	return btd_profile_get_policy_uuid(profile);
 }
 
 bool btd_adapter_is_profile_allowed(struct btd_adapter *adapter,
diff --git a/src/device.c b/src/device.c
index 8da576ec5932..ec74c44ac4aa 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2547,27 +2547,6 @@ static struct btd_service *find_connectable_service(struct btd_device *dev,
 	return NULL;
 }
 
-static const char *service_policy_uuid(const struct btd_profile *profile)
-{
-	if (!profile)
-		return NULL;
-
-	/*
-	 * For A2DP device services, apply admin policy by local role UUID:
-	 * - a2dp-sink profile is local source role  (110a)
-	 * - a2dp-source profile is local sink role  (110b)
-	 */
-	if (profile->name) {
-		if (!strcmp(profile->name, "a2dp-sink"))
-			return A2DP_SOURCE_UUID;
-
-		if (!strcmp(profile->name, "a2dp-source"))
-			return A2DP_SINK_UUID;
-	}
-
-	return profile->remote_uuid;
-}
-
 bool btd_device_all_services_allowed(struct btd_device *dev)
 {
 	GSList *l;
@@ -2579,7 +2558,7 @@ bool btd_device_all_services_allowed(struct btd_device *dev)
 	for (l = dev->services; l != NULL; l = g_slist_next(l)) {
 		service = l->data;
 		profile = btd_service_get_profile(service);
-		uuid = service_policy_uuid(profile);
+		uuid = btd_profile_get_policy_uuid(profile);
 
 		if (!profile || !profile->auto_connect || !uuid)
 			continue;
@@ -2614,7 +2593,7 @@ void btd_device_update_allowed_services(struct btd_device *dev)
 	for (l = dev->services; l != NULL; l = g_slist_next(l)) {
 		service = l->data;
 		profile = btd_service_get_profile(service);
-		uuid = service_policy_uuid(profile);
+		uuid = btd_profile_get_policy_uuid(profile);
 
 		if (!profile || !uuid)
 			continue;
diff --git a/src/profile.c b/src/profile.c
index 97fffe9b4d5c..e5b1cdfc5d33 100644
--- a/src/profile.c
+++ b/src/profile.c
@@ -16,6 +16,7 @@
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdlib.h>
+#include <string.h>
 #include <errno.h>
 
 #include <glib.h>
@@ -753,6 +754,29 @@ void btd_profile_foreach(void (*func)(struct btd_profile *p, void *data),
 	}
 }
 
+const char *btd_profile_get_policy_uuid(const struct btd_profile *profile)
+{
+	if (!profile)
+		return NULL;
+
+	/*
+	 * The admin allowlist is expressed in terms of the services the local
+	 * adapter exposes, while btd_profile names and remote_uuid describe
+	 * the remote role. The A2DP profiles therefore have to be inverted:
+	 * the "a2dp-source" profile drives the local Sink server and the
+	 * "a2dp-sink" profile drives the local Source server.
+	 */
+	if (profile->name) {
+		if (!strcmp(profile->name, "a2dp-source"))
+			return A2DP_SINK_UUID;
+
+		if (!strcmp(profile->name, "a2dp-sink"))
+			return A2DP_SOURCE_UUID;
+	}
+
+	return profile->remote_uuid;
+}
+
 static struct btd_profile *btd_profile_find_uuid(const char *uuid)
 {
 	GSList *l, *next;
diff --git a/src/profile.h b/src/profile.h
index 04a99528b4be..270f09ea2b96 100644
--- a/src/profile.h
+++ b/src/profile.h
@@ -84,6 +84,13 @@ struct btd_profile {
 void btd_profile_foreach(void (*func)(struct btd_profile *p, void *data),
 								void *data);
 
+/*
+ * Return the UUID of the local service a profile provides, for use by the
+ * admin policy allowlist. Returns NULL when the profile has no service to
+ * match against.
+ */
+const char *btd_profile_get_policy_uuid(const struct btd_profile *profile);
+
 int btd_profile_register(struct btd_profile *profile);
 void btd_profile_unregister(struct btd_profile *profile);
 
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH BlueZ v1 3/4] battery: Document the unknown sentinels and fix a stale name
  2026-09-10 18:42 [PATCH BlueZ v1 1/4] gatt-server: Check prepare write length before reallocating Luiz Augusto von Dentz
  2026-09-10 18:42 ` [PATCH BlueZ v1 2/4] adapter: Unify the A2DP admin allowlist UUID mapping Luiz Augusto von Dentz
@ 2026-09-10 18:42 ` Luiz Augusto von Dentz
  2026-09-10 18:42 ` [PATCH BlueZ v1 4/4] client/bluetoothctl: Declare the controller helper in its own header Luiz Augusto von Dentz
  2026-09-10 20:06 ` [BlueZ,v1,1/4] gatt-server: Check prepare write length before reallocating bluez.test.bot
  3 siblings, 0 replies; 5+ messages in thread
From: Luiz Augusto von Dentz @ 2026-09-10 18:42 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

btd_battery_update() treats UINT8_MAX and btd_battery_update_charging()
treats -1 as "unknown", invalidating the D-Bus property rather than
setting it. Neither was documented at the prototypes.

Also rename unregister_if_path_has_prefix() to
unregister_if_provider_matches(); it no longer compares path prefixes,
it compares the owning provider.

Assisted-by: opencode:claude-opus-5
---
 src/battery.c | 4 ++--
 src/battery.h | 8 ++++++++
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/battery.c b/src/battery.c
index 181bf3846d52..dbfe56881259 100644
--- a/src/battery.c
+++ b/src/battery.c
@@ -664,7 +664,7 @@ static bool match_provider_path(const void *data, const void *user_data)
 	return strcmp(provider->path, path) == 0;
 }
 
-static void unregister_if_path_has_prefix(void *data, void *user_data)
+static void unregister_if_provider_matches(void *data, void *user_data)
 {
 	struct btd_battery *battery = data;
 	struct battery_provider *provider = user_data;
@@ -678,7 +678,7 @@ static void battery_provider_free(gpointer data)
 	struct battery_provider *provider = data;
 
 	/* Unregister batteries registered by this provider. */
-	queue_foreach(batteries, unregister_if_path_has_prefix, provider);
+	queue_foreach(batteries, unregister_if_provider_matches, provider);
 
 	if (provider->owner)
 		g_free(provider->owner);
diff --git a/src/battery.h b/src/battery.h
index 2b459809cba6..5990c8e0b87f 100644
--- a/src/battery.h
+++ b/src/battery.h
@@ -18,7 +18,15 @@ struct btd_battery *btd_battery_register_component(const char *device_path,
 					 const char *identifier,
 					 const char *source);
 bool btd_battery_unregister(struct btd_battery *battery);
+
+/* Pass UINT8_MAX as percentage to mark the level as unknown, which
+ * invalidates the Percentage property instead of setting it.
+ */
 bool btd_battery_update(struct btd_battery *battery, uint8_t percentage);
+
+/* charging is 0 or 1 when known, or -1 to mark the state as unknown, which
+ * invalidates the Charging property instead of setting it.
+ */
 bool btd_battery_update_charging(struct btd_battery *battery, int charging);
 
 struct btd_battery_provider_manager *
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH BlueZ v1 4/4] client/bluetoothctl: Declare the controller helper in its own header
  2026-09-10 18:42 [PATCH BlueZ v1 1/4] gatt-server: Check prepare write length before reallocating Luiz Augusto von Dentz
  2026-09-10 18:42 ` [PATCH BlueZ v1 2/4] adapter: Unify the A2DP admin allowlist UUID mapping Luiz Augusto von Dentz
  2026-09-10 18:42 ` [PATCH BlueZ v1 3/4] battery: Document the unknown sentinels and fix a stale name Luiz Augusto von Dentz
@ 2026-09-10 18:42 ` Luiz Augusto von Dentz
  2026-09-10 20:06 ` [BlueZ,v1,1/4] gatt-server: Check prepare write length before reallocating bluez.test.bot
  3 siblings, 0 replies; 5+ messages in thread
From: Luiz Augusto von Dentz @ 2026-09-10 18:42 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

bluetoothctl_get_default_controller() is implemented in main.c but was
declared in admin.h, the header of one of the submenus that consumes it.
Move the declaration to a new client/main.h so main.c also sees it.

While at it, drop the bluetooth/bluetooth.h include added to admin.c,
which is unused.

Assisted-by: opencode:claude-opus-5
---
 Makefile.tools |  1 +
 client/admin.c |  2 +-
 client/admin.h |  2 --
 client/main.c  |  1 +
 client/main.h  | 11 +++++++++++
 5 files changed, 14 insertions(+), 3 deletions(-)
 create mode 100644 client/main.h

diff --git a/Makefile.tools b/Makefile.tools
index cb113f96161e..6844a52ac739 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -12,6 +12,7 @@ client_bluetoothctl_SOURCES = client/main.c \
 					client/adv_monitor.c \
 					client/gatt.h client/gatt.c \
 					client/admin.h client/admin.c \
+					client/main.h \
 					client/player.h client/player.c \
 					client/mgmt.h client/mgmt.c \
 					client/assistant.h client/assistant.c \
diff --git a/client/admin.c b/client/admin.c
index a6fba2f1ce1d..98276f56c652 100644
--- a/client/admin.c
+++ b/client/admin.c
@@ -16,11 +16,11 @@
 #include <string.h>
 #include <stdlib.h>
 
-#include "bluetooth/bluetooth.h"
 #include "gdbus/gdbus.h"
 #include "src/shared/shell.h"
 
 #include "admin.h"
+#include "main.h"
 #define _GNU_SOURCE
 
 static DBusConnection *dbus_conn;
diff --git a/client/admin.h b/client/admin.h
index 00423d9d35cb..0047770dc737 100644
--- a/client/admin.h
+++ b/client/admin.h
@@ -10,5 +10,3 @@
 
 void admin_add_submenu(void);
 void admin_remove_submenu(void);
-
-GDBusProxy *bluetoothctl_get_default_controller(void);
diff --git a/client/main.c b/client/main.c
index d8d2e32d9556..8f7a7c4135ca 100644
--- a/client/main.c
+++ b/client/main.c
@@ -28,6 +28,7 @@
 #include "src/shared/util.h"
 #include "src/shared/ad.h"
 #include "gdbus/gdbus.h"
+#include "main.h"
 #include "print.h"
 #include "agent.h"
 #include "gatt.h"
diff --git a/client/main.h b/client/main.h
new file mode 100644
index 000000000000..0d2af5c5014c
--- /dev/null
+++ b/client/main.h
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2026  Collabora Ltd.
+ *
+ *
+ */
+
+GDBusProxy *bluetoothctl_get_default_controller(void);
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* RE: [BlueZ,v1,1/4] gatt-server: Check prepare write length before reallocating
  2026-09-10 18:42 [PATCH BlueZ v1 1/4] gatt-server: Check prepare write length before reallocating Luiz Augusto von Dentz
                   ` (2 preceding siblings ...)
  2026-09-10 18:42 ` [PATCH BlueZ v1 4/4] client/bluetoothctl: Declare the controller helper in its own header Luiz Augusto von Dentz
@ 2026-09-10 20:06 ` bluez.test.bot
  3 siblings, 0 replies; 5+ messages in thread
From: bluez.test.bot @ 2026-09-10 20:06 UTC (permalink / raw)
  To: linux-bluetooth, luiz.dentz

[-- Attachment #1: Type: text/plain, Size: 1263 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/series/1162311/

---Test result---

Test Summary:
CheckPatch                    PASS      1.18 seconds
GitLint                       FAIL      0.78 seconds
BuildEll                      PASS      19.61 seconds
BluezMake                     PASS      382.03 seconds
MakeCheck                     PASS      14.41 seconds
MakeDistcheck                 PASS      138.47 seconds
CheckValgrind                 PASS      233.42 seconds
CheckSmatch                   PASS      288.75 seconds
bluezmakeextell               PASS      92.09 seconds
IncrementalBuild              PASS      423.28 seconds
ScanBuild                     PASS      1123.91 seconds

Details
##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[BlueZ,v1,4/4] client/bluetoothctl: Declare the controller helper in its own header

1: T1 Title exceeds max length (83>80): "[BlueZ,v1,4/4] client/bluetoothctl: Declare the controller helper in its own header"


https://github.com/bluez/bluez/pull/2518

---
Regards,
Linux Bluetooth


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-09-10 20:06 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-10 18:42 [PATCH BlueZ v1 1/4] gatt-server: Check prepare write length before reallocating Luiz Augusto von Dentz
2026-09-10 18:42 ` [PATCH BlueZ v1 2/4] adapter: Unify the A2DP admin allowlist UUID mapping Luiz Augusto von Dentz
2026-09-10 18:42 ` [PATCH BlueZ v1 3/4] battery: Document the unknown sentinels and fix a stale name Luiz Augusto von Dentz
2026-09-10 18:42 ` [PATCH BlueZ v1 4/4] client/bluetoothctl: Declare the controller helper in its own header Luiz Augusto von Dentz
2026-09-10 20:06 ` [BlueZ,v1,1/4] gatt-server: Check prepare write length before reallocating bluez.test.bot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.