Commit b8c3bf0e authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files
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.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 7a07a29e 1d1ab5d3
Loading
Loading
Loading
Loading
+12 −3
Original line number Diff line number Diff line
@@ -54,7 +54,10 @@ void aosp_do_open(struct hci_dev *hdev)
	/* LE Get Vendor Capabilities Command */
	skb = __hci_cmd_sync(hdev, hci_opcode_pack(0x3f, 0x153), 0, NULL,
			     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)",
			   PTR_ERR(skb));
		return;
@@ -152,7 +155,10 @@ static int enable_quality_report(struct hci_dev *hdev)

	skb = __hci_cmd_sync(hdev, BQR_OPCODE, sizeof(cp), &cp,
			     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)",
			   PTR_ERR(skb));
		return PTR_ERR(skb);
@@ -171,7 +177,10 @@ static int disable_quality_report(struct hci_dev *hdev)

	skb = __hci_cmd_sync(hdev, BQR_OPCODE, sizeof(cp), &cp,
			     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)",
			   PTR_ERR(skb));
		return PTR_ERR(skb);
+2 −9
Original line number Diff line number Diff line
@@ -1551,8 +1551,8 @@ static void cis_add(struct iso_list_data *d, struct bt_iso_qos *qos)
	cis->cis_id = qos->cis;
	cis->c_sdu  = cpu_to_le16(qos->out.sdu);
	cis->p_sdu  = cpu_to_le16(qos->in.sdu);
	cis->c_phy  = qos->out.phy;
	cis->p_phy  = qos->in.phy;
	cis->c_phy  = qos->out.phy ? qos->out.phy : qos->in.phy;
	cis->p_phy  = qos->in.phy ? qos->in.phy : qos->out.phy;
	cis->c_rtn  = qos->out.rtn;
	cis->p_rtn  = qos->in.rtn;

@@ -1735,13 +1735,6 @@ struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst,
	if (!qos->in.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)) {
		hci_conn_drop(cis);
		return ERR_PTR(-EINVAL);
+5 −2
Original line number Diff line number Diff line
@@ -328,14 +328,17 @@ static u8 hci_cc_delete_stored_link_key(struct hci_dev *hdev, void *data,
					struct sk_buff *skb)
{
	struct hci_rp_delete_stored_link_key *rp = data;
	u16 num_keys;

	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);

	if (rp->status)
		return rp->status;

	if (rp->num_keys <= hdev->stored_num_keys)
		hdev->stored_num_keys -= le16_to_cpu(rp->num_keys);
	num_keys = le16_to_cpu(rp->num_keys);

	if (num_keys <= hdev->stored_num_keys)
		hdev->stored_num_keys -= num_keys;
	else
		hdev->stored_num_keys = 0;

+23 −12
Original line number Diff line number Diff line
@@ -44,6 +44,9 @@ static void iso_sock_kill(struct sock *sk);
/* ----- ISO socket info ----- */
#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 bt_sock		bt;
	bdaddr_t		src;
@@ -57,7 +60,7 @@ struct iso_pinfo {
	__u32			flags;
	struct bt_iso_qos	qos;
	__u8			base_len;
	__u8			base[HCI_MAX_PER_AD_LENGTH];
	__u8			base[BASE_MAX_LENGTH];
	struct iso_conn		*conn;
};

@@ -370,15 +373,24 @@ static int iso_connect_cis(struct sock *sk)
	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)
{
	struct iso_conn *conn = iso_pi(sk)->conn;
	struct bt_iso_qos *qos = iso_sock_get_qos(sk);
	struct hci_iso_data_hdr *hdr;
	int len = 0;

	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;

	len = skb->len;
@@ -1177,8 +1189,10 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
		}

		len = min_t(unsigned int, sizeof(qos), optlen);
		if (len != sizeof(qos))
			return -EINVAL;
		if (len != sizeof(qos)) {
			err = -EINVAL;
			break;
		}

		memset(&qos, 0, sizeof(qos));

@@ -1233,7 +1247,7 @@ static int iso_sock_getsockopt(struct socket *sock, int level, int optname,
{
	struct sock *sk = sock->sk;
	int len, err = 0;
	struct bt_iso_qos qos;
	struct bt_iso_qos *qos;
	u8 base_len;
	u8 *base;

@@ -1246,7 +1260,7 @@ static int iso_sock_getsockopt(struct socket *sock, int level, int optname,

	switch (optname) {
	case BT_DEFER_SETUP:
		if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
		if (sk->sk_state == BT_CONNECTED) {
			err = -EINVAL;
			break;
		}
@@ -1258,13 +1272,10 @@ static int iso_sock_getsockopt(struct socket *sock, int level, int optname,
		break;

	case BT_ISO_QOS:
		if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONNECT2)
			qos = iso_pi(sk)->conn->hcon->iso_qos;
		else
			qos = iso_pi(sk)->qos;
		qos = iso_sock_get_qos(sk);

		len = min_t(unsigned int, len, sizeof(qos));
		if (copy_to_user(optval, (char *)&qos, len))
		len = min_t(unsigned int, len, sizeof(*qos));
		if (copy_to_user(optval, qos, len))
			err = -EFAULT;

		break;
+6 −7
Original line number Diff line number Diff line
@@ -1970,11 +1970,11 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
						   bdaddr_t *dst,
						   u8 link_type)
{
	struct l2cap_chan *c, *c1 = NULL;
	struct l2cap_chan *c, *tmp, *c1 = NULL;

	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)
			continue;

@@ -1993,12 +1993,11 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
			dst_match = !bacmp(&c->dst, dst);
			if (src_match && dst_match) {
				c = l2cap_chan_hold_unless_zero(c);
				if (!c)
					continue;

				if (c) {
					read_unlock(&chan_list_lock);
					return c;
				}
			}

			/* Closest match */
			src_any = !bacmp(&c->src, BDADDR_ANY);
Loading