public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
From: Bastien Nocera <hadess@hadess.net>
To: git-commits@fedoraproject.org
Subject: [rpms/bluez] f43: Update to latest upstream HEAD to fix a number of possible crashes
Date: Fri, 17 Jul 2026 12:29:46 GMT	[thread overview]
Message-ID: <178429138636.1.1830937039761259664.rpms-bluez-0bb713b6503e@fedoraproject.org> (raw)

A new commit has been pushed.

Repo   : rpms/bluez
Branch : f43
Commit : 0bb713b6503eb7e8bc237cf2aa18772b5aa5222c
Author : Bastien Nocera <hadess@hadess.net>
Date   : 2026-07-17T14:29:34+02:00
Stats  : +2383/-89 in 3 file(s)
URL    : https://src.fedoraproject.org/rpms/bluez/c/0bb713b6503eb7e8bc237cf2aa18772b5aa5222c?branch=f43

Log:
Update to latest upstream HEAD to fix a number of possible crashes

---
diff --git a/0001-adapter-Fix-crash-on-dev_disconnected.patch b/0001-adapter-Fix-crash-on-dev_disconnected.patch
deleted file mode 100644
index 1723c41..0000000
--- a/0001-adapter-Fix-crash-on-dev_disconnected.patch
+++ /dev/null
@@ -1,86 +0,0 @@
-From 5bc6aa79e53700d56fc1f9f9364573ba4c78da65 Mon Sep 17 00:00:00 2001
-From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
-Date: Thu, 2 Jul 2026 11:43:52 -0400
-Subject: [PATCH] adapter: Fix crash on dev_disconnected
-
-Commit 5d836f1c697c ("adapter: Fix failed bonding attempt after LE
-link disconnection") introduces a regression since it attempts to
-call device_is_connected after adapter_remove_connection which may
-free the device causing the following backtrace:
-
-    #0 0x5cd6e384262f in btd_device_bearer_is_connected src/device.c:3754
-    #1 0x5cd6e384266f in btd_device_is_connected src/device.c:3745
-    #2 0x5cd6e37f8614 in dev_disconnected src/adapter.c:8626
-
-Fixes: https://github.com/bluez/bluez/issues/2221
----
- src/adapter.c | 25 +++++++++++++++++++++----
- 1 file changed, 21 insertions(+), 4 deletions(-)
-
-diff --git a/src/adapter.c b/src/adapter.c
-index 538f63e0a153..210225243f00 100644
---- a/src/adapter.c
-+++ b/src/adapter.c
-@@ -7612,12 +7612,16 @@ struct agent *adapter_get_agent(struct btd_adapter *adapter)
- static void adapter_remove_connection(struct btd_adapter *adapter,
- 						struct btd_device *device,
- 						uint8_t bdaddr_type,
--						uint8_t reason)
-+						uint8_t reason,
-+						bool *removed)
- {
- 	bool remove_device = false;
- 
- 	DBG("");
- 
-+	if (removed)
-+		*removed = false;
-+
- 	if (!g_slist_find(adapter->connections, device)) {
- 		btd_error(adapter->dev_id, "No matching connection for device");
- 		return;
-@@ -7638,6 +7642,9 @@ static void adapter_remove_connection(struct btd_adapter *adapter,
- 
- 		DBG("Removing temporary device %s", path);
- 		btd_adapter_remove_device(adapter, device);
-+
-+		if (removed)
-+			*removed = true;
- 	}
- }
- 
-@@ -7665,10 +7672,10 @@ static void adapter_stop(struct btd_adapter *adapter)
- 		uint8_t addr_type = btd_device_get_bdaddr_type(device);
- 
- 		adapter_remove_connection(adapter, device, BDADDR_BREDR,
--						MGMT_DEV_DISCONN_UNKNOWN);
-+						MGMT_DEV_DISCONN_UNKNOWN, NULL);
- 		if (addr_type != BDADDR_BREDR)
- 			adapter_remove_connection(adapter, device, addr_type,
--						MGMT_DEV_DISCONN_UNKNOWN);
-+						MGMT_DEV_DISCONN_UNKNOWN, NULL);
- 	}
- 
- 	g_dbus_emit_property_changed(dbus_conn, adapter->path,
-@@ -8618,7 +8625,17 @@ static void dev_disconnected(struct btd_adapter *adapter,
- 
- 	device = btd_adapter_find_device(adapter, &addr->bdaddr, addr->type);
- 	if (device) {
--		adapter_remove_connection(adapter, device, addr->type, reason);
-+		bool removed;
-+
-+		adapter_remove_connection(adapter, device, addr->type, reason,
-+						&removed);
-+		/* No need to continue if device was removed from the adapter,
-+		 * as it will be freed and the disconnect notify will be called
-+		 * in the device free callback.
-+		 */
-+		if (removed)
-+			return;
-+
- 		disconnect_notify(device, reason);
- 	}
- 
--- 
-2.54.0
-

diff --git a/5.87-bug-fixes-1.patch b/5.87-bug-fixes-1.patch
new file mode 100644
index 0000000..3915783
--- /dev/null
+++ b/5.87-bug-fixes-1.patch
@@ -0,0 +1,2377 @@
+From 5bc6aa79e53700d56fc1f9f9364573ba4c78da65 Mon Sep 17 00:00:00 2001
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Date: Thu, 2 Jul 2026 11:43:52 -0400
+Subject: [PATCH 01/19] adapter: Fix crash on dev_disconnected
+
+Commit 5d836f1c697c ("adapter: Fix failed bonding attempt after LE
+link disconnection") introduces a regression since it attempts to
+call device_is_connected after adapter_remove_connection which may
+free the device causing the following backtrace:
+
+    #0 0x5cd6e384262f in btd_device_bearer_is_connected src/device.c:3754
+    #1 0x5cd6e384266f in btd_device_is_connected src/device.c:3745
+    #2 0x5cd6e37f8614 in dev_disconnected src/adapter.c:8626
+
+Fixes: https://github.com/bluez/bluez/issues/2221
+---
+ src/adapter.c | 25 +++++++++++++++++++++----
+ 1 file changed, 21 insertions(+), 4 deletions(-)
+
+diff --git a/src/adapter.c b/src/adapter.c
+index 538f63e0a153..210225243f00 100644
+--- a/src/adapter.c
++++ b/src/adapter.c
+@@ -7612,12 +7612,16 @@ struct agent *adapter_get_agent(struct btd_adapter *adapter)
+ static void adapter_remove_connection(struct btd_adapter *adapter,
+ 						struct btd_device *device,
+ 						uint8_t bdaddr_type,
+-						uint8_t reason)
++						uint8_t reason,
++						bool *removed)
+ {
+ 	bool remove_device = false;
+ 
+ 	DBG("");
+ 
++	if (removed)
++		*removed = false;
++
+ 	if (!g_slist_find(adapter->connections, device)) {
+ 		btd_error(adapter->dev_id, "No matching connection for device");
+ 		return;
+@@ -7638,6 +7642,9 @@ static void adapter_remove_connection(struct btd_adapter *adapter,
+ 
+ 		DBG("Removing temporary device %s", path);
+ 		btd_adapter_remove_device(adapter, device);
++
++		if (removed)
++			*removed = true;
+ 	}
+ }
+ 
+@@ -7665,10 +7672,10 @@ static void adapter_stop(struct btd_adapter *adapter)
+ 		uint8_t addr_type = btd_device_get_bdaddr_type(device);
+ 
+ 		adapter_remove_connection(adapter, device, BDADDR_BREDR,
+-						MGMT_DEV_DISCONN_UNKNOWN);
++						MGMT_DEV_DISCONN_UNKNOWN, NULL);
+ 		if (addr_type != BDADDR_BREDR)
+ 			adapter_remove_connection(adapter, device, addr_type,
+-						MGMT_DEV_DISCONN_UNKNOWN);
++						MGMT_DEV_DISCONN_UNKNOWN, NULL);
+ 	}
+ 
+ 	g_dbus_emit_property_changed(dbus_conn, adapter->path,
+@@ -8618,7 +8625,17 @@ static void dev_disconnected(struct btd_adapter *adapter,
+ 
+ 	device = btd_adapter_find_device(adapter, &addr->bdaddr, addr->type);
+ 	if (device) {
+-		adapter_remove_connection(adapter, device, addr->type, reason);
++		bool removed;
++
++		adapter_remove_connection(adapter, device, addr->type, reason,
++						&removed);
++		/* No need to continue if device was removed from the adapter,
++		 * as it will be freed and the disconnect notify will be called
++		 * in the device free callback.
++		 */
++		if (removed)
++			return;
++
+ 		disconnect_notify(device, reason);
+ 	}
+ 
+-- 
+2.54.0
+
+
+From b84aa894921037e1b1de00d282db2ee27a4ce63f Mon Sep 17 00:00:00 2001
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Date: Mon, 6 Jul 2026 10:59:28 -0400
+Subject: [PATCH 02/19] l2test: Fix calling getsockopt(BT_PHY)
+
+getsockopt(BT_PHY) expectes a 32 bits argument not a
+sizeof(struct sockaddr_l2).
+---
+ tools/l2test.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/tools/l2test.c b/tools/l2test.c
+index aa05f5247c5e..08d2269936b9 100644
+--- a/tools/l2test.c
++++ b/tools/l2test.c
+@@ -358,7 +358,8 @@ static int print_info(int sk, struct l2cap_options *opts)
+ 	struct sockaddr_l2 addr;
+ 	socklen_t optlen;
+ 	struct l2cap_conninfo conn;
+-	int prio, phy;
++	int prio;
++	uint32_t phy;
+ 	char ba[18];
+ 
+ 	/* Get connection information */
+@@ -414,6 +415,8 @@ static int print_info(int sk, struct l2cap_options *opts)
+ 		conn.dev_class[0], prio, rcvbuf);
+ 
+ 
++	optlen = sizeof(phy);
++
+ 	if (!getsockopt(sk, SOL_BLUETOOTH, BT_PHY, &phy, &optlen)) {
+ 		syslog(LOG_INFO, "Supported PHY: 0x%08x", phy);
+ 		print_bitfield(2, phy, phy_table);
+-- 
+2.54.0
+
+
+From 3f283c8e0ab3bad17ee8c13fa0dcf251a16e4e25 Mon Sep 17 00:00:00 2001
+From: raghavendra <raghavendra.rao@collabora.com>
+Date: Thu, 2 Jul 2026 18:39:04 +0530
+Subject: [PATCH 03/19] shared/bap: Validate codec configuration parameters
+
+This is required for PTS test ASCS/SR/SPE/BI-07-C
+---
+ src/shared/bap.c | 22 ++++++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+
+diff --git a/src/shared/bap.c b/src/shared/bap.c
+index 1f61227f82a7..6bc044a63758 100644
+--- a/src/shared/bap.c
++++ b/src/shared/bap.c
+@@ -29,6 +29,7 @@
+ #include "src/shared/gatt-client.h"
+ #include "src/shared/bap.h"
+ #include "src/shared/ascs.h"
++#include "src/shared/lc3.h"
+ #include "src/shared/bap-debug.h"
+ 
+ /* Maximum number of ASE(s) */
+@@ -3157,6 +3158,7 @@ static uint8_t ep_config(struct bt_bap_endpoint *ep, struct bt_bap *bap,
+ 	struct iovec cc;
+ 	const struct queue_entry *e;
+ 	struct bt_bap_codec codec;
++	uint8_t *ltv;
+ 
+ 	DBG(bap, "ep %p id 0x%02x dir 0x%02x", ep, ep->id, ep->dir);
+ 
+@@ -3190,6 +3192,19 @@ static uint8_t ep_config(struct bt_bap_endpoint *ep, struct bt_bap *bap,
+ 		return 0;
+ 	}
+ 
++	ltv = cc.iov_base;
++
++	if (req->codec.id == LC3_ID && cc.iov_len == 3 &&
++			ltv[0] == 0x02 &&
++			ltv[1] == LC3_CONFIG_DURATION &&
++			ltv[2] != LC3_CONFIG_DURATION_7_5 &&
++			ltv[2] != LC3_CONFIG_DURATION_10) {
++		ascs_ase_rsp_add(rsp, req->ase,
++				BT_ASCS_RSP_CONF_INVALID,
++				BT_ASCS_REASON_CODEC_DATA);
++		return 0;
++	}
++
+ 	switch (ep->dir) {
+ 	case BT_BAP_SINK:
+ 		e = queue_get_entries(bap->ldb->sinks);
+@@ -3207,6 +3222,13 @@ static uint8_t ep_config(struct bt_bap_endpoint *ep, struct bt_bap *bap,
+ 	codec.cid = le16_to_cpu(req->codec.cid);
+ 	codec.vid = le16_to_cpu(req->codec.vid);
+ 
++	if (codec.id != 0xff && (codec.cid || codec.vid)) {
++		ascs_ase_rsp_add(rsp, req->ase,
++				BT_ASCS_RSP_CONF_INVALID,
++				BT_ASCS_REASON_CODEC);
++		return 0;
++	}
++
+ 	for (; e; e = e->next) {
+ 		struct bt_bap_pac *pac = e->data;
+ 
+-- 
+2.54.0
+
+
+From 5c1c679ec304b8aadaa287cca59b38589d339e91 Mon Sep 17 00:00:00 2001
+From: raghavendra <raghavendra.rao@collabora.com>
+Date: Thu, 2 Jul 2026 18:39:05 +0530
+Subject: [PATCH 04/19] shared/bap: Validate unicast QoS configuration
+
+This is required for PTS tests ASCS/SR/SPE/BI-08-C and ASCS/SR/SPE/BI-10-C.
+---
+ src/shared/bap.c | 26 ++++++++++++++++++++++++++
+ 1 file changed, 26 insertions(+)
+
+diff --git a/src/shared/bap.c b/src/shared/bap.c
+index 6bc044a63758..f2be7c07ba5d 100644
+--- a/src/shared/bap.c
++++ b/src/shared/bap.c
+@@ -3316,6 +3316,32 @@ static uint8_t ep_qos(struct bt_bap_endpoint *ep, struct bt_bap *bap,
+ 		return 0;
+ 	}
+ 
++	if (ep->stream->lpac->codec.id == LC3_ID &&
++			qos->ucast.io_qos.interval < 0x0000ff) {
++		ascs_ase_rsp_add(rsp, ep->id,
++				BT_ASCS_RSP_CONF_INVALID,
++				BT_ASCS_REASON_INTERVAL);
++		return 0;
++	}
++
++	if (qos->ucast.framing != BT_ASCS_QOS_FRAMING_UNFRAMED &&
++			qos->ucast.framing != BT_ASCS_QOS_FRAMING_FRAMED) {
++		ascs_ase_rsp_add(rsp, ep->id,
++				BT_ASCS_RSP_CONF_INVALID,
++				BT_ASCS_REASON_FRAMING);
++		return 0;
++	}
++
++	if (!qos->ucast.io_qos.phys ||
++			(qos->ucast.io_qos.phys & ~(BT_BAP_CONFIG_PHY_1M |
++					BT_BAP_CONFIG_PHY_2M |
++					BT_BAP_CONFIG_PHY_CODEC))) {
++		ascs_ase_rsp_add(rsp, ep->id,
++				BT_ASCS_RSP_CONF_INVALID,
++				BT_ASCS_REASON_PHY);
++		return 0;
++	}
++
+ 	return stream_qos(ep->stream, qos, rsp);
+ }
+ 
+-- 
+2.54.0
+
+
+From 13b14db95089382701f54a46e6ef0120b69d4a62 Mon Sep 17 00:00:00 2001
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Date: Tue, 7 Jul 2026 14:34:30 -0400
+Subject: [PATCH 05/19] shared/bap: Use util_ltv_foreach to process metadata
+
+This makes use of util_ltv_foreach to process the metadata entries
+instead of attempting to iterate over the entries manually which
+probably only works with the exact same order as used by PTS.
+---
+ src/shared/bap.c | 84 ++++++++++++++++++++++++++++++++++--------------
+ 1 file changed, 59 insertions(+), 25 deletions(-)
+
+diff --git a/src/shared/bap.c b/src/shared/bap.c
+index f2be7c07ba5d..db6f4f204787 100644
+--- a/src/shared/bap.c
++++ b/src/shared/bap.c
+@@ -3404,35 +3404,69 @@ static uint8_t stream_enable(struct bt_bap_stream *stream, struct iovec *meta,
+ 	return 0;
+ }
+ 
+-static bool ascs_metadata_rsp(struct bt_bap_endpoint *ep, struct iovec *meta,
+-							struct iovec *rsp)
++struct bap_metadata_process {
++	struct bt_bap_endpoint *ep;
++	uint16_t context;
++	struct iovec *rsp;
++	uint8_t err;
++};
++
++static void bap_metadata_process(size_t i, uint8_t l, uint8_t t, uint8_t *v,
++					void *user_data)
+ {
+-	struct bt_ltv *ltv;
+-	uint16_t supported_context = 0;
++	struct bap_metadata_process *data = user_data;
+ 	uint16_t context;
+ 
++	switch (t) {
++	case BAP_METADATA_PREF_CONTEXT_LTV_TYPE:
++		break;
++	case BAP_METADATA_CONTEXT_LTV_TYPE:
++		if (l != sizeof(context)) {
++			ascs_ase_rsp_add(data->rsp, data->ep->id,
++					BT_ASCS_RSP_METADATA_INVALID, t);
++			data->err = BT_ASCS_RSP_METADATA_INVALID;
++			break;
++		}
++
++		context = get_le16(v);
++		if (!context || (context & ~data->context)) {
++			ascs_ase_rsp_add(data->rsp, data->ep->id,
++					BT_ASCS_RSP_METADATA_INVALID, t);
++			data->err = BT_ASCS_RSP_METADATA_INVALID;
++		}
++
++		break;
++	case BAP_METADATA_PROGRAM_INFO_LTV_TYPE:
++	case BAP_METADATA_LANGUAGE_LTV_TYPE:
++		break;
++	default:
++		ascs_ase_rsp_add(data->rsp, data->ep->id,
++					BT_ASCS_RSP_METADATA_UNSUPPORTED,
++					t);
++		data->err = BT_ASCS_RSP_METADATA_UNSUPPORTED;
++		break;
++	};
++}
++
++static bool ascs_metadata_rsp(struct bt_bap_endpoint *ep, struct bt_bap *bap,
++				struct iovec *meta, struct iovec *rsp)
++{
++	struct bap_metadata_process data = {
++		.ep = ep,
++		.rsp = rsp,
++		.err = 0,
++	};
++
+ 	if (ep->stream && ep->stream->lpac)
+-		supported_context = ep->stream->lpac->qos.supported_context;
++		data.context = ep->stream->lpac->qos.supported_context;
+ 
+-	ltv = meta->iov_base;
+-	if (meta->iov_len >= sizeof(*ltv) &&
+-			(ltv->type < BAP_METADATA_PREF_CONTEXT_LTV_TYPE ||
+-			ltv->type > BAP_METADATA_LANGUAGE_LTV_TYPE)) {
+-		ascs_ase_rsp_add(rsp, ep->id,
+-				BT_ASCS_RSP_METADATA_UNSUPPORTED, ltv->type);
+-		return true;
+-	}
++	util_ltv_foreach(meta->iov_base, meta->iov_len, NULL,
++				bap_metadata_process, &data);
+ 
+-	if (meta->iov_len >= sizeof(*ltv) + sizeof(context) &&
+-			ltv->type == BAP_METADATA_CONTEXT_LTV_TYPE &&
+-			ltv->len == sizeof(context) + 1) {
+-		context = get_le16(ltv->value);
+-		if (!context || (context & ~supported_context)) {
+-			ascs_ase_rsp_add(rsp, ep->id,
+-					BT_ASCS_RSP_METADATA_INVALID,
+-					ltv->type);
+-			return true;
+-		}
++	if (data.err) {
++		DBG(bap, "ep %p id 0x%02x metadata error 0x%02x", ep, ep->id,
++				data.err);
++		return true;
+ 	}
+ 
+ 	return false;
+@@ -3469,7 +3503,7 @@ static uint8_t ep_enable(struct bt_bap_endpoint *ep, struct bt_bap *bap,
+ 		return 0;
+ 	}
+ 
+-	if (ascs_metadata_rsp(ep, &meta, rsp))
++	if (ascs_metadata_rsp(ep, bap, &meta, rsp))
+ 		return 0;
+ 
+ 	if (!ep->stream) {
+@@ -3705,7 +3739,7 @@ static uint8_t ep_metadata(struct bt_bap_endpoint *ep,
+ 	meta.iov_base = util_iov_pull_mem(iov, req->len);
+ 	meta.iov_len = req->len;
+ 
+-	if (ascs_metadata_rsp(ep, &meta, rsp))
++	if (ascs_metadata_rsp(ep, stream->bap, &meta, rsp))
+ 		return 0;
+ 
+ 	return stream_metadata(ep->stream, &meta, rsp);
+-- 
+2.54.0
+
+
+From 9e9f0a370c591c126c39225f5f50b88915d11095 Mon Sep 17 00:00:00 2001
+From: Rahul Samana <rahul.samana@oss.qualcomm.com>
+Date: Tue, 7 Jul 2026 12:05:43 +0530
+Subject: [PATCH 06/19] gobex: Fix use-after-free when cancelling SRM PUT
+ transfer
+
+In SRM mode put_get_data() queues the next packet during encoding of
+the current one, so transfer->req_id and pending_req->id can diverge.
+When g_obex_cancel_transfer() cancels the queued packet from tx_queue,
+cancel_complete() frees the transfer while pending_req still holds a
+callback pointing to it. Its G_OBEX_DEFAULT_TIMEOUT (10s) then fires
+on freed memory causing a SIGSEGV.
+
+Fix by clearing pending_req->rsp_func if it belongs to the same
+transfer being cancelled.
+---
+ gobex/gobex.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/gobex/gobex.c b/gobex/gobex.c
+index df80d79f31bb..10a438391eae 100644
+--- a/gobex/gobex.c
++++ b/gobex/gobex.c
+@@ -861,6 +861,14 @@ gboolean g_obex_cancel_req(GObex *obex, guint req_id, gboolean remove_callback)
+ 
+ 	g_queue_delete_link(obex->tx_queue, match);
+ 
++	/* In SRM mode pending_req may belong to the same transfer but carry
++	 * a different req_id. Clear its callback to avoid use-after-free
++	 * when its timeout fires after transfer_free().
++	 */
++	if (remove_callback && obex->pending_req &&
++				obex->pending_req->rsp_data == p->rsp_data)
++		obex->pending_req->rsp_func = NULL;
++
+ immediate_completion:
+ 	p->cancelled = TRUE;
+ 	p->obex = g_obex_ref(obex);
+-- 
+2.54.0
+
+
+From 82af2beafc39510e2c4a439bf44faea711d6503f Mon Sep 17 00:00:00 2001
+From: Tom Catshoek <tomcatshoek@zeelandnet.nl>
+Date: Thu, 9 Jul 2026 14:27:04 +0200
+Subject: [PATCH 07/19] adapter: Fix crash on UUID discovery filter match
+
+is_filter_match() looks up each discovery-filter UUID in the queue of
+services parsed from a device advertisement. When that services list was
+migrated from a GSList to a struct queue, the queue_find() call kept
+GLib's g_slist_find_custom() argument order, passing the UUID string
+where queue_find() expects a match function and the comparison function
+where it expects the match data.
+
+As a result queue_find() calls the UUID string as if it were a function,
+jumping into non-executable heap and crashing bluetoothd with SIGSEGV as
+soon as an advertisement matches a UUID filter configured via
+SetDiscoveryFilter.
+
+Add a queue_match_func_t helper and pass the arguments in the correct
+order.
+
+Fixes: https://github.com/bluez/bluez/issues/2282
+---
+ src/adapter.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/src/adapter.c b/src/adapter.c
+index 210225243f00..4ffa32a52c13 100644
+--- a/src/adapter.c
++++ b/src/adapter.c
+@@ -7184,6 +7184,14 @@ static void adapter_msd_notify(struct btd_adapter *adapter,
+ 	}
+ }
+ 
++static bool match_uuid(const void *data, const void *match_data)
++{
++	const char *uuid = data;
++	const char *match = match_data;
++
++	return strcmp(uuid, match) == 0;
++}
++
+ static bool is_filter_match(GSList *discovery_filter, struct eir_data *eir_data,
+ 								int8_t rssi)
+ {
+@@ -7216,8 +7224,7 @@ static bool is_filter_match(GSList *discovery_filter, struct eir_data *eir_data,
+ 				 * uuid.
+ 				 */
+ 				if (queue_find(eir_data->services,
+-							m->data,
+-							g_strcmp) != NULL)
++							match_uuid, m->data))
+ 					got_match = true;
+ 			}
+ 		}
+-- 
+2.54.0
+
+
+From b7d71e5067856b0daf2f1f73b3fc95483236610e Mon Sep 17 00:00:00 2001
+From: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com>
+Date: Fri, 10 Jul 2026 12:28:17 +0500
+Subject: [PATCH 08/19] a2dp: Fix loading of remote SEP from cache
+
+Commit 912f5efb0dd9 ("a2dp: Fix handling of codec capability storage")
+added an 'i >= 2' condition to the loop that parses the stored codec
+capabilities. Since i starts at 0 the loop body never runs, i stays 0,
+and the subsequent 'if (i != size)' check discards every endpoint found
+in the cache:
+
+  load_remote_sep() Unable to load LastUsed: rseid 6 not found
+
+With no remote SEP loaded, avdtp_discover() can no longer take the
+cached path and issues AVDTP Discover/Get All Capabilities on every
+reconnect, and a2dp_setup_remote_path() returns NULL so the transport
+ends up at /org/bluez/hciX/dev_YY/fd0 instead of .../sepN/fd0.
+
+The condition was presumably meant to bound the writes into data[128],
+which the original commit did not actually fix: caps is read with
+'%512s' so size / 2 can be up to 256. Validate size up front instead.
+
+Fixes: https://github.com/bluez/bluez/issues/2285
+---
+ profiles/audio/a2dp.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
+index c8adc3122563..a4ba1dacf943 100644
+--- a/profiles/audio/a2dp.c
++++ b/profiles/audio/a2dp.c
+@@ -2398,7 +2398,16 @@ static void load_remote_sep(struct a2dp_channel *chan, GKeyFile *key_file,
+ 			delay_reporting = false;
+ 		}
+ 
+-		for (i = 0, size = strlen(caps); i < size && i >= 2; i += 2) {
++		size = strlen(caps);
++
++		g_free(value);
++
++		if (size % 2 || size / 2 > (int) sizeof(data)) {
++			warn("Unable to load Endpoint: seid %u", rseid);
++			continue;
++		}
++
++		for (i = 0; i < size; i += 2) {
+ 			uint8_t *tmp = data + i / 2;
+ 
+ 			if (sscanf(caps + i, "%02hhx", tmp) != 1) {
+@@ -2407,8 +2416,6 @@ static void load_remote_sep(struct a2dp_channel *chan, GKeyFile *key_file,
+ 			}
+ 		}
+ 
+-		g_free(value);
+-
+ 		if (i != size)
+ 			continue;
+ 
+-- 
+2.54.0
+
+
+From 2a3d3b0e6f83516736c3c8191fb9440475171600 Mon Sep 17 00:00:00 2001
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Date: Fri, 10 Jul 2026 14:47:14 -0400
+Subject: [PATCH 09/19] monitor: Fix printing subpages bits after all subpages
+
+This fixes printing the decoded subpage bitfields after all subpages
+rather then after the subpage itself:
+
+before:
+
+        Features[1/0][8]:
+        00 03 00 00 00 00 00 00                          ........
+        Features[1/1][8]:
+        00 00 00 00 00 00 00 00                          ........
+        Features[1/2][8]:
+        00 00 00 00 00 00 00 00                          ........
+          Shorter Connection Intervals
+          Shorter Connection Intervals (Host Support)
+
+after:
+
+        Features[1/0][8]:
+        00 03 00 00 00 00 00 00                          ........
+          Shorter Connection Intervals
+          Shorter Connection Intervals (Host Support)
+---
+ monitor/packet.c | 33 +++++++++++++++++----------------
+ 1 file changed, 17 insertions(+), 16 deletions(-)
+
+diff --git a/monitor/packet.c b/monitor/packet.c
+index e62ad4cfb337..ba6ff8e8e551 100644
+--- a/monitor/packet.c
++++ b/monitor/packet.c
+@@ -2925,17 +2925,29 @@ static const struct bitfield_data features_msft[] = {
+ 
+ static void print_features_subpage(uint8_t page, uint8_t subpages,
+ 					const uint8_t *features_array,
+-					uint64_t *features)
++					uint64_t *features,
++					const struct bitfield_data *table)
+ {
+ 	int i, j;
+ 	char str[18];
+ 
+ 	for (i = 0; i < subpages; i++) {
++		uint64_t mask;
++
+ 		for (j = 0; j < 8; j++)
+ 			features[i] |= ((uint64_t) features_array[i * 8 + j])
+ 					<< (j * 8);
+ 		sprintf(str, "Features[%u/%u]", page, i);
+ 		print_hex_field(str, &features_array[i * 8], 8);
++
++		if (!table)
++			continue;
++
++		mask = print_bitfield(2, features[i], table);
++		if (mask)
++			print_text(COLOR_UNKNOWN_FEATURE_BIT,
++				"  Unknown features (0x%16.16" PRIx64 ")",
++				mask);
+ 	}
+ }
+ 
+@@ -2943,16 +2955,13 @@ static void print_features(uint8_t page, const uint8_t *features_array,
+ 								uint8_t type)
+ {
+ 	const struct bitfield_data *features_table = NULL;
+-	uint64_t mask, features[3] = {};
++	uint64_t features[3] = {};
+ 	uint8_t subpages = 1;
+-	int i;
+ 
+ 	/* LE pages 1-10 are 192 bits (24 octets) each */
+ 	if (type == 0x01 && page)
+ 		subpages = 3;
+ 
+-	print_features_subpage(page, subpages, features_array, features);
+-
+ 	switch (type) {
+ 	case 0x00:
+ 		switch (page) {
+@@ -2985,16 +2994,8 @@ static void print_features(uint8_t page, const uint8_t *features_array,
+ 		break;
+ 	}
+ 
+-	if (!features_table)
+-		return;
+-
+-	for (i = 0; i < subpages; i++) {
+-		mask = print_bitfield(2, features[i], features_table);
+-		if (mask)
+-			print_text(COLOR_UNKNOWN_FEATURE_BIT,
+-				"  Unknown features (0x%16.16" PRIx64 ")",
+-				mask);
+-	}
++	print_features_subpage(page, subpages, features_array, features,
++							features_table);
+ }
+ 
+ void packet_print_features_lmp(const uint8_t *features, uint8_t page)
+@@ -11065,7 +11066,7 @@ static const struct opcode_data opcode_table[] = {
+ 				"LE Read Minimum Supported Connection Interval",
+ 				null_cmd, 0, true, le_read_conn_interval_rsp,
+ 				sizeof(struct bt_hci_rsp_le_read_conn_interval),
+-				true },
++				false },
+ 	{ }
+ };
+ 
+-- 
+2.54.0
+
+
+From 0f2f53fd04d4eb73801de1f8ca16a40e3b12c034 Mon Sep 17 00:00:00 2001
+From: Pauli Virtanen <pav@iki.fi>
+Date: Mon, 13 Jul 2026 16:50:23 +0300
+Subject: [PATCH 10/19] tools/sco-tester: fix missing clear of io_id in
+ callbacks
+
+Fixes issues
+
+GLib-CRITICAL **: Source ID 126 was not found when attempting to remove it
+---
+ tools/sco-tester.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/tools/sco-tester.c b/tools/sco-tester.c
+index a2185b8ef198..fca99a91c20f 100644
+--- a/tools/sco-tester.c
++++ b/tools/sco-tester.c
+@@ -1415,6 +1415,8 @@ static gboolean sco_accept_cb(GIOChannel *io, GIOCondition cond,
+ 	gboolean ret;
+ 	GIOChannel *new_io;
+ 
++	data->io_id = 0;
++
+ 	tester_debug("New connection");
+ 
+ 	sk = g_io_channel_unix_get_fd(io);
+-- 
+2.54.0
+
+
+From 9353c0ea9f6c1bacff00d9afef0d963796d86bd3 Mon Sep 17 00:00:00 2001
+From: Pauli Virtanen <pav@iki.fi>
+Date: Mon, 13 Jul 2026 16:50:24 +0300
+Subject: [PATCH 11/19] tools/6lowpan-tester: fix race in Client Connect -
+ Disable
+
+It's possible client_l2cap_disconnect_cb() is called after 6lowpan
+disable on connect. Prevent failing test in finish_step() in this case.
+---
+ tools/6lowpan-tester.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/tools/6lowpan-tester.c b/tools/6lowpan-tester.c
+index 95fdf206fc0c..738714d68dd1 100644
+--- a/tools/6lowpan-tester.c
++++ b/tools/6lowpan-tester.c
+@@ -648,8 +648,11 @@ static void client_l2cap_connect_cb(uint16_t handle, uint16_t cid,
+ 	if (cdata->disable_on_connect) {
+ 		if (write_6lowpan("6lowpan_enable", "0"))
+ 			tester_test_failed();
+-		else
++		else {
++			data->handle = 0;
++			data->dcid = 0;
+ 			tester_test_passed();
++		}
+ 	}
+ }
+ 
+-- 
+2.54.0
+
+
+From ba08e0f6be0f2ac17de3c0609c64e1d1acaa1563 Mon Sep 17 00:00:00 2001
+From: Pauli Virtanen <pav@iki.fi>
+Date: Mon, 13 Jul 2026 16:50:25 +0300
+Subject: [PATCH 12/19] tools/6lowpan-tester: add test for VHCI teardown
+ without disable
+
+Check 6lowpan teardown when controller disappers with active devices.
+Add test
+
+Client Connect - No Disable
+---
+ tools/6lowpan-tester.c | 28 +++++++++++++++++++++++-----
+ 1 file changed, 23 insertions(+), 5 deletions(-)
+
+diff --git a/tools/6lowpan-tester.c b/tools/6lowpan-tester.c
+index 738714d68dd1..a8faf6eb5976 100644
+--- a/tools/6lowpan-tester.c
++++ b/tools/6lowpan-tester.c
+@@ -76,6 +76,9 @@ struct client_data {
+ 
+ 	/* Interface listener socket type, SOCK_RAW / DGRAM */
+ 	int sk_type;
++
++	/* Don't disable 6lowpan before adapter teardown */
++	bool no_teardown_disable;
+ };
+ 
+ static void print_debug(const char *str, void *user_data)
+@@ -264,6 +267,7 @@ static void test_pre_setup(const void *test_data)
+ static void test_post_teardown(const void *test_data)
+ {
+ 	struct test_data *data = tester_get_data();
++	const struct client_data *cdata = data->test_data;
+ 	int ret;
+ 
+ 	if (data->io_id > 0) {
+@@ -276,11 +280,13 @@ static void test_post_teardown(const void *test_data)
+ 		data->packet_fd = -1;
+ 	}
+ 
+-	ret = write_6lowpan("6lowpan_enable", "0");
+-	if (ret < 0) {
+-		tester_warn("Failed to disable 6lowpan");
+-		tester_post_teardown_failed();
+-		return;
++	if (!cdata || !cdata->no_teardown_disable) {
++		ret = write_6lowpan("6lowpan_enable", "0");
++		if (ret < 0) {
++			tester_warn("Failed to disable 6lowpan");
++			tester_post_teardown_failed();
++			return;
++		}
+ 	}
+ 
+ 	hciemu_unref(data->hciemu);
+@@ -317,6 +323,10 @@ static const struct client_data client_connect_disable = {
+ 	.disable_on_connect = true,
+ };
+ 
++static const struct client_data client_connect_no_disable = {
++	.no_teardown_disable = true,
++};
++
+ static const struct client_data client_connect_disconnect = {
+ 	.disconnect = true,
+ };
+@@ -653,6 +663,10 @@ static void client_l2cap_connect_cb(uint16_t handle, uint16_t cid,
+ 			data->dcid = 0;
+ 			tester_test_passed();
+ 		}
++	} else if (cdata->no_teardown_disable) {
++		data->handle = 0;
++		data->dcid = 0;
++		tester_test_passed();
+ 	}
+ }
+ 
+@@ -708,6 +722,10 @@ int main(int argc, char *argv[])
+ 							setup_powered_client,
+ 							test_connect);
+ 
++	test_6lowpan("Client Connect - No Disable", &client_connect_no_disable,
++							setup_powered_client,
++							test_connect);
++
+ 	test_6lowpan("Client Connect - Disconnect", &client_connect_disconnect,
+ 							setup_powered_client,
+ 							test_connect);
+-- 
+2.54.0
+
+
+From 1cfe2d8b2cbb8c645439464a217053d3cdc41e5f Mon Sep 17 00:00:00 2001
+From: Pauli Virtanen <pav@iki.fi>
+Date: Mon, 13 Jul 2026 16:50:26 +0300
+Subject: [PATCH 13/19] tools/l2cap-tester: fix Set PHY test spurious failures
+
+Setting BT_PHY does not take effect instantaneously as kernel waits for
+controller, so checking getsockopt() sometimes fails here. In PHY tests,
+use retry with timeout to check again later.
+---
+ tools/l2cap-tester.c | 18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+diff --git a/tools/l2cap-tester.c b/tools/l2cap-tester.c
+index a8cac3902b32..2771aee65814 100644
+--- a/tools/l2cap-tester.c
++++ b/tools/l2cap-tester.c
+@@ -277,7 +277,7 @@ static void test_data_free(void *test_data)
+ #define test_l2cap(name, type, data, setup, func) \
+ 	do { \
+ 		struct test_data *user; \
+-		user = malloc(sizeof(struct test_data)); \
++		user = calloc(1, sizeof(struct test_data)); \
+ 		if (!user) \
+ 			break; \
+ 		user->hciemu_type = type; \
+@@ -1657,8 +1657,10 @@ static gboolean socket_closed_cb(GIOChannel *io, GIOCondition cond,
+ 		tester_print("err %d != %d expected_err", -err,
+ 						l2data->expect_err);
+ 		tester_test_failed();
+-	} else
++	} else if (!data->step)
+ 		tester_test_passed();
++	else
++		tester_test_failed();
+ 
+ 	return FALSE;
+ }
+@@ -1729,12 +1731,13 @@ static gboolean check_phy(gpointer args)
+ 	}
+ 
+ 	if (l2data->phy && l2data->phy != data->phys) {
+-		tester_warn("phy 0x%08x != 0x%08x", l2data->phy, data->phys);
+-		tester_test_failed();
+-		goto done;
++		tester_print("phy 0x%08x != 0x%08x", l2data->phy, data->phys);
++
++		/* Retry */
++		return TRUE;
+ 	}
+ 
+-	tester_test_passed();
++	data->step--;
+ 
+ done:
+ 	shutdown(sk, SHUT_WR);
+@@ -1770,7 +1773,8 @@ static int check_phys(struct test_data *data, int sk)
+ 		}
+ 
+ 		/* Wait for the PHY to change */
+-		g_idle_add(check_phy, INT_TO_PTR(sk));
++		data->step++;
++		g_timeout_add(50, check_phy, INT_TO_PTR(sk));
+ 
+ 		return -EINPROGRESS;
+ 	}
+-- 
+2.54.0
+
+
+From 7f826d003ee7bc07698ddecf804697d55e7b9c86 Mon Sep 17 00:00:00 2001
+From: Ferose <ferose2@gmail.com>
+Date: Sat, 11 Jul 2026 00:02:30 -0700
+Subject: [PATCH 14/19] shared/bap: Fix rejecting re-attach of the same fd
+
+When the remote's STREAMING ASE notification arrives before
+iso_connect_cb() fires, the race handler in bap_state()
+(profiles/audio/bap.c) already attaches the io to the stream; the
+comment there notes "Order of STREAMING and iso_connect_cb() is
+nondeterministic". When iso_connect_cb() then calls
+bt_bap_stream_set_io() with the same fd, the guard in
+bap_ucast_set_io() sees an attached, non-connecting io and returns
+false. iso_connect_cb() treats that as fatal:
+
+  profiles/audio/bap.c:iso_connect_cb() Unable to set IO
+  profiles/audio/transport.c:bap_state_changed() Unable to get stream IO
+
+and tears down a CIS that btmon shows was established successfully
+(CIS Established status 0, both ISO data paths set up). With a device
+whose STREAMING notifications consistently win the race, streaming is
+never possible.
+
+Treat re-attaching the fd that is already attached as a no-op success,
+without re-running the per-stream state actions (which would send a
+duplicate Receiver Start Ready to a linked source ASE). Attaching a
+different fd to a non-connecting io remains an error.
+
+Fixes: https://github.com/bluez/bluez/issues/2223
+---
+ src/shared/bap.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/src/shared/bap.c b/src/shared/bap.c
+index db6f4f204787..1660b8b2c1cf 100644
+--- a/src/shared/bap.c
++++ b/src/shared/bap.c
+@@ -2589,9 +2589,18 @@ static unsigned int bap_bcast_release(struct bt_bap_stream *stream,
+ 
+ static bool bap_ucast_set_io(struct bt_bap_stream *stream, int fd)
+ {
+-	if (!stream || (fd >= 0 && stream->io && !stream->io->connecting))
++	if (!stream)
+ 		return false;
+ 
++	/*
++	 * The STREAMING state handler may already have attached this io
++	 * if the remote's ASE notification raced ahead of iso_connect_cb
++	 * (see bap_state() in profiles/audio/bap.c). Re-attaching the
++	 * same fd is a no-op success; only a different fd is an error.
++	 */
++	if (fd >= 0 && stream->io && !stream->io->connecting)
++		return stream_io_get_fd(stream->io) == fd;
++
+ 	bap_stream_set_io(stream, INT_TO_PTR(fd));
+ 
+ 	queue_foreach(stream->links, bap_stream_set_io, INT_TO_PTR(fd));
+-- 
+2.54.0
+
+
+From bc49d63210f23e0724e07f3e5838aff05fbaa4aa Mon Sep 17 00:00:00 2001
+From: Pauli Virtanen <pav@iki.fi>
+Date: Sat, 11 Jul 2026 12:15:25 +0300
+Subject: [PATCH 15/19] lib: add iso_data_* macros to hci.h
+
+Add macros for parsing ISO Data Packet header items.
+---
+ lib/bluetooth/hci.h | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/lib/bluetooth/hci.h b/lib/bluetooth/hci.h
+index 732477ec4b55..2e4aa394e13e 100644
+--- a/lib/bluetooth/hci.h
++++ b/lib/bluetooth/hci.h
+@@ -2335,6 +2335,12 @@ typedef struct {
+ #define iso_flags_ts(f)		((f >> 2) & 0x0001)
+ #define iso_flags_pack(pb, ts)	((pb & 0x03) | ((ts & 0x01) << 2))
+ 
++/* ISO data length and flags pack/unpack */
++#define iso_data_len_pack(h, f)	((__u16) (((h) & 0x0fff) | \
++						  (((f) & 0x3) << 14)))
++#define iso_data_len(h)		((h) & 0x0fff)
++#define iso_data_flags(h)	((h) >> 14)
++
+ #endif /* _NO_HCI_DEFS */
+ 
+ /* HCI Socket options */
+-- 
+2.54.0
+
+
+From 1309d5f9305d132bc09705ffa4afa113c6491c2b Mon Sep 17 00:00:00 2001
+From: Pauli Virtanen <pav@iki.fi>
+Date: Sat, 11 Jul 2026 12:15:26 +0300
+Subject: [PATCH 16/19] monitor: fix parsing of ISO packet data header and slen
+ check
+
+Check PB flag to see whether timestamp and data headers are present.
+
+Check bounds before accessing data. Bump handle_str length to fit
+maximum.
+
+Byteswap length values, and mask Packet_Status_Flag correctly.  Remove
+SDU length check, as we are not tracking fragmentation.
+
+Fixes: https://github.com/bluez/bluez/issues/2292
+Assisted-by: GLM-5.2
+---
+ monitor/packet.c | 69 ++++++++++++++++++++++++++++++++----------------
+ 1 file changed, 46 insertions(+), 23 deletions(-)
+
+diff --git a/monitor/packet.c b/monitor/packet.c
+index ba6ff8e8e551..fb053e2b413f 100644
+--- a/monitor/packet.c
++++ b/monitor/packet.c
+@@ -14541,20 +14541,23 @@ void packet_hci_isodata(struct timeval *tv, struct ucred *cred, uint16_t index,
+ 				bool in, const void *data, uint16_t size)
+ {
+ 	const struct bt_hci_iso_hdr *hdr = data;
+-	const struct bt_hci_iso_data_start *start;
+-	uint16_t handle = le16_to_cpu(hdr->handle);
+-	uint8_t flags = acl_flags(handle);
++	uint16_t handle, dlen;
++	uint8_t flags, pb_flag;
+ 	char label[8];
+-	char handle_str[56], extra_str[50], ts_str[16] = { 0 };
+-	struct index_buf_pool *pool = &index_list[index].iso;
++	char handle_str[100], extra_str[70], ts_str[16] = { 0 };
++	char sn_str[16] = { 0 }, slen_str[32] = { 0 };
++	struct index_buf_pool *pool;
+ 	struct packet_conn_data *conn;
+ 	size_t ts_size = 0;
++	bool have_hdr;
+ 
+ 	if (index >= MAX_INDEX) {
+ 		print_field("Invalid index (%d).", index);
+ 		return;
+ 	}
+ 
++	pool = &index_list[index].iso;
++
+ 	index_list[index].frame++;
+ 
+ 	if (size < sizeof(*hdr))
+@@ -14563,11 +14566,18 @@ void packet_hci_isodata(struct timeval *tv, struct ucred *cred, uint16_t index,
+ 	data += sizeof(*hdr);
+ 	size -= sizeof(*hdr);
+ 
++	handle = le16_to_cpu(hdr->handle);
++	flags = acl_flags(handle);
++	pb_flag = iso_flags_pb(flags);
++	dlen = le16_to_cpu(hdr->dlen);
++
++	have_hdr = (pb_flag == 0x00 || pb_flag == 0x02);
++
+ 	/* Detect if timestamp field is preset */
+ 	if (iso_flags_ts(flags)) {
+ 		ts_size = sizeof(uint32_t);
+ 
+-		if (size < ts_size)
++		if (size < ts_size || !have_hdr)
+ 			goto malformed;
+ 
+ 		snprintf(ts_str, sizeof(ts_str), " ts %u", get_le32(data));
+@@ -14576,20 +14586,40 @@ void packet_hci_isodata(struct timeval *tv, struct ucred *cred, uint16_t index,
+ 		size -= ts_size;
+ 	}
+ 
+-	start = data;
++	if (have_hdr) {
++		const struct bt_hci_iso_data_start *start = data;
++		uint8_t sflags;
++		uint16_t slen;
++
++		if (size < sizeof(*start))
++			goto malformed;
++
++		sflags = iso_data_flags(le16_to_cpu(start->slen));
++		slen = iso_data_len(le16_to_cpu(start->slen));
++
++		if (slen)
++			snprintf(slen_str, sizeof(slen_str), " slen %u", slen);
++		if (sflags)
++			snprintf(slen_str + strlen(slen_str),
++					sizeof(slen_str) - strlen(slen_str),
++					" sflags %u", sflags);
++
++		snprintf(sn_str, sizeof(sn_str), " SN %u",
++							le16_to_cpu(start->sn));
++	}
++
+ 	conn = packet_get_conn_data(handle);
+ 
+ 	if (!in && pool->total)
+-		sprintf(handle_str, "Handle %d [%u/%u] SN %u",
+-			acl_handle(handle), ++pool->tx, pool->total, start->sn);
++		sprintf(handle_str, "Handle %d [%u/%u]%s",
++			acl_handle(handle), ++pool->tx, pool->total, sn_str);
+ 	else
+-		sprintf(handle_str, "Handle %u SN %u", acl_handle(handle),
+-			start->sn);
++		sprintf(handle_str, "Handle %u%s", acl_handle(handle), sn_str);
+ 
+ 	handle_str_append_addr(handle_str, conn);
+ 
+-	sprintf(extra_str, "flags 0x%2.2x dlen %u slen %u%s", flags, hdr->dlen,
+-							start->slen, ts_str);
++	sprintf(extra_str, "flags 0x%2.2x dlen %u%s%s", flags, dlen, slen_str,
++									ts_str);
+ 
+ 	if (conn)
+ 		sprintf(label, "%s", conn_type_str(conn->type));
+@@ -14601,18 +14631,11 @@ void packet_hci_isodata(struct timeval *tv, struct ucred *cred, uint16_t index,
+ 
+ 	if (!in)
+ 		packet_enqueue_tx(tv, acl_handle(handle),
+-					index_list[index].frame, hdr->dlen);
++					index_list[index].frame, dlen);
+ 
+-	if (size + ts_size != hdr->dlen) {
++	if (size + ts_size != dlen) {
+ 		print_text(COLOR_ERROR, "invalid packet size (%d != %d)",
+-						size + (int)ts_size, hdr->dlen);
+-		packet_hexdump(data, size);
+-		return;
+-	}
+-
+-	if (size != start->slen + 4) {
+-		print_text(COLOR_ERROR, "invalid packet slen (%d+4 != %d)",
+-							start->slen, size);
++						size + (int)ts_size, dlen);
+ 		packet_hexdump(data, size);
+ 		return;
+ 	}
+-- 
+2.54.0
+
+
+From 7482aceece7044e688f20f113263b50c21d69fb6 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Danis?= <frederic.danis@collabora.com>
+Date: Wed, 15 Jul 2026 17:51:44 +0200
+Subject: [PATCH 17/19] profiles/audio: fix UAF on external media service
+ teardown
+
+Keep media_app endpoint/player queues in sync with object lifetime to
+avoid stale pointers during proxy removal.
+
+When admin allowlist reapply removes audio services, endpoint/player
+objects may be destroyed through non-proxy paths first.
+Later proxy_removed_cb calls queue_remove_if() and matching by path
+can dereference freed endpoint/player memory.
+
+Fix by:
+- adding media_app back-references in media_endpoint/local_player
+- unlinking from app queues inside media_endpoint_remove or
+  local_player_remove
+- setting ownership when app-registering endpoint/player objects
+
+This prevents heap-use-after-free in match_endpoint_by_path or
+match_player_by_path during service disconnect.
+
+Assisted-by: GPT:GPT-5.3-Codex
+---
+ profiles/audio/media.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/profiles/audio/media.c b/profiles/audio/media.c
+index 5d9ea2cbcbce..95f9580b08ff 100644
+--- a/profiles/audio/media.c
++++ b/profiles/audio/media.c
+@@ -136,12 +136,14 @@ struct media_endpoint {
+ 	guint			watch;
+ 	GSList			*requests;
+ 	struct media_adapter	*adapter;
++	struct media_app	*app;
+ 	GSList			*transports;
+ 	struct endpoint_features	features;
+ };
+ 
+ struct local_player {
+ 	struct media_adapter	*adapter;
++	struct media_app	*app;
+ 	char			*sender;	/* Player DBus bus id */
+ 	char			*path;		/* Player object path */
+ 	GHashTable		*settings;	/* Player settings */
+@@ -305,6 +307,11 @@ static void media_endpoint_remove(void *data)
+ 	}
+ #endif
+ 
++	if (endpoint->app) {
++		queue_remove(endpoint->app->endpoints, endpoint);
++		endpoint->app = NULL;
++	}
++
+ 	info("Endpoint unregistered: sender=%s path=%s", endpoint->sender,
+ 			endpoint->path);
+ 
+@@ -2076,6 +2083,11 @@ static void local_player_remove(void *data)
+ {
+ 	struct local_player *mp = data;
+ 
++	if (mp->app) {
++		queue_remove(mp->app->players, mp);
++		mp->app = NULL;
++	}
++
+ 	info("Player unregistered: sender=%s path=%s", mp->sender, mp->path);
+ 
+ 	local_player_destroy(mp);
+@@ -3168,6 +3180,8 @@ static void app_register_endpoint(void *data, void *user_data)
+ 		return;
+ 	}
+ 
++	endpoint->app = app;
++
+ 	queue_push_tail(app->endpoints, endpoint);
+ 
+ 	return;
+@@ -3196,6 +3210,8 @@ static void app_register_player(void *data, void *user_data)
+ 	if (!player)
+ 		return;
+ 
++	player->app = app;
++
+ 	if (g_dbus_proxy_get_property(proxy, "PlaybackStatus", &iter)) {
+ 		if (!set_status(player, &iter))
+ 			goto fail;
+-- 
+2.54.0
+
+
+From b0abe23f58f1ecc44d9d0b6b328be72d2d2113b8 Mon Sep 17 00:00:00 2001
+From: Naga Bhavani Akella <naga.akella@oss.qualcomm.com>
+Date: Wed, 15 Jul 2026 14:09:56 +0530
+Subject: [PATCH 18/19] doc/org.bluez.ChannelSounding1:Add Used by reference
+ and Examples
+
+Add :Used by: field linking to bluetoothctl cs submenu and
+Examples section showing corresponding bluetoothctl cs commands
+for D-Bus methods
+---
+ Makefile.am                        |   2 +
+ doc/org.bluez.ChannelSounding1.rst | 534 +++++++++++++++++++++++++++++
+ 2 files changed, 536 insertions(+)
+ create mode 100644 doc/org.bluez.ChannelSounding1.rst
+
+diff --git a/Makefile.am b/Makefile.am
+index 76c4ab5d4f4e..23b96c2e303f 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -405,6 +405,7 @@ man_MANS += doc/org.bluez.Telephony.5 doc/org.bluez.Call.5
+ man_MANS += doc/org.bluez.ThermometerManager.5 \
+ 		doc/org.bluez.Thermometer.5 \
+ 		doc/org.bluez.ThermometerWatcher.5
++man_MANS += doc/org.bluez.ChannelSounding1.5
+ endif
+ manual_pages += doc/bluetoothd.8
+ manual_pages += doc/hci.7 doc/mgmt.7 doc/l2cap.7 doc/rfcomm.7 doc/sco.7 \
+@@ -445,6 +446,7 @@ manual_pages += doc/org.bluez.Telephony.5 doc/org.bluez.Call.5
+ manual_pages += doc/org.bluez.ThermometerManager.5 \
+ 		doc/org.bluez.Thermometer.5 \
+ 		doc/org.bluez.ThermometerWatcher.5
++manual_pages += doc/org.bluez.ChannelSounding1.5
+ 
+ EXTRA_DIST += src/genbuiltin src/bluetooth.conf \
+ 			src/main.conf profiles/network/network.conf \
+diff --git a/doc/org.bluez.ChannelSounding1.rst b/doc/org.bluez.ChannelSounding1.rst
+new file mode 100644
+index 000000000000..c06e1d7285e0
+--- /dev/null
++++ b/doc/org.bluez.ChannelSounding1.rst
+@@ -0,0 +1,534 @@
++==========================
++org.bluez.ChannelSounding1
++==========================
++
++----------------------------------------------
++BlueZ D-Bus Channel Sounding API documentation
++----------------------------------------------
++
++:Version: BlueZ
++:Date: June 2026
++:Manual section: 5
++:Manual group: Linux System Administration
++
++Interface
++=========
++
++:Service:	org.bluez
++:Interface:	org.bluez.ChannelSounding1
++:Object path:	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
++:Used by:	**bluetoothctl(1)**, **bluetoothctl-cs(1)**
++
++Methods
++-------
++
++void StartMeasurement(dict params)
++``````````````````````````````````
++
++Starts a Channel Sounding distance measurement procedure on the connected
++device. All configuration is supplied in a single ``a{sv}`` dictionary.
++Any key that is omitted retains its current value in the daemon.
++
++The device to measure is identified by the D-Bus object path on which
++this method is called
++(``[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX``).
++Only one measurement per device object may be active at a time. Calling
++**StartMeasurement** while a session is already active returns
++``org.bluez.Error.InProgress``.
++
++When ``role`` is Reflector (``0x02``), this method does not start a CS
++distance measurement: a Reflector never initiates a procedure locally,
++so it cannot start one via this call. Instead, all given configuration
++is applied and stored so the controller is ready to respond once a
++remote Initiator begins a procedure, and the method returns success
++without arming a local measurement session. The ``Active`` property
++only transitions to ``true`` when a remote-initiated procedure
++actually starts, which may happen well after this method returns (or
++not at all, if the remote never initiates one). Clients that watch
++``PropertiesChanged`` for ``Active`` (as **bluetoothctl-cs(1)** does)
++are notified of both the remote-initiated start and its eventual stop.
++
++For Initiator role (or Both), ``duration_secs`` and the device object
++path are the parameters that matter to start a measurement; every
++other key below is optional configuration with a usable default. For
++Reflector role, only ``role``, ``sync_ant_sel`` and ``max_tx_power``
++are required or have any effect — the remaining keys are accepted but
++otherwise unused, since no local procedure is armed.
++
++Supported dictionary keys:
++
++:uint32 duration_secs (Default: 0):
++
++	Duration in seconds before the measurement is stopped
++	automatically. A value of 0 disables the automatic timeout.
++
++:byte role (Default: 0x03):
++
++	CS role to use for the measurement.
++
++	Possible values:
++
++	:0x01: Initiator
++	:0x02: Reflector
++	:0x03: Both (Initiator and Reflector)
++
++:byte sync_ant_sel (Default: 0xFF):
++
++	CS sync antenna selection. Values 0xFE and 0xFF are reserved
++	by the Bluetooth specification.
++
++:byte max_tx_power (Default: 0x14):
++
++	Maximum TX power in dBm, treated as a signed value. Valid
++	range is -127 to +20 dBm.
++
++:byte config_id:
++
++	CS configuration identifier.
++
++:byte main_mode_type:
++
++	Main CS mode used in the procedure.
++
++:byte sub_mode_type:
++
++	Sub-mode within the main mode. Set to 0xFF when unused.
++
++:byte main_mode_min_steps:
++
++	Minimum number of CS main mode steps per CS subevent.
++
++:byte main_mode_max_steps:
++
++	Maximum number of CS main mode steps per CS subevent.
++
++:byte main_mode_repetition:
++
++	Number of times the main mode steps are repeated in a
++	subevent.
++
++:byte mode0_steps:
++
++	Number of CS Mode 0 steps at the beginning of each subevent.
++
++:byte rtt_types:
++
++	Round Trip Time measurement types for the configuration.
++
++:byte sync_phy:
++
++	PHY used for CS sync packets.
++
++	Possible values:
++
++	:0x01: LE 1M PHY
++	:0x02: LE 2M PHY
++
++:array{byte} channel_map:
++
++	10-byte channel map bitmap. Must be exactly 10 bytes.
++
++:byte channel_map_repetition:
++
++	Number of consecutive repetitions of the channel map.
++
++:byte channel_selection_type:
++
++	Algorithm used for CS channel selection.
++
++:byte channel_shape:
++
++	Shape used in the channel selection algorithm.
++
++:byte channel_jump:
++
++	Channel jump size used in the channel selection algorithm.
++
++:byte companion_signal_enable:
++
++	Set to 1 to transmit a companion signal alongside the CS
++	tone, 0 to disable.
++
++:uint16 max_procedure_duration:
++
++	Maximum duration of a single CS measurement procedure.
++
++:uint16 min_period_between_procedures:
++
++	Minimum time between consecutive CS measurement procedures.
++
++:uint16 max_period_between_procedures:
++
++	Maximum time between consecutive CS measurement procedures.
++
++:uint16 max_procedure_count:
++
++	Maximum number of CS measurement procedures to run.
++	A value of 0 means no limit.
++
++:array{byte} min_sub_event_len:
++
++	Minimum CS subevent length as a 3-byte little-endian value.
++	Must be exactly 3 bytes.
++
++:array{byte} max_sub_event_len:
++
++	Maximum CS subevent length as a 3-byte little-endian value.
++	Must be exactly 3 bytes.
++
++:byte tone_antenna_config_selection:
++
++	Antenna configuration used for CS tone exchanges.
++
++:byte phy:
++
++	PHY used during CS procedures.
++
++	Possible values:
++
++	:0x01: LE 1M PHY
++	:0x02: LE 2M PHY
++
++:byte tx_power_delta:
++
++	Difference between remote and local TX power during CS
++	procedures. 0x80 indicates not applicable.
++
++:byte preferred_peer_antenna:
++
++	Preferred antenna to be used by the peer device.
++
++:byte snr_control_initiator:
++
++	SNR control setting for the initiator role.
++	0xFF indicates no preference.
++
++:byte snr_control_reflector:
++
++	SNR control setting for the reflector role.
++	0xFF indicates no preference.
++
++Possible errors:
++
++:org.bluez.Error.InProgress:
++:org.bluez.Error.InvalidArgs:
++:org.freedesktop.DBus.Error.Failed:
++
++Examples:
++
++:bluetoothctl set role then start:
++	| [cs] > role 0x01
++	| [cs] > main_mode_type 2
++	| [cs] > start AA:BB:CC:DD:EE:FF
++:bluetoothctl start with defaults:
++	| [cs] > start [dev_addr] [duration_secs]
++:bluetoothctl configure as Reflector (applies settings, does not start a measurement):
++	| [cs] > role 0x02
++	| [cs] > start
++
++void StopMeasurement(void)
++``````````````````````````
++
++Stops the active Channel Sounding distance measurement on this device.
++The device is identified by the D-Bus object path on which this method
++is called — no session identifier is required.
++
++Raises ``org.bluez.Error.NotConnected`` if no measurement is active.
++
++Possible errors:
++
++:org.bluez.Error.NotConnected:
++:org.freedesktop.DBus.Error.Failed:
++
++In **bluetoothctl(1)**, the device address argument may be omitted only
++when a single measurement is active; it is required when multiple
++measurements are active.
++
++Examples:
++
++:bluetoothctl stop the only active measurement:
++	| [cs] > stop
++:bluetoothctl stop a specific device when multiple are active:
++	| [cs] > stop AA:BB:CC:DD:EE:FF
++
++Signals
++-------
++
++void ProcedureData(dict data)
++``````````````````````````````
++
++Emitted when a Channel Sounding measurement procedure completes on this
++device, carrying the raw CS procedure results as reported by the
++controller. Consumers such as an external ranging estimation daemon
++subscribe to this signal to compute distance estimates.
++
++:dict data:
++
++	:int32 procedureCounter:
++
++		Procedure counter value from the controller.
++
++	:int32 procedureSequence:
++
++		Sequence number of this procedure.
++
++	:byte initiatorSelectedTxPower:
++
++		TX power selected by the Initiator, treated as a signed
++		value.
++
++	:byte reflectorSelectedTxPower:
++
++		TX power selected by the Reflector, treated as a signed
++		value.
++
++	:uint32 initiatorSubeventCount:
++
++		Number of subevent results reported by the Initiator.
++
++	:array{dict} initiatorSubeventResults:
++
++		Present only when ``initiatorSubeventCount`` is greater
++		than 0. One entry per Initiator subevent, each with the
++		fields described in `Subevent Result`_ below.
++
++	:byte initiatorProcedureAbortReason:
++
++		Reason the Initiator's procedure was aborted, 0 if not
++		aborted.
++
++	:uint32 reflectorSubeventCount:
++
++		Number of subevent results reported by the Reflector.
++
++	:array{dict} reflectorSubeventResults:
++
++		Present only when ``reflectorSubeventCount`` is greater
++		than 0. One entry per Reflector subevent, each with the
++		fields described in `Subevent Result`_ below.
++
++	:byte reflectorProcedureAbortReason:
++
++		Reason the Reflector's procedure was aborted, 0 if not
++		aborted.
++
++	:dict procedureEnableConfig:
++
++		:byte toneAntennaConfigSelection:
++
++			Antenna configuration used for CS tone exchanges.
++
++		:uint32 subeventLenUs:
++
++			Subevent length in microseconds.
++
++		:byte subeventsPerEvent:
++
++			Number of subevents per event.
++
++		:uint32 subeventInterval:
++
++			Interval between subevents.
++
++		:uint32 eventInterval:
++
++			Interval between events.
++
++		:uint32 procedureInterval:
++
++			Interval between procedures.
++
++		:uint32 procedureCount:
++
++			Number of procedures configured.
++
++		:uint32 maxProcedureLen:
++
++			Maximum procedure length.
++
++	:dict csConfigParam:
++
++		:byte modeType:
++
++			Main CS mode used in the procedure.
++
++		:byte subModeType:
++
++			Sub-mode within the main mode.
++
++		:byte rttType:
++
++			Round Trip Time measurement type.
++
++		:array{byte} channelMap:
++
++			10-byte channel map bitmap.
++
++		:byte minMainModeSteps:
++		:byte maxMainModeSteps:
++		:byte mainModeRepetition:
++		:byte mode0Steps:
++
++		:byte role:
++
++			CS role in effect for the procedure (Initiator,
++			Reflector, or Both).
++
++		:byte csSyncPhyType:
++
++			PHY used for CS sync packets.
++
++		:byte channelSelectionType:
++		:byte ch3cShapeType:
++		:byte ch3cJump:
++		:byte channelMapRepetition:
++		:byte tIp1TimeUs:
++		:byte tIp2TimeUs:
++		:byte tFcsTimeUs:
++		:byte tPmTimeUs:
++		:byte tSwTimeUsSupportedByLocal:
++		:byte tSwTimeUsSupportedByRemote:
++
++		:uint32 bleConnInterval:
++
++			BLE connection interval in effect during the
++			procedure.
++
++Subevent Result
++~~~~~~~~~~~~~~~~
++
++Each element of ``initiatorSubeventResults`` and
++``reflectorSubeventResults`` is a dict with the following fields:
++
++:int32 startAclConnEvtCounter:
++
++	ACL connection event counter at the start of the subevent.
++
++:int32 freqComp:
++
++	Frequency compensation value.
++
++:byte refPwrLvl:
++
++	Reference power level, treated as a signed value.
++
++:byte numAntPaths:
++
++	Number of antenna paths used.
++
++:byte subeventAbortReason:
++
++	Reason the subevent was aborted, 0 if not aborted.
++
++:uint64 timestampNanos:
++
++	Timestamp of the subevent result, in nanoseconds.
++
++:uint32 numSteps:
++
++	Number of steps reported in this subevent.
++
++:array{dict} stepData:
++
++	One entry per step. Each entry has:
++
++	:byte stepMode:
++
++		CS step mode (0-3).
++
++	:byte stepChannel:
++
++		Channel used for the step.
++
++	:dict modeZeroData:
++
++		Present when ``stepMode`` is 0.
++
++		:byte packetQuality:
++		:byte packetRssiDbm:
++		:byte packetAntenna:
++
++		:int32 initiatorMeasuredFreqOffset:
++
++			Frequency offset measured by the Initiator.
++
++	:dict modeOneData:
++
++		Present when ``stepMode`` is 1.
++
++		:byte packetQuality:
++		:byte packetNadm:
++		:byte packetRssiDbm:
++
++		:int32 toaTodInitiator:
++
++			Time of Arrival / Time of Departure at the
++			Initiator.
++
++		:int32 todToaReflector:
++
++			Time of Departure / Time of Arrival at the
++			Reflector.
++
++		:byte packetAntenna:
++
++		:array{int32} packetPct1:
++
++			In-phase/quadrature sample pair, as
++			``[i_sample, q_sample]``.
++
++		:array{int32} packetPct2:
++
++			In-phase/quadrature sample pair, as
++			``[i_sample, q_sample]``.
++
++	:dict modeTwoData:
++
++		Present when ``stepMode`` is 2.
++
++		:byte antennaPermutationIndex:
++
++		:array{int32} tonePctIQSamples:
++
++			Interleaved in-phase/quadrature tone samples, as
++			``[i_sample, q_sample, ...]`` — one pair per
++			antenna path.
++
++		:array{byte} toneQualityIndicators:
++
++			One quality indicator byte per antenna path.
++
++	:dict modeThreeData:
++
++		Present when ``stepMode`` is 3. Contains the combined
++		fields of both **modeOneData** and **modeTwoData**.
++
++Properties
++----------
++
++boolean Active [readonly]
++`````````````````````````
++
++Indicates whether a CS distance measurement procedure is currently
++active on this device.
++
++Set to ``true`` when a procedure starts — either because the local
++Initiator called **StartMeasurement** successfully, or because the
++remote Initiator enabled a CS procedure on the local Reflector.
++
++Set to ``false`` when the procedure stops for any reason: the local
++application called **StopMeasurement**, the measurement duration timer
++expired, or the ACL connection was dropped.
++
++This property emits ``PropertiesChanged`` on every transition so that
++clients can track measurement state without polling.
++
++RESOURCES
++=========
++
++http://www.bluez.org
++
++REPORTING BUGS
++==============
++
++linux-bluetooth@vger.kernel.org
+-- 
+2.54.0
+
+
+From 30db66dc971bd1cd95d4a7b0eea296367ab65b3b Mon Sep 17 00:00:00 2001
+From: Naga Bhavani Akella <naga.akella@oss.qualcomm.com>
+Date: Wed, 15 Jul 2026 14:09:57 +0530
+Subject: [PATCH 19/19] doc/bluetoothctl-cs: Add :Uses: fields and document
+ arguments
+
+Add :Uses: fields to link commands to their corresponding D-Bus API
+methods, and document command arguments with usage examples
+---
+ Makefile.tools          |   5 +-
+ doc/bluetoothctl-cs.rst | 546 ++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 549 insertions(+), 2 deletions(-)
+ create mode 100644 doc/bluetoothctl-cs.rst
+
+diff --git a/Makefile.tools b/Makefile.tools
+index 6188449f1565..0646d52e14dc 100644
+--- a/Makefile.tools
++++ b/Makefile.tools
+@@ -359,7 +359,7 @@ man_MANS += doc/rctest.1 doc/l2ping.1 doc/btattach.1 doc/isotest.1 \
+ 		doc/bluetoothctl-gatt.1 doc/bluetoothctl-player.1 \
+ 		doc/bluetoothctl-scan.1 doc/bluetoothctl-transport.1 \
+ 		doc/bluetoothctl-assistant.1 doc/bluetoothctl-hci.1 \
+-		doc/bluetoothctl-telephony.1
++		doc/bluetoothctl-telephony.1 doc/bluetoothctl-cs.1
+ 
+ endif
+ 
+@@ -465,7 +465,8 @@ manual_pages += doc/hciattach.1 doc/hciconfig.1 doc/hcitool.1 \
+ 			doc/bluetoothctl-transport.1 \
+ 			doc/bluetoothctl-assistant.1 \
+ 			doc/bluetoothctl-hci.1 \
+-			doc/bluetoothctl-telephony.1
++			doc/bluetoothctl-telephony.1 \
++			doc/bluetoothctl-cs.1
+ 
+ if HID2HCI
+ udevdir = $(UDEV_DIR)
+diff --git a/doc/bluetoothctl-cs.rst b/doc/bluetoothctl-cs.rst
+new file mode 100644
+index 000000000000..bbc1d8565f91
+--- /dev/null
++++ b/doc/bluetoothctl-cs.rst
+@@ -0,0 +1,546 @@
++================
++bluetoothctl-cs
++================
++
++--------------------------
++Channel Sounding Submenu
++--------------------------
++
++:Version: BlueZ
++:Copyright: Free use of this software is granted under the terms of the GNU
++            Lesser General Public Licenses (LGPL).
++:Date: June 2026
++:Manual section: 1
++:Manual group: Linux System Administration
++
++SYNOPSIS
++========
++
++**bluetoothctl** [--options] [cs.commands]
++
++This submenu controls Bluetooth Channel Sounding (CS) distance measurement
++using the **org.bluez.ChannelSounding1(5)** D-Bus interface. It allows
++starting and stopping measurements and inspecting the current parameter
++state and active session identifier.
++
++Each CS parameter has its own **cs.<param>** set command (see the
++**CS Parameter Commands** section below). Overrides are applied to
++the local parameter state immediately, so **show** reflects them
++right away; **start** always uses whatever values are currently set.
++
++
++Channel Sounding Commands
++=========================
++
++start
++-----
++
++Starts a distance measurement on the connected device using the
++currently set CS parameters (see the **cs.<param>** commands below).
++All configuration is sent to the daemon in a single **StartMeasurement**
++call. On success the device path is printed to the console. Multiple
++simultaneous sessions across different devices are supported; each is
++tracked independently.
++
++Calling **start** on a device that already has an active measurement
++returns an error without starting a second session on the same device.
++
++For Initiator role (or Both), the mandatory parameters are the
++positional ``dev_addr`` and ``duration_secs``; every ``cs.<param>``
++command below is optional configuration with a usable default.
++
++If ``role`` is set to Reflector (``0x02``, via **cs.role**), **start**
++does not begin measuring distance: a Reflector never initiates a CS
++procedure. It only pushes the current parameters to the daemon and
++arms the device to respond once the remote Initiator starts one; the
++call still succeeds. When the remote side starts or stops a procedure,
++the console prints ``Measurement started``/``Measurement stopped`` for
++that device — use **show** or watch the ``Active`` property to see
++the same transition. In this role the only parameters that are
++required or have any effect are ``role``, ``sync_ant_sel`` and
++``max_tx_power``; every other **cs.<param>** command below is
++accepted but unused.
++
++Positional arguments are optional:
++
++- ``dev_addr`` — Bluetooth address of the target device; uses the only
++  available CS-capable device when omitted.
++- ``duration_secs`` — auto-stop timeout in seconds; ``0`` (default) means
++  no timeout.
++
++:Usage: **> start [dev_addr] [duration_secs]**
++:Uses: **org.bluez.ChannelSounding1(5)** method **StartMeasurement**
++:[dev_addr]: Bluetooth address of the target device (optional; uses the
++             only available CS-capable device when omitted)
++:[duration_secs]: Seconds before auto-stop (optional, default 0 = no timeout)
++
++:Example Start with all defaults, no timeout:
++	| **> start**
++:Example Start on a specific device:
++	| **> start AA:BB:CC:DD:EE:FF**
++:Example Start on a specific device with 10-second auto-stop:
++	| **> start AA:BB:CC:DD:EE:FF 10**
++:Example Start with 10-second auto-stop (single device, address omitted):
++	| **> start 0 10**
++:Example Start with 5-minute auto-stop:
++	| **> start AA:BB:CC:DD:EE:FF 300**
++
++stop
++----
++
++Stops an active CS distance measurement. When only one measurement is
++running the device address may be omitted. When multiple measurements
++are active the address is required to identify which one to stop.
++
++:Usage: **> stop [dev_addr]**
++:Uses: **org.bluez.ChannelSounding1(5)** method **StopMeasurement**
++:[dev_addr]: Bluetooth address of the device to stop (optional when
++             only one session is active; required otherwise)
++:Example Stop the only active measurement:
++	| **> stop**
++:Example Stop a specific device when multiple are active:
++	| **> stop AA:BB:CC:DD:EE:FF**
++:Example Stop a second device:
++	| **> stop 11:22:33:44:55:66**
++
++show
++----
++
++Displays all active measurements (device path for each) and the full
++set of CS parameter values that will be used on the next **start** call.
++When no measurements are active, ``none`` is shown.
++
++The parameter output is divided into three sections:
++
++- **Default Settings** — role, CS sync antenna selection, max TX power.
++- **CS Config Params** — per-procedure configuration fields including
++  mode type, step counts, PHY, and channel map.
++- **CS Frequency Params** — procedure scheduling fields including
++  duration, period, subevent lengths, and SNR control.
++
++:Usage: **> show**
++:Example Show active session and all CS parameters:
++	| **> show**
++
++CS Parameter Commands
++======================
++
++Each CS parameter is set with its own command, of the form
++``cs.<param> <value>``. Entering a param command with no value shows
++its current setting. Overrides apply to the local parameter state
++immediately, so **show** reflects them right away; **start** always
++uses whatever values are currently set. Array-valued parameters
++(``channel_map``, ``min_sub_event_len``, ``max_sub_event_len``) take
++colon-separated hex bytes with no ``0x`` prefix.
++
++:Usage: **> <param> [value]**
++
++role
++----
++
++Get/set the CS role.
++
++:Usage: **> role [0x01|0x02|0x03]**
++:[0x01|0x02|0x03]: ``0x01`` Initiator, ``0x02`` Reflector, ``0x03`` Both
++                   (optional, shows current if omitted; default ``0x03``)
++:Example Show current role:
++	| **> role**
++:Example Set role to Initiator only:
++	| **> role 0x01**
++:Example Set role to Reflector only (does not measure):
++	| **> role 0x02**
++:Example Set role to both Initiator and Reflector:
++	| **> role 0x03**
++
++sync_ant_sel
++------------
++
++Get/set the CS sync antenna selection.
++
++:Usage: **> sync_ant_sel [value]**
++:[value]: CS sync antenna selection; ``0xFE``/``0xFF`` reserved
++          (optional, shows current if omitted; default ``0xFF``)
++:Example Show current antenna selection:
++	| **> sync_ant_sel**
++:Example Select antenna 1:
++	| **> sync_ant_sel 0x01**
++
++max_tx_power
++------------
++
++Get/set the maximum TX power.
++
++:Usage: **> max_tx_power [dBm]**
++:[dBm]: Max TX power in dBm, signed (optional, shows current if
++        omitted; range −127 to +20; default ``20``)
++:Example Show current max TX power:
++	| **> max_tx_power**
++:Example Reduce max TX power to 10 dBm:
++	| **> max_tx_power 10**
++
++config_id
++---------
++
++Get/set the CS configuration identifier.
++
++:Usage: **> config_id [value]**
++:[value]: CS configuration identifier (optional, shows current if
++          omitted; default ``0``)
++:Example Show current config id:
++	| **> config_id**
++:Example Set config id to 1:
++	| **> config_id 1**
++
++main_mode_type
++--------------
++
++Get/set the CS main mode type.
++
++:Usage: **> main_mode_type [1|2|3]**
++:[1|2|3]: ``1`` Mode 1 (RTT), ``2`` Mode 2 (PBR), ``3`` Both (optional,
++          shows current if omitted; default ``1``)
++:Example Show current main mode type:
++	| **> main_mode_type**
++:Example Set main mode to Mode 2 (PBR):
++	| **> main_mode_type 2**
++:Example Set main mode to both RTT and PBR:
++	| **> main_mode_type 3**
++
++sub_mode_type
++-------------
++
++Get/set the CS sub-mode type within the main mode.
++
++:Usage: **> sub_mode_type [value]**
++:[value]: Sub-mode within main mode; ``0xFF`` = unused (optional,
++          shows current if omitted; default ``0xFF``)
++:Example Show current sub-mode type:
++	| **> sub_mode_type**
++:Example Set sub-mode type to 0x01:
++	| **> sub_mode_type 0x01**
++
++main_mode_min_steps
++--------------------
++
++Get/set the minimum CS main mode steps per subevent.
++
++:Usage: **> main_mode_min_steps [value]**
++:[value]: Min CS main mode steps per subevent (optional, shows
++          current if omitted; default ``2``)
++:Example Show current value:
++	| **> main_mode_min_steps**
++:Example Set minimum steps to 4:
++	| **> main_mode_min_steps 4**
++
++main_mode_max_steps
++--------------------
++
++Get/set the maximum CS main mode steps per subevent.
++
++:Usage: **> main_mode_max_steps [value]**
++:[value]: Max CS main mode steps per subevent (optional, shows
++          current if omitted; default ``3``)
++:Example Show current value:
++	| **> main_mode_max_steps**
++:Example Set maximum steps to 8:
++	| **> main_mode_max_steps 8**
++
++main_mode_repetition
++---------------------
++
++Get/set how many times main mode steps are repeated in a subevent.
++
++:Usage: **> main_mode_repetition [value]**
++:[value]: Repetition count (optional, shows current if omitted;
++          default ``1``)
++:Example Show current value:
++	| **> main_mode_repetition**
++:Example Repeat main mode steps twice:
++	| **> main_mode_repetition 2**
++
++mode0_steps
++-----------
++
++Get/set the number of CS Mode 0 steps at the beginning of each
++subevent.
++
++:Usage: **> mode0_steps [value]**
++:[value]: CS Mode 0 step count (optional, shows current if omitted;
++          default ``2``)
++:Example Show current value:
++	| **> mode0_steps**
++:Example Set Mode 0 steps to 3:
++	| **> mode0_steps 3**
++
++rtt_types
++---------
++
++Get/set the RTT measurement types bitmask.
++
++:Usage: **> rtt_types [value]**
++:[value]: RTT measurement types bitmask (optional, shows current if
++          omitted; default ``0``)
++:Example Show current value:
++	| **> rtt_types**
++:Example Set RTT types bitmask:
++	| **> rtt_types 0x01**
++
++sync_phy
++--------
++
++Get/set the PHY used for CS sync.
++
++:Usage: **> sync_phy [0x01|0x02]**
++:[0x01|0x02]: ``0x01`` LE 1M, ``0x02`` LE 2M (optional, shows current
++              if omitted; default ``0x01``)
++:Example Show current sync PHY:
++	| **> sync_phy**
++:Example Set CS sync PHY to LE 2M:
++	| **> sync_phy 0x02**
++
++channel_map
++-----------
++
++Get/set the 10-byte CS channel map bitmap.
++
++:Usage: **> channel_map [b0:b1:...:b9]**
++:[b0:b1:...:b9]: 10 colon-separated hex bytes (optional, shows current
++                 if omitted; default ``FC:FF:7F:FC:FF:FF:FF:FF:FF:1F``)
++:Example Show current channel map:
++	| **> channel_map**
++:Example Set a custom channel map (all enabled):
++	| **> channel_map FF:FF:FF:FF:FF:FF:FF:FF:FF:FF**
++
++channel_map_repetition
++-----------------------
++
++Get/set the number of consecutive repetitions of the channel map.
++
++:Usage: **> channel_map_repetition [value]**
++:[value]: Repetition count (optional, shows current if omitted;
++          default ``1``)
++:Example Show current value:
++	| **> channel_map_repetition**
++:Example Repeat the channel map 3 times:
++	| **> channel_map_repetition 3**
++
++channel_selection_type
++-----------------------
++
++Get/set the CS channel selection algorithm.
++
++:Usage: **> channel_selection_type [value]**
++:[value]: Channel selection algorithm (optional, shows current if
++          omitted; default ``0``)
++:Example Show current value:
++	| **> channel_selection_type**
++:Example Select algorithm 1:
++	| **> channel_selection_type 1**
++
++channel_shape
++-------------
++
++Get/set the shape used in the channel selection algorithm.
++
++:Usage: **> channel_shape [value]**
++:[value]: Channel shape (optional, shows current if omitted; default
++          ``0``)
++:Example Show current value:
++	| **> channel_shape**
++:Example Set channel shape to 1:
++	| **> channel_shape 1**
++
++channel_jump
++------------
++
++Get/set the channel jump size.
++
++:Usage: **> channel_jump [value]**
++:[value]: Channel jump size (optional, shows current if omitted;
++          default ``2``)
++:Example Show current value:
++	| **> channel_jump**
++:Example Set channel jump to 4:
++	| **> channel_jump 4**
++
++companion_signal_enable
++------------------------
++
++Get/set whether the companion signal is transmitted.
++
++:Usage: **> companion_signal_enable [0|1]**
++:[0|1]: ``1`` to transmit companion signal, ``0`` to disable (optional,
++        shows current if omitted; default ``0``)
++:Example Show current value:
++	| **> companion_signal_enable**
++:Example Enable the companion signal:
++	| **> companion_signal_enable 1**
++
++max_procedure_duration
++-----------------------
++
++Get/set the maximum duration of one CS measurement procedure.
++
++:Usage: **> max_procedure_duration [value]**
++:[value]: Maximum procedure duration (optional, shows current if
++          omitted; default ``1600``)
++:Example Show current value:
++	| **> max_procedure_duration**
++:Example Set max procedure duration to 800:
++	| **> max_procedure_duration 800**
++
++min_period_between_procedures
++-------------------------------
++
++Get/set the minimum time between consecutive procedures.
++
++:Usage: **> min_period_between_procedures [value]**
++:[value]: Minimum period (optional, shows current if omitted; default
++          ``30``)
++:Example Show current value:
++	| **> min_period_between_procedures**
++:Example Set minimum period to 50:
++	| **> min_period_between_procedures 50**
++
++max_period_between_procedures
++-------------------------------
++
++Get/set the maximum time between consecutive procedures.
++
++:Usage: **> max_period_between_procedures [value]**
++:[value]: Maximum period (optional, shows current if omitted; default
++          ``150``)
++:Example Show current value:
++	| **> max_period_between_procedures**
++:Example Set maximum period to 200:
++	| **> max_period_between_procedures 200**
++
++max_procedure_count
++--------------------
++
++Get/set the maximum number of procedures.
++
++:Usage: **> max_procedure_count [value]**
++:[value]: Max procedure count; ``0`` = no limit (optional, shows
++          current if omitted; default ``0``)
++:Example Show current value:
++	| **> max_procedure_count**
++:Example Limit the procedure count to 100:
++	| **> max_procedure_count 100**
++
++min_sub_event_len
++------------------
++
++Get/set the minimum CS subevent length.
++
++:Usage: **> min_sub_event_len [b0:b1:b2]**
++:[b0:b1:b2]: 3-byte LE value, colon-separated hex (optional, shows
++             current if omitted; default ``00:20:00``)
++:Example Show current value:
++	| **> min_sub_event_len**
++:Example Set minimum subevent length:
++	| **> min_sub_event_len 00:10:00**
++
++max_sub_event_len
++------------------
++
++Get/set the maximum CS subevent length.
++
++:Usage: **> max_sub_event_len [b0:b1:b2]**
++:[b0:b1:b2]: 3-byte LE value, colon-separated hex (optional, shows
++             current if omitted; default ``03:20:00``)
++:Example Show current value:
++	| **> max_sub_event_len**
++:Example Set maximum subevent length:
++	| **> max_sub_event_len 04:20:00**
++
++tone_antenna_config_selection
++-------------------------------
++
++Get/set the antenna configuration for CS tone exchanges.
++
++:Usage: **> tone_antenna_config_selection [value]**
++:[value]: Antenna config selection (optional, shows current if
++          omitted; default ``0x07``)
++:Example Show current value:
++	| **> tone_antenna_config_selection**
++:Example Set antenna config to 0x01:
++	| **> tone_antenna_config_selection 0x01**
++
++phy
++---
++
++Get/set the PHY used for CS procedures.
++
++:Usage: **> phy [0x01|0x02]**
++:[0x01|0x02]: ``0x01`` LE 1M, ``0x02`` LE 2M (optional, shows current
++              if omitted; default ``0x01``)
++:Example Show current procedure PHY:
++	| **> phy**
++:Example Set CS procedure PHY to LE 2M:
++	| **> phy 0x02**
++
++tx_power_delta
++--------------
++
++Get/set the remote vs local TX power delta.
++
++:Usage: **> tx_power_delta [value]**
++:[value]: TX power delta; ``0x80`` = not applicable (optional, shows
++          current if omitted; default ``0x80``)
++:Example Show current value:
++	| **> tx_power_delta**
++:Example Set TX power delta to 0x05:
++	| **> tx_power_delta 0x05**
++
++preferred_peer_antenna
++-----------------------
++
++Get/set the preferred antenna for the peer device.
++
++:Usage: **> preferred_peer_antenna [value]**
++:[value]: Preferred peer antenna (optional, shows current if omitted;
++          default ``0x03``)
++:Example Show current value:
++	| **> preferred_peer_antenna**
++:Example Prefer antenna 1 on the peer:
++	| **> preferred_peer_antenna 0x01**
++
++snr_control_initiator
++----------------------
++
++Get/set the SNR control for the initiator.
++
++:Usage: **> snr_control_initiator [value]**
++:[value]: SNR control; ``0xFF`` = no preference (optional, shows
++          current if omitted; default ``0xFF``)
++:Example Show current value:
++	| **> snr_control_initiator**
++:Example Prefer high SNR on the initiator:
++	| **> snr_control_initiator 0x01**
++
++snr_control_reflector
++----------------------
++
++Get/set the SNR control for the reflector.
++
++:Usage: **> snr_control_reflector [value]**
++:[value]: SNR control; ``0xFF`` = no preference (optional, shows
++          current if omitted; default ``0xFF``)
++:Example Show current value:
++	| **> snr_control_reflector**
++:Example Prefer high SNR on the reflector:
++	| **> snr_control_reflector 0x01**
++:Example Prefer high SNR on both roles:
++	| **> snr_control_initiator 0x01**
++	| **> snr_control_reflector 0x01**
++
++RESOURCES
++=========
++
++http://www.bluez.org
++
++REPORTING BUGS
++==============
++
++linux-bluetooth@vger.kernel.org
+-- 
+2.54.0
+

diff --git a/bluez.spec b/bluez.spec
index 425a311..89514a1 100644
--- a/bluez.spec
+++ b/bluez.spec
@@ -6,15 +6,15 @@
 
 Name:    bluez
 Version: 5.87
-Release: 2%{?dist}
+Release: 3%{?dist}
 Summary: Bluetooth utilities
 License: GPL-2.0-or-later
 URL:     http://www.bluez.org/
 
 Source0: https://www.kernel.org/pub/linux/bluetooth/%{name}-%{version}.tar.xz
 
-# https://git.kernel.org/pub/scm/bluetooth/bluez.git/commit/?id=5bc6aa79e53700d56fc1f9f9364573ba4c78da65
-Patch1: 0001-adapter-Fix-crash-on-dev_disconnected.patch
+# git format-patch --stdout 5.87...30db66dc971bd1cd95d4a7b0eea296367ab65b3b
+Patch1: 5.87-bug-fixes-1.patch
 
 BuildRequires: dbus-devel >= 1.6
 BuildRequires: glib2-devel
@@ -340,6 +340,9 @@ install emulator/btvirt ${RPM_BUILD_ROOT}/%{_libexecdir}/bluetooth/
 %{_userunitdir}/obex.service
 
 %changelog
+* Fri Jul 17 2026 Bastien Nocera <bnocera@redhat.com> - 5.87-3
+- Update to latest upstream HEAD to fix a number of possible crashes
+
 * Wed Jul 08 2026 Bastien Nocera <bnocera@redhat.com> - 5.87-2
 - Add post-release crash fix on disconnection
 

                 reply	other threads:[~2026-07-17 12:29 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=178429138636.1.1830937039761259664.rpms-bluez-0bb713b6503e@fedoraproject.org \
    --to=hadess@hadess.net \
    --cc=git-commits@fedoraproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox