Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Bluetooth: fix kernel oops in store_pending_adv_report

Fix kernel oops observed when an ext adv data is larger than 31 bytes.

This can be reproduced by setting up an advertiser with advertisement
larger than 31 bytes. The issue is not sensitive to the advertisement
content. In particular, this was reproduced with an advertisement of
229 bytes filled with 'A'. See stack trace below.

This is fixed by not catching ext_adv as legacy adv are only cached to
be able to concatenate a scanable adv with its scan response before
sending it up through mgmt.

With ext_adv, this is no longer necessary.

general protection fault: 0000 [#1] SMP PTI
CPU: 6 PID: 205 Comm: kworker/u17:0 Not tainted 5.4.0-37-generic #41-Ubuntu
Hardware name: Dell Inc. XPS 15 7590/0CF6RR, BIOS 1.7.0 05/11/2020
Workqueue: hci0 hci_rx_work [bluetooth]
RIP: 0010:hci_bdaddr_list_lookup+0x1e/0x40 [bluetooth]
Code: ff ff e9 26 ff ff ff 0f 1f 44 00 00 0f 1f 44 00 00 55 48 8b 07 48 89 e5 48 39 c7 75 0a eb 24 48 8b 00 48 39 f8 74 1c 44 8b 06 <44> 39 40 10 75 ef 44 0f b7 4e 04 66 44 39 48 14 75 e3 38 50 16 75
RSP: 0018:ffffbc6a40493c70 EFLAGS: 00010286
RAX: 4141414141414141 RBX: 000000000000001b RCX: 0000000000000000
RDX: 0000000000000000 RSI: ffff9903e76c100f RDI: ffff9904289d4b28
RBP: ffffbc6a40493c70 R08: 0000000093570362 R09: 0000000000000000
R10: 0000000000000000 R11: ffff9904344eae38 R12: ffff9904289d4000
R13: 0000000000000000 R14: 00000000ffffffa3 R15: ffff9903e76c100f
FS: 0000000000000000(0000) GS:ffff990434580000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007feed125a000 CR3: 00000001b860a003 CR4: 00000000003606e0
Call Trace:
process_adv_report+0x12e/0x560 [bluetooth]
hci_le_meta_evt+0x7b2/0xba0 [bluetooth]
hci_event_packet+0x1c29/0x2a90 [bluetooth]
hci_rx_work+0x19b/0x360 [bluetooth]
process_one_work+0x1eb/0x3b0
worker_thread+0x4d/0x400
kthread+0x104/0x140

Fixes: c215e9397b00 ("Bluetooth: Process extended ADV report event")
Reported-by: Andy Nguyen <theflow@google.com>
Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
Reported-by: Balakrishna Godavarthi <bgodavar@codeaurora.org>
Signed-off-by: Alain Michaud <alainm@chromium.org>
Tested-by: Sonny Sasaka <sonnysasaka@chromium.org>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Alain Michaud and committed by
Linus Torvalds
a2ec905d 417385c4

+19 -7
+19 -7
net/bluetooth/hci_event.c
··· 1338 1338 { 1339 1339 struct discovery_state *d = &hdev->discovery; 1340 1340 1341 + if (len > HCI_MAX_AD_LENGTH) 1342 + return; 1343 + 1341 1344 bacpy(&d->last_adv_addr, bdaddr); 1342 1345 d->last_adv_addr_type = bdaddr_type; 1343 1346 d->last_adv_rssi = rssi; ··· 5358 5355 5359 5356 static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, 5360 5357 u8 bdaddr_type, bdaddr_t *direct_addr, 5361 - u8 direct_addr_type, s8 rssi, u8 *data, u8 len) 5358 + u8 direct_addr_type, s8 rssi, u8 *data, u8 len, 5359 + bool ext_adv) 5362 5360 { 5363 5361 struct discovery_state *d = &hdev->discovery; 5364 5362 struct smp_irk *irk; ··· 5378 5374 default: 5379 5375 bt_dev_err_ratelimited(hdev, "unknown advertising packet " 5380 5376 "type: 0x%02x", type); 5377 + return; 5378 + } 5379 + 5380 + if (!ext_adv && len > HCI_MAX_AD_LENGTH) { 5381 + bt_dev_err_ratelimited(hdev, "legacy adv larger than 31 bytes"); 5381 5382 return; 5382 5383 } 5383 5384 ··· 5446 5437 */ 5447 5438 conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, type, 5448 5439 direct_addr); 5449 - if (conn && type == LE_ADV_IND) { 5440 + if (!ext_adv && conn && type == LE_ADV_IND && len <= HCI_MAX_AD_LENGTH) { 5450 5441 /* Store report for later inclusion by 5451 5442 * mgmt_device_connected 5452 5443 */ ··· 5500 5491 * event or send an immediate device found event if the data 5501 5492 * should not be stored for later. 5502 5493 */ 5503 - if (!has_pending_adv_report(hdev)) { 5494 + if (!ext_adv && !has_pending_adv_report(hdev)) { 5504 5495 /* If the report will trigger a SCAN_REQ store it for 5505 5496 * later merging. 5506 5497 */ ··· 5535 5526 /* If the new report will trigger a SCAN_REQ store it for 5536 5527 * later merging. 5537 5528 */ 5538 - if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) { 5529 + if (!ext_adv && (type == LE_ADV_IND || 5530 + type == LE_ADV_SCAN_IND)) { 5539 5531 store_pending_adv_report(hdev, bdaddr, bdaddr_type, 5540 5532 rssi, flags, data, len); 5541 5533 return; ··· 5576 5566 rssi = ev->data[ev->length]; 5577 5567 process_adv_report(hdev, ev->evt_type, &ev->bdaddr, 5578 5568 ev->bdaddr_type, NULL, 0, rssi, 5579 - ev->data, ev->length); 5569 + ev->data, ev->length, false); 5580 5570 } else { 5581 5571 bt_dev_err(hdev, "Dropping invalid advertising data"); 5582 5572 } ··· 5648 5638 if (legacy_evt_type != LE_ADV_INVALID) { 5649 5639 process_adv_report(hdev, legacy_evt_type, &ev->bdaddr, 5650 5640 ev->bdaddr_type, NULL, 0, ev->rssi, 5651 - ev->data, ev->length); 5641 + ev->data, ev->length, 5642 + !(evt_type & LE_EXT_ADV_LEGACY_PDU)); 5652 5643 } 5653 5644 5654 5645 ptr += sizeof(*ev) + ev->length; ··· 5847 5836 5848 5837 process_adv_report(hdev, ev->evt_type, &ev->bdaddr, 5849 5838 ev->bdaddr_type, &ev->direct_addr, 5850 - ev->direct_addr_type, ev->rssi, NULL, 0); 5839 + ev->direct_addr_type, ev->rssi, NULL, 0, 5840 + false); 5851 5841 5852 5842 ptr += sizeof(*ev); 5853 5843 }