diff options
Diffstat (limited to 'net/bluetooth/hci_event.c')
| -rw-r--r-- | net/bluetooth/hci_event.c | 26 | 
1 files changed, 19 insertions, 7 deletions
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index cfeaee347db3..af9d7f2ff8ba 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1338,6 +1338,9 @@ static void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr,  {  	struct discovery_state *d = &hdev->discovery; +	if (len > HCI_MAX_AD_LENGTH) +		return; +  	bacpy(&d->last_adv_addr, bdaddr);  	d->last_adv_addr_type = bdaddr_type;  	d->last_adv_rssi = rssi; @@ -5355,7 +5358,8 @@ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,  static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,  			       u8 bdaddr_type, bdaddr_t *direct_addr, -			       u8 direct_addr_type, s8 rssi, u8 *data, u8 len) +			       u8 direct_addr_type, s8 rssi, u8 *data, u8 len, +			       bool ext_adv)  {  	struct discovery_state *d = &hdev->discovery;  	struct smp_irk *irk; @@ -5377,6 +5381,11 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,  		return;  	} +	if (!ext_adv && len > HCI_MAX_AD_LENGTH) { +		bt_dev_err_ratelimited(hdev, "legacy adv larger than 31 bytes"); +		return; +	} +  	/* Find the end of the data in case the report contains padded zero  	 * bytes at the end causing an invalid length value.  	 * @@ -5437,7 +5446,7 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,  	 */  	conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, type,  								direct_addr); -	if (conn && type == LE_ADV_IND) { +	if (!ext_adv && conn && type == LE_ADV_IND && len <= HCI_MAX_AD_LENGTH) {  		/* Store report for later inclusion by  		 * mgmt_device_connected  		 */ @@ -5491,7 +5500,7 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,  	 * event or send an immediate device found event if the data  	 * should not be stored for later.  	 */ -	if (!has_pending_adv_report(hdev)) { +	if (!ext_adv &&	!has_pending_adv_report(hdev)) {  		/* If the report will trigger a SCAN_REQ store it for  		 * later merging.  		 */ @@ -5526,7 +5535,8 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,  		/* If the new report will trigger a SCAN_REQ store it for  		 * later merging.  		 */ -		if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) { +		if (!ext_adv && (type == LE_ADV_IND || +				 type == LE_ADV_SCAN_IND)) {  			store_pending_adv_report(hdev, bdaddr, bdaddr_type,  						 rssi, flags, data, len);  			return; @@ -5566,7 +5576,7 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)  			rssi = ev->data[ev->length];  			process_adv_report(hdev, ev->evt_type, &ev->bdaddr,  					   ev->bdaddr_type, NULL, 0, rssi, -					   ev->data, ev->length); +					   ev->data, ev->length, false);  		} else {  			bt_dev_err(hdev, "Dropping invalid advertising data");  		} @@ -5638,7 +5648,8 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)  		if (legacy_evt_type != LE_ADV_INVALID) {  			process_adv_report(hdev, legacy_evt_type, &ev->bdaddr,  					   ev->bdaddr_type, NULL, 0, ev->rssi, -					   ev->data, ev->length); +					   ev->data, ev->length, +					   !(evt_type & LE_EXT_ADV_LEGACY_PDU));  		}  		ptr += sizeof(*ev) + ev->length; @@ -5836,7 +5847,8 @@ static void hci_le_direct_adv_report_evt(struct hci_dev *hdev,  		process_adv_report(hdev, ev->evt_type, &ev->bdaddr,  				   ev->bdaddr_type, &ev->direct_addr, -				   ev->direct_addr_type, ev->rssi, NULL, 0); +				   ev->direct_addr_type, ev->rssi, NULL, 0, +				   false);  		ptr += sizeof(*ev);  	}  | 
