Skip to content

Commit febb2d2

Browse files
author
Paolo Abeni
committed
Merge tag 'for-net-2022-04-27' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth
Luiz Augusto von Dentz says: ==================== bluetooth pull request for net: - Fix regression causing some HCI events to be discarded when they shouldn't. * tag 'for-net-2022-04-27' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth: Bluetooth: hci_sync: Cleanup hci_conn if it cannot be aborted Bluetooth: hci_event: Fix creating hci_conn object on error status Bluetooth: hci_event: Fix checking for invalid handle on error status ==================== Link: https://lore.kernel.org/r/20220427234031.1257281-1-luiz.dentz@gmail.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2 parents d2b52ec + 9b3628d commit febb2d2

5 files changed

Lines changed: 83 additions & 43 deletions

File tree

include/net/bluetooth/hci.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,7 @@ enum {
578578
#define HCI_ERROR_CONNECTION_TIMEOUT 0x08
579579
#define HCI_ERROR_REJ_LIMITED_RESOURCES 0x0d
580580
#define HCI_ERROR_REJ_BAD_ADDR 0x0f
581+
#define HCI_ERROR_INVALID_PARAMETERS 0x12
581582
#define HCI_ERROR_REMOTE_USER_TERM 0x13
582583
#define HCI_ERROR_REMOTE_LOW_RESOURCES 0x14
583584
#define HCI_ERROR_REMOTE_POWER_OFF 0x15

include/net/bluetooth/hci_core.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1156,7 +1156,7 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
11561156

11571157
void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);
11581158

1159-
void hci_le_conn_failed(struct hci_conn *conn, u8 status);
1159+
void hci_conn_failed(struct hci_conn *conn, u8 status);
11601160

11611161
/*
11621162
* hci_conn_get() and hci_conn_put() are used to control the life-time of an

net/bluetooth/hci_conn.c

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ static void le_conn_timeout(struct work_struct *work)
670670
/* Disable LE Advertising */
671671
le_disable_advertising(hdev);
672672
hci_dev_lock(hdev);
673-
hci_le_conn_failed(conn, HCI_ERROR_ADVERTISING_TIMEOUT);
673+
hci_conn_failed(conn, HCI_ERROR_ADVERTISING_TIMEOUT);
674674
hci_dev_unlock(hdev);
675675
return;
676676
}
@@ -873,7 +873,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src, uint8_t src_type)
873873
EXPORT_SYMBOL(hci_get_route);
874874

875875
/* This function requires the caller holds hdev->lock */
876-
void hci_le_conn_failed(struct hci_conn *conn, u8 status)
876+
static void hci_le_conn_failed(struct hci_conn *conn, u8 status)
877877
{
878878
struct hci_dev *hdev = conn->hdev;
879879
struct hci_conn_params *params;
@@ -886,8 +886,6 @@ void hci_le_conn_failed(struct hci_conn *conn, u8 status)
886886
params->conn = NULL;
887887
}
888888

889-
conn->state = BT_CLOSED;
890-
891889
/* If the status indicates successful cancellation of
892890
* the attempt (i.e. Unknown Connection Id) there's no point of
893891
* notifying failure since we'll go back to keep trying to
@@ -899,10 +897,6 @@ void hci_le_conn_failed(struct hci_conn *conn, u8 status)
899897
mgmt_connect_failed(hdev, &conn->dst, conn->type,
900898
conn->dst_type, status);
901899

902-
hci_connect_cfm(conn, status);
903-
904-
hci_conn_del(conn);
905-
906900
/* Since we may have temporarily stopped the background scanning in
907901
* favor of connection establishment, we should restart it.
908902
*/
@@ -914,6 +908,28 @@ void hci_le_conn_failed(struct hci_conn *conn, u8 status)
914908
hci_enable_advertising(hdev);
915909
}
916910

911+
/* This function requires the caller holds hdev->lock */
912+
void hci_conn_failed(struct hci_conn *conn, u8 status)
913+
{
914+
struct hci_dev *hdev = conn->hdev;
915+
916+
bt_dev_dbg(hdev, "status 0x%2.2x", status);
917+
918+
switch (conn->type) {
919+
case LE_LINK:
920+
hci_le_conn_failed(conn, status);
921+
break;
922+
case ACL_LINK:
923+
mgmt_connect_failed(hdev, &conn->dst, conn->type,
924+
conn->dst_type, status);
925+
break;
926+
}
927+
928+
conn->state = BT_CLOSED;
929+
hci_connect_cfm(conn, status);
930+
hci_conn_del(conn);
931+
}
932+
917933
static void create_le_conn_complete(struct hci_dev *hdev, void *data, int err)
918934
{
919935
struct hci_conn *conn = data;

net/bluetooth/hci_event.c

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2834,7 +2834,7 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status)
28342834
bt_dev_dbg(hdev, "status 0x%2.2x", status);
28352835

28362836
/* All connection failure handling is taken care of by the
2837-
* hci_le_conn_failed function which is triggered by the HCI
2837+
* hci_conn_failed function which is triggered by the HCI
28382838
* request completion callbacks used for connecting.
28392839
*/
28402840
if (status)
@@ -2859,7 +2859,7 @@ static void hci_cs_le_ext_create_conn(struct hci_dev *hdev, u8 status)
28592859
bt_dev_dbg(hdev, "status 0x%2.2x", status);
28602860

28612861
/* All connection failure handling is taken care of by the
2862-
* hci_le_conn_failed function which is triggered by the HCI
2862+
* hci_conn_failed function which is triggered by the HCI
28632863
* request completion callbacks used for connecting.
28642864
*/
28652865
if (status)
@@ -3067,18 +3067,20 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
30673067
{
30683068
struct hci_ev_conn_complete *ev = data;
30693069
struct hci_conn *conn;
3070+
u8 status = ev->status;
30703071

3071-
if (__le16_to_cpu(ev->handle) > HCI_CONN_HANDLE_MAX) {
3072-
bt_dev_err(hdev, "Ignoring HCI_Connection_Complete for invalid handle");
3073-
return;
3074-
}
3075-
3076-
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
3072+
bt_dev_dbg(hdev, "status 0x%2.2x", status);
30773073

30783074
hci_dev_lock(hdev);
30793075

30803076
conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
30813077
if (!conn) {
3078+
/* In case of error status and there is no connection pending
3079+
* just unlock as there is nothing to cleanup.
3080+
*/
3081+
if (ev->status)
3082+
goto unlock;
3083+
30823084
/* Connection may not exist if auto-connected. Check the bredr
30833085
* allowlist to see if this device is allowed to auto connect.
30843086
* If link is an ACL type, create a connection class
@@ -3122,8 +3124,14 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
31223124
goto unlock;
31233125
}
31243126

3125-
if (!ev->status) {
3127+
if (!status) {
31263128
conn->handle = __le16_to_cpu(ev->handle);
3129+
if (conn->handle > HCI_CONN_HANDLE_MAX) {
3130+
bt_dev_err(hdev, "Invalid handle: 0x%4.4x > 0x%4.4x",
3131+
conn->handle, HCI_CONN_HANDLE_MAX);
3132+
status = HCI_ERROR_INVALID_PARAMETERS;
3133+
goto done;
3134+
}
31273135

31283136
if (conn->type == ACL_LINK) {
31293137
conn->state = BT_CONFIG;
@@ -3164,19 +3172,14 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
31643172
hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
31653173
&cp);
31663174
}
3167-
} else {
3168-
conn->state = BT_CLOSED;
3169-
if (conn->type == ACL_LINK)
3170-
mgmt_connect_failed(hdev, &conn->dst, conn->type,
3171-
conn->dst_type, ev->status);
31723175
}
31733176

31743177
if (conn->type == ACL_LINK)
31753178
hci_sco_setup(conn, ev->status);
31763179

3177-
if (ev->status) {
3178-
hci_connect_cfm(conn, ev->status);
3179-
hci_conn_del(conn);
3180+
done:
3181+
if (status) {
3182+
hci_conn_failed(conn, status);
31803183
} else if (ev->link_type == SCO_LINK) {
31813184
switch (conn->setting & SCO_AIRMODE_MASK) {
31823185
case SCO_AIRMODE_CVSD:
@@ -3185,7 +3188,7 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
31853188
break;
31863189
}
31873190

3188-
hci_connect_cfm(conn, ev->status);
3191+
hci_connect_cfm(conn, status);
31893192
}
31903193

31913194
unlock:
@@ -4676,6 +4679,7 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,
46764679
{
46774680
struct hci_ev_sync_conn_complete *ev = data;
46784681
struct hci_conn *conn;
4682+
u8 status = ev->status;
46794683

46804684
switch (ev->link_type) {
46814685
case SCO_LINK:
@@ -4690,12 +4694,7 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,
46904694
return;
46914695
}
46924696

4693-
if (__le16_to_cpu(ev->handle) > HCI_CONN_HANDLE_MAX) {
4694-
bt_dev_err(hdev, "Ignoring HCI_Sync_Conn_Complete for invalid handle");
4695-
return;
4696-
}
4697-
4698-
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
4697+
bt_dev_dbg(hdev, "status 0x%2.2x", status);
46994698

47004699
hci_dev_lock(hdev);
47014700

@@ -4729,9 +4728,17 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,
47294728
goto unlock;
47304729
}
47314730

4732-
switch (ev->status) {
4731+
switch (status) {
47334732
case 0x00:
47344733
conn->handle = __le16_to_cpu(ev->handle);
4734+
if (conn->handle > HCI_CONN_HANDLE_MAX) {
4735+
bt_dev_err(hdev, "Invalid handle: 0x%4.4x > 0x%4.4x",
4736+
conn->handle, HCI_CONN_HANDLE_MAX);
4737+
status = HCI_ERROR_INVALID_PARAMETERS;
4738+
conn->state = BT_CLOSED;
4739+
break;
4740+
}
4741+
47354742
conn->state = BT_CONNECTED;
47364743
conn->type = ev->link_type;
47374744

@@ -4775,8 +4782,8 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,
47754782
}
47764783
}
47774784

4778-
hci_connect_cfm(conn, ev->status);
4779-
if (ev->status)
4785+
hci_connect_cfm(conn, status);
4786+
if (status)
47804787
hci_conn_del(conn);
47814788

47824789
unlock:
@@ -5527,11 +5534,6 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
55275534
struct smp_irk *irk;
55285535
u8 addr_type;
55295536

5530-
if (handle > HCI_CONN_HANDLE_MAX) {
5531-
bt_dev_err(hdev, "Ignoring HCI_LE_Connection_Complete for invalid handle");
5532-
return;
5533-
}
5534-
55355537
hci_dev_lock(hdev);
55365538

55375539
/* All controllers implicitly stop advertising in the event of a
@@ -5541,6 +5543,12 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
55415543

55425544
conn = hci_lookup_le_connect(hdev);
55435545
if (!conn) {
5546+
/* In case of error status and there is no connection pending
5547+
* just unlock as there is nothing to cleanup.
5548+
*/
5549+
if (status)
5550+
goto unlock;
5551+
55445552
conn = hci_conn_add(hdev, LE_LINK, bdaddr, role);
55455553
if (!conn) {
55465554
bt_dev_err(hdev, "no memory for new connection");
@@ -5603,8 +5611,14 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
56035611

56045612
conn->dst_type = ev_bdaddr_type(hdev, conn->dst_type, NULL);
56055613

5614+
if (handle > HCI_CONN_HANDLE_MAX) {
5615+
bt_dev_err(hdev, "Invalid handle: 0x%4.4x > 0x%4.4x", handle,
5616+
HCI_CONN_HANDLE_MAX);
5617+
status = HCI_ERROR_INVALID_PARAMETERS;
5618+
}
5619+
56065620
if (status) {
5607-
hci_le_conn_failed(conn, status);
5621+
hci_conn_failed(conn, status);
56085622
goto unlock;
56095623
}
56105624

net/bluetooth/hci_sync.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4408,12 +4408,21 @@ static int hci_reject_conn_sync(struct hci_dev *hdev, struct hci_conn *conn,
44084408
static int hci_abort_conn_sync(struct hci_dev *hdev, struct hci_conn *conn,
44094409
u8 reason)
44104410
{
4411+
int err;
4412+
44114413
switch (conn->state) {
44124414
case BT_CONNECTED:
44134415
case BT_CONFIG:
44144416
return hci_disconnect_sync(hdev, conn, reason);
44154417
case BT_CONNECT:
4416-
return hci_connect_cancel_sync(hdev, conn);
4418+
err = hci_connect_cancel_sync(hdev, conn);
4419+
/* Cleanup hci_conn object if it cannot be cancelled as it
4420+
* likelly means the controller and host stack are out of sync.
4421+
*/
4422+
if (err)
4423+
hci_conn_failed(conn, err);
4424+
4425+
return err;
44174426
case BT_CONNECT2:
44184427
return hci_reject_conn_sync(hdev, conn, reason);
44194428
default:

0 commit comments

Comments
 (0)