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

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

 - eir: Fix NULL pointer deference on eir_get_service_data
 - eir: Fix possible crashes on eir_create_adv_data
 - hci_sync: Fix broadcast/PA when using an existing instance
 - ISO: Fix using BT_SK_PA_SYNC to detect BIS sockets
 - ISO: Fix not using bc_sid as advertisement SID
 - MGMT: Fix sparse errors

* tag 'for-net-2025-06-11' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth:
  Bluetooth: MGMT: Fix sparse errors
  Bluetooth: ISO: Fix not using bc_sid as advertisement SID
  Bluetooth: ISO: Fix using BT_SK_PA_SYNC to detect BIS sockets
  Bluetooth: eir: Fix possible crashes on eir_create_adv_data
  Bluetooth: hci_sync: Fix broadcast/PA when using an existing instance
  Bluetooth: Fix NULL pointer deference on eir_get_service_data
====================

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


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 43fb2b30 7dd38ba4
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -242,6 +242,7 @@ struct adv_info {
	__u8	mesh;
	__u8	instance;
	__u8	handle;
	__u8	sid;
	__u32	flags;
	__u16	timeout;
	__u16	remaining_time;
@@ -1551,13 +1552,14 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
				 u16 timeout);
struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst,
			      __u8 dst_type, struct bt_iso_qos *qos);
struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst,
struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, __u8 sid,
			      struct bt_iso_qos *qos,
			      __u8 base_len, __u8 *base);
struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
				 __u8 dst_type, struct bt_iso_qos *qos);
struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst,
				 __u8 dst_type, struct bt_iso_qos *qos,
				 __u8 dst_type, __u8 sid,
				 struct bt_iso_qos *qos,
				 __u8 data_len, __u8 *data);
struct hci_conn *hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst,
		       __u8 dst_type, __u8 sid, struct bt_iso_qos *qos);
@@ -1832,6 +1834,7 @@ int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,

void hci_adv_instances_clear(struct hci_dev *hdev);
struct adv_info *hci_find_adv_instance(struct hci_dev *hdev, u8 instance);
struct adv_info *hci_find_adv_sid(struct hci_dev *hdev, u8 sid);
struct adv_info *hci_get_next_instance(struct hci_dev *hdev, u8 instance);
struct adv_info *hci_add_adv_instance(struct hci_dev *hdev, u8 instance,
				      u32 flags, u16 adv_data_len, u8 *adv_data,
@@ -1839,7 +1842,7 @@ struct adv_info *hci_add_adv_instance(struct hci_dev *hdev, u8 instance,
				      u16 timeout, u16 duration, s8 tx_power,
				      u32 min_interval, u32 max_interval,
				      u8 mesh_handle);
struct adv_info *hci_add_per_instance(struct hci_dev *hdev, u8 instance,
struct adv_info *hci_add_per_instance(struct hci_dev *hdev, u8 instance, u8 sid,
				      u32 flags, u8 data_len, u8 *data,
				      u32 min_interval, u32 max_interval);
int hci_set_adv_instance_data(struct hci_dev *hdev, u8 instance,
+2 −2
Original line number Diff line number Diff line
@@ -115,8 +115,8 @@ int hci_enable_ext_advertising_sync(struct hci_dev *hdev, u8 instance);
int hci_enable_advertising_sync(struct hci_dev *hdev);
int hci_enable_advertising(struct hci_dev *hdev);

int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 data_len,
			   u8 *data, u32 flags, u16 min_interval,
int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 sid,
			   u8 data_len, u8 *data, u32 flags, u16 min_interval,
			   u16 max_interval, u16 sync_interval);

int hci_disable_per_advertising_sync(struct hci_dev *hdev, u8 instance);
+10 −7
Original line number Diff line number Diff line
@@ -242,7 +242,7 @@ u8 eir_create_per_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
	return ad_len;
}

u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr, u8 size)
{
	struct adv_info *adv = NULL;
	u8 ad_len = 0, flags = 0;
@@ -286,7 +286,7 @@ u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
		/* If flags would still be empty, then there is no need to
		 * include the "Flags" AD field".
		 */
		if (flags) {
		if (flags && (ad_len + eir_precalc_len(1) <= size)) {
			ptr[0] = 0x02;
			ptr[1] = EIR_FLAGS;
			ptr[2] = flags;
@@ -316,7 +316,8 @@ u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
		}

		/* Provide Tx Power only if we can provide a valid value for it */
		if (adv_tx_power != HCI_TX_POWER_INVALID) {
		if (adv_tx_power != HCI_TX_POWER_INVALID &&
		    (ad_len + eir_precalc_len(1) <= size)) {
			ptr[0] = 0x02;
			ptr[1] = EIR_TX_POWER;
			ptr[2] = (u8)adv_tx_power;
@@ -366,17 +367,19 @@ u8 eir_create_scan_rsp(struct hci_dev *hdev, u8 instance, u8 *ptr)

void *eir_get_service_data(u8 *eir, size_t eir_len, u16 uuid, size_t *len)
{
	while ((eir = eir_get_data(eir, eir_len, EIR_SERVICE_DATA, len))) {
	size_t dlen;

	while ((eir = eir_get_data(eir, eir_len, EIR_SERVICE_DATA, &dlen))) {
		u16 value = get_unaligned_le16(eir);

		if (uuid == value) {
			if (len)
				*len -= 2;
				*len = dlen - 2;
			return &eir[2];
		}

		eir += *len;
		eir_len -= *len;
		eir += dlen;
		eir_len -= dlen;
	}

	return NULL;
+1 −1
Original line number Diff line number Diff line
@@ -9,7 +9,7 @@

void eir_create(struct hci_dev *hdev, u8 *data);

u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr);
u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr, u8 size);
u8 eir_create_scan_rsp(struct hci_dev *hdev, u8 instance, u8 *ptr);
u8 eir_create_per_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr);

+24 −7
Original line number Diff line number Diff line
@@ -1501,8 +1501,8 @@ static int qos_set_bis(struct hci_dev *hdev, struct bt_iso_qos *qos)

/* This function requires the caller holds hdev->lock */
static struct hci_conn *hci_add_bis(struct hci_dev *hdev, bdaddr_t *dst,
				    struct bt_iso_qos *qos, __u8 base_len,
				    __u8 *base)
				    __u8 sid, struct bt_iso_qos *qos,
				    __u8 base_len, __u8 *base)
{
	struct hci_conn *conn;
	int err;
@@ -1543,6 +1543,7 @@ static struct hci_conn *hci_add_bis(struct hci_dev *hdev, bdaddr_t *dst,
		return conn;

	conn->state = BT_CONNECT;
	conn->sid = sid;

	hci_conn_hold(conn);
	return conn;
@@ -2062,7 +2063,8 @@ static int create_big_sync(struct hci_dev *hdev, void *data)
	if (qos->bcast.bis)
		sync_interval = interval * 4;

	err = hci_start_per_adv_sync(hdev, qos->bcast.bis, conn->le_per_adv_data_len,
	err = hci_start_per_adv_sync(hdev, qos->bcast.bis, conn->sid,
				     conn->le_per_adv_data_len,
				     conn->le_per_adv_data, flags, interval,
				     interval, sync_interval);
	if (err)
@@ -2134,7 +2136,7 @@ static void create_big_complete(struct hci_dev *hdev, void *data, int err)
	}
}

struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst,
struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, __u8 sid,
			      struct bt_iso_qos *qos,
			      __u8 base_len, __u8 *base)
{
@@ -2156,7 +2158,7 @@ struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst,
						   base, base_len);

	/* We need hci_conn object using the BDADDR_ANY as dst */
	conn = hci_add_bis(hdev, dst, qos, base_len, eir);
	conn = hci_add_bis(hdev, dst, sid, qos, base_len, eir);
	if (IS_ERR(conn))
		return conn;

@@ -2207,20 +2209,35 @@ static void bis_mark_per_adv(struct hci_conn *conn, void *data)
}

struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst,
				 __u8 dst_type, struct bt_iso_qos *qos,
				 __u8 dst_type, __u8 sid,
				 struct bt_iso_qos *qos,
				 __u8 base_len, __u8 *base)
{
	struct hci_conn *conn;
	int err;
	struct iso_list_data data;

	conn = hci_bind_bis(hdev, dst, qos, base_len, base);
	conn = hci_bind_bis(hdev, dst, sid, qos, base_len, base);
	if (IS_ERR(conn))
		return conn;

	if (conn->state == BT_CONNECTED)
		return conn;

	/* Check if SID needs to be allocated then search for the first
	 * available.
	 */
	if (conn->sid == HCI_SID_INVALID) {
		u8 sid;

		for (sid = 0; sid <= 0x0f; sid++) {
			if (!hci_find_adv_sid(hdev, sid)) {
				conn->sid = sid;
				break;
			}
		}
	}

	data.big = qos->bcast.big;
	data.bis = qos->bcast.bis;

Loading