Commit 3491bb7d authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files
Luiz Augusto von Dentz says:

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

 - Fix build after header cleanup
 - hci_sync: Fix hci_resume_advertising_sync
 - hci_event: Fix UAF in hci_conn_tx_dequeue
 - hci_event: Fix UAF in hci_acl_create_conn_sync
 - MGMT: Fix possible UAFs

* tag 'for-net-2025-09-22' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth:
  Bluetooth: MGMT: Fix possible UAFs
  Bluetooth: hci_event: Fix UAF in hci_acl_create_conn_sync
  Bluetooth: hci_event: Fix UAF in hci_conn_tx_dequeue
  Bluetooth: hci_sync: Fix hci_resume_advertising_sync
  Bluetooth: Fix build after header cleanup
====================

Link: https://patch.msgid.link/20250922143315.3007176-1-luiz.dentz@gmail.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 207b45e8 302a1f67
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -312,7 +312,9 @@ config BT_HCIBCM4377

config BT_HCIBPA10X
	tristate "HCI BPA10x USB driver"
	depends on BT_HCIUART
	depends on USB
	select BT_HCIUART_H4
	help
	  Bluetooth HCI BPA10x USB driver.
	  This driver provides support for the Digianswer BPA 100/105 Bluetooth
@@ -437,8 +439,10 @@ config BT_MTKSDIO

config BT_MTKUART
	tristate "MediaTek HCI UART driver"
	depends on BT_HCIUART
	depends on SERIAL_DEV_BUS
	depends on USB || !BT_HCIBTUSB_MTK
	select BT_HCIUART_H4
	select BT_MTK
	help
	  MediaTek Bluetooth HCI UART driver.
@@ -483,7 +487,9 @@ config BT_VIRTIO

config BT_NXPUART
	tristate "NXP protocol support"
	depends on BT_HCIUART
	depends on SERIAL_DEV_BUS
	select BT_HCIUART_H4
	select CRC32
	select CRC8
	help
+4 −4
Original line number Diff line number Diff line
@@ -121,10 +121,6 @@ void hci_uart_set_flow_control(struct hci_uart *hu, bool enable);
void hci_uart_set_speeds(struct hci_uart *hu, unsigned int init_speed,
			 unsigned int oper_speed);

#ifdef CONFIG_BT_HCIUART_H4
int h4_init(void);
int h4_deinit(void);

struct h4_recv_pkt {
	u8  type;	/* Packet type */
	u8  hlen;	/* Header length */
@@ -162,6 +158,10 @@ struct h4_recv_pkt {
	.lsize = 2, \
	.maxlen = HCI_MAX_FRAME_SIZE \

#ifdef CONFIG_BT_HCIUART_H4
int h4_init(void);
int h4_deinit(void);

struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb,
			    const unsigned char *buffer, int count,
			    const struct h4_recv_pkt *pkts, int pkts_count);
+21 −0
Original line number Diff line number Diff line
@@ -1245,6 +1245,27 @@ static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev,
	return NULL;
}

static inline struct hci_conn *hci_conn_hash_lookup_role(struct hci_dev *hdev,
							 __u8 type, __u8 role,
							 bdaddr_t *ba)
{
	struct hci_conn_hash *h = &hdev->conn_hash;
	struct hci_conn  *c;

	rcu_read_lock();

	list_for_each_entry_rcu(c, &h->list, list) {
		if (c->type == type && c->role == role && !bacmp(&c->dst, ba)) {
			rcu_read_unlock();
			return c;
		}
	}

	rcu_read_unlock();

	return NULL;
}

static inline struct hci_conn *hci_conn_hash_lookup_le(struct hci_dev *hdev,
						       bdaddr_t *ba,
						       __u8 ba_type)
+27 −3
Original line number Diff line number Diff line
@@ -3087,8 +3087,18 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,

	hci_dev_lock(hdev);

	/* Check for existing connection:
	 *
	 * 1. If it doesn't exist then it must be receiver/slave role.
	 * 2. If it does exist confirm that it is connecting/BT_CONNECT in case
	 *    of initiator/master role since there could be a collision where
	 *    either side is attempting to connect or something like a fuzzing
	 *    testing is trying to play tricks to destroy the hcon object before
	 *    it even attempts to connect (e.g. hcon->state == BT_OPEN).
	 */
	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
	if (!conn) {
	if (!conn ||
	    (conn->role == HCI_ROLE_MASTER && conn->state != BT_CONNECT)) {
		/* In case of error status and there is no connection pending
		 * just unlock as there is nothing to cleanup.
		 */
@@ -4391,6 +4401,8 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data,

	bt_dev_dbg(hdev, "num %d", ev->num);

	hci_dev_lock(hdev);

	for (i = 0; i < ev->num; i++) {
		struct hci_comp_pkts_info *info = &ev->handles[i];
		struct hci_conn *conn;
@@ -4472,6 +4484,8 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data,
	}

	queue_work(hdev->workqueue, &hdev->tx_work);

	hci_dev_unlock(hdev);
}

static void hci_mode_change_evt(struct hci_dev *hdev, void *data,
@@ -5634,8 +5648,18 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
	 */
	hci_dev_clear_flag(hdev, HCI_LE_ADV);

	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, bdaddr);
	if (!conn) {
	/* Check for existing connection:
	 *
	 * 1. If it doesn't exist then use the role to create a new object.
	 * 2. If it does exist confirm that it is connecting/BT_CONNECT in case
	 *    of initiator/master role since there could be a collision where
	 *    either side is attempting to connect or something like a fuzzing
	 *    testing is trying to play tricks to destroy the hcon object before
	 *    it even attempts to connect (e.g. hcon->state == BT_OPEN).
	 */
	conn = hci_conn_hash_lookup_role(hdev, LE_LINK, role, bdaddr);
	if (!conn ||
	    (conn->role == HCI_ROLE_MASTER && conn->state != BT_CONNECT)) {
		/* In case of error status and there is no connection pending
		 * just unlock as there is nothing to cleanup.
		 */
+7 −0
Original line number Diff line number Diff line
@@ -2594,6 +2594,13 @@ static int hci_resume_advertising_sync(struct hci_dev *hdev)
			hci_remove_ext_adv_instance_sync(hdev, adv->instance,
							 NULL);
		}

		/* If current advertising instance is set to instance 0x00
		 * then we need to re-enable it.
		 */
		if (!hdev->cur_adv_instance)
			err = hci_enable_ext_advertising_sync(hdev,
							      hdev->cur_adv_instance);
	} else {
		/* Schedule for most recent instance to be restarted and begin
		 * the software rotation loop
Loading