Commit b8c3bf0e authored by Jakub Kicinski's avatar Jakub Kicinski

Merge tag 'for-net-2022-08-08' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth

Luiz Augusto von Dentz says:

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

 - Fixes various issues related to ISO channel/socket support
 - Fixes issues when building with C=1
 - Fix cancel uninitilized work which blocks syzbot to run

* tag 'for-net-2022-08-08' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth:
  Bluetooth: ISO: Fix not using the correct QoS
  Bluetooth: don't try to cancel uninitialized works at mgmt_index_removed()
  Bluetooth: ISO: Fix iso_sock_getsockopt for BT_DEFER_SETUP
  Bluetooth: MGMT: Fixes build warnings with C=1
  Bluetooth: hci_event: Fix build warning with C=1
  Bluetooth: ISO: Fix memory corruption
  Bluetooth: Fix null pointer deref on unexpected status event
  Bluetooth: ISO: Fix info leak in iso_sock_getsockopt()
  Bluetooth: hci_conn: Fix updating ISO QoS PHY
  Bluetooth: ISO: unlock on error path in iso_sock_setsockopt()
  Bluetooth: L2CAP: Fix l2cap_global_chan_by_psm regression
====================

Link: https://lore.kernel.org/r/20220809001224.412807-1-luiz.dentz@gmail.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 7a07a29e 1d1ab5d3
...@@ -54,7 +54,10 @@ void aosp_do_open(struct hci_dev *hdev) ...@@ -54,7 +54,10 @@ void aosp_do_open(struct hci_dev *hdev)
/* LE Get Vendor Capabilities Command */ /* LE Get Vendor Capabilities Command */
skb = __hci_cmd_sync(hdev, hci_opcode_pack(0x3f, 0x153), 0, NULL, skb = __hci_cmd_sync(hdev, hci_opcode_pack(0x3f, 0x153), 0, NULL,
HCI_CMD_TIMEOUT); HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR_OR_NULL(skb)) {
if (!skb)
skb = ERR_PTR(-EIO);
bt_dev_err(hdev, "AOSP get vendor capabilities (%ld)", bt_dev_err(hdev, "AOSP get vendor capabilities (%ld)",
PTR_ERR(skb)); PTR_ERR(skb));
return; return;
...@@ -152,7 +155,10 @@ static int enable_quality_report(struct hci_dev *hdev) ...@@ -152,7 +155,10 @@ static int enable_quality_report(struct hci_dev *hdev)
skb = __hci_cmd_sync(hdev, BQR_OPCODE, sizeof(cp), &cp, skb = __hci_cmd_sync(hdev, BQR_OPCODE, sizeof(cp), &cp,
HCI_CMD_TIMEOUT); HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR_OR_NULL(skb)) {
if (!skb)
skb = ERR_PTR(-EIO);
bt_dev_err(hdev, "Enabling Android BQR failed (%ld)", bt_dev_err(hdev, "Enabling Android BQR failed (%ld)",
PTR_ERR(skb)); PTR_ERR(skb));
return PTR_ERR(skb); return PTR_ERR(skb);
...@@ -171,7 +177,10 @@ static int disable_quality_report(struct hci_dev *hdev) ...@@ -171,7 +177,10 @@ static int disable_quality_report(struct hci_dev *hdev)
skb = __hci_cmd_sync(hdev, BQR_OPCODE, sizeof(cp), &cp, skb = __hci_cmd_sync(hdev, BQR_OPCODE, sizeof(cp), &cp,
HCI_CMD_TIMEOUT); HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR_OR_NULL(skb)) {
if (!skb)
skb = ERR_PTR(-EIO);
bt_dev_err(hdev, "Disabling Android BQR failed (%ld)", bt_dev_err(hdev, "Disabling Android BQR failed (%ld)",
PTR_ERR(skb)); PTR_ERR(skb));
return PTR_ERR(skb); return PTR_ERR(skb);
......
...@@ -1551,8 +1551,8 @@ static void cis_add(struct iso_list_data *d, struct bt_iso_qos *qos) ...@@ -1551,8 +1551,8 @@ static void cis_add(struct iso_list_data *d, struct bt_iso_qos *qos)
cis->cis_id = qos->cis; cis->cis_id = qos->cis;
cis->c_sdu = cpu_to_le16(qos->out.sdu); cis->c_sdu = cpu_to_le16(qos->out.sdu);
cis->p_sdu = cpu_to_le16(qos->in.sdu); cis->p_sdu = cpu_to_le16(qos->in.sdu);
cis->c_phy = qos->out.phy; cis->c_phy = qos->out.phy ? qos->out.phy : qos->in.phy;
cis->p_phy = qos->in.phy; cis->p_phy = qos->in.phy ? qos->in.phy : qos->out.phy;
cis->c_rtn = qos->out.rtn; cis->c_rtn = qos->out.rtn;
cis->p_rtn = qos->in.rtn; cis->p_rtn = qos->in.rtn;
...@@ -1735,13 +1735,6 @@ struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst, ...@@ -1735,13 +1735,6 @@ struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst,
if (!qos->in.latency) if (!qos->in.latency)
qos->in.latency = qos->out.latency; qos->in.latency = qos->out.latency;
/* Mirror PHYs that are disabled as SDU will be set to 0 */
if (!qos->in.phy)
qos->in.phy = qos->out.phy;
if (!qos->out.phy)
qos->out.phy = qos->in.phy;
if (!hci_le_set_cig_params(cis, qos)) { if (!hci_le_set_cig_params(cis, qos)) {
hci_conn_drop(cis); hci_conn_drop(cis);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
......
...@@ -328,14 +328,17 @@ static u8 hci_cc_delete_stored_link_key(struct hci_dev *hdev, void *data, ...@@ -328,14 +328,17 @@ static u8 hci_cc_delete_stored_link_key(struct hci_dev *hdev, void *data,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct hci_rp_delete_stored_link_key *rp = data; struct hci_rp_delete_stored_link_key *rp = data;
u16 num_keys;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status) if (rp->status)
return rp->status; return rp->status;
if (rp->num_keys <= hdev->stored_num_keys) num_keys = le16_to_cpu(rp->num_keys);
hdev->stored_num_keys -= le16_to_cpu(rp->num_keys);
if (num_keys <= hdev->stored_num_keys)
hdev->stored_num_keys -= num_keys;
else else
hdev->stored_num_keys = 0; hdev->stored_num_keys = 0;
......
...@@ -44,6 +44,9 @@ static void iso_sock_kill(struct sock *sk); ...@@ -44,6 +44,9 @@ static void iso_sock_kill(struct sock *sk);
/* ----- ISO socket info ----- */ /* ----- ISO socket info ----- */
#define iso_pi(sk) ((struct iso_pinfo *)sk) #define iso_pi(sk) ((struct iso_pinfo *)sk)
#define EIR_SERVICE_DATA_LENGTH 4
#define BASE_MAX_LENGTH (HCI_MAX_PER_AD_LENGTH - EIR_SERVICE_DATA_LENGTH)
struct iso_pinfo { struct iso_pinfo {
struct bt_sock bt; struct bt_sock bt;
bdaddr_t src; bdaddr_t src;
...@@ -57,7 +60,7 @@ struct iso_pinfo { ...@@ -57,7 +60,7 @@ struct iso_pinfo {
__u32 flags; __u32 flags;
struct bt_iso_qos qos; struct bt_iso_qos qos;
__u8 base_len; __u8 base_len;
__u8 base[HCI_MAX_PER_AD_LENGTH]; __u8 base[BASE_MAX_LENGTH];
struct iso_conn *conn; struct iso_conn *conn;
}; };
...@@ -370,15 +373,24 @@ static int iso_connect_cis(struct sock *sk) ...@@ -370,15 +373,24 @@ static int iso_connect_cis(struct sock *sk)
return err; return err;
} }
static struct bt_iso_qos *iso_sock_get_qos(struct sock *sk)
{
if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONNECT2)
return &iso_pi(sk)->conn->hcon->iso_qos;
return &iso_pi(sk)->qos;
}
static int iso_send_frame(struct sock *sk, struct sk_buff *skb) static int iso_send_frame(struct sock *sk, struct sk_buff *skb)
{ {
struct iso_conn *conn = iso_pi(sk)->conn; struct iso_conn *conn = iso_pi(sk)->conn;
struct bt_iso_qos *qos = iso_sock_get_qos(sk);
struct hci_iso_data_hdr *hdr; struct hci_iso_data_hdr *hdr;
int len = 0; int len = 0;
BT_DBG("sk %p len %d", sk, skb->len); BT_DBG("sk %p len %d", sk, skb->len);
if (skb->len > iso_pi(sk)->qos.out.sdu) if (skb->len > qos->out.sdu)
return -EMSGSIZE; return -EMSGSIZE;
len = skb->len; len = skb->len;
...@@ -1177,8 +1189,10 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -1177,8 +1189,10 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
} }
len = min_t(unsigned int, sizeof(qos), optlen); len = min_t(unsigned int, sizeof(qos), optlen);
if (len != sizeof(qos)) if (len != sizeof(qos)) {
return -EINVAL; err = -EINVAL;
break;
}
memset(&qos, 0, sizeof(qos)); memset(&qos, 0, sizeof(qos));
...@@ -1233,7 +1247,7 @@ static int iso_sock_getsockopt(struct socket *sock, int level, int optname, ...@@ -1233,7 +1247,7 @@ static int iso_sock_getsockopt(struct socket *sock, int level, int optname,
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
int len, err = 0; int len, err = 0;
struct bt_iso_qos qos; struct bt_iso_qos *qos;
u8 base_len; u8 base_len;
u8 *base; u8 *base;
...@@ -1246,7 +1260,7 @@ static int iso_sock_getsockopt(struct socket *sock, int level, int optname, ...@@ -1246,7 +1260,7 @@ static int iso_sock_getsockopt(struct socket *sock, int level, int optname,
switch (optname) { switch (optname) {
case BT_DEFER_SETUP: case BT_DEFER_SETUP:
if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) { if (sk->sk_state == BT_CONNECTED) {
err = -EINVAL; err = -EINVAL;
break; break;
} }
...@@ -1258,13 +1272,10 @@ static int iso_sock_getsockopt(struct socket *sock, int level, int optname, ...@@ -1258,13 +1272,10 @@ static int iso_sock_getsockopt(struct socket *sock, int level, int optname,
break; break;
case BT_ISO_QOS: case BT_ISO_QOS:
if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONNECT2) qos = iso_sock_get_qos(sk);
qos = iso_pi(sk)->conn->hcon->iso_qos;
else
qos = iso_pi(sk)->qos;
len = min_t(unsigned int, len, sizeof(qos)); len = min_t(unsigned int, len, sizeof(*qos));
if (copy_to_user(optval, (char *)&qos, len)) if (copy_to_user(optval, qos, len))
err = -EFAULT; err = -EFAULT;
break; break;
......
...@@ -1970,11 +1970,11 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, ...@@ -1970,11 +1970,11 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
bdaddr_t *dst, bdaddr_t *dst,
u8 link_type) u8 link_type)
{ {
struct l2cap_chan *c, *c1 = NULL; struct l2cap_chan *c, *tmp, *c1 = NULL;
read_lock(&chan_list_lock); read_lock(&chan_list_lock);
list_for_each_entry(c, &chan_list, global_l) { list_for_each_entry_safe(c, tmp, &chan_list, global_l) {
if (state && c->state != state) if (state && c->state != state)
continue; continue;
...@@ -1993,12 +1993,11 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, ...@@ -1993,12 +1993,11 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
dst_match = !bacmp(&c->dst, dst); dst_match = !bacmp(&c->dst, dst);
if (src_match && dst_match) { if (src_match && dst_match) {
c = l2cap_chan_hold_unless_zero(c); c = l2cap_chan_hold_unless_zero(c);
if (!c) if (c) {
continue;
read_unlock(&chan_list_lock); read_unlock(&chan_list_lock);
return c; return c;
} }
}
/* Closest match */ /* Closest match */
src_any = !bacmp(&c->src, BDADDR_ANY); src_any = !bacmp(&c->src, BDADDR_ANY);
......
...@@ -3819,7 +3819,7 @@ static int set_blocked_keys(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -3819,7 +3819,7 @@ static int set_blocked_keys(struct sock *sk, struct hci_dev *hdev, void *data,
hci_blocked_keys_clear(hdev); hci_blocked_keys_clear(hdev);
for (i = 0; i < keys->key_count; ++i) { for (i = 0; i < key_count; ++i) {
struct blocked_key *b = kzalloc(sizeof(*b), GFP_KERNEL); struct blocked_key *b = kzalloc(sizeof(*b), GFP_KERNEL);
if (!b) { if (!b) {
...@@ -4624,8 +4624,7 @@ static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -4624,8 +4624,7 @@ static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
u32 current_flags = __le32_to_cpu(cp->current_flags); u32 current_flags = __le32_to_cpu(cp->current_flags);
bt_dev_dbg(hdev, "Set device flags %pMR (type 0x%x) = 0x%x", bt_dev_dbg(hdev, "Set device flags %pMR (type 0x%x) = 0x%x",
&cp->addr.bdaddr, cp->addr.type, &cp->addr.bdaddr, cp->addr.type, current_flags);
__le32_to_cpu(current_flags));
// We should take hci_dev_lock() early, I think.. conn_flags can change // We should take hci_dev_lock() early, I think.. conn_flags can change
supported_flags = hdev->conn_flags; supported_flags = hdev->conn_flags;
...@@ -8936,6 +8935,8 @@ void mgmt_index_removed(struct hci_dev *hdev) ...@@ -8936,6 +8935,8 @@ void mgmt_index_removed(struct hci_dev *hdev)
HCI_MGMT_EXT_INDEX_EVENTS); HCI_MGMT_EXT_INDEX_EVENTS);
/* Cancel any remaining timed work */ /* Cancel any remaining timed work */
if (!hci_dev_test_flag(hdev, HCI_MGMT))
return;
cancel_delayed_work_sync(&hdev->discov_off); cancel_delayed_work_sync(&hdev->discov_off);
cancel_delayed_work_sync(&hdev->service_cache); cancel_delayed_work_sync(&hdev->service_cache);
cancel_delayed_work_sync(&hdev->rpa_expired); cancel_delayed_work_sync(&hdev->rpa_expired);
......
...@@ -120,7 +120,10 @@ static bool read_supported_features(struct hci_dev *hdev, ...@@ -120,7 +120,10 @@ static bool read_supported_features(struct hci_dev *hdev,
skb = __hci_cmd_sync(hdev, hdev->msft_opcode, sizeof(cp), &cp, skb = __hci_cmd_sync(hdev, hdev->msft_opcode, sizeof(cp), &cp,
HCI_CMD_TIMEOUT); HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR_OR_NULL(skb)) {
if (!skb)
skb = ERR_PTR(-EIO);
bt_dev_err(hdev, "Failed to read MSFT supported features (%ld)", bt_dev_err(hdev, "Failed to read MSFT supported features (%ld)",
PTR_ERR(skb)); PTR_ERR(skb));
return false; return false;
...@@ -319,8 +322,11 @@ static int msft_remove_monitor_sync(struct hci_dev *hdev, ...@@ -319,8 +322,11 @@ static int msft_remove_monitor_sync(struct hci_dev *hdev,
skb = __hci_cmd_sync(hdev, hdev->msft_opcode, sizeof(cp), &cp, skb = __hci_cmd_sync(hdev, hdev->msft_opcode, sizeof(cp), &cp,
HCI_CMD_TIMEOUT); HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) if (IS_ERR_OR_NULL(skb)) {
if (!skb)
return -EIO;
return PTR_ERR(skb); return PTR_ERR(skb);
}
return msft_le_cancel_monitor_advertisement_cb(hdev, hdev->msft_opcode, return msft_le_cancel_monitor_advertisement_cb(hdev, hdev->msft_opcode,
monitor, skb); monitor, skb);
...@@ -432,8 +438,11 @@ static int msft_add_monitor_sync(struct hci_dev *hdev, ...@@ -432,8 +438,11 @@ static int msft_add_monitor_sync(struct hci_dev *hdev,
HCI_CMD_TIMEOUT); HCI_CMD_TIMEOUT);
kfree(cp); kfree(cp);
if (IS_ERR(skb)) if (IS_ERR_OR_NULL(skb)) {
if (!skb)
return -EIO;
return PTR_ERR(skb); return PTR_ERR(skb);
}
return msft_le_monitor_advertisement_cb(hdev, hdev->msft_opcode, return msft_le_monitor_advertisement_cb(hdev, hdev->msft_opcode,
monitor, skb); monitor, skb);
......
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