FAILED: patch "[PATCH] Bluetooth: hci_event: move wake reason storage into validated" failed to apply to 6.12-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.12.y
git checkout FETCH_HEAD
git cherry-pick -x 2b2bf47cd75518c36fa2d41380e4a40641cc89cd
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026040703-universal-spool-dbb7@gregkh' --subject-prefix 'PATCH 6.12.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 2b2bf47cd75518c36fa2d41380e4a40641cc89cd Mon Sep 17 00:00:00 2001
From: Oleh Konko <[email protected]>
Date: Thu, 26 Mar 2026 17:31:24 +0000
Subject: [PATCH] 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().
net/bluetooth/hci_event.c +35 -59
@@ -80,6 +80,10 @@ static void *hci_le_ev_skb_pull(struct hci_dev *hdev, struct sk_buff *skb,return data; } +static void hci_store_wake_reason(struct hci_dev *hdev, + const bdaddr_t *bdaddr, u8 addr_type) + __must_hold(&hdev->lock); +static u8 hci_cc_inquiry_cancel (struct hci_dev *hdev,void *data,struct sk_buff *skb) {
@@ -3111,6 +3115,7 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,bt_dev_dbg (hdev,"status 0x%2.2x" , status);hci_dev_lock (hdev); +hci_store_wake_reason (hdev, &ev->bdaddr,BDADDR_BREDR );/* Check for existing connection: *
@@ -3274,6 +3279,10 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data,bt_dev_dbg (hdev,"bdaddr %pMR type 0x%x" , &ev->bdaddr, ev->link_type); +hci_dev_lock (hdev); +hci_store_wake_reason (hdev, &ev->bdaddr,BDADDR_BREDR ); +hci_dev_unlock (hdev); +/* Reject incoming connection from device with same BD ADDR against * CVE-2020-26555 */
@@ -5021,6 +5030,7 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,bt_dev_dbg (hdev,"status 0x%2.2x" , status);hci_dev_lock (hdev); +hci_store_wake_reason (hdev, &ev->bdaddr,BDADDR_BREDR ); conn =hci_conn_hash_lookup_ba (hdev, ev->link_type, &ev->bdaddr);if (!conn) {
@@ -5713,6 +5723,7 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,int err;hci_dev_lock (hdev); +hci_store_wake_reason (hdev, bdaddr, bdaddr_type);/* All controllers implicitly stop advertising in the event of a * connection, so ensure that the state bit is cleared.
@@ -6005,6 +6016,7 @@ static void hci_le_past_received_evt(struct hci_dev *hdev, void *data,bt_dev_dbg (hdev,"status 0x%2.2x" , ev->status);hci_dev_lock (hdev); +hci_store_wake_reason (hdev, &ev->bdaddr, ev->bdaddr_type);hci_dev_clear_flag (hdev,HCI_PA_SYNC );
@@ -6403,6 +6415,8 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, void *data, info->length + 1))break ; +hci_store_wake_reason (hdev, &info->bdaddr, info->bdaddr_type); +if (info->length <=max_adv_len (hdev)) { rssi = info->data[info->length]; process_adv_report(hdev, info->type, &info->bdaddr,
@@ -6491,6 +6505,8 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, void *data, info->length))break ; +hci_store_wake_reason (hdev, &info->bdaddr, info->bdaddr_type); + evt_type =__le16_to_cpu (info->type) &LE_EXT_ADV_EVT_TYPE_MASK ; legacy_evt_type =ext_evt_type_to_legacy (hdev, evt_type);
@@ -6536,6 +6552,7 @@ static void hci_le_pa_sync_established_evt(struct hci_dev *hdev, void *data,bt_dev_dbg (hdev,"status 0x%2.2x" , ev->status);hci_dev_lock (hdev); +hci_store_wake_reason (hdev, &ev->bdaddr, ev->bdaddr_type);hci_dev_clear_flag (hdev,HCI_PA_SYNC );
@@ -6834,6 +6851,8 @@ static void hci_le_direct_adv_report_evt(struct hci_dev *hdev, void *data,for (i =0 ; i < ev->num; i++) {struct hci_ev_le_direct_adv_info *info = &ev->info[i]; +hci_store_wake_reason (hdev, &info->bdaddr, info->bdaddr_type); + process_adv_report(hdev, info->type, &info->bdaddr, info->bdaddr_type, &info->direct_addr, info->direct_addr_type, HCI_ADV_PHY_1M, 0,
@@ -7517,73 +7536,29 @@ static bool hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode,return true; } -static void hci_store_wake_reason (struct hci_dev *hdev,u8 event, -struct sk_buff *skb) +static void hci_store_wake_reason (struct hci_dev *hdev, +const bdaddr_t *bdaddr,u8 addr_type) + __must_hold(&hdev->lock) { -struct hci_ev_le_advertising_info *adv; -struct hci_ev_le_direct_adv_info *direct_adv; -struct hci_ev_le_ext_adv_info *ext_adv; -const struct hci_ev_conn_complete *conn_complete = (void *)skb->data; -const struct hci_ev_conn_request *conn_request = (void *)skb->data; - -hci_dev_lock (hdev); +lockdep_assert_held (&hdev->lock);/* If we are currently suspended and this is the first BT event seen, * save the wake reason associated with the event. */ if (!hdev->suspended || hdev->wake_reason) - goto unlock; +return ; + +if (!bdaddr) { + hdev->wake_reason =MGMT_WAKE_REASON_UNEXPECTED ; +return ; + }/* Default to remote wake. Values for wake_reason are documented in the * Bluez mgmt api docs. */ hdev->wake_reason =MGMT_WAKE_REASON_REMOTE_WAKE ; - -/* Once configured for remote wakeup, we should only wake up for -* reconnections. It's useful to see which device is waking us up so -* keep track of the bdaddr of the connection event that woke us up. -*/ -if (event ==HCI_EV_CONN_REQUEST ) { -bacpy (&hdev->wake_addr, &conn_request->bdaddr); - hdev->wake_addr_type =BDADDR_BREDR ; - }else if (event ==HCI_EV_CONN_COMPLETE ) { -bacpy (&hdev->wake_addr, &conn_complete->bdaddr); - hdev->wake_addr_type =BDADDR_BREDR ; - }else if (event ==HCI_EV_LE_META ) { -struct hci_ev_le_meta *le_ev = (void *)skb->data; -u8 subevent = le_ev->subevent; -u8 *ptr = &skb->data[sizeof (*le_ev)]; -u8 num_reports = *ptr; - -if ((subevent ==HCI_EV_LE_ADVERTISING_REPORT || - subevent ==HCI_EV_LE_DIRECT_ADV_REPORT || - subevent ==HCI_EV_LE_EXT_ADV_REPORT ) && - num_reports) { - adv = (void *)(ptr +1 ); - direct_adv = (void *)(ptr +1 ); - ext_adv = (void *)(ptr +1 ); - -switch (subevent) { -case HCI_EV_LE_ADVERTISING_REPORT : -bacpy (&hdev->wake_addr, &adv->bdaddr); - hdev->wake_addr_type = adv->bdaddr_type; -break ; -case HCI_EV_LE_DIRECT_ADV_REPORT : -bacpy (&hdev->wake_addr, &direct_adv->bdaddr); - hdev->wake_addr_type = direct_adv->bdaddr_type; -break ; -case HCI_EV_LE_EXT_ADV_REPORT : -bacpy (&hdev->wake_addr, &ext_adv->bdaddr); - hdev->wake_addr_type = ext_adv->bdaddr_type; -break ; - } - } - }else { - hdev->wake_reason =MGMT_WAKE_REASON_UNEXPECTED ; - } - -unlock: -hci_dev_unlock (hdev); +bacpy (&hdev->wake_addr, bdaddr); + hdev->wake_addr_type = addr_type; }#define HCI_EV_VL (_op, _func, _min_len, _max_len) \
@@ -7830,14 +7805,15 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)skb_pull (skb,HCI_EVENT_HDR_SIZE ); -/* Store wake reason if we're suspended */ -hci_store_wake_reason (hdev, event, skb); -bt_dev_dbg (hdev,"event 0x%2.2x" , event);hci_event_func (hdev, event, skb, &opcode, &status, &req_complete, &req_complete_skb); +hci_dev_lock (hdev); +hci_store_wake_reason (hdev,NULL ,0 ); +hci_dev_unlock (hdev); +if (req_complete) {req_complete (hdev, status, opcode); }else if (req_complete_skb) {