2023-08-04 01:19:24

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH v2 1/5] Bluetooth: hci_sync: Fix handling of HCI_OP_CREATE_CONN_CANCEL

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

When sending HCI_OP_CREATE_CONN_CANCEL it shall Wait for
HCI_EV_CONN_COMPLETE, not HCI_EV_CMD_STATUS, when the reason is
anything but HCI_ERROR_REMOTE_POWER_OFF. This reason is used when
suspending or powering off, where we don't want to wait for the peer's
response.

Signed-off-by: Luiz Augusto von Dentz <[email protected]>
---
net/bluetooth/hci_sync.c | 11 +++++++++++
1 file changed, 11 insertions(+)

diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index e114409628d1..a9b048d7b419 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -5321,6 +5321,17 @@ static int hci_connect_cancel_sync(struct hci_dev *hdev, struct hci_conn *conn,
if (hdev->hci_ver < BLUETOOTH_VER_1_2)
return 0;

+ /* Wait for HCI_EV_CONN_COMPLETE, not HCI_EV_CMD_STATUS, when the
+ * reason is anything but HCI_ERROR_REMOTE_POWER_OFF. This reason is
+ * used when suspending or powering off, where we don't want to wait
+ * for the peer's response.
+ */
+ if (reason != HCI_ERROR_REMOTE_POWER_OFF)
+ return __hci_cmd_sync_status_sk(hdev, HCI_OP_CREATE_CONN_CANCEL,
+ 6, &conn->dst,
+ HCI_EV_CONN_COMPLETE,
+ HCI_CMD_TIMEOUT, NULL);
+
return __hci_cmd_sync_status(hdev, HCI_OP_CREATE_CONN_CANCEL,
6, &conn->dst, HCI_CMD_TIMEOUT);
}
--
2.41.0



2023-08-04 01:30:23

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH v2 3/5] Bluetooth: ISO: Fix not checking for valid CIG/CIS IDs

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

Valid range of CIG/CIS are 0x00 to 0xEF, so this checks they are
properly checked before attempting to use HCI_OP_LE_SET_CIG_PARAMS.

Fixes: ccf74f2390d6 ("Bluetooth: Add BTPROTO_ISO socket type")
Signed-off-by: Luiz Augusto von Dentz <[email protected]>
---
net/bluetooth/iso.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
index 358954bfbb32..6b66d6a88b9a 100644
--- a/net/bluetooth/iso.c
+++ b/net/bluetooth/iso.c
@@ -1187,6 +1187,12 @@ static bool check_io_qos(struct bt_iso_io_qos *qos)

static bool check_ucast_qos(struct bt_iso_qos *qos)
{
+ if (qos->ucast.cig > 0xef && qos->ucast.cig != BT_ISO_QOS_CIG_UNSET)
+ return false;
+
+ if (qos->ucast.cis > 0xef && qos->ucast.cis != BT_ISO_QOS_CIS_UNSET)
+ return false;
+
if (qos->ucast.sca > 0x07)
return false;

--
2.41.0


2023-08-04 01:31:22

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH v2 4/5] Bluetooth: hci_conn: Fix modifying handle while aborting

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

This introduces hci_conn_set_handle which takes care of verifying the
conditions where the hci_conn handle can be modified, including when
hci_conn_abort has been called and also checks that the handles is
valid as well.

Signed-off-by: Luiz Augusto von Dentz <[email protected]>
---
include/net/bluetooth/hci_core.h | 1 +
net/bluetooth/hci_conn.c | 30 ++++++++++++++++++++++++++++++
net/bluetooth/hci_event.c | 29 +++++++++++------------------
3 files changed, 42 insertions(+), 18 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 8200a6689b39..d2a3a2a9fd7d 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1425,6 +1425,7 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);

void hci_conn_failed(struct hci_conn *conn, u8 status);
+u8 hci_conn_set_handle(struct hci_conn *conn, u16 handle);

/*
* hci_conn_get() and hci_conn_put() are used to control the life-time of an
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 923bb7e7be2b..13bd2753abbb 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -1231,6 +1231,36 @@ void hci_conn_failed(struct hci_conn *conn, u8 status)
hci_conn_del(conn);
}

+/* This function requires the caller holds hdev->lock */
+u8 hci_conn_set_handle(struct hci_conn *conn, u16 handle)
+{
+ struct hci_dev *hdev = conn->hdev;
+
+ bt_dev_dbg(hdev, "hcon %p handle 0x%4.4x", conn, handle);
+
+ if (conn->handle == handle)
+ return 0;
+
+ if (handle > HCI_CONN_HANDLE_MAX) {
+ bt_dev_err(hdev, "Invalid handle: 0x%4.4x > 0x%4.4x",
+ handle, HCI_CONN_HANDLE_MAX);
+ return HCI_ERROR_INVALID_PARAMETERS;
+ }
+
+ /* If abort_reason has been sent it means the connection is being
+ * aborted and the handle shall not be changed.
+ */
+ if (conn->abort_reason) {
+ bt_dev_err(hdev, "hcon %p abort_reason 0x%2.2x", conn,
+ conn->abort_reason);
+ return conn->abort_reason;
+ }
+
+ conn->handle = handle;
+
+ return 0;
+}
+
static void create_le_conn_complete(struct hci_dev *hdev, void *data, int err)
{
struct hci_conn *conn;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index f1fcece29e7d..218da9b0fe8f 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3179,13 +3179,9 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
}

if (!status) {
- conn->handle = __le16_to_cpu(ev->handle);
- if (conn->handle > HCI_CONN_HANDLE_MAX) {
- bt_dev_err(hdev, "Invalid handle: 0x%4.4x > 0x%4.4x",
- conn->handle, HCI_CONN_HANDLE_MAX);
- status = HCI_ERROR_INVALID_PARAMETERS;
+ status = hci_conn_set_handle(conn, __le16_to_cpu(ev->handle));
+ if (status)
goto done;
- }

if (conn->type == ACL_LINK) {
conn->state = BT_CONFIG;
@@ -3849,11 +3845,9 @@ static u8 hci_cc_le_set_cig_params(struct hci_dev *hdev, void *data,
if (conn->state != BT_BOUND && conn->state != BT_CONNECT)
continue;

- conn->handle = __le16_to_cpu(rp->handle[i]);
+ if (hci_conn_set_handle(conn, __le16_to_cpu(rp->handle[i])))
+ continue;

- bt_dev_dbg(hdev, "%p handle 0x%4.4x parent %p", conn,
- conn->handle, conn->parent);
-
if (conn->state == BT_CONNECT)
pending = true;
}
@@ -5039,11 +5033,8 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,

switch (status) {
case 0x00:
- conn->handle = __le16_to_cpu(ev->handle);
- if (conn->handle > HCI_CONN_HANDLE_MAX) {
- bt_dev_err(hdev, "Invalid handle: 0x%4.4x > 0x%4.4x",
- conn->handle, HCI_CONN_HANDLE_MAX);
- status = HCI_ERROR_INVALID_PARAMETERS;
+ status = hci_conn_set_handle(conn, __le16_to_cpu(ev->handle));
+ if (status) {
conn->state = BT_CLOSED;
break;
}
@@ -6978,7 +6969,7 @@ static void hci_le_create_big_complete_evt(struct hci_dev *hdev, void *data,
{
struct hci_evt_le_create_big_complete *ev = data;
struct hci_conn *conn;
- __u8 bis_idx = 0;
+ __u8 i = 0;

BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);

@@ -6996,7 +6987,9 @@ static void hci_le_create_big_complete_evt(struct hci_dev *hdev, void *data,
conn->iso_qos.bcast.big != ev->handle)
continue;

- conn->handle = __le16_to_cpu(ev->bis_handle[bis_idx++]);
+ if (hci_conn_set_handle(conn,
+ __le16_to_cpu(ev->bis_handle[i++])))
+ continue;

if (!ev->status) {
conn->state = BT_CONNECTED;
@@ -7015,7 +7008,7 @@ static void hci_le_create_big_complete_evt(struct hci_dev *hdev, void *data,
rcu_read_lock();
}

- if (!ev->status && !bis_idx)
+ if (!ev->status && !i)
/* If no BISes have been connected for the BIG,
* terminate. This is in case all bound connections
* have been closed before the BIG creation
--
2.41.0


2023-08-04 01:59:32

by bluez.test.bot

[permalink] [raw]
Subject: RE: [v2,1/5] Bluetooth: hci_sync: Fix handling of HCI_OP_CREATE_CONN_CANCEL

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

Dear Submitter,

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

----- Output -----

error: patch failed: net/bluetooth/hci_sync.c:5389
error: net/bluetooth/hci_sync.c: patch does not apply
hint: Use 'git am --show-current-patch' to see the failed patch

Please resolve the issue and submit the patches again.


---
Regards,
Linux Bluetooth

2023-08-04 02:11:15

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH v2 5/5] Bluetooth: hci_conn: Fix not allowing valid CIS ID

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

Only the number of CIS shall be limited to 0x1f, the CIS ID in the
other hand is up to 0xef.

Fixes: 26afbd826ee3 ("Bluetooth: Add initial implementation of CIS connections")
Signed-off-by: Luiz Augusto von Dentz <[email protected]>
---
net/bluetooth/hci_conn.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 13bd2753abbb..84f2ac21a85a 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -1849,9 +1849,12 @@ static bool hci_le_set_cig_params(struct hci_conn *conn, struct bt_iso_qos *qos)
cis_add(&data, qos);
}

- /* Reprogram all CIS(s) with the same CIG */
- for (data.cig = qos->ucast.cig, data.cis = 0x00; data.cis < 0x11;
- data.cis++) {
+ /* Reprogram all CIS(s) with the same CIG, valid range are:
+ * num_cis: 0x00 to 0x1F
+ * cis_id: 0x00 to 0xEF
+ */
+ for (data.cig = qos->ucast.cig, data.cis = 0x00; data.cis < 0xf0 &&
+ data.pdu.cp.num_cis < ARRAY_SIZE(data.pdu.cis); data.cis++) {
data.count = 0;

hci_conn_hash_list_state(hdev, cis_list, ISO_LINK, BT_BOUND,
--
2.41.0


2023-08-04 16:57:25

by Pauli Virtanen

[permalink] [raw]
Subject: Re: [PATCH v2 4/5] Bluetooth: hci_conn: Fix modifying handle while aborting

Hi Luiz,

to, 2023-08-03 kello 17:11 -0700, Luiz Augusto von Dentz kirjoitti:
> From: Luiz Augusto von Dentz <[email protected]>
>
> This introduces hci_conn_set_handle which takes care of verifying the
> conditions where the hci_conn handle can be modified, including when
> hci_conn_abort has been called and also checks that the handles is
> valid as well.

It looks there could still be problem vs. sequences of the type

[kernel] hci_acl_create_connection(AA:AA:AA:AA:AA:AA)
[controller] < Create Connection AA:AA:AA:AA:AA:AA
[controller] > Connection Complete handle X
[kernel] hci_conn_complete_evt(handle X)
[kernel] hci_acl_create_connection(BB:BB:BB:BB:BB:BB)
[kernel] hci_abort_conn(handle X)
[controller] > Disconnect Complete handle X (from remote)
[kernel] hci_disconn_complete_evt(handle X)
[controller] < Create Connection BB:BB:BB:BB:BB:BB
[controller] > Connection Complete handle X (same handle value)
[kernel] hci_conn_complete_evt(handle X)
...
[kernel] hci_abort_conn_sync(handle X)

This would seem to terminate the wrong connection.

Some flag/abort_reason could be checked to see if the looked up conn is
to be aborted before doing it. This can also be used to make
hci_disconnect_all_sync iteration UAF-safe.

It's unclear to me if you agree that tasks from hdev->workqueue and
hdev->req_workqueue can run concurrently, so that locking is needed.

>
> Signed-off-by: Luiz Augusto von Dentz <[email protected]>
> ---
> include/net/bluetooth/hci_core.h | 1 +
> net/bluetooth/hci_conn.c | 30 ++++++++++++++++++++++++++++++
> net/bluetooth/hci_event.c | 29 +++++++++++------------------
> 3 files changed, 42 insertions(+), 18 deletions(-)
>
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 8200a6689b39..d2a3a2a9fd7d 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -1425,6 +1425,7 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
> void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);
>
> void hci_conn_failed(struct hci_conn *conn, u8 status);
> +u8 hci_conn_set_handle(struct hci_conn *conn, u16 handle);
>
> /*
> * hci_conn_get() and hci_conn_put() are used to control the life-time of an
> diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
> index 923bb7e7be2b..13bd2753abbb 100644
> --- a/net/bluetooth/hci_conn.c
> +++ b/net/bluetooth/hci_conn.c
> @@ -1231,6 +1231,36 @@ void hci_conn_failed(struct hci_conn *conn, u8 status)
> hci_conn_del(conn);
> }
>
> +/* This function requires the caller holds hdev->lock */
> +u8 hci_conn_set_handle(struct hci_conn *conn, u16 handle)
> +{
> + struct hci_dev *hdev = conn->hdev;
> +
> + bt_dev_dbg(hdev, "hcon %p handle 0x%4.4x", conn, handle);
> +
> + if (conn->handle == handle)
> + return 0;
> +
> + if (handle > HCI_CONN_HANDLE_MAX) {
> + bt_dev_err(hdev, "Invalid handle: 0x%4.4x > 0x%4.4x",
> + handle, HCI_CONN_HANDLE_MAX);
> + return HCI_ERROR_INVALID_PARAMETERS;
> + }
> +
> + /* If abort_reason has been sent it means the connection is being
> + * aborted and the handle shall not be changed.
> + */
> + if (conn->abort_reason) {
> + bt_dev_err(hdev, "hcon %p abort_reason 0x%2.2x", conn,
> + conn->abort_reason);
> + return conn->abort_reason;
> + }
> +
> + conn->handle = handle;
> +
> + return 0;
> +}
> +
> static void create_le_conn_complete(struct hci_dev *hdev, void *data, int err)
> {
> struct hci_conn *conn;
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index f1fcece29e7d..218da9b0fe8f 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -3179,13 +3179,9 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
> }
>
> if (!status) {
> - conn->handle = __le16_to_cpu(ev->handle);
> - if (conn->handle > HCI_CONN_HANDLE_MAX) {
> - bt_dev_err(hdev, "Invalid handle: 0x%4.4x > 0x%4.4x",
> - conn->handle, HCI_CONN_HANDLE_MAX);
> - status = HCI_ERROR_INVALID_PARAMETERS;
> + status = hci_conn_set_handle(conn, __le16_to_cpu(ev->handle));
> + if (status)
> goto done;
> - }
>
> if (conn->type == ACL_LINK) {
> conn->state = BT_CONFIG;
> @@ -3849,11 +3845,9 @@ static u8 hci_cc_le_set_cig_params(struct hci_dev *hdev, void *data,
> if (conn->state != BT_BOUND && conn->state != BT_CONNECT)
> continue;
>
> - conn->handle = __le16_to_cpu(rp->handle[i]);
> + if (hci_conn_set_handle(conn, __le16_to_cpu(rp->handle[i])))
> + continue;
>
> - bt_dev_dbg(hdev, "%p handle 0x%4.4x parent %p", conn,
> - conn->handle, conn->parent);
> -
> if (conn->state == BT_CONNECT)
> pending = true;
> }
> @@ -5039,11 +5033,8 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,
>
> switch (status) {
> case 0x00:
> - conn->handle = __le16_to_cpu(ev->handle);
> - if (conn->handle > HCI_CONN_HANDLE_MAX) {
> - bt_dev_err(hdev, "Invalid handle: 0x%4.4x > 0x%4.4x",
> - conn->handle, HCI_CONN_HANDLE_MAX);
> - status = HCI_ERROR_INVALID_PARAMETERS;
> + status = hci_conn_set_handle(conn, __le16_to_cpu(ev->handle));
> + if (status) {
> conn->state = BT_CLOSED;
> break;
> }
> @@ -6978,7 +6969,7 @@ static void hci_le_create_big_complete_evt(struct hci_dev *hdev, void *data,
> {
> struct hci_evt_le_create_big_complete *ev = data;
> struct hci_conn *conn;
> - __u8 bis_idx = 0;
> + __u8 i = 0;
>
> BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
>
> @@ -6996,7 +6987,9 @@ static void hci_le_create_big_complete_evt(struct hci_dev *hdev, void *data,
> conn->iso_qos.bcast.big != ev->handle)
> continue;
>
> - conn->handle = __le16_to_cpu(ev->bis_handle[bis_idx++]);
> + if (hci_conn_set_handle(conn,
> + __le16_to_cpu(ev->bis_handle[i++])))
> + continue;
>
> if (!ev->status) {
> conn->state = BT_CONNECTED;
> @@ -7015,7 +7008,7 @@ static void hci_le_create_big_complete_evt(struct hci_dev *hdev, void *data,
> rcu_read_lock();
> }
>
> - if (!ev->status && !bis_idx)
> + if (!ev->status && !i)
> /* If no BISes have been connected for the BIG,
> * terminate. This is in case all bound connections
> * have been closed before the BIG creation


2023-08-04 23:45:25

by patchwork-bot+bluetooth

[permalink] [raw]
Subject: Re: [PATCH v2 1/5] Bluetooth: hci_sync: Fix handling of HCI_OP_CREATE_CONN_CANCEL

Hello:

This series was applied to bluetooth/bluetooth-next.git (master)
by Luiz Augusto von Dentz <[email protected]>:

On Thu, 3 Aug 2023 17:11:11 -0700 you wrote:
> From: Luiz Augusto von Dentz <[email protected]>
>
> When sending HCI_OP_CREATE_CONN_CANCEL it shall Wait for
> HCI_EV_CONN_COMPLETE, not HCI_EV_CMD_STATUS, when the reason is
> anything but HCI_ERROR_REMOTE_POWER_OFF. This reason is used when
> suspending or powering off, where we don't want to wait for the peer's
> response.
>
> [...]

Here is the summary with links:
- [v2,1/5] Bluetooth: hci_sync: Fix handling of HCI_OP_CREATE_CONN_CANCEL
https://git.kernel.org/bluetooth/bluetooth-next/c/0e4cdf2f6122
- [v2,2/5] Bluetooth: hci_sync: Fix UAF on hci_abort_conn_sync
https://git.kernel.org/bluetooth/bluetooth-next/c/bdc83c443c30
- [v2,3/5] Bluetooth: ISO: Fix not checking for valid CIG/CIS IDs
https://git.kernel.org/bluetooth/bluetooth-next/c/e5ab05c24643
- [v2,4/5] Bluetooth: hci_conn: Fix modifying handle while aborting
(no matching commit)
- [v2,5/5] Bluetooth: hci_conn: Fix not allowing valid CIS ID
https://git.kernel.org/bluetooth/bluetooth-next/c/90b1f9ebdea4

You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



2023-08-05 01:08:58

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [PATCH v2 4/5] Bluetooth: hci_conn: Fix modifying handle while aborting

Hi Pauli,

On Fri, Aug 4, 2023 at 9:28 AM Pauli Virtanen <[email protected]> wrote:
>
> Hi Luiz,
>
> to, 2023-08-03 kello 17:11 -0700, Luiz Augusto von Dentz kirjoitti:
> > From: Luiz Augusto von Dentz <[email protected]>
> >
> > This introduces hci_conn_set_handle which takes care of verifying the
> > conditions where the hci_conn handle can be modified, including when
> > hci_conn_abort has been called and also checks that the handles is
> > valid as well.
>
> It looks there could still be problem vs. sequences of the type
>
> [kernel] hci_acl_create_connection(AA:AA:AA:AA:AA:AA)
> [controller] < Create Connection AA:AA:AA:AA:AA:AA
> [controller] > Connection Complete handle X
> [kernel] hci_conn_complete_evt(handle X)
> [kernel] hci_acl_create_connection(BB:BB:BB:BB:BB:BB)
> [kernel] hci_abort_conn(handle X)
> [controller] > Disconnect Complete handle X (from remote)
> [kernel] hci_disconn_complete_evt(handle X)
> [controller] < Create Connection BB:BB:BB:BB:BB:BB
> [controller] > Connection Complete handle X (same handle value)
> [kernel] hci_conn_complete_evt(handle X)
> ...
> [kernel] hci_abort_conn_sync(handle X)
>
> This would seem to terminate the wrong connection.

Perhaps we need a test for it, it shall also be possible to cancel the callback.

> Some flag/abort_reason could be checked to see if the looked up conn is
> to be aborted before doing it. This can also be used to make
> hci_disconnect_all_sync iteration UAF-safe.

Yep, I am also thinking of introducing some functions to lookup on the
cmd_sync_queue to avoid submitting duplicated commands, or for example
if we want to cancel a callback.

> It's unclear to me if you agree that tasks from hdev->workqueue and
> hdev->req_workqueue can run concurrently, so that locking is needed.

I think what we should do is to check if we can have a more clear
separation, because the workqueue is used for example by the likes of
rx_work which does process everything we receive from the controller,
which perhaps is not the best idea given in case of HCI events it
might be better to process them in the same context of commands for
example, to ensure that HCI states is not being modified concurrently
which seems to be what causes the most problems.

> >
> > Signed-off-by: Luiz Augusto von Dentz <[email protected]>
> > ---
> > include/net/bluetooth/hci_core.h | 1 +
> > net/bluetooth/hci_conn.c | 30 ++++++++++++++++++++++++++++++
> > net/bluetooth/hci_event.c | 29 +++++++++++------------------
> > 3 files changed, 42 insertions(+), 18 deletions(-)
> >
> > diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> > index 8200a6689b39..d2a3a2a9fd7d 100644
> > --- a/include/net/bluetooth/hci_core.h
> > +++ b/include/net/bluetooth/hci_core.h
> > @@ -1425,6 +1425,7 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
> > void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);
> >
> > void hci_conn_failed(struct hci_conn *conn, u8 status);
> > +u8 hci_conn_set_handle(struct hci_conn *conn, u16 handle);
> >
> > /*
> > * hci_conn_get() and hci_conn_put() are used to control the life-time of an
> > diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
> > index 923bb7e7be2b..13bd2753abbb 100644
> > --- a/net/bluetooth/hci_conn.c
> > +++ b/net/bluetooth/hci_conn.c
> > @@ -1231,6 +1231,36 @@ void hci_conn_failed(struct hci_conn *conn, u8 status)
> > hci_conn_del(conn);
> > }
> >
> > +/* This function requires the caller holds hdev->lock */
> > +u8 hci_conn_set_handle(struct hci_conn *conn, u16 handle)
> > +{
> > + struct hci_dev *hdev = conn->hdev;
> > +
> > + bt_dev_dbg(hdev, "hcon %p handle 0x%4.4x", conn, handle);
> > +
> > + if (conn->handle == handle)
> > + return 0;
> > +
> > + if (handle > HCI_CONN_HANDLE_MAX) {
> > + bt_dev_err(hdev, "Invalid handle: 0x%4.4x > 0x%4.4x",
> > + handle, HCI_CONN_HANDLE_MAX);
> > + return HCI_ERROR_INVALID_PARAMETERS;
> > + }
> > +
> > + /* If abort_reason has been sent it means the connection is being
> > + * aborted and the handle shall not be changed.
> > + */
> > + if (conn->abort_reason) {
> > + bt_dev_err(hdev, "hcon %p abort_reason 0x%2.2x", conn,
> > + conn->abort_reason);
> > + return conn->abort_reason;
> > + }
> > +
> > + conn->handle = handle;
> > +
> > + return 0;
> > +}
> > +
> > static void create_le_conn_complete(struct hci_dev *hdev, void *data, int err)
> > {
> > struct hci_conn *conn;
> > diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> > index f1fcece29e7d..218da9b0fe8f 100644
> > --- a/net/bluetooth/hci_event.c
> > +++ b/net/bluetooth/hci_event.c
> > @@ -3179,13 +3179,9 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
> > }
> >
> > if (!status) {
> > - conn->handle = __le16_to_cpu(ev->handle);
> > - if (conn->handle > HCI_CONN_HANDLE_MAX) {
> > - bt_dev_err(hdev, "Invalid handle: 0x%4.4x > 0x%4.4x",
> > - conn->handle, HCI_CONN_HANDLE_MAX);
> > - status = HCI_ERROR_INVALID_PARAMETERS;
> > + status = hci_conn_set_handle(conn, __le16_to_cpu(ev->handle));
> > + if (status)
> > goto done;
> > - }
> >
> > if (conn->type == ACL_LINK) {
> > conn->state = BT_CONFIG;
> > @@ -3849,11 +3845,9 @@ static u8 hci_cc_le_set_cig_params(struct hci_dev *hdev, void *data,
> > if (conn->state != BT_BOUND && conn->state != BT_CONNECT)
> > continue;
> >
> > - conn->handle = __le16_to_cpu(rp->handle[i]);
> > + if (hci_conn_set_handle(conn, __le16_to_cpu(rp->handle[i])))
> > + continue;
> >
> > - bt_dev_dbg(hdev, "%p handle 0x%4.4x parent %p", conn,
> > - conn->handle, conn->parent);
> > -
> > if (conn->state == BT_CONNECT)
> > pending = true;
> > }
> > @@ -5039,11 +5033,8 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,
> >
> > switch (status) {
> > case 0x00:
> > - conn->handle = __le16_to_cpu(ev->handle);
> > - if (conn->handle > HCI_CONN_HANDLE_MAX) {
> > - bt_dev_err(hdev, "Invalid handle: 0x%4.4x > 0x%4.4x",
> > - conn->handle, HCI_CONN_HANDLE_MAX);
> > - status = HCI_ERROR_INVALID_PARAMETERS;
> > + status = hci_conn_set_handle(conn, __le16_to_cpu(ev->handle));
> > + if (status) {
> > conn->state = BT_CLOSED;
> > break;
> > }
> > @@ -6978,7 +6969,7 @@ static void hci_le_create_big_complete_evt(struct hci_dev *hdev, void *data,
> > {
> > struct hci_evt_le_create_big_complete *ev = data;
> > struct hci_conn *conn;
> > - __u8 bis_idx = 0;
> > + __u8 i = 0;
> >
> > BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
> >
> > @@ -6996,7 +6987,9 @@ static void hci_le_create_big_complete_evt(struct hci_dev *hdev, void *data,
> > conn->iso_qos.bcast.big != ev->handle)
> > continue;
> >
> > - conn->handle = __le16_to_cpu(ev->bis_handle[bis_idx++]);
> > + if (hci_conn_set_handle(conn,
> > + __le16_to_cpu(ev->bis_handle[i++])))
> > + continue;
> >
> > if (!ev->status) {
> > conn->state = BT_CONNECTED;
> > @@ -7015,7 +7008,7 @@ static void hci_le_create_big_complete_evt(struct hci_dev *hdev, void *data,
> > rcu_read_lock();
> > }
> >
> > - if (!ev->status && !bis_idx)
> > + if (!ev->status && !i)
> > /* If no BISes have been connected for the BIG,
> > * terminate. This is in case all bound connections
> > * have been closed before the BIG creation
>


--
Luiz Augusto von Dentz