Skip to content

Commit 160c131

Browse files
committed
Merge tag 'for-net-2023-04-10' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth
Luiz Augusto von Dentz says: ==================== bluetooth pull request for net: - Fix not setting Dath Path for broadcast sink - Fix not cleaning up on LE Connection failure - SCO: Fix possible circular locking dependency - L2CAP: Fix use-after-free in l2cap_disconnect_{req,rsp} - Fix race condition in hidp_session_thread - btbcm: Fix logic error in forming the board name - btbcm: Fix use after free in btsdio_remove * tag 'for-net-2023-04-10' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth: Bluetooth: L2CAP: Fix use-after-free in l2cap_disconnect_{req,rsp} Bluetooth: Set ISO Data Path on broadcast sink Bluetooth: hci_conn: Fix possible UAF Bluetooth: SCO: Fix possible circular locking dependency sco_sock_getsockopt Bluetooth: SCO: Fix possible circular locking dependency on sco_connect_cfm bluetooth: btbcm: Fix logic error in forming the board name. Bluetooth: btsdio: fix use after free bug in btsdio_remove due to race condition Bluetooth: Fix race condition in hidp_session_thread Bluetooth: Fix printing errors if LE Connection times out Bluetooth: hci_conn: Fix not cleaning up on LE Connection failure ==================== Link: https://lore.kernel.org/r/20230410172718.4067798-1-luiz.dentz@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents a450672 + a2a9339 commit 160c131

9 files changed

Lines changed: 129 additions & 106 deletions

File tree

drivers/bluetooth/btbcm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ static const char *btbcm_get_board_name(struct device *dev)
511511
len = strlen(tmp) + 1;
512512
board_type = devm_kzalloc(dev, len, GFP_KERNEL);
513513
strscpy(board_type, tmp, len);
514-
for (i = 0; i < board_type[i]; i++) {
514+
for (i = 0; i < len; i++) {
515515
if (board_type[i] == '/')
516516
board_type[i] = '-';
517517
}

drivers/bluetooth/btsdio.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ static void btsdio_remove(struct sdio_func *func)
358358
if (!data)
359359
return;
360360

361+
cancel_work_sync(&data->work);
361362
hdev = data->hdev;
362363

363364
sdio_set_drvdata(func, NULL);

include/net/bluetooth/hci_core.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,7 @@ enum {
954954
HCI_CONN_STK_ENCRYPT,
955955
HCI_CONN_AUTH_INITIATOR,
956956
HCI_CONN_DROP,
957+
HCI_CONN_CANCEL,
957958
HCI_CONN_PARAM_REMOVAL_PEND,
958959
HCI_CONN_NEW_LINK_KEY,
959960
HCI_CONN_SCANNING,

net/bluetooth/hci_conn.c

Lines changed: 53 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ static const struct sco_param esco_param_msbc[] = {
6868
};
6969

7070
/* This function requires the caller holds hdev->lock */
71-
static void hci_connect_le_scan_cleanup(struct hci_conn *conn)
71+
static void hci_connect_le_scan_cleanup(struct hci_conn *conn, u8 status)
7272
{
7373
struct hci_conn_params *params;
7474
struct hci_dev *hdev = conn->hdev;
@@ -88,9 +88,28 @@ static void hci_connect_le_scan_cleanup(struct hci_conn *conn)
8888

8989
params = hci_pend_le_action_lookup(&hdev->pend_le_conns, bdaddr,
9090
bdaddr_type);
91-
if (!params || !params->explicit_connect)
91+
if (!params)
9292
return;
9393

94+
if (params->conn) {
95+
hci_conn_drop(params->conn);
96+
hci_conn_put(params->conn);
97+
params->conn = NULL;
98+
}
99+
100+
if (!params->explicit_connect)
101+
return;
102+
103+
/* If the status indicates successful cancellation of
104+
* the attempt (i.e. Unknown Connection Id) there's no point of
105+
* notifying failure since we'll go back to keep trying to
106+
* connect. The only exception is explicit connect requests
107+
* where a timeout + cancel does indicate an actual failure.
108+
*/
109+
if (status && status != HCI_ERROR_UNKNOWN_CONN_ID)
110+
mgmt_connect_failed(hdev, &conn->dst, conn->type,
111+
conn->dst_type, status);
112+
94113
/* The connection attempt was doing scan for new RPA, and is
95114
* in scan phase. If params are not associated with any other
96115
* autoconnect action, remove them completely. If they are, just unmark
@@ -178,7 +197,7 @@ static void le_scan_cleanup(struct work_struct *work)
178197
rcu_read_unlock();
179198

180199
if (c == conn) {
181-
hci_connect_le_scan_cleanup(conn);
200+
hci_connect_le_scan_cleanup(conn, 0x00);
182201
hci_conn_cleanup(conn);
183202
}
184203

@@ -1049,6 +1068,17 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
10491068
return conn;
10501069
}
10511070

1071+
static bool hci_conn_unlink(struct hci_conn *conn)
1072+
{
1073+
if (!conn->link)
1074+
return false;
1075+
1076+
conn->link->link = NULL;
1077+
conn->link = NULL;
1078+
1079+
return true;
1080+
}
1081+
10521082
int hci_conn_del(struct hci_conn *conn)
10531083
{
10541084
struct hci_dev *hdev = conn->hdev;
@@ -1060,15 +1090,16 @@ int hci_conn_del(struct hci_conn *conn)
10601090
cancel_delayed_work_sync(&conn->idle_work);
10611091

10621092
if (conn->type == ACL_LINK) {
1063-
struct hci_conn *sco = conn->link;
1064-
if (sco) {
1065-
sco->link = NULL;
1093+
struct hci_conn *link = conn->link;
1094+
1095+
if (link) {
1096+
hci_conn_unlink(conn);
10661097
/* Due to race, SCO connection might be not established
10671098
* yet at this point. Delete it now, otherwise it is
10681099
* possible for it to be stuck and can't be deleted.
10691100
*/
1070-
if (sco->handle == HCI_CONN_HANDLE_UNSET)
1071-
hci_conn_del(sco);
1101+
if (link->handle == HCI_CONN_HANDLE_UNSET)
1102+
hci_conn_del(link);
10721103
}
10731104

10741105
/* Unacked frames */
@@ -1084,7 +1115,7 @@ int hci_conn_del(struct hci_conn *conn)
10841115
struct hci_conn *acl = conn->link;
10851116

10861117
if (acl) {
1087-
acl->link = NULL;
1118+
hci_conn_unlink(conn);
10881119
hci_conn_drop(acl);
10891120
}
10901121

@@ -1179,31 +1210,8 @@ EXPORT_SYMBOL(hci_get_route);
11791210
static void hci_le_conn_failed(struct hci_conn *conn, u8 status)
11801211
{
11811212
struct hci_dev *hdev = conn->hdev;
1182-
struct hci_conn_params *params;
11831213

1184-
params = hci_pend_le_action_lookup(&hdev->pend_le_conns, &conn->dst,
1185-
conn->dst_type);
1186-
if (params && params->conn) {
1187-
hci_conn_drop(params->conn);
1188-
hci_conn_put(params->conn);
1189-
params->conn = NULL;
1190-
}
1191-
1192-
/* If the status indicates successful cancellation of
1193-
* the attempt (i.e. Unknown Connection Id) there's no point of
1194-
* notifying failure since we'll go back to keep trying to
1195-
* connect. The only exception is explicit connect requests
1196-
* where a timeout + cancel does indicate an actual failure.
1197-
*/
1198-
if (status != HCI_ERROR_UNKNOWN_CONN_ID ||
1199-
(params && params->explicit_connect))
1200-
mgmt_connect_failed(hdev, &conn->dst, conn->type,
1201-
conn->dst_type, status);
1202-
1203-
/* Since we may have temporarily stopped the background scanning in
1204-
* favor of connection establishment, we should restart it.
1205-
*/
1206-
hci_update_passive_scan(hdev);
1214+
hci_connect_le_scan_cleanup(conn, status);
12071215

12081216
/* Enable advertising in case this was a failed connection
12091217
* attempt as a peripheral.
@@ -1237,15 +1245,15 @@ static void create_le_conn_complete(struct hci_dev *hdev, void *data, int err)
12371245
{
12381246
struct hci_conn *conn = data;
12391247

1248+
bt_dev_dbg(hdev, "err %d", err);
1249+
12401250
hci_dev_lock(hdev);
12411251

12421252
if (!err) {
1243-
hci_connect_le_scan_cleanup(conn);
1253+
hci_connect_le_scan_cleanup(conn, 0x00);
12441254
goto done;
12451255
}
12461256

1247-
bt_dev_err(hdev, "request failed to create LE connection: err %d", err);
1248-
12491257
/* Check if connection is still pending */
12501258
if (conn != hci_lookup_le_connect(hdev))
12511259
goto done;
@@ -2438,6 +2446,12 @@ void hci_conn_hash_flush(struct hci_dev *hdev)
24382446
c->state = BT_CLOSED;
24392447

24402448
hci_disconn_cfm(c, HCI_ERROR_LOCAL_HOST_TERM);
2449+
2450+
/* Unlink before deleting otherwise it is possible that
2451+
* hci_conn_del removes the link which may cause the list to
2452+
* contain items already freed.
2453+
*/
2454+
hci_conn_unlink(c);
24412455
hci_conn_del(c);
24422456
}
24432457
}
@@ -2775,6 +2789,9 @@ int hci_abort_conn(struct hci_conn *conn, u8 reason)
27752789
{
27762790
int r = 0;
27772791

2792+
if (test_and_set_bit(HCI_CONN_CANCEL, &conn->flags))
2793+
return 0;
2794+
27782795
switch (conn->state) {
27792796
case BT_CONNECTED:
27802797
case BT_CONFIG:

net/bluetooth/hci_event.c

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2881,16 +2881,6 @@ static void cs_le_create_conn(struct hci_dev *hdev, bdaddr_t *peer_addr,
28812881

28822882
conn->resp_addr_type = peer_addr_type;
28832883
bacpy(&conn->resp_addr, peer_addr);
2884-
2885-
/* We don't want the connection attempt to stick around
2886-
* indefinitely since LE doesn't have a page timeout concept
2887-
* like BR/EDR. Set a timer for any connection that doesn't use
2888-
* the accept list for connecting.
2889-
*/
2890-
if (filter_policy == HCI_LE_USE_PEER_ADDR)
2891-
queue_delayed_work(conn->hdev->workqueue,
2892-
&conn->le_conn_timeout,
2893-
conn->conn_timeout);
28942884
}
28952885

28962886
static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status)
@@ -5902,6 +5892,12 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
59025892
if (status)
59035893
goto unlock;
59045894

5895+
/* Drop the connection if it has been aborted */
5896+
if (test_bit(HCI_CONN_CANCEL, &conn->flags)) {
5897+
hci_conn_drop(conn);
5898+
goto unlock;
5899+
}
5900+
59055901
if (conn->dst_type == ADDR_LE_DEV_PUBLIC)
59065902
addr_type = BDADDR_LE_PUBLIC;
59075903
else
@@ -6995,7 +6991,7 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
69956991
bis->iso_qos.in.latency = le16_to_cpu(ev->interval) * 125 / 100;
69966992
bis->iso_qos.in.sdu = le16_to_cpu(ev->max_pdu);
69976993

6998-
hci_connect_cfm(bis, ev->status);
6994+
hci_iso_setup_path(bis);
69996995
}
70006996

70016997
hci_dev_unlock(hdev);

net/bluetooth/hci_sync.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,9 @@ int __hci_cmd_sync_status_sk(struct hci_dev *hdev, u16 opcode, u32 plen,
246246

247247
skb = __hci_cmd_sync_sk(hdev, opcode, plen, param, event, timeout, sk);
248248
if (IS_ERR(skb)) {
249-
bt_dev_err(hdev, "Opcode 0x%4x failed: %ld", opcode,
250-
PTR_ERR(skb));
249+
if (!event)
250+
bt_dev_err(hdev, "Opcode 0x%4x failed: %ld", opcode,
251+
PTR_ERR(skb));
251252
return PTR_ERR(skb);
252253
}
253254

@@ -5126,8 +5127,11 @@ static int hci_le_connect_cancel_sync(struct hci_dev *hdev,
51265127
if (test_bit(HCI_CONN_SCANNING, &conn->flags))
51275128
return 0;
51285129

5130+
if (test_and_set_bit(HCI_CONN_CANCEL, &conn->flags))
5131+
return 0;
5132+
51295133
return __hci_cmd_sync_status(hdev, HCI_OP_LE_CREATE_CONN_CANCEL,
5130-
6, &conn->dst, HCI_CMD_TIMEOUT);
5134+
0, NULL, HCI_CMD_TIMEOUT);
51315135
}
51325136

51335137
static int hci_connect_cancel_sync(struct hci_dev *hdev, struct hci_conn *conn)
@@ -6102,6 +6106,9 @@ int hci_le_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn)
61026106
conn->conn_timeout, NULL);
61036107

61046108
done:
6109+
if (err == -ETIMEDOUT)
6110+
hci_le_connect_cancel_sync(hdev, conn);
6111+
61056112
/* Re-enable advertising after the connection attempt is finished. */
61066113
hci_resume_advertising_sync(hdev);
61076114
return err;

net/bluetooth/hidp/core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ static void hidp_set_timer(struct hidp_session *session)
433433
static void hidp_del_timer(struct hidp_session *session)
434434
{
435435
if (session->idle_to > 0)
436-
del_timer(&session->timer);
436+
del_timer_sync(&session->timer);
437437
}
438438

439439
static void hidp_process_report(struct hidp_session *session, int type,

net/bluetooth/l2cap_core.c

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4652,33 +4652,27 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
46524652

46534653
BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
46544654

4655-
mutex_lock(&conn->chan_lock);
4656-
4657-
chan = __l2cap_get_chan_by_scid(conn, dcid);
4655+
chan = l2cap_get_chan_by_scid(conn, dcid);
46584656
if (!chan) {
4659-
mutex_unlock(&conn->chan_lock);
46604657
cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid);
46614658
return 0;
46624659
}
46634660

4664-
l2cap_chan_hold(chan);
4665-
l2cap_chan_lock(chan);
4666-
46674661
rsp.dcid = cpu_to_le16(chan->scid);
46684662
rsp.scid = cpu_to_le16(chan->dcid);
46694663
l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
46704664

46714665
chan->ops->set_shutdown(chan);
46724666

4667+
mutex_lock(&conn->chan_lock);
46734668
l2cap_chan_del(chan, ECONNRESET);
4669+
mutex_unlock(&conn->chan_lock);
46744670

46754671
chan->ops->close(chan);
46764672

46774673
l2cap_chan_unlock(chan);
46784674
l2cap_chan_put(chan);
46794675

4680-
mutex_unlock(&conn->chan_lock);
4681-
46824676
return 0;
46834677
}
46844678

@@ -4698,33 +4692,27 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn,
46984692

46994693
BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
47004694

4701-
mutex_lock(&conn->chan_lock);
4702-
4703-
chan = __l2cap_get_chan_by_scid(conn, scid);
4695+
chan = l2cap_get_chan_by_scid(conn, scid);
47044696
if (!chan) {
47054697
mutex_unlock(&conn->chan_lock);
47064698
return 0;
47074699
}
47084700

4709-
l2cap_chan_hold(chan);
4710-
l2cap_chan_lock(chan);
4711-
47124701
if (chan->state != BT_DISCONN) {
47134702
l2cap_chan_unlock(chan);
47144703
l2cap_chan_put(chan);
4715-
mutex_unlock(&conn->chan_lock);
47164704
return 0;
47174705
}
47184706

4707+
mutex_lock(&conn->chan_lock);
47194708
l2cap_chan_del(chan, 0);
4709+
mutex_unlock(&conn->chan_lock);
47204710

47214711
chan->ops->close(chan);
47224712

47234713
l2cap_chan_unlock(chan);
47244714
l2cap_chan_put(chan);
47254715

4726-
mutex_unlock(&conn->chan_lock);
4727-
47284716
return 0;
47294717
}
47304718

0 commit comments

Comments
 (0)