Commit 010a74f5 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge tag 'for-net-2023-01-17' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth

Luiz Augusto von Dentz says:

====================
bluetooth pull request for net:

 - Fix a buffer overflow in mgmt_mesh_add
 - Fix use HCI_OP_LE_READ_BUFFER_SIZE_V2
 - Fix hci_qca shutdown on closed serdev
 - Fix possible circular locking dependencies on ISO code
 - Fix possible deadlock in rfcomm_sk_state_change

* tag 'for-net-2023-01-17' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth:
  Bluetooth: Fix possible deadlock in rfcomm_sk_state_change
  Bluetooth: ISO: Fix possible circular locking dependency
  Bluetooth: hci_event: Fix Invalid wait context
  Bluetooth: ISO: Fix possible circular locking dependency
  Bluetooth: hci_sync: fix memory leak in hci_update_adv_data()
  Bluetooth: hci_qca: Fix driver shutdown on closed serdev
  Bluetooth: hci_conn: Fix memory leaks
  Bluetooth: hci_sync: Fix use HCI_OP_LE_READ_BUFFER_SIZE_V2
  Bluetooth: Fix a buffer overflow in mgmt_mesh_add()
====================

Link: https://lore.kernel.org/r/20230118002944.1679845-1-luiz.dentz@gmail.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 423c1d36 1d80d57f
...@@ -2164,10 +2164,17 @@ static void qca_serdev_shutdown(struct device *dev) ...@@ -2164,10 +2164,17 @@ static void qca_serdev_shutdown(struct device *dev)
int timeout = msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS); int timeout = msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS);
struct serdev_device *serdev = to_serdev_device(dev); struct serdev_device *serdev = to_serdev_device(dev);
struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev); struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev);
struct hci_uart *hu = &qcadev->serdev_hu;
struct hci_dev *hdev = hu->hdev;
struct qca_data *qca = hu->priv;
const u8 ibs_wake_cmd[] = { 0xFD }; const u8 ibs_wake_cmd[] = { 0xFD };
const u8 edl_reset_soc_cmd[] = { 0x01, 0x00, 0xFC, 0x01, 0x05 }; const u8 edl_reset_soc_cmd[] = { 0x01, 0x00, 0xFC, 0x01, 0x05 };
if (qcadev->btsoc_type == QCA_QCA6390) { if (qcadev->btsoc_type == QCA_QCA6390) {
if (test_bit(QCA_BT_OFF, &qca->flags) ||
!test_bit(HCI_RUNNING, &hdev->flags))
return;
serdev_device_write_flush(serdev); serdev_device_write_flush(serdev);
ret = serdev_device_write_buf(serdev, ibs_wake_cmd, ret = serdev_device_write_buf(serdev, ibs_wake_cmd,
sizeof(ibs_wake_cmd)); sizeof(ibs_wake_cmd));
......
...@@ -821,6 +821,7 @@ static void terminate_big_destroy(struct hci_dev *hdev, void *data, int err) ...@@ -821,6 +821,7 @@ static void terminate_big_destroy(struct hci_dev *hdev, void *data, int err)
static int hci_le_terminate_big(struct hci_dev *hdev, u8 big, u8 bis) static int hci_le_terminate_big(struct hci_dev *hdev, u8 big, u8 bis)
{ {
struct iso_list_data *d; struct iso_list_data *d;
int ret;
bt_dev_dbg(hdev, "big 0x%2.2x bis 0x%2.2x", big, bis); bt_dev_dbg(hdev, "big 0x%2.2x bis 0x%2.2x", big, bis);
...@@ -831,8 +832,12 @@ static int hci_le_terminate_big(struct hci_dev *hdev, u8 big, u8 bis) ...@@ -831,8 +832,12 @@ static int hci_le_terminate_big(struct hci_dev *hdev, u8 big, u8 bis)
d->big = big; d->big = big;
d->bis = bis; d->bis = bis;
return hci_cmd_sync_queue(hdev, terminate_big_sync, d, ret = hci_cmd_sync_queue(hdev, terminate_big_sync, d,
terminate_big_destroy); terminate_big_destroy);
if (ret)
kfree(d);
return ret;
} }
static int big_terminate_sync(struct hci_dev *hdev, void *data) static int big_terminate_sync(struct hci_dev *hdev, void *data)
...@@ -857,6 +862,7 @@ static int big_terminate_sync(struct hci_dev *hdev, void *data) ...@@ -857,6 +862,7 @@ static int big_terminate_sync(struct hci_dev *hdev, void *data)
static int hci_le_big_terminate(struct hci_dev *hdev, u8 big, u16 sync_handle) static int hci_le_big_terminate(struct hci_dev *hdev, u8 big, u16 sync_handle)
{ {
struct iso_list_data *d; struct iso_list_data *d;
int ret;
bt_dev_dbg(hdev, "big 0x%2.2x sync_handle 0x%4.4x", big, sync_handle); bt_dev_dbg(hdev, "big 0x%2.2x sync_handle 0x%4.4x", big, sync_handle);
...@@ -867,8 +873,12 @@ static int hci_le_big_terminate(struct hci_dev *hdev, u8 big, u16 sync_handle) ...@@ -867,8 +873,12 @@ static int hci_le_big_terminate(struct hci_dev *hdev, u8 big, u16 sync_handle)
d->big = big; d->big = big;
d->sync_handle = sync_handle; d->sync_handle = sync_handle;
return hci_cmd_sync_queue(hdev, big_terminate_sync, d, ret = hci_cmd_sync_queue(hdev, big_terminate_sync, d,
terminate_big_destroy); terminate_big_destroy);
if (ret)
kfree(d);
return ret;
} }
/* Cleanup BIS connection /* Cleanup BIS connection
......
...@@ -3848,8 +3848,11 @@ static u8 hci_cc_le_set_cig_params(struct hci_dev *hdev, void *data, ...@@ -3848,8 +3848,11 @@ static u8 hci_cc_le_set_cig_params(struct hci_dev *hdev, void *data,
conn->handle, conn->link); conn->handle, conn->link);
/* Create CIS if LE is already connected */ /* Create CIS if LE is already connected */
if (conn->link && conn->link->state == BT_CONNECTED) if (conn->link && conn->link->state == BT_CONNECTED) {
rcu_read_unlock();
hci_le_create_cis(conn->link); hci_le_create_cis(conn->link);
rcu_read_lock();
}
if (i == rp->num_handles) if (i == rp->num_handles)
break; break;
......
...@@ -3572,7 +3572,7 @@ static const struct hci_init_stage hci_init2[] = { ...@@ -3572,7 +3572,7 @@ static const struct hci_init_stage hci_init2[] = {
static int hci_le_read_buffer_size_sync(struct hci_dev *hdev) static int hci_le_read_buffer_size_sync(struct hci_dev *hdev)
{ {
/* Use Read LE Buffer Size V2 if supported */ /* Use Read LE Buffer Size V2 if supported */
if (hdev->commands[41] & 0x20) if (iso_capable(hdev) && hdev->commands[41] & 0x20)
return __hci_cmd_sync_status(hdev, return __hci_cmd_sync_status(hdev,
HCI_OP_LE_READ_BUFFER_SIZE_V2, HCI_OP_LE_READ_BUFFER_SIZE_V2,
0, NULL, HCI_CMD_TIMEOUT); 0, NULL, HCI_CMD_TIMEOUT);
...@@ -3597,10 +3597,10 @@ static int hci_le_read_supported_states_sync(struct hci_dev *hdev) ...@@ -3597,10 +3597,10 @@ static int hci_le_read_supported_states_sync(struct hci_dev *hdev)
/* LE Controller init stage 2 command sequence */ /* LE Controller init stage 2 command sequence */
static const struct hci_init_stage le_init2[] = { static const struct hci_init_stage le_init2[] = {
/* HCI_OP_LE_READ_BUFFER_SIZE */
HCI_INIT(hci_le_read_buffer_size_sync),
/* HCI_OP_LE_READ_LOCAL_FEATURES */ /* HCI_OP_LE_READ_LOCAL_FEATURES */
HCI_INIT(hci_le_read_local_features_sync), HCI_INIT(hci_le_read_local_features_sync),
/* HCI_OP_LE_READ_BUFFER_SIZE */
HCI_INIT(hci_le_read_buffer_size_sync),
/* HCI_OP_LE_READ_SUPPORTED_STATES */ /* HCI_OP_LE_READ_SUPPORTED_STATES */
HCI_INIT(hci_le_read_supported_states_sync), HCI_INIT(hci_le_read_supported_states_sync),
{} {}
...@@ -6187,20 +6187,13 @@ int hci_get_random_address(struct hci_dev *hdev, bool require_privacy, ...@@ -6187,20 +6187,13 @@ int hci_get_random_address(struct hci_dev *hdev, bool require_privacy,
static int _update_adv_data_sync(struct hci_dev *hdev, void *data) static int _update_adv_data_sync(struct hci_dev *hdev, void *data)
{ {
u8 instance = *(u8 *)data; u8 instance = PTR_ERR(data);
kfree(data);
return hci_update_adv_data_sync(hdev, instance); return hci_update_adv_data_sync(hdev, instance);
} }
int hci_update_adv_data(struct hci_dev *hdev, u8 instance) int hci_update_adv_data(struct hci_dev *hdev, u8 instance)
{ {
u8 *inst_ptr = kmalloc(1, GFP_KERNEL); return hci_cmd_sync_queue(hdev, _update_adv_data_sync,
ERR_PTR(instance), NULL);
if (!inst_ptr)
return -ENOMEM;
*inst_ptr = instance;
return hci_cmd_sync_queue(hdev, _update_adv_data_sync, inst_ptr, NULL);
} }
...@@ -289,15 +289,15 @@ static int iso_connect_bis(struct sock *sk) ...@@ -289,15 +289,15 @@ static int iso_connect_bis(struct sock *sk)
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
hci_dev_put(hdev); hci_dev_put(hdev);
err = iso_chan_add(conn, sk, NULL);
if (err)
return err;
lock_sock(sk); lock_sock(sk);
/* Update source addr of the socket */ /* Update source addr of the socket */
bacpy(&iso_pi(sk)->src, &hcon->src); bacpy(&iso_pi(sk)->src, &hcon->src);
err = iso_chan_add(conn, sk, NULL);
if (err)
goto release;
if (hcon->state == BT_CONNECTED) { if (hcon->state == BT_CONNECTED) {
iso_sock_clear_timer(sk); iso_sock_clear_timer(sk);
sk->sk_state = BT_CONNECTED; sk->sk_state = BT_CONNECTED;
...@@ -306,7 +306,6 @@ static int iso_connect_bis(struct sock *sk) ...@@ -306,7 +306,6 @@ static int iso_connect_bis(struct sock *sk)
iso_sock_set_timer(sk, sk->sk_sndtimeo); iso_sock_set_timer(sk, sk->sk_sndtimeo);
} }
release:
release_sock(sk); release_sock(sk);
return err; return err;
...@@ -372,15 +371,15 @@ static int iso_connect_cis(struct sock *sk) ...@@ -372,15 +371,15 @@ static int iso_connect_cis(struct sock *sk)
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
hci_dev_put(hdev); hci_dev_put(hdev);
err = iso_chan_add(conn, sk, NULL);
if (err)
return err;
lock_sock(sk); lock_sock(sk);
/* Update source addr of the socket */ /* Update source addr of the socket */
bacpy(&iso_pi(sk)->src, &hcon->src); bacpy(&iso_pi(sk)->src, &hcon->src);
err = iso_chan_add(conn, sk, NULL);
if (err)
goto release;
if (hcon->state == BT_CONNECTED) { if (hcon->state == BT_CONNECTED) {
iso_sock_clear_timer(sk); iso_sock_clear_timer(sk);
sk->sk_state = BT_CONNECTED; sk->sk_state = BT_CONNECTED;
...@@ -392,7 +391,6 @@ static int iso_connect_cis(struct sock *sk) ...@@ -392,7 +391,6 @@ static int iso_connect_cis(struct sock *sk)
iso_sock_set_timer(sk, sk->sk_sndtimeo); iso_sock_set_timer(sk, sk->sk_sndtimeo);
} }
release:
release_sock(sk); release_sock(sk);
return err; return err;
...@@ -895,13 +893,10 @@ static int iso_listen_bis(struct sock *sk) ...@@ -895,13 +893,10 @@ static int iso_listen_bis(struct sock *sk)
if (!hdev) if (!hdev)
return -EHOSTUNREACH; return -EHOSTUNREACH;
hci_dev_lock(hdev);
err = hci_pa_create_sync(hdev, &iso_pi(sk)->dst, err = hci_pa_create_sync(hdev, &iso_pi(sk)->dst,
le_addr_type(iso_pi(sk)->dst_type), le_addr_type(iso_pi(sk)->dst_type),
iso_pi(sk)->bc_sid); iso_pi(sk)->bc_sid);
hci_dev_unlock(hdev);
hci_dev_put(hdev); hci_dev_put(hdev);
return err; return err;
...@@ -1432,33 +1427,29 @@ static void iso_conn_ready(struct iso_conn *conn) ...@@ -1432,33 +1427,29 @@ static void iso_conn_ready(struct iso_conn *conn)
struct sock *parent; struct sock *parent;
struct sock *sk = conn->sk; struct sock *sk = conn->sk;
struct hci_ev_le_big_sync_estabilished *ev; struct hci_ev_le_big_sync_estabilished *ev;
struct hci_conn *hcon;
BT_DBG("conn %p", conn); BT_DBG("conn %p", conn);
if (sk) { if (sk) {
iso_sock_ready(conn->sk); iso_sock_ready(conn->sk);
} else { } else {
iso_conn_lock(conn); hcon = conn->hcon;
if (!hcon)
if (!conn->hcon) {
iso_conn_unlock(conn);
return; return;
}
ev = hci_recv_event_data(conn->hcon->hdev, ev = hci_recv_event_data(hcon->hdev,
HCI_EVT_LE_BIG_SYNC_ESTABILISHED); HCI_EVT_LE_BIG_SYNC_ESTABILISHED);
if (ev) if (ev)
parent = iso_get_sock_listen(&conn->hcon->src, parent = iso_get_sock_listen(&hcon->src,
&conn->hcon->dst, &hcon->dst,
iso_match_big, ev); iso_match_big, ev);
else else
parent = iso_get_sock_listen(&conn->hcon->src, parent = iso_get_sock_listen(&hcon->src,
BDADDR_ANY, NULL, NULL); BDADDR_ANY, NULL, NULL);
if (!parent) { if (!parent)
iso_conn_unlock(conn);
return; return;
}
lock_sock(parent); lock_sock(parent);
...@@ -1466,30 +1457,29 @@ static void iso_conn_ready(struct iso_conn *conn) ...@@ -1466,30 +1457,29 @@ static void iso_conn_ready(struct iso_conn *conn)
BTPROTO_ISO, GFP_ATOMIC, 0); BTPROTO_ISO, GFP_ATOMIC, 0);
if (!sk) { if (!sk) {
release_sock(parent); release_sock(parent);
iso_conn_unlock(conn);
return; return;
} }
iso_sock_init(sk, parent); iso_sock_init(sk, parent);
bacpy(&iso_pi(sk)->src, &conn->hcon->src); bacpy(&iso_pi(sk)->src, &hcon->src);
iso_pi(sk)->src_type = conn->hcon->src_type; iso_pi(sk)->src_type = hcon->src_type;
/* If hcon has no destination address (BDADDR_ANY) it means it /* If hcon has no destination address (BDADDR_ANY) it means it
* was created by HCI_EV_LE_BIG_SYNC_ESTABILISHED so we need to * was created by HCI_EV_LE_BIG_SYNC_ESTABILISHED so we need to
* initialize using the parent socket destination address. * initialize using the parent socket destination address.
*/ */
if (!bacmp(&conn->hcon->dst, BDADDR_ANY)) { if (!bacmp(&hcon->dst, BDADDR_ANY)) {
bacpy(&conn->hcon->dst, &iso_pi(parent)->dst); bacpy(&hcon->dst, &iso_pi(parent)->dst);
conn->hcon->dst_type = iso_pi(parent)->dst_type; hcon->dst_type = iso_pi(parent)->dst_type;
conn->hcon->sync_handle = iso_pi(parent)->sync_handle; hcon->sync_handle = iso_pi(parent)->sync_handle;
} }
bacpy(&iso_pi(sk)->dst, &conn->hcon->dst); bacpy(&iso_pi(sk)->dst, &hcon->dst);
iso_pi(sk)->dst_type = conn->hcon->dst_type; iso_pi(sk)->dst_type = hcon->dst_type;
hci_conn_hold(conn->hcon); hci_conn_hold(hcon);
__iso_chan_add(conn, sk, parent); iso_chan_add(conn, sk, parent);
if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags)) if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags))
sk->sk_state = BT_CONNECT2; sk->sk_state = BT_CONNECT2;
...@@ -1500,8 +1490,6 @@ static void iso_conn_ready(struct iso_conn *conn) ...@@ -1500,8 +1490,6 @@ static void iso_conn_ready(struct iso_conn *conn)
parent->sk_data_ready(parent); parent->sk_data_ready(parent);
release_sock(parent); release_sock(parent);
iso_conn_unlock(conn);
} }
} }
......
...@@ -27,7 +27,7 @@ struct mgmt_mesh_tx { ...@@ -27,7 +27,7 @@ struct mgmt_mesh_tx {
struct sock *sk; struct sock *sk;
u8 handle; u8 handle;
u8 instance; u8 instance;
u8 param[sizeof(struct mgmt_cp_mesh_send) + 29]; u8 param[sizeof(struct mgmt_cp_mesh_send) + 31];
}; };
struct mgmt_pending_cmd { struct mgmt_pending_cmd {
......
...@@ -391,6 +391,7 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a ...@@ -391,6 +391,7 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a
addr->sa_family != AF_BLUETOOTH) addr->sa_family != AF_BLUETOOTH)
return -EINVAL; return -EINVAL;
sock_hold(sk);
lock_sock(sk); lock_sock(sk);
if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) { if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) {
...@@ -410,14 +411,18 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a ...@@ -410,14 +411,18 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a
d->sec_level = rfcomm_pi(sk)->sec_level; d->sec_level = rfcomm_pi(sk)->sec_level;
d->role_switch = rfcomm_pi(sk)->role_switch; d->role_switch = rfcomm_pi(sk)->role_switch;
/* Drop sock lock to avoid potential deadlock with the RFCOMM lock */
release_sock(sk);
err = rfcomm_dlc_open(d, &rfcomm_pi(sk)->src, &sa->rc_bdaddr, err = rfcomm_dlc_open(d, &rfcomm_pi(sk)->src, &sa->rc_bdaddr,
sa->rc_channel); sa->rc_channel);
if (!err) lock_sock(sk);
if (!err && !sock_flag(sk, SOCK_ZAPPED))
err = bt_sock_wait_state(sk, BT_CONNECTED, err = bt_sock_wait_state(sk, BT_CONNECTED,
sock_sndtimeo(sk, flags & O_NONBLOCK)); sock_sndtimeo(sk, flags & O_NONBLOCK));
done: done:
release_sock(sk); release_sock(sk);
sock_put(sk);
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment