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: hci_event: move wake reason storage into validated event handlers

hci_store_wake_reason() is called from hci_event_packet() immediately
after stripping the HCI event header but before hci_event_func()
enforces the per-event minimum payload length from hci_ev_table.
This means a short HCI event frame can reach bacpy() before any bounds
check runs.

Rather than duplicating skb parsing and per-event length checks inside
hci_store_wake_reason(), move wake-address storage into the individual
event handlers after their existing event-length validation has
succeeded. Convert hci_store_wake_reason() into a small helper that only
stores an already-validated bdaddr while the caller holds hci_dev_lock().
Use the same helper after hci_event_func() with a NULL address to
preserve the existing unexpected-wake fallback semantics when no
validated event handler records a wake address.

Annotate the helper with __must_hold(&hdev->lock) and add
lockdep_assert_held(&hdev->lock) so future call paths keep the lock
contract explicit.

Call the helper from hci_conn_request_evt(), hci_conn_complete_evt(),
hci_sync_conn_complete_evt(), le_conn_complete_evt(),
hci_le_adv_report_evt(), hci_le_ext_adv_report_evt(),
hci_le_direct_adv_report_evt(), hci_le_pa_sync_established_evt(), and
hci_le_past_received_evt().

Fixes: 2f20216c1d6f ("Bluetooth: Emit controller suspend and resume events")
Cc: stable@vger.kernel.org
Signed-off-by: Oleh Konko <security@1seal.org>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

authored by

Oleh Konko and committed by
Luiz Augusto von Dentz
2b2bf47c 8a5b0135

+35 -59
+35 -59
net/bluetooth/hci_event.c
··· 80 80 return data; 81 81 } 82 82 83 + static void hci_store_wake_reason(struct hci_dev *hdev, 84 + const bdaddr_t *bdaddr, u8 addr_type) 85 + __must_hold(&hdev->lock); 86 + 83 87 static u8 hci_cc_inquiry_cancel(struct hci_dev *hdev, void *data, 84 88 struct sk_buff *skb) 85 89 { ··· 3115 3111 bt_dev_dbg(hdev, "status 0x%2.2x", status); 3116 3112 3117 3113 hci_dev_lock(hdev); 3114 + hci_store_wake_reason(hdev, &ev->bdaddr, BDADDR_BREDR); 3118 3115 3119 3116 /* Check for existing connection: 3120 3117 * ··· 3278 3273 __u8 flags = 0; 3279 3274 3280 3275 bt_dev_dbg(hdev, "bdaddr %pMR type 0x%x", &ev->bdaddr, ev->link_type); 3276 + 3277 + hci_dev_lock(hdev); 3278 + hci_store_wake_reason(hdev, &ev->bdaddr, BDADDR_BREDR); 3279 + hci_dev_unlock(hdev); 3281 3280 3282 3281 /* Reject incoming connection from device with same BD ADDR against 3283 3282 * CVE-2020-26555 ··· 5030 5021 bt_dev_dbg(hdev, "status 0x%2.2x", status); 5031 5022 5032 5023 hci_dev_lock(hdev); 5024 + hci_store_wake_reason(hdev, &ev->bdaddr, BDADDR_BREDR); 5033 5025 5034 5026 conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 5035 5027 if (!conn) { ··· 5723 5713 int err; 5724 5714 5725 5715 hci_dev_lock(hdev); 5716 + hci_store_wake_reason(hdev, bdaddr, bdaddr_type); 5726 5717 5727 5718 /* All controllers implicitly stop advertising in the event of a 5728 5719 * connection, so ensure that the state bit is cleared. ··· 6016 6005 bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); 6017 6006 6018 6007 hci_dev_lock(hdev); 6008 + hci_store_wake_reason(hdev, &ev->bdaddr, ev->bdaddr_type); 6019 6009 6020 6010 hci_dev_clear_flag(hdev, HCI_PA_SYNC); 6021 6011 ··· 6415 6403 info->length + 1)) 6416 6404 break; 6417 6405 6406 + hci_store_wake_reason(hdev, &info->bdaddr, info->bdaddr_type); 6407 + 6418 6408 if (info->length <= max_adv_len(hdev)) { 6419 6409 rssi = info->data[info->length]; 6420 6410 process_adv_report(hdev, info->type, &info->bdaddr, ··· 6505 6491 info->length)) 6506 6492 break; 6507 6493 6494 + hci_store_wake_reason(hdev, &info->bdaddr, info->bdaddr_type); 6495 + 6508 6496 evt_type = __le16_to_cpu(info->type) & LE_EXT_ADV_EVT_TYPE_MASK; 6509 6497 legacy_evt_type = ext_evt_type_to_legacy(hdev, evt_type); 6510 6498 ··· 6552 6536 bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); 6553 6537 6554 6538 hci_dev_lock(hdev); 6539 + hci_store_wake_reason(hdev, &ev->bdaddr, ev->bdaddr_type); 6555 6540 6556 6541 hci_dev_clear_flag(hdev, HCI_PA_SYNC); 6557 6542 ··· 6850 6833 6851 6834 for (i = 0; i < ev->num; i++) { 6852 6835 struct hci_ev_le_direct_adv_info *info = &ev->info[i]; 6836 + 6837 + hci_store_wake_reason(hdev, &info->bdaddr, info->bdaddr_type); 6853 6838 6854 6839 process_adv_report(hdev, info->type, &info->bdaddr, 6855 6840 info->bdaddr_type, &info->direct_addr, ··· 7536 7517 return true; 7537 7518 } 7538 7519 7539 - static void hci_store_wake_reason(struct hci_dev *hdev, u8 event, 7540 - struct sk_buff *skb) 7520 + static void hci_store_wake_reason(struct hci_dev *hdev, 7521 + const bdaddr_t *bdaddr, u8 addr_type) 7522 + __must_hold(&hdev->lock) 7541 7523 { 7542 - struct hci_ev_le_advertising_info *adv; 7543 - struct hci_ev_le_direct_adv_info *direct_adv; 7544 - struct hci_ev_le_ext_adv_info *ext_adv; 7545 - const struct hci_ev_conn_complete *conn_complete = (void *)skb->data; 7546 - const struct hci_ev_conn_request *conn_request = (void *)skb->data; 7547 - 7548 - hci_dev_lock(hdev); 7524 + lockdep_assert_held(&hdev->lock); 7549 7525 7550 7526 /* If we are currently suspended and this is the first BT event seen, 7551 7527 * save the wake reason associated with the event. 7552 7528 */ 7553 7529 if (!hdev->suspended || hdev->wake_reason) 7554 - goto unlock; 7530 + return; 7531 + 7532 + if (!bdaddr) { 7533 + hdev->wake_reason = MGMT_WAKE_REASON_UNEXPECTED; 7534 + return; 7535 + } 7555 7536 7556 7537 /* Default to remote wake. Values for wake_reason are documented in the 7557 7538 * Bluez mgmt api docs. 7558 7539 */ 7559 7540 hdev->wake_reason = MGMT_WAKE_REASON_REMOTE_WAKE; 7560 - 7561 - /* Once configured for remote wakeup, we should only wake up for 7562 - * reconnections. It's useful to see which device is waking us up so 7563 - * keep track of the bdaddr of the connection event that woke us up. 7564 - */ 7565 - if (event == HCI_EV_CONN_REQUEST) { 7566 - bacpy(&hdev->wake_addr, &conn_request->bdaddr); 7567 - hdev->wake_addr_type = BDADDR_BREDR; 7568 - } else if (event == HCI_EV_CONN_COMPLETE) { 7569 - bacpy(&hdev->wake_addr, &conn_complete->bdaddr); 7570 - hdev->wake_addr_type = BDADDR_BREDR; 7571 - } else if (event == HCI_EV_LE_META) { 7572 - struct hci_ev_le_meta *le_ev = (void *)skb->data; 7573 - u8 subevent = le_ev->subevent; 7574 - u8 *ptr = &skb->data[sizeof(*le_ev)]; 7575 - u8 num_reports = *ptr; 7576 - 7577 - if ((subevent == HCI_EV_LE_ADVERTISING_REPORT || 7578 - subevent == HCI_EV_LE_DIRECT_ADV_REPORT || 7579 - subevent == HCI_EV_LE_EXT_ADV_REPORT) && 7580 - num_reports) { 7581 - adv = (void *)(ptr + 1); 7582 - direct_adv = (void *)(ptr + 1); 7583 - ext_adv = (void *)(ptr + 1); 7584 - 7585 - switch (subevent) { 7586 - case HCI_EV_LE_ADVERTISING_REPORT: 7587 - bacpy(&hdev->wake_addr, &adv->bdaddr); 7588 - hdev->wake_addr_type = adv->bdaddr_type; 7589 - break; 7590 - case HCI_EV_LE_DIRECT_ADV_REPORT: 7591 - bacpy(&hdev->wake_addr, &direct_adv->bdaddr); 7592 - hdev->wake_addr_type = direct_adv->bdaddr_type; 7593 - break; 7594 - case HCI_EV_LE_EXT_ADV_REPORT: 7595 - bacpy(&hdev->wake_addr, &ext_adv->bdaddr); 7596 - hdev->wake_addr_type = ext_adv->bdaddr_type; 7597 - break; 7598 - } 7599 - } 7600 - } else { 7601 - hdev->wake_reason = MGMT_WAKE_REASON_UNEXPECTED; 7602 - } 7603 - 7604 - unlock: 7605 - hci_dev_unlock(hdev); 7541 + bacpy(&hdev->wake_addr, bdaddr); 7542 + hdev->wake_addr_type = addr_type; 7606 7543 } 7607 7544 7608 7545 #define HCI_EV_VL(_op, _func, _min_len, _max_len) \ ··· 7805 7830 7806 7831 skb_pull(skb, HCI_EVENT_HDR_SIZE); 7807 7832 7808 - /* Store wake reason if we're suspended */ 7809 - hci_store_wake_reason(hdev, event, skb); 7810 - 7811 7833 bt_dev_dbg(hdev, "event 0x%2.2x", event); 7812 7834 7813 7835 hci_event_func(hdev, event, skb, &opcode, &status, &req_complete, 7814 7836 &req_complete_skb); 7837 + 7838 + hci_dev_lock(hdev); 7839 + hci_store_wake_reason(hdev, NULL, 0); 7840 + hci_dev_unlock(hdev); 7815 7841 7816 7842 if (req_complete) { 7817 7843 req_complete(hdev, status, opcode);