* [PATCH v2 2/7] Bluetooth: hci_core: Introduce HCI_CONN_FLAG_PAST
2025-10-07 14:49 [PATCH v2 1/7] Bluetooth: HCI: Add initial support for PAST Luiz Augusto von Dentz
@ 2025-10-07 14:49 ` Luiz Augusto von Dentz
2025-10-07 14:49 ` [PATCH v2 3/7] Bluetooth: ISO: Add support to bind to trigger PAST Luiz Augusto von Dentz
` (5 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2025-10-07 14:49 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This introduces a new device flag so userspace can indicate if it
wants to enable PAST Receiver for a specific device.
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
include/net/bluetooth/hci_core.h | 1 +
net/bluetooth/hci_sync.c | 55 +++++++++++++++++++++++++++++++-
2 files changed, 55 insertions(+), 1 deletion(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 894e01717b55..2a765a0521b4 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -166,6 +166,7 @@ enum hci_conn_flags {
HCI_CONN_FLAG_REMOTE_WAKEUP = BIT(0),
HCI_CONN_FLAG_DEVICE_PRIVACY = BIT(1),
HCI_CONN_FLAG_ADDRESS_RESOLUTION = BIT(2),
+ HCI_CONN_FLAG_PAST = BIT(3),
};
typedef u8 hci_conn_flags_t;
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index 277b2c096195..5051413f1a97 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -4324,6 +4324,10 @@ static int hci_le_set_event_mask_sync(struct hci_dev *hdev)
if (ll_privacy_capable(hdev))
hdev->conn_flags |= HCI_CONN_FLAG_ADDRESS_RESOLUTION;
+ /* Mark PAST if supported */
+ if (past_capable(hdev))
+ hdev->conn_flags |= HCI_CONN_FLAG_PAST;
+
/* If the controller supports Extended Scanner Filter
* Policies, enable the corresponding event.
*/
@@ -7024,10 +7028,41 @@ static void create_pa_complete(struct hci_dev *hdev, void *data, int err)
hci_dev_unlock(hdev);
}
+static int hci_le_past_params_sync(struct hci_dev *hdev, struct hci_conn *conn,
+ struct hci_conn *acl, struct bt_iso_qos *qos)
+{
+ struct hci_cp_le_past_params cp;
+ int err;
+
+ memset(&cp, 0, sizeof(cp));
+ cp.handle = cpu_to_le16(acl->handle);
+ /* An HCI_LE_Periodic_Advertising_Sync_Transfer_Received event is sent
+ * to the Host. HCI_LE_Periodic_Advertising_Report events will be
+ * enabled with duplicate filtering enabled.
+ */
+ cp.mode = 0x03;
+ cp.skip = cpu_to_le16(qos->bcast.skip);
+ cp.sync_timeout = cpu_to_le16(qos->bcast.sync_timeout);
+ cp.cte_type = qos->bcast.sync_cte_type;
+
+ /* HCI_LE_PAST_PARAMS command returns a command complete event so it
+ * cannot wait for HCI_EV_LE_PAST_RECEIVED.
+ */
+ err = __hci_cmd_sync_status(hdev, HCI_OP_LE_PAST_PARAMS,
+ sizeof(cp), &cp, HCI_CMD_TIMEOUT);
+ if (err)
+ return err;
+
+ /* Wait for HCI_EV_LE_PAST_RECEIVED event */
+ return __hci_cmd_sync_status_sk(hdev, HCI_OP_NOP, 0, NULL,
+ HCI_EV_LE_PAST_RECEIVED,
+ conn->conn_timeout, NULL);
+}
+
static int hci_le_pa_create_sync(struct hci_dev *hdev, void *data)
{
struct hci_cp_le_pa_create_sync cp;
- struct hci_conn *conn = data;
+ struct hci_conn *conn = data, *le;
struct bt_iso_qos *qos = &conn->iso_qos;
int err;
@@ -7059,6 +7094,24 @@ static int hci_le_pa_create_sync(struct hci_dev *hdev, void *data)
hci_update_passive_scan_sync(hdev);
+ /* Check if PAST is possible:
+ *
+ * 1. Check if an ACL connection with the destination address exists
+ * 2. Check if that HCI_CONN_FLAG_PAST has been set which indicates that
+ * user really intended to use PAST.
+ */
+ le = hci_conn_hash_lookup_le(hdev, &conn->dst, conn->dst_type);
+ if (le) {
+ struct hci_conn_params *params;
+
+ params = hci_conn_params_lookup(hdev, &le->dst, le->dst_type);
+ if (params && params->flags & HCI_CONN_FLAG_PAST) {
+ err = hci_le_past_params_sync(hdev, conn, le, qos);
+ if (!err)
+ goto done;
+ }
+ }
+
/* SID has not been set listen for HCI_EV_LE_EXT_ADV_REPORT to update
* it.
*/
--
2.51.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v2 3/7] Bluetooth: ISO: Add support to bind to trigger PAST
2025-10-07 14:49 [PATCH v2 1/7] Bluetooth: HCI: Add initial support for PAST Luiz Augusto von Dentz
2025-10-07 14:49 ` [PATCH v2 2/7] Bluetooth: hci_core: Introduce HCI_CONN_FLAG_PAST Luiz Augusto von Dentz
@ 2025-10-07 14:49 ` Luiz Augusto von Dentz
2025-10-07 16:16 ` Pauli Virtanen
2025-10-07 14:49 ` [PATCH v2 4/7] Bluetooth: HCI: Always use the identity address when initializing a connection Luiz Augusto von Dentz
` (4 subsequent siblings)
6 siblings, 1 reply; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2025-10-07 14:49 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This makes it possible to bind to a different destination address
after being connected (BT_CONNECTED, BT_CONNECT2) which then triggers
PAST Sender proceedure to transfer the PA Sync to the destination
address.
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
include/net/bluetooth/hci_sync.h | 1 +
net/bluetooth/hci_sync.c | 90 ++++++++++++++++++++++++++++++++
net/bluetooth/iso.c | 80 +++++++++++++++++++++-------
3 files changed, 153 insertions(+), 18 deletions(-)
diff --git a/include/net/bluetooth/hci_sync.h b/include/net/bluetooth/hci_sync.h
index e352a4e0ef8d..3133f40fa9f9 100644
--- a/include/net/bluetooth/hci_sync.h
+++ b/include/net/bluetooth/hci_sync.h
@@ -188,3 +188,4 @@ int hci_le_conn_update_sync(struct hci_dev *hdev, struct hci_conn *conn,
int hci_connect_pa_sync(struct hci_dev *hdev, struct hci_conn *conn);
int hci_connect_big_sync(struct hci_dev *hdev, struct hci_conn *conn);
+int hci_past_sync(struct hci_conn *conn, struct hci_conn *le);
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index 5051413f1a97..571e07f81523 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -7228,3 +7228,93 @@ int hci_connect_big_sync(struct hci_dev *hdev, struct hci_conn *conn)
return hci_cmd_sync_queue_once(hdev, hci_le_big_create_sync, conn,
create_big_complete);
}
+
+struct past_data {
+ struct hci_conn *conn;
+ struct hci_conn *le;
+};
+
+static void past_complete(struct hci_dev *hdev, void *data, int err)
+{
+ struct past_data *past = data;
+
+ bt_dev_dbg(hdev, "err %d", err);
+
+ kfree(past);
+}
+
+static int hci_le_past_set_info_sync(struct hci_dev *hdev, void *data)
+{
+ struct past_data *past = data;
+ struct hci_cp_le_past_set_info cp;
+
+ hci_dev_lock(hdev);
+
+ if (!hci_conn_valid(hdev, past->conn) ||
+ !hci_conn_valid(hdev, past->le)) {
+ hci_dev_unlock(hdev);
+ return -ECANCELED;
+ }
+
+ memset(&cp, 0, sizeof(cp));
+ cp.handle = cpu_to_le16(past->le->handle);
+ cp.adv_handle = past->conn->iso_qos.bcast.bis;
+
+ hci_dev_unlock(hdev);
+
+ return __hci_cmd_sync_status(hdev, HCI_OP_LE_PAST_SET_INFO,
+ sizeof(cp), &cp, HCI_CMD_TIMEOUT);
+}
+
+static int hci_le_past_sync(struct hci_dev *hdev, void *data)
+{
+ struct past_data *past = data;
+ struct hci_cp_le_past cp;
+
+ hci_dev_lock(hdev);
+
+ if (!hci_conn_valid(hdev, past->conn) ||
+ !hci_conn_valid(hdev, past->le))
+ return -ECANCELED;
+
+ memset(&cp, 0, sizeof(cp));
+ cp.handle = past->le->handle;
+ cp.sync_handle = cpu_to_le16(past->conn->sync_handle);
+
+ hci_dev_unlock(hdev);
+
+ return __hci_cmd_sync_status(hdev, HCI_OP_LE_PAST,
+ sizeof(cp), &cp, HCI_CMD_TIMEOUT);
+}
+
+int hci_past_sync(struct hci_conn *conn, struct hci_conn *le)
+{
+ struct past_data *data;
+ int err;
+
+ if (conn->type != BIS_LINK && conn->type != PA_LINK)
+ return -EINVAL;
+
+ if (!past_sender_capable(conn->hdev))
+ return -EOPNOTSUPP;
+
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->conn = conn;
+ data->le = le;
+
+ if (conn->role == HCI_ROLE_MASTER)
+ err = hci_cmd_sync_queue_once(conn->hdev,
+ hci_le_past_set_info_sync, data,
+ past_complete);
+ else
+ err = hci_cmd_sync_queue_once(conn->hdev, hci_le_past_sync,
+ data, past_complete);
+
+ if (err)
+ kfree(data);
+
+ return err;
+}
diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
index 7f66f287c14e..d4c8772152bd 100644
--- a/net/bluetooth/iso.c
+++ b/net/bluetooth/iso.c
@@ -987,20 +987,13 @@ static int iso_sock_bind_bc(struct socket *sock, struct sockaddr *addr,
return 0;
}
-static int iso_sock_bind_pa_sk(struct sock *sk, struct sockaddr_iso *sa,
+static int iso_sock_rebind_bis(struct sock *sk, struct sockaddr_iso *sa,
int addr_len)
{
int err = 0;
- if (sk->sk_type != SOCK_SEQPACKET) {
- err = -EINVAL;
- goto done;
- }
-
- if (addr_len != sizeof(*sa) + sizeof(*sa->iso_bc)) {
- err = -EINVAL;
- goto done;
- }
+ if (!test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags))
+ return -EBADFD;
if (sa->iso_bc->bc_num_bis > ISO_MAX_NUM_BIS) {
err = -EINVAL;
@@ -1023,6 +1016,58 @@ static int iso_sock_bind_pa_sk(struct sock *sk, struct sockaddr_iso *sa,
return err;
}
+static int iso_sock_rebind_bc(struct sock *sk, struct sockaddr_iso *sa,
+ int addr_len)
+{
+ struct hci_conn *bis;
+ struct hci_conn *le;
+ int err;
+
+ if (sk->sk_type != SOCK_SEQPACKET || !iso_pi(sk)->conn)
+ return -EINVAL;
+
+ /* Check if it is really a Broadcast address being requested */
+ if (addr_len != sizeof(*sa) + sizeof(*sa->iso_bc))
+ return -EINVAL;
+
+ /* Check if the address hasn't changed then perhaps only the number of
+ * bis has changed.
+ */
+ if (!bacmp(&iso_pi(sk)->dst, &sa->iso_bc->bc_bdaddr) ||
+ !bacmp(&sa->iso_bc->bc_bdaddr, BDADDR_ANY))
+ return iso_sock_rebind_bis(sk, sa, addr_len);
+
+ /* Check if the address type is of LE type */
+ if (!bdaddr_type_is_le(sa->iso_bc->bc_bdaddr_type))
+ return -EINVAL;
+
+ iso_conn_lock(iso_pi(sk)->conn);
+ bis = iso_pi(sk)->conn->hcon;
+ iso_conn_unlock(iso_pi(sk)->conn);
+
+ if (!bis)
+ return -EINVAL;
+
+ hci_dev_lock(bis->hdev);
+
+ /* Lookup existing LE connection to rebind to */
+ le = hci_conn_hash_lookup_le(bis->hdev, &sa->iso_bc->bc_bdaddr,
+ le_addr_type(sa->iso_bc->bc_bdaddr_type));
+ if (!le) {
+ hci_dev_unlock(bis->hdev);
+ return -EINVAL;
+ }
+
+ BT_DBG("sk %p %pMR type %u", sk, &sa->iso_bc->bc_bdaddr,
+ sa->iso_bc->bc_bdaddr_type);
+
+ err = hci_past_sync(bis, le);
+
+ hci_dev_unlock(bis->hdev);
+
+ return err;
+}
+
static int iso_sock_bind(struct socket *sock, struct sockaddr *addr,
int addr_len)
{
@@ -1038,14 +1083,13 @@ static int iso_sock_bind(struct socket *sock, struct sockaddr *addr,
lock_sock(sk);
- /* Allow the user to bind a PA sync socket to a number
- * of BISes to sync to.
- */
- if ((sk->sk_state == BT_CONNECT2 ||
- sk->sk_state == BT_CONNECTED) &&
- test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags)) {
- err = iso_sock_bind_pa_sk(sk, sa, addr_len);
- goto done;
+ if ((sk->sk_state == BT_CONNECT2 || sk->sk_state == BT_CONNECTED) &&
+ addr_len > sizeof(*sa)) {
+ release_sock(sk);
+ /* Allow the user to rebind to a different address using
+ * PAST procedures.
+ */
+ return iso_sock_rebind_bc(sk, sa, addr_len);
}
if (sk->sk_state != BT_OPEN) {
--
2.51.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [PATCH v2 3/7] Bluetooth: ISO: Add support to bind to trigger PAST
2025-10-07 14:49 ` [PATCH v2 3/7] Bluetooth: ISO: Add support to bind to trigger PAST Luiz Augusto von Dentz
@ 2025-10-07 16:16 ` Pauli Virtanen
2025-10-07 17:50 ` Luiz Augusto von Dentz
0 siblings, 1 reply; 10+ messages in thread
From: Pauli Virtanen @ 2025-10-07 16:16 UTC (permalink / raw)
To: Luiz Augusto von Dentz, linux-bluetooth
ti, 2025-10-07 kello 10:49 -0400, Luiz Augusto von Dentz kirjoitti:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> This makes it possible to bind to a different destination address
> after being connected (BT_CONNECTED, BT_CONNECT2) which then triggers
> PAST Sender proceedure to transfer the PA Sync to the destination
> address.
>
> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> ---
> include/net/bluetooth/hci_sync.h | 1 +
> net/bluetooth/hci_sync.c | 90 ++++++++++++++++++++++++++++++++
> net/bluetooth/iso.c | 80 +++++++++++++++++++++-------
> 3 files changed, 153 insertions(+), 18 deletions(-)
>
> diff --git a/include/net/bluetooth/hci_sync.h b/include/net/bluetooth/hci_sync.h
> index e352a4e0ef8d..3133f40fa9f9 100644
> --- a/include/net/bluetooth/hci_sync.h
> +++ b/include/net/bluetooth/hci_sync.h
> @@ -188,3 +188,4 @@ int hci_le_conn_update_sync(struct hci_dev *hdev, struct hci_conn *conn,
>
> int hci_connect_pa_sync(struct hci_dev *hdev, struct hci_conn *conn);
> int hci_connect_big_sync(struct hci_dev *hdev, struct hci_conn *conn);
> +int hci_past_sync(struct hci_conn *conn, struct hci_conn *le);
> diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
> index 5051413f1a97..571e07f81523 100644
> --- a/net/bluetooth/hci_sync.c
> +++ b/net/bluetooth/hci_sync.c
> @@ -7228,3 +7228,93 @@ int hci_connect_big_sync(struct hci_dev *hdev, struct hci_conn *conn)
> return hci_cmd_sync_queue_once(hdev, hci_le_big_create_sync, conn,
> create_big_complete);
> }
> +
> +struct past_data {
> + struct hci_conn *conn;
> + struct hci_conn *le;
> +};
> +
> +static void past_complete(struct hci_dev *hdev, void *data, int err)
> +{
> + struct past_data *past = data;
> +
> + bt_dev_dbg(hdev, "err %d", err);
> +
> + kfree(past);
> +}
> +
> +static int hci_le_past_set_info_sync(struct hci_dev *hdev, void *data)
> +{
> + struct past_data *past = data;
> + struct hci_cp_le_past_set_info cp;
> +
> + hci_dev_lock(hdev);
> +
> + if (!hci_conn_valid(hdev, past->conn) ||
> + !hci_conn_valid(hdev, past->le)) {
> + hci_dev_unlock(hdev);
> + return -ECANCELED;
> + }
> +
> + memset(&cp, 0, sizeof(cp));
> + cp.handle = cpu_to_le16(past->le->handle);
> + cp.adv_handle = past->conn->iso_qos.bcast.bis;
> +
> + hci_dev_unlock(hdev);
> +
> + return __hci_cmd_sync_status(hdev, HCI_OP_LE_PAST_SET_INFO,
> + sizeof(cp), &cp, HCI_CMD_TIMEOUT);
> +}
> +
> +static int hci_le_past_sync(struct hci_dev *hdev, void *data)
> +{
> + struct past_data *past = data;
> + struct hci_cp_le_past cp;
> +
> + hci_dev_lock(hdev);
> +
> + if (!hci_conn_valid(hdev, past->conn) ||
> + !hci_conn_valid(hdev, past->le))
> + return -ECANCELED;
> +
> + memset(&cp, 0, sizeof(cp));
> + cp.handle = past->le->handle;
> + cp.sync_handle = cpu_to_le16(past->conn->sync_handle);
> +
> + hci_dev_unlock(hdev);
> +
> + return __hci_cmd_sync_status(hdev, HCI_OP_LE_PAST,
> + sizeof(cp), &cp, HCI_CMD_TIMEOUT);
> +}
> +
> +int hci_past_sync(struct hci_conn *conn, struct hci_conn *le)
> +{
> + struct past_data *data;
> + int err;
> +
> + if (conn->type != BIS_LINK && conn->type != PA_LINK)
> + return -EINVAL;
> +
> + if (!past_sender_capable(conn->hdev))
> + return -EOPNOTSUPP;
> +
> + data = kmalloc(sizeof(*data), GFP_KERNEL);
> + if (!data)
> + return -ENOMEM;
> +
> + data->conn = conn;
> + data->le = le;
> +
> + if (conn->role == HCI_ROLE_MASTER)
> + err = hci_cmd_sync_queue_once(conn->hdev,
> + hci_le_past_set_info_sync, data,
> + past_complete);
> + else
> + err = hci_cmd_sync_queue_once(conn->hdev, hci_le_past_sync,
> + data, past_complete);
> +
> + if (err)
> + kfree(data);
> +
> + return err;
> +}
> diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
> index 7f66f287c14e..d4c8772152bd 100644
> --- a/net/bluetooth/iso.c
> +++ b/net/bluetooth/iso.c
> @@ -987,20 +987,13 @@ static int iso_sock_bind_bc(struct socket *sock, struct sockaddr *addr,
> return 0;
> }
>
> -static int iso_sock_bind_pa_sk(struct sock *sk, struct sockaddr_iso *sa,
> +static int iso_sock_rebind_bis(struct sock *sk, struct sockaddr_iso *sa,
> int addr_len)
> {
> int err = 0;
>
> - if (sk->sk_type != SOCK_SEQPACKET) {
> - err = -EINVAL;
> - goto done;
> - }
> -
> - if (addr_len != sizeof(*sa) + sizeof(*sa->iso_bc)) {
> - err = -EINVAL;
> - goto done;
> - }
> + if (!test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags))
> + return -EBADFD;
>
> if (sa->iso_bc->bc_num_bis > ISO_MAX_NUM_BIS) {
> err = -EINVAL;
> @@ -1023,6 +1016,58 @@ static int iso_sock_bind_pa_sk(struct sock *sk, struct sockaddr_iso *sa,
> return err;
> }
>
> +static int iso_sock_rebind_bc(struct sock *sk, struct sockaddr_iso *sa,
> + int addr_len)
> +{
> + struct hci_conn *bis;
> + struct hci_conn *le;
> + int err;
> +
> + if (sk->sk_type != SOCK_SEQPACKET || !iso_pi(sk)->conn)
> + return -EINVAL;
> +
> + /* Check if it is really a Broadcast address being requested */
> + if (addr_len != sizeof(*sa) + sizeof(*sa->iso_bc))
> + return -EINVAL;
> +
> + /* Check if the address hasn't changed then perhaps only the number of
> + * bis has changed.
> + */
> + if (!bacmp(&iso_pi(sk)->dst, &sa->iso_bc->bc_bdaddr) ||
> + !bacmp(&sa->iso_bc->bc_bdaddr, BDADDR_ANY))
> + return iso_sock_rebind_bis(sk, sa, addr_len);
> +
> + /* Check if the address type is of LE type */
> + if (!bdaddr_type_is_le(sa->iso_bc->bc_bdaddr_type))
> + return -EINVAL;
> +
> + iso_conn_lock(iso_pi(sk)->conn);
> + bis = iso_pi(sk)->conn->hcon;
> + iso_conn_unlock(iso_pi(sk)->conn);
> +
> + if (!bis)
> + return -EINVAL;
> +
> + hci_dev_lock(bis->hdev);
No lock is held here before hdev lock. If bis is freed concurrently,
this is UAF.
Maybe:
hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
iso_pi(sk)->src_type);
if (!hdev)
return -EHOSTUNREACH;
hci_dev_lock(hdev);
iso_conn_lock(iso_pi(sk)->conn);
bis = iso_pi(sk)->conn->hcon;
if (bis->hdev != hdev)
bis = NULL;
iso_conn_unlock(iso_pi(sk)->conn);
if (!bis) {
hci_dev_unlock(hdev);
hci_dev_put(hdev);
return -EINVAL;
}
...
hci_dev_put(hdev);
Or maybe hdev can be get also from iso_pi(sk)->conn->hcon, how the
locking and ownership seem to work currently for iso_conn need
contortions:
/* Must be called on unlocked sk */
static struct hci_conn *iso_get_sk_hdev(struct sock *sk)
{
struct hci_dev *hdev = NULL;
/* Lock sk: access to iso_pi(sk)->conn needs sk lock because
* iso_disconn_cfm() -> iso_conn_del() -> iso_chan_del()
* sets iso_pi(sk)->conn = NULL under hdev->lock & sk lock
*/
lock_sock(sk);
conn = iso_pi(sk)->conn;
/* Lock conn: does not seem to be really necessary as code
* paths that touch conn->hcon seem to all hold sk lock
* based on a quick look
*/
iso_conn_lock(conn);
if (conn->hcon)
hdev = hci_dev_hold(conn->hcon->hdev);
iso_conn_unlock(conn);
release_sock(sk);
return hdev;
}
> +
> + /* Lookup existing LE connection to rebind to */
> + le = hci_conn_hash_lookup_le(bis->hdev, &sa->iso_bc->bc_bdaddr,
> + le_addr_type(sa->iso_bc->bc_bdaddr_type));
> + if (!le) {
> + hci_dev_unlock(bis->hdev);
> + return -EINVAL;
> + }
> +
> + BT_DBG("sk %p %pMR type %u", sk, &sa->iso_bc->bc_bdaddr,
> + sa->iso_bc->bc_bdaddr_type);
> +
> + err = hci_past_sync(bis, le);
> +
> + hci_dev_unlock(bis->hdev);
> +
> + return err;
> +}
> +
> static int iso_sock_bind(struct socket *sock, struct sockaddr *addr,
> int addr_len)
> {
> @@ -1038,14 +1083,13 @@ static int iso_sock_bind(struct socket *sock, struct sockaddr *addr,
>
> lock_sock(sk);
>
> - /* Allow the user to bind a PA sync socket to a number
> - * of BISes to sync to.
> - */
> - if ((sk->sk_state == BT_CONNECT2 ||
> - sk->sk_state == BT_CONNECTED) &&
> - test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags)) {
> - err = iso_sock_bind_pa_sk(sk, sa, addr_len);
> - goto done;
> + if ((sk->sk_state == BT_CONNECT2 || sk->sk_state == BT_CONNECTED) &&
> + addr_len > sizeof(*sa)) {
> + release_sock(sk);
> + /* Allow the user to rebind to a different address using
> + * PAST procedures.
> + */
> + return iso_sock_rebind_bc(sk, sa, addr_len);
> }
>
> if (sk->sk_state != BT_OPEN) {
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH v2 3/7] Bluetooth: ISO: Add support to bind to trigger PAST
2025-10-07 16:16 ` Pauli Virtanen
@ 2025-10-07 17:50 ` Luiz Augusto von Dentz
0 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2025-10-07 17:50 UTC (permalink / raw)
To: Pauli Virtanen; +Cc: linux-bluetooth
Hi Pauli,
On Tue, Oct 7, 2025 at 12:16 PM Pauli Virtanen <pav@iki.fi> wrote:
>
> ti, 2025-10-07 kello 10:49 -0400, Luiz Augusto von Dentz kirjoitti:
> > From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> >
> > This makes it possible to bind to a different destination address
> > after being connected (BT_CONNECTED, BT_CONNECT2) which then triggers
> > PAST Sender proceedure to transfer the PA Sync to the destination
> > address.
> >
> > Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> > ---
> > include/net/bluetooth/hci_sync.h | 1 +
> > net/bluetooth/hci_sync.c | 90 ++++++++++++++++++++++++++++++++
> > net/bluetooth/iso.c | 80 +++++++++++++++++++++-------
> > 3 files changed, 153 insertions(+), 18 deletions(-)
> >
> > diff --git a/include/net/bluetooth/hci_sync.h b/include/net/bluetooth/hci_sync.h
> > index e352a4e0ef8d..3133f40fa9f9 100644
> > --- a/include/net/bluetooth/hci_sync.h
> > +++ b/include/net/bluetooth/hci_sync.h
> > @@ -188,3 +188,4 @@ int hci_le_conn_update_sync(struct hci_dev *hdev, struct hci_conn *conn,
> >
> > int hci_connect_pa_sync(struct hci_dev *hdev, struct hci_conn *conn);
> > int hci_connect_big_sync(struct hci_dev *hdev, struct hci_conn *conn);
> > +int hci_past_sync(struct hci_conn *conn, struct hci_conn *le);
> > diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
> > index 5051413f1a97..571e07f81523 100644
> > --- a/net/bluetooth/hci_sync.c
> > +++ b/net/bluetooth/hci_sync.c
> > @@ -7228,3 +7228,93 @@ int hci_connect_big_sync(struct hci_dev *hdev, struct hci_conn *conn)
> > return hci_cmd_sync_queue_once(hdev, hci_le_big_create_sync, conn,
> > create_big_complete);
> > }
> > +
> > +struct past_data {
> > + struct hci_conn *conn;
> > + struct hci_conn *le;
> > +};
> > +
> > +static void past_complete(struct hci_dev *hdev, void *data, int err)
> > +{
> > + struct past_data *past = data;
> > +
> > + bt_dev_dbg(hdev, "err %d", err);
> > +
> > + kfree(past);
> > +}
> > +
> > +static int hci_le_past_set_info_sync(struct hci_dev *hdev, void *data)
> > +{
> > + struct past_data *past = data;
> > + struct hci_cp_le_past_set_info cp;
> > +
> > + hci_dev_lock(hdev);
> > +
> > + if (!hci_conn_valid(hdev, past->conn) ||
> > + !hci_conn_valid(hdev, past->le)) {
> > + hci_dev_unlock(hdev);
> > + return -ECANCELED;
> > + }
> > +
> > + memset(&cp, 0, sizeof(cp));
> > + cp.handle = cpu_to_le16(past->le->handle);
> > + cp.adv_handle = past->conn->iso_qos.bcast.bis;
> > +
> > + hci_dev_unlock(hdev);
> > +
> > + return __hci_cmd_sync_status(hdev, HCI_OP_LE_PAST_SET_INFO,
> > + sizeof(cp), &cp, HCI_CMD_TIMEOUT);
> > +}
> > +
> > +static int hci_le_past_sync(struct hci_dev *hdev, void *data)
> > +{
> > + struct past_data *past = data;
> > + struct hci_cp_le_past cp;
> > +
> > + hci_dev_lock(hdev);
> > +
> > + if (!hci_conn_valid(hdev, past->conn) ||
> > + !hci_conn_valid(hdev, past->le))
> > + return -ECANCELED;
> > +
> > + memset(&cp, 0, sizeof(cp));
> > + cp.handle = past->le->handle;
> > + cp.sync_handle = cpu_to_le16(past->conn->sync_handle);
> > +
> > + hci_dev_unlock(hdev);
> > +
> > + return __hci_cmd_sync_status(hdev, HCI_OP_LE_PAST,
> > + sizeof(cp), &cp, HCI_CMD_TIMEOUT);
> > +}
> > +
> > +int hci_past_sync(struct hci_conn *conn, struct hci_conn *le)
> > +{
> > + struct past_data *data;
> > + int err;
> > +
> > + if (conn->type != BIS_LINK && conn->type != PA_LINK)
> > + return -EINVAL;
> > +
> > + if (!past_sender_capable(conn->hdev))
> > + return -EOPNOTSUPP;
> > +
> > + data = kmalloc(sizeof(*data), GFP_KERNEL);
> > + if (!data)
> > + return -ENOMEM;
> > +
> > + data->conn = conn;
> > + data->le = le;
> > +
> > + if (conn->role == HCI_ROLE_MASTER)
> > + err = hci_cmd_sync_queue_once(conn->hdev,
> > + hci_le_past_set_info_sync, data,
> > + past_complete);
> > + else
> > + err = hci_cmd_sync_queue_once(conn->hdev, hci_le_past_sync,
> > + data, past_complete);
> > +
> > + if (err)
> > + kfree(data);
> > +
> > + return err;
> > +}
> > diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
> > index 7f66f287c14e..d4c8772152bd 100644
> > --- a/net/bluetooth/iso.c
> > +++ b/net/bluetooth/iso.c
> > @@ -987,20 +987,13 @@ static int iso_sock_bind_bc(struct socket *sock, struct sockaddr *addr,
> > return 0;
> > }
> >
> > -static int iso_sock_bind_pa_sk(struct sock *sk, struct sockaddr_iso *sa,
> > +static int iso_sock_rebind_bis(struct sock *sk, struct sockaddr_iso *sa,
> > int addr_len)
> > {
> > int err = 0;
> >
> > - if (sk->sk_type != SOCK_SEQPACKET) {
> > - err = -EINVAL;
> > - goto done;
> > - }
> > -
> > - if (addr_len != sizeof(*sa) + sizeof(*sa->iso_bc)) {
> > - err = -EINVAL;
> > - goto done;
> > - }
> > + if (!test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags))
> > + return -EBADFD;
> >
> > if (sa->iso_bc->bc_num_bis > ISO_MAX_NUM_BIS) {
> > err = -EINVAL;
> > @@ -1023,6 +1016,58 @@ static int iso_sock_bind_pa_sk(struct sock *sk, struct sockaddr_iso *sa,
> > return err;
> > }
> >
> > +static int iso_sock_rebind_bc(struct sock *sk, struct sockaddr_iso *sa,
> > + int addr_len)
> > +{
> > + struct hci_conn *bis;
> > + struct hci_conn *le;
> > + int err;
> > +
> > + if (sk->sk_type != SOCK_SEQPACKET || !iso_pi(sk)->conn)
> > + return -EINVAL;
> > +
> > + /* Check if it is really a Broadcast address being requested */
> > + if (addr_len != sizeof(*sa) + sizeof(*sa->iso_bc))
> > + return -EINVAL;
> > +
> > + /* Check if the address hasn't changed then perhaps only the number of
> > + * bis has changed.
> > + */
> > + if (!bacmp(&iso_pi(sk)->dst, &sa->iso_bc->bc_bdaddr) ||
> > + !bacmp(&sa->iso_bc->bc_bdaddr, BDADDR_ANY))
> > + return iso_sock_rebind_bis(sk, sa, addr_len);
> > +
> > + /* Check if the address type is of LE type */
> > + if (!bdaddr_type_is_le(sa->iso_bc->bc_bdaddr_type))
> > + return -EINVAL;
> > +
> > + iso_conn_lock(iso_pi(sk)->conn);
> > + bis = iso_pi(sk)->conn->hcon;
> > + iso_conn_unlock(iso_pi(sk)->conn);
> > +
> > + if (!bis)
> > + return -EINVAL;
> > +
> > + hci_dev_lock(bis->hdev);
>
> No lock is held here before hdev lock. If bis is freed concurrently,
> this is UAF.
>
> Maybe:
>
> hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
> iso_pi(sk)->src_type);
> if (!hdev)
> return -EHOSTUNREACH;
>
> hci_dev_lock(hdev);
>
> iso_conn_lock(iso_pi(sk)->conn);
> bis = iso_pi(sk)->conn->hcon;
> if (bis->hdev != hdev)
> bis = NULL;
> iso_conn_unlock(iso_pi(sk)->conn);
>
> if (!bis) {
> hci_dev_unlock(hdev);
> hci_dev_put(hdev);
> return -EINVAL;
> }
>
> ...
>
> hci_dev_put(hdev);
>
> Or maybe hdev can be get also from iso_pi(sk)->conn->hcon, how the
> locking and ownership seem to work currently for iso_conn need
> contortions:
>
> /* Must be called on unlocked sk */
> static struct hci_conn *iso_get_sk_hdev(struct sock *sk)
> {
> struct hci_dev *hdev = NULL;
>
> /* Lock sk: access to iso_pi(sk)->conn needs sk lock because
> * iso_disconn_cfm() -> iso_conn_del() -> iso_chan_del()
> * sets iso_pi(sk)->conn = NULL under hdev->lock & sk lock
> */
This is a good comment, but in practice the race mentioned above only
happens between bind and a disconnect/release/shutdown if the socket
itself is shutdown concurrently, which is why we almost never
experience this sort of UAF with the likes of bluetoothd since we
don't do threads in the daemon, in fact this might only be possible
with virtual controller where the fuzzy testing goes to extreme with
both doing threads and artificially generating responses from the
controller.
> lock_sock(sk);
>
> conn = iso_pi(sk)->conn;
>
> /* Lock conn: does not seem to be really necessary as code
> * paths that touch conn->hcon seem to all hold sk lock
> * based on a quick look
> */
> iso_conn_lock(conn);
> if (conn->hcon)
> hdev = hci_dev_hold(conn->hcon->hdev);
> iso_conn_unlock(conn);
>
> release_sock(sk);
>
> return hdev;
> }
This may not be a bad idea, that said perhaps we will need to
generalize it and then export as bt_sock, anyway I can incorporate
something like this first to see the behavior in the context of PAST.
Btw, Ive seen some subsystem do use sk_bound_dev_if then use
netdev_get_by_index which seem to be the equivalent to hci_dev_get,
but I don't know if it is safe to use sk_bound_dev_if since that seem
to assume a net_dev not hci_dev so maybe it is safer to store the
hci_dev index somewhere else.
>
> > +
> > + /* Lookup existing LE connection to rebind to */
> > + le = hci_conn_hash_lookup_le(bis->hdev, &sa->iso_bc->bc_bdaddr,
> > + le_addr_type(sa->iso_bc->bc_bdaddr_type));
> > + if (!le) {
> > + hci_dev_unlock(bis->hdev);
> > + return -EINVAL;
> > + }
> > +
> > + BT_DBG("sk %p %pMR type %u", sk, &sa->iso_bc->bc_bdaddr,
> > + sa->iso_bc->bc_bdaddr_type);
> > +
> > + err = hci_past_sync(bis, le);
> > +
> > + hci_dev_unlock(bis->hdev);
> > +
> > + return err;
> > +}
> > +
> > static int iso_sock_bind(struct socket *sock, struct sockaddr *addr,
> > int addr_len)
> > {
> > @@ -1038,14 +1083,13 @@ static int iso_sock_bind(struct socket *sock, struct sockaddr *addr,
> >
> > lock_sock(sk);
> >
> > - /* Allow the user to bind a PA sync socket to a number
> > - * of BISes to sync to.
> > - */
> > - if ((sk->sk_state == BT_CONNECT2 ||
> > - sk->sk_state == BT_CONNECTED) &&
> > - test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags)) {
> > - err = iso_sock_bind_pa_sk(sk, sa, addr_len);
> > - goto done;
> > + if ((sk->sk_state == BT_CONNECT2 || sk->sk_state == BT_CONNECTED) &&
> > + addr_len > sizeof(*sa)) {
> > + release_sock(sk);
> > + /* Allow the user to rebind to a different address using
> > + * PAST procedures.
> > + */
> > + return iso_sock_rebind_bc(sk, sa, addr_len);
> > }
> >
> > if (sk->sk_state != BT_OPEN) {
--
Luiz Augusto von Dentz
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 4/7] Bluetooth: HCI: Always use the identity address when initializing a connection
2025-10-07 14:49 [PATCH v2 1/7] Bluetooth: HCI: Add initial support for PAST Luiz Augusto von Dentz
2025-10-07 14:49 ` [PATCH v2 2/7] Bluetooth: hci_core: Introduce HCI_CONN_FLAG_PAST Luiz Augusto von Dentz
2025-10-07 14:49 ` [PATCH v2 3/7] Bluetooth: ISO: Add support to bind to trigger PAST Luiz Augusto von Dentz
@ 2025-10-07 14:49 ` Luiz Augusto von Dentz
2025-10-07 14:49 ` [PATCH v2 5/7] Bluetooth: ISO: Attempt to resolve broadcast address Luiz Augusto von Dentz
` (3 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2025-10-07 14:49 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This makes sure hci_conn is initialized with the identity address if
a matching IRK exists which avoids the trouble of having to do it at
multiple places which seems to be missing (e.g. CIS, BIS and PA).
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
include/net/bluetooth/hci_core.h | 4 +--
net/bluetooth/hci_conn.c | 43 ++++++++++++++++++++------------
net/bluetooth/hci_event.c | 20 +++++++--------
net/bluetooth/hci_sync.c | 2 +-
4 files changed, 40 insertions(+), 29 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 2a765a0521b4..c1889e1aa477 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1563,9 +1563,9 @@ int hci_le_create_cis_pending(struct hci_dev *hdev);
int hci_conn_check_create_cis(struct hci_conn *conn);
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
- u8 role, u16 handle);
+ u8 dst_type, u8 role, u16 handle);
struct hci_conn *hci_conn_add_unset(struct hci_dev *hdev, int type,
- bdaddr_t *dst, u8 role);
+ bdaddr_t *dst, u8 dst_type, u8 role);
void hci_conn_del(struct hci_conn *conn);
void hci_conn_hash_flush(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 111f0e37b672..88485b6aeedc 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -911,10 +911,12 @@ static int hci_conn_hash_alloc_unset(struct hci_dev *hdev)
U16_MAX, GFP_ATOMIC);
}
-static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
+static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type,
+ bdaddr_t *dst, u8 dst_type,
u8 role, u16 handle)
{
struct hci_conn *conn;
+ struct smp_irk *irk = NULL;
switch (type) {
case ACL_LINK:
@@ -926,12 +928,14 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t
case PA_LINK:
if (!hdev->iso_mtu)
return ERR_PTR(-ECONNREFUSED);
+ irk = hci_get_irk(hdev, dst, dst_type);
break;
case LE_LINK:
if (hdev->le_mtu && hdev->le_mtu < HCI_MIN_LE_MTU)
return ERR_PTR(-ECONNREFUSED);
if (!hdev->le_mtu && hdev->acl_mtu < HCI_MIN_LE_MTU)
return ERR_PTR(-ECONNREFUSED);
+ irk = hci_get_irk(hdev, dst, dst_type);
break;
case SCO_LINK:
case ESCO_LINK:
@@ -949,7 +953,15 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t
if (!conn)
return ERR_PTR(-ENOMEM);
- bacpy(&conn->dst, dst);
+ /* If and IRK exists use its identity address */
+ if (!irk) {
+ bacpy(&conn->dst, dst);
+ conn->dst_type = dst_type;
+ } else {
+ bacpy(&conn->dst, &irk->bdaddr);
+ conn->dst_type = irk->addr_type;
+ }
+
bacpy(&conn->src, &hdev->bdaddr);
conn->handle = handle;
conn->hdev = hdev;
@@ -1047,7 +1059,7 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t
}
struct hci_conn *hci_conn_add_unset(struct hci_dev *hdev, int type,
- bdaddr_t *dst, u8 role)
+ bdaddr_t *dst, u8 dst_type, u8 role)
{
int handle;
@@ -1057,16 +1069,16 @@ struct hci_conn *hci_conn_add_unset(struct hci_dev *hdev, int type,
if (unlikely(handle < 0))
return ERR_PTR(-ECONNREFUSED);
- return __hci_conn_add(hdev, type, dst, role, handle);
+ return __hci_conn_add(hdev, type, dst, dst_type, role, handle);
}
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
- u8 role, u16 handle)
+ u8 dst_type, u8 role, u16 handle)
{
if (handle > HCI_CONN_HANDLE_MAX)
return ERR_PTR(-EINVAL);
- return __hci_conn_add(hdev, type, dst, role, handle);
+ return __hci_conn_add(hdev, type, dst, dst_type, role, handle);
}
static void hci_conn_cleanup_child(struct hci_conn *conn, u8 reason)
@@ -1398,14 +1410,13 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
if (conn) {
bacpy(&conn->dst, dst);
} else {
- conn = hci_conn_add_unset(hdev, LE_LINK, dst, role);
+ conn = hci_conn_add_unset(hdev, LE_LINK, dst, dst_type, role);
if (IS_ERR(conn))
return conn;
hci_conn_hold(conn);
conn->pending_sec_level = sec_level;
}
- conn->dst_type = dst_type;
conn->sec_level = BT_SECURITY_LOW;
conn->conn_timeout = conn_timeout;
conn->le_adv_phy = phy;
@@ -1575,7 +1586,7 @@ static struct hci_conn *hci_add_bis(struct hci_dev *hdev, bdaddr_t *dst,
memcmp(conn->le_per_adv_data, base, base_len)))
return ERR_PTR(-EADDRINUSE);
- conn = hci_conn_add_unset(hdev, BIS_LINK, dst, HCI_ROLE_MASTER);
+ conn = hci_conn_add_unset(hdev, BIS_LINK, dst, 0, HCI_ROLE_MASTER);
if (IS_ERR(conn))
return conn;
@@ -1621,7 +1632,8 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
BT_DBG("requesting refresh of dst_addr");
- conn = hci_conn_add_unset(hdev, LE_LINK, dst, HCI_ROLE_MASTER);
+ conn = hci_conn_add_unset(hdev, LE_LINK, dst, dst_type,
+ HCI_ROLE_MASTER);
if (IS_ERR(conn))
return conn;
@@ -1632,7 +1644,6 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
conn->state = BT_CONNECT;
set_bit(HCI_CONN_SCANNING, &conn->flags);
- conn->dst_type = dst_type;
conn->sec_level = BT_SECURITY_LOW;
conn->pending_sec_level = sec_level;
conn->conn_timeout = conn_timeout;
@@ -1669,7 +1680,8 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
if (!acl) {
- acl = hci_conn_add_unset(hdev, ACL_LINK, dst, HCI_ROLE_MASTER);
+ acl = hci_conn_add_unset(hdev, ACL_LINK, dst, 0,
+ HCI_ROLE_MASTER);
if (IS_ERR(acl))
return acl;
}
@@ -1738,7 +1750,7 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
sco = hci_conn_hash_lookup_ba(hdev, type, dst);
if (!sco) {
- sco = hci_conn_add_unset(hdev, type, dst, HCI_ROLE_MASTER);
+ sco = hci_conn_add_unset(hdev, type, dst, 0, HCI_ROLE_MASTER);
if (IS_ERR(sco)) {
hci_conn_drop(acl);
return sco;
@@ -1930,7 +1942,7 @@ struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst,
cis = hci_conn_hash_lookup_cis(hdev, dst, dst_type, qos->ucast.cig,
qos->ucast.cis);
if (!cis) {
- cis = hci_conn_add_unset(hdev, CIS_LINK, dst,
+ cis = hci_conn_add_unset(hdev, CIS_LINK, dst, dst_type,
HCI_ROLE_MASTER);
if (IS_ERR(cis))
return cis;
@@ -2121,12 +2133,11 @@ struct hci_conn *hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst,
bt_dev_dbg(hdev, "dst %pMR type %d sid %d", dst, dst_type, sid);
- conn = hci_conn_add_unset(hdev, PA_LINK, dst, HCI_ROLE_SLAVE);
+ conn = hci_conn_add_unset(hdev, PA_LINK, dst, dst_type, HCI_ROLE_SLAVE);
if (IS_ERR(conn))
return conn;
conn->iso_qos = *qos;
- conn->dst_type = dst_type;
conn->sid = sid;
conn->state = BT_LISTEN;
conn->conn_timeout = msecs_to_jiffies(qos->bcast.sync_timeout * 10);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index f1735a7e48a7..ba0a7b41611f 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2267,7 +2267,7 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
} else {
if (!conn) {
conn = hci_conn_add_unset(hdev, ACL_LINK, &cp->bdaddr,
- HCI_ROLE_MASTER);
+ 0, HCI_ROLE_MASTER);
if (IS_ERR(conn))
bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn));
}
@@ -3123,7 +3123,8 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
&ev->bdaddr,
BDADDR_BREDR)) {
conn = hci_conn_add_unset(hdev, ev->link_type,
- &ev->bdaddr, HCI_ROLE_SLAVE);
+ &ev->bdaddr, 0,
+ HCI_ROLE_SLAVE);
if (IS_ERR(conn)) {
bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn));
goto unlock;
@@ -3299,7 +3300,7 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data,
conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
&ev->bdaddr);
if (!conn) {
- conn = hci_conn_add_unset(hdev, ev->link_type, &ev->bdaddr,
+ conn = hci_conn_add_unset(hdev, ev->link_type, &ev->bdaddr, 0,
HCI_ROLE_SLAVE);
if (IS_ERR(conn)) {
bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn));
@@ -5660,14 +5661,13 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
if (status)
goto unlock;
- conn = hci_conn_add_unset(hdev, LE_LINK, bdaddr, role);
+ conn = hci_conn_add_unset(hdev, LE_LINK, bdaddr, bdaddr_type,
+ role);
if (IS_ERR(conn)) {
bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn));
goto unlock;
}
- conn->dst_type = bdaddr_type;
-
/* If we didn't have a hci_conn object previously
* but we're in central role this must be something
* initiated using an accept list. Since accept list based
@@ -5949,7 +5949,7 @@ static void hci_le_past_received_evt(struct hci_dev *hdev, void *data,
goto unlock;
/* Add connection to indicate PA sync event */
- pa_sync = hci_conn_add_unset(hdev, PA_LINK, BDADDR_ANY,
+ pa_sync = hci_conn_add_unset(hdev, PA_LINK, BDADDR_ANY, 0,
HCI_ROLE_SLAVE);
if (IS_ERR(pa_sync))
@@ -6482,7 +6482,7 @@ static void hci_le_pa_sync_established_evt(struct hci_dev *hdev, void *data,
goto unlock;
/* Add connection to indicate PA sync event */
- pa_sync = hci_conn_add_unset(hdev, PA_LINK, BDADDR_ANY,
+ pa_sync = hci_conn_add_unset(hdev, PA_LINK, BDADDR_ANY, 0,
HCI_ROLE_SLAVE);
if (IS_ERR(pa_sync))
@@ -6923,7 +6923,7 @@ static void hci_le_cis_req_evt(struct hci_dev *hdev, void *data,
cis = hci_conn_hash_lookup_handle(hdev, cis_handle);
if (!cis) {
- cis = hci_conn_add(hdev, CIS_LINK, &acl->dst,
+ cis = hci_conn_add(hdev, CIS_LINK, &acl->dst, acl->dst_type,
HCI_ROLE_SLAVE, cis_handle);
if (IS_ERR(cis)) {
hci_le_reject_cis(hdev, ev->cis_handle);
@@ -7040,7 +7040,7 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
bt_dev_dbg(hdev, "ignore too large handle %u", handle);
continue;
}
- bis = hci_conn_add(hdev, BIS_LINK, BDADDR_ANY,
+ bis = hci_conn_add(hdev, BIS_LINK, BDADDR_ANY, 0,
HCI_ROLE_SLAVE, handle);
if (IS_ERR(bis))
continue;
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index 571e07f81523..b5e58cbf0d46 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -7013,7 +7013,7 @@ static void create_pa_complete(struct hci_dev *hdev, void *data, int err)
goto unlock;
/* Add connection to indicate PA sync error */
- pa_sync = hci_conn_add_unset(hdev, PA_LINK, BDADDR_ANY,
+ pa_sync = hci_conn_add_unset(hdev, PA_LINK, BDADDR_ANY, 0,
HCI_ROLE_SLAVE);
if (IS_ERR(pa_sync))
--
2.51.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v2 5/7] Bluetooth: ISO: Attempt to resolve broadcast address
2025-10-07 14:49 [PATCH v2 1/7] Bluetooth: HCI: Add initial support for PAST Luiz Augusto von Dentz
` (2 preceding siblings ...)
2025-10-07 14:49 ` [PATCH v2 4/7] Bluetooth: HCI: Always use the identity address when initializing a connection Luiz Augusto von Dentz
@ 2025-10-07 14:49 ` Luiz Augusto von Dentz
2025-10-07 14:49 ` [PATCH v2 6/7] Bluetooth: MGMT: Allow use of Set Device Flags without Add Device Luiz Augusto von Dentz
` (2 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2025-10-07 14:49 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Broadcasters maybe using RPAs which can change over time and not
matching the address used as destination in the socket, so this
attempts to resolve the addresses then match with the socket
address, in case that uses an indentity address, or then match the
IRKs if both broadcaster and socket are using RPAs.
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
net/bluetooth/iso.c | 58 ++++++++++++++++++++++++++++++---------------
1 file changed, 39 insertions(+), 19 deletions(-)
diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
index d4c8772152bd..83cda8dad4d8 100644
--- a/net/bluetooth/iso.c
+++ b/net/bluetooth/iso.c
@@ -87,8 +87,8 @@ static void iso_sock_disconn(struct sock *sk);
typedef bool (*iso_sock_match_t)(struct sock *sk, void *data);
-static struct sock *iso_get_sock(bdaddr_t *src, bdaddr_t *dst,
- enum bt_sock_state state,
+static struct sock *iso_get_sock(struct hci_dev *hdev, bdaddr_t *src,
+ bdaddr_t *dst, enum bt_sock_state state,
iso_sock_match_t match, void *data);
/* ---- ISO timers ---- */
@@ -638,8 +638,8 @@ static struct sock *__iso_get_sock_listen_by_sid(bdaddr_t *ba, bdaddr_t *bc,
* match func data - pass -1 to ignore
* Returns closest match.
*/
-static struct sock *iso_get_sock(bdaddr_t *src, bdaddr_t *dst,
- enum bt_sock_state state,
+static struct sock *iso_get_sock(struct hci_dev *hdev, bdaddr_t *src,
+ bdaddr_t *dst, enum bt_sock_state state,
iso_sock_match_t match, void *data)
{
struct sock *sk = NULL, *sk1 = NULL;
@@ -651,8 +651,25 @@ static struct sock *iso_get_sock(bdaddr_t *src, bdaddr_t *dst,
continue;
/* Match Broadcast destination */
- if (bacmp(dst, BDADDR_ANY) && bacmp(&iso_pi(sk)->dst, dst))
- continue;
+ if (bacmp(dst, BDADDR_ANY) && bacmp(&iso_pi(sk)->dst, dst)) {
+ struct smp_irk *irk1, *irk2;
+
+ /* Check if destination is an RPA that we can resolve */
+ irk1 = hci_find_irk_by_rpa(hdev, dst);
+ if (!irk1)
+ continue;
+
+ /* Match with identity address */
+ if (bacmp(&iso_pi(sk)->dst, &irk1->bdaddr)) {
+ /* Check if socket destination address is also
+ * an RPA and if the IRK matches.
+ */
+ irk2 = hci_find_irk_by_rpa(hdev,
+ &iso_pi(sk)->dst);
+ if (!irk2 || irk1 != irk2)
+ continue;
+ }
+ }
/* Use Match function if provided */
if (match && !match(sk, data))
@@ -1992,6 +2009,7 @@ static void iso_conn_ready(struct iso_conn *conn)
struct hci_ev_le_pa_sync_established *ev2 = NULL;
struct hci_ev_le_per_adv_report *ev3 = NULL;
struct hci_conn *hcon;
+ struct hci_dev *hdev;
BT_DBG("conn %p", conn);
@@ -2002,13 +2020,15 @@ static void iso_conn_ready(struct iso_conn *conn)
if (!hcon)
return;
+ hdev = hcon->hdev;
+
if (test_bit(HCI_CONN_BIG_SYNC, &hcon->flags)) {
/* A BIS slave hcon is notified to the ISO layer
* after the Command Complete for the LE Setup
* ISO Data Path command is received. Get the
* parent socket that matches the hcon BIG handle.
*/
- parent = iso_get_sock(&hcon->src, &hcon->dst,
+ parent = iso_get_sock(hdev, &hcon->src, &hcon->dst,
BT_LISTEN, iso_match_big_hcon,
hcon);
} else if (test_bit(HCI_CONN_BIG_SYNC_FAILED, &hcon->flags)) {
@@ -2016,12 +2036,12 @@ static void iso_conn_ready(struct iso_conn *conn)
HCI_EVT_LE_BIG_SYNC_ESTABLISHED);
/* Get reference to PA sync parent socket, if it exists */
- parent = iso_get_sock(&hcon->src, &hcon->dst,
+ parent = iso_get_sock(hdev, &hcon->src, &hcon->dst,
BT_LISTEN,
iso_match_pa_sync_flag,
NULL);
if (!parent && ev)
- parent = iso_get_sock(&hcon->src,
+ parent = iso_get_sock(hdev, &hcon->src,
&hcon->dst,
BT_LISTEN,
iso_match_big, ev);
@@ -2029,7 +2049,7 @@ static void iso_conn_ready(struct iso_conn *conn)
ev2 = hci_recv_event_data(hcon->hdev,
HCI_EV_LE_PA_SYNC_ESTABLISHED);
if (ev2)
- parent = iso_get_sock(&hcon->src,
+ parent = iso_get_sock(hdev, &hcon->src,
&hcon->dst,
BT_LISTEN,
iso_match_sid, ev2);
@@ -2037,7 +2057,7 @@ static void iso_conn_ready(struct iso_conn *conn)
ev3 = hci_recv_event_data(hcon->hdev,
HCI_EV_LE_PER_ADV_REPORT);
if (ev3)
- parent = iso_get_sock(&hcon->src,
+ parent = iso_get_sock(hdev, &hcon->src,
&hcon->dst,
BT_LISTEN,
iso_match_sync_handle_pa_report,
@@ -2045,7 +2065,7 @@ static void iso_conn_ready(struct iso_conn *conn)
}
if (!parent)
- parent = iso_get_sock(&hcon->src, BDADDR_ANY,
+ parent = iso_get_sock(hdev, &hcon->src, BDADDR_ANY,
BT_LISTEN, NULL, NULL);
if (!parent)
@@ -2182,7 +2202,7 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
*/
ev1 = hci_recv_event_data(hdev, HCI_EV_LE_PA_SYNC_ESTABLISHED);
if (ev1) {
- sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_LISTEN,
+ sk = iso_get_sock(hdev, &hdev->bdaddr, bdaddr, BT_LISTEN,
iso_match_sid, ev1);
if (sk && !ev1->status) {
iso_pi(sk)->sync_handle = le16_to_cpu(ev1->handle);
@@ -2194,7 +2214,7 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
ev1a = hci_recv_event_data(hdev, HCI_EV_LE_PAST_RECEIVED);
if (ev1a) {
- sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_LISTEN,
+ sk = iso_get_sock(hdev, &hdev->bdaddr, bdaddr, BT_LISTEN,
iso_match_sid_past, ev1a);
if (sk && !ev1a->status) {
iso_pi(sk)->sync_handle = le16_to_cpu(ev1a->sync_handle);
@@ -2207,7 +2227,7 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
ev2 = hci_recv_event_data(hdev, HCI_EVT_LE_BIG_INFO_ADV_REPORT);
if (ev2) {
/* Check if BIGInfo report has already been handled */
- sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_CONNECTED,
+ sk = iso_get_sock(hdev, &hdev->bdaddr, bdaddr, BT_CONNECTED,
iso_match_sync_handle, ev2);
if (sk) {
sock_put(sk);
@@ -2216,10 +2236,10 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
}
/* Try to get PA sync socket, if it exists */
- sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_CONNECT2,
+ sk = iso_get_sock(hdev, &hdev->bdaddr, bdaddr, BT_CONNECT2,
iso_match_sync_handle, ev2);
if (!sk)
- sk = iso_get_sock(&hdev->bdaddr, bdaddr,
+ sk = iso_get_sock(hdev, &hdev->bdaddr, bdaddr,
BT_LISTEN,
iso_match_sync_handle,
ev2);
@@ -2258,7 +2278,7 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
u8 *base;
struct hci_conn *hcon;
- sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_LISTEN,
+ sk = iso_get_sock(hdev, &hdev->bdaddr, bdaddr, BT_LISTEN,
iso_match_sync_handle_pa_report, ev3);
if (!sk)
goto done;
@@ -2308,7 +2328,7 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
hcon->le_per_adv_data_len = 0;
}
} else {
- sk = iso_get_sock(&hdev->bdaddr, BDADDR_ANY,
+ sk = iso_get_sock(hdev, &hdev->bdaddr, BDADDR_ANY,
BT_LISTEN, NULL, NULL);
}
--
2.51.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v2 6/7] Bluetooth: MGMT: Allow use of Set Device Flags without Add Device
2025-10-07 14:49 [PATCH v2 1/7] Bluetooth: HCI: Add initial support for PAST Luiz Augusto von Dentz
` (3 preceding siblings ...)
2025-10-07 14:49 ` [PATCH v2 5/7] Bluetooth: ISO: Attempt to resolve broadcast address Luiz Augusto von Dentz
@ 2025-10-07 14:49 ` Luiz Augusto von Dentz
2025-10-07 14:49 ` [PATCH v2 7/7] Bluetooth: ISO: Fix not updating BIS sender source address Luiz Augusto von Dentz
2025-10-07 15:36 ` [v2,1/7] Bluetooth: HCI: Add initial support for PAST bluez.test.bot
6 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2025-10-07 14:49 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
In certain cases setting devices flags like HCI_CONN_FLAG_PAST it
shouldn't require to do Add Device first since it may not need to add
an auto-connect policy, so this instead just automatically creates
a hci_conn_params if one cannot be found using HCI_AUTO_CONN_DISABLED.
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
net/bluetooth/mgmt.c | 148 ++++++++++++++++++++++---------------------
1 file changed, 76 insertions(+), 72 deletions(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 4b7cab707d69..02d52b413abf 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -5118,6 +5118,69 @@ static void device_flags_changed(struct sock *sk, struct hci_dev *hdev,
mgmt_event(MGMT_EV_DEVICE_FLAGS_CHANGED, hdev, &ev, sizeof(ev), sk);
}
+static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
+{
+ struct hci_conn *conn;
+
+ conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
+ if (!conn)
+ return false;
+
+ if (conn->dst_type != type)
+ return false;
+
+ if (conn->state != BT_CONNECTED)
+ return false;
+
+ return true;
+}
+
+/* This function requires the caller holds hdev->lock */
+static struct hci_conn_params *hci_conn_params_set(struct hci_dev *hdev,
+ bdaddr_t *addr, u8 addr_type,
+ u8 auto_connect)
+{
+ struct hci_conn_params *params;
+
+ params = hci_conn_params_add(hdev, addr, addr_type);
+ if (!params)
+ return NULL;
+
+ if (params->auto_connect == auto_connect)
+ return params;
+
+ hci_pend_le_list_del_init(params);
+
+ switch (auto_connect) {
+ case HCI_AUTO_CONN_DISABLED:
+ case HCI_AUTO_CONN_LINK_LOSS:
+ /* If auto connect is being disabled when we're trying to
+ * connect to device, keep connecting.
+ */
+ if (params->explicit_connect)
+ hci_pend_le_list_add(params, &hdev->pend_le_conns);
+ break;
+ case HCI_AUTO_CONN_REPORT:
+ if (params->explicit_connect)
+ hci_pend_le_list_add(params, &hdev->pend_le_conns);
+ else
+ hci_pend_le_list_add(params, &hdev->pend_le_reports);
+ break;
+ case HCI_AUTO_CONN_DIRECT:
+ case HCI_AUTO_CONN_ALWAYS:
+ if (!is_connected(hdev, addr, addr_type))
+ hci_pend_le_list_add(params, &hdev->pend_le_conns);
+ break;
+ }
+
+ params->auto_connect = auto_connect;
+
+ bt_dev_dbg(hdev, "addr %pMR (type %u) auto_connect %u",
+ addr, addr_type, auto_connect);
+
+ return params;
+}
+
static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
@@ -5161,9 +5224,16 @@ static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
le_addr_type(cp->addr.type));
if (!params) {
- bt_dev_warn(hdev, "No such LE device %pMR (0x%x)",
- &cp->addr.bdaddr, le_addr_type(cp->addr.type));
- goto unlock;
+ /* Create a new hci_conn_params if it doesn't exist */
+ params = hci_conn_params_set(hdev, &cp->addr.bdaddr,
+ le_addr_type(cp->addr.type),
+ HCI_AUTO_CONN_DISABLED);
+ if (!params) {
+ bt_dev_warn(hdev, "No such LE device %pMR (0x%x)",
+ &cp->addr.bdaddr,
+ le_addr_type(cp->addr.type));
+ goto unlock;
+ }
}
supported_flags = hdev->conn_flags;
@@ -7550,68 +7620,6 @@ static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
return err;
}
-static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
-{
- struct hci_conn *conn;
-
- conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
- if (!conn)
- return false;
-
- if (conn->dst_type != type)
- return false;
-
- if (conn->state != BT_CONNECTED)
- return false;
-
- return true;
-}
-
-/* This function requires the caller holds hdev->lock */
-static int hci_conn_params_set(struct hci_dev *hdev, bdaddr_t *addr,
- u8 addr_type, u8 auto_connect)
-{
- struct hci_conn_params *params;
-
- params = hci_conn_params_add(hdev, addr, addr_type);
- if (!params)
- return -EIO;
-
- if (params->auto_connect == auto_connect)
- return 0;
-
- hci_pend_le_list_del_init(params);
-
- switch (auto_connect) {
- case HCI_AUTO_CONN_DISABLED:
- case HCI_AUTO_CONN_LINK_LOSS:
- /* If auto connect is being disabled when we're trying to
- * connect to device, keep connecting.
- */
- if (params->explicit_connect)
- hci_pend_le_list_add(params, &hdev->pend_le_conns);
- break;
- case HCI_AUTO_CONN_REPORT:
- if (params->explicit_connect)
- hci_pend_le_list_add(params, &hdev->pend_le_conns);
- else
- hci_pend_le_list_add(params, &hdev->pend_le_reports);
- break;
- case HCI_AUTO_CONN_DIRECT:
- case HCI_AUTO_CONN_ALWAYS:
- if (!is_connected(hdev, addr, addr_type))
- hci_pend_le_list_add(params, &hdev->pend_le_conns);
- break;
- }
-
- params->auto_connect = auto_connect;
-
- bt_dev_dbg(hdev, "addr %pMR (type %u) auto_connect %u",
- addr, addr_type, auto_connect);
-
- return 0;
-}
-
static void device_added(struct sock *sk, struct hci_dev *hdev,
bdaddr_t *bdaddr, u8 type, u8 action)
{
@@ -7723,17 +7731,13 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
/* If the connection parameters don't exist for this device,
* they will be created and configured with defaults.
*/
- if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
- auto_conn) < 0) {
+ params = hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
+ auto_conn);
+ if (!params) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
MGMT_STATUS_FAILED, &cp->addr,
sizeof(cp->addr));
goto unlock;
- } else {
- params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
- addr_type);
- if (params)
- current_flags = params->flags;
}
cmd = mgmt_pending_new(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
--
2.51.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v2 7/7] Bluetooth: ISO: Fix not updating BIS sender source address
2025-10-07 14:49 [PATCH v2 1/7] Bluetooth: HCI: Add initial support for PAST Luiz Augusto von Dentz
` (4 preceding siblings ...)
2025-10-07 14:49 ` [PATCH v2 6/7] Bluetooth: MGMT: Allow use of Set Device Flags without Add Device Luiz Augusto von Dentz
@ 2025-10-07 14:49 ` Luiz Augusto von Dentz
2025-10-07 15:36 ` [v2,1/7] Bluetooth: HCI: Add initial support for PAST bluez.test.bot
6 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2025-10-07 14:49 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
The source address for a BIS sender/Broadcast Source shall be updated
with the advertisement address since in case privacy is enabled it may
use an RPA rather than an identity address.
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
net/bluetooth/iso.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
index 83cda8dad4d8..817c7ef1ec68 100644
--- a/net/bluetooth/iso.c
+++ b/net/bluetooth/iso.c
@@ -2014,6 +2014,25 @@ static void iso_conn_ready(struct iso_conn *conn)
BT_DBG("conn %p", conn);
if (sk) {
+ /* Attempt to update source address in case of BIS Sender if
+ * the advertisement is using a random address.
+ */
+ if (conn->hcon->type == BIS_LINK &&
+ conn->hcon->role == HCI_ROLE_MASTER &&
+ !bacmp(&conn->hcon->dst, BDADDR_ANY)) {
+ struct hci_conn *bis = conn->hcon;
+ struct adv_info *adv;
+
+ adv = hci_find_adv_instance(bis->hdev,
+ bis->iso_qos.bcast.bis);
+ if (adv && bacmp(&adv->random_addr, BDADDR_ANY)) {
+ lock_sock(sk);
+ iso_pi(sk)->src_type = BDADDR_LE_RANDOM;
+ bacpy(&iso_pi(sk)->src, &adv->random_addr);
+ release_sock(sk);
+ }
+ }
+
iso_sock_ready(conn->sk);
} else {
hcon = conn->hcon;
--
2.51.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* RE: [v2,1/7] Bluetooth: HCI: Add initial support for PAST
2025-10-07 14:49 [PATCH v2 1/7] Bluetooth: HCI: Add initial support for PAST Luiz Augusto von Dentz
` (5 preceding siblings ...)
2025-10-07 14:49 ` [PATCH v2 7/7] Bluetooth: ISO: Fix not updating BIS sender source address Luiz Augusto von Dentz
@ 2025-10-07 15:36 ` bluez.test.bot
6 siblings, 0 replies; 10+ messages in thread
From: bluez.test.bot @ 2025-10-07 15:36 UTC (permalink / raw)
To: linux-bluetooth, luiz.dentz
[-- Attachment #1: Type: text/plain, Size: 3799 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/project/bluetooth/list/?series=1009062
---Test result---
Test Summary:
CheckPatch PENDING 0.57 seconds
GitLint PENDING 0.40 seconds
SubjectPrefix PASS 0.45 seconds
BuildKernel PASS 24.59 seconds
CheckAllWarning PASS 27.27 seconds
CheckSparse WARNING 30.76 seconds
BuildKernel32 PASS 24.58 seconds
TestRunnerSetup PASS 486.71 seconds
TestRunner_l2cap-tester PASS 23.93 seconds
TestRunner_iso-tester PASS 70.01 seconds
TestRunner_bnep-tester PASS 6.07 seconds
TestRunner_mgmt-tester FAIL 116.58 seconds
TestRunner_rfcomm-tester PASS 9.36 seconds
TestRunner_sco-tester PASS 14.42 seconds
TestRunner_ioctl-tester PASS 10.06 seconds
TestRunner_mesh-tester FAIL 12.83 seconds
TestRunner_smp-tester PASS 8.43 seconds
TestRunner_userchan-tester PASS 6.35 seconds
IncrementalBuild PENDING 0.90 seconds
Details
##############################
Test: CheckPatch - PENDING
Desc: Run checkpatch.pl script
Output:
##############################
Test: GitLint - PENDING
Desc: Run gitlint
Output:
##############################
Test: CheckSparse - WARNING
Desc: Run sparse tool with linux kernel
Output:
net/bluetooth/hci_event.c: note: in included file (through include/net/bluetooth/hci_core.h):net/bluetooth/hci_sync.c:7281:19: warning: incorrect type in assignment (different base types)net/bluetooth/hci_sync.c:7281:19: expected restricted __le16 [addressable] [usertype] handlenet/bluetooth/hci_sync.c:7281:19: got unsigned short [usertype] handlenet/bluetooth/hci_sync.c:7281:19: warning: incorrect type in assignment (different base types)net/bluetooth/hci_sync.c:7281:19: expected restricted __le16 [addressable] [usertype] handlenet/bluetooth/hci_sync.c:7281:19: got unsigned short [usertype] handlenet/bluetooth/hci_sync.c:7281:19: warning: incorrect type in assignment (different base types)net/bluetooth/hci_sync.c:7281:19: expected restricted __le16 [addressable] [usertype] handlenet/bluetooth/hci_sync.c:7281:19: got unsigned short [usertype] handlenet/bluetooth/hci_event.c: note: in included file (through include/net/bluetooth/hci_core.h):net/bluetooth/hci_sync.c:7281:19: warning: incorrect type in assignment (different base types)net/bluetooth/hci_sync.c:7281:19: expected restricted __le16 [addressable] [usertype] handlenet/bluetooth/hci_sync.c:7281:19: got unsigned short [usertype] handle
##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner
Output:
Total: 490, Passed: 483 (98.6%), Failed: 3, Not Run: 4
Failed Test Cases
Read Exp Feature - Success Failed 0.104 seconds
LL Privacy - Set Flags 1 (Add to RL) Failed 0.146 seconds
LL Privacy - Start Discovery 1 (Disable RL) Failed 0.183 seconds
##############################
Test: TestRunner_mesh-tester - FAIL
Desc: Run mesh-tester with test-runner
Output:
Total: 10, Passed: 8 (80.0%), Failed: 2, Not Run: 0
Failed Test Cases
Mesh - Send cancel - 1 Timed out 1.900 seconds
Mesh - Send cancel - 2 Timed out 1.997 seconds
##############################
Test: IncrementalBuild - PENDING
Desc: Incremental build with the patches in the series
Output:
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 10+ messages in thread