From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3351C3D6CB6 for ; Wed, 15 Jul 2026 23:55:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784159734; cv=none; b=kPFJaFz8zJOCzfwWy86C1TVGZAeoLNvWtXpf+kb8tw+EzseaX7yNIqfoFv1OnOSV9HGEyULrIkJpZrlnPN7DOld8HL7leCX7O7fKY1dDI2jmDqrF9gDo67iIVFHl7Ts5kCU22cerGobjSGdjVZ9m2vQhsexKzYJi4goI/BQktYw= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784159734; c=relaxed/simple; bh=q4YQKDWRv5iiznbGhwcojzUMfGj4UI+o6DKm4M6V0V0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CuFJivfYjqy1pIPhiJvUXEaTE5FCWl4kO3IIt3jkQ5Lh5OiSqBrhHtEaP7r1Pbu+YW9SKrzvj/qSTtS/qoyHWGEfFj+PymM3XA6aadXuL0rZrnf84CnBvGSlr+85yS8kWecXpl0vZn+mu8BtLWYDRqKsL0sTCRRbkKJIikTTx8g= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Dnwy9TCS; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Dnwy9TCS" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 97DC51F00A3D; Wed, 15 Jul 2026 23:55:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784159733; bh=wWZHK0bZEaLi56b5I4vFP9tLnLe6a5T9PLr6k0OlCl8=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Dnwy9TCSA0QwfsYoBNlRWx80IflJNAyEfCfIN+vnEKYr7Qzz4eP4+NgKF4Flgywgq P/oz0Jk2GbvhTzIC70xFuNeiEuhOUJbobaeL83bHNmcbn245gsT6eQCkCcwWYY9Zu0 dA99AgVnptRLJ2w482Wjrs2lnRuBXr+AyJYlTVHICbH+ly+Uqi5eihvQ4MqmS9v8mI 9tpGHcA2um9uln54nsNnE2vuzovL8Nc6rLgZ+f3QCfz0gx9Eivc0K5DatTYWdzMKfF k0tzT5ZwvrRRsU7HcCOm0c9zvEW4eqXxttlqjS5bWHPtfGV2PHJwIMuVJa8wTO+L4C abQgUJX/i6C4g== From: Sasha Levin To: stable@vger.kernel.org Cc: Cen Zhang , Luiz Augusto von Dentz , Sasha Levin Subject: [PATCH 6.6.y 3/4] Bluetooth: hci_sync: annotate data-races around hdev->req_status Date: Wed, 15 Jul 2026 19:55:28 -0400 Message-ID: <20260715235529.525959-3-sashal@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260715235529.525959-1-sashal@kernel.org> References: <2026071350-agent-mustard-7408@gregkh> <20260715235529.525959-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: stable@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Cen Zhang [ Upstream commit b6807cfc195ef99e1ac37b2e1e60df40295daa8c ] __hci_cmd_sync_sk() sets hdev->req_status under hdev->req_lock: hdev->req_status = HCI_REQ_PEND; However, several other functions read or write hdev->req_status without holding any lock: - hci_send_cmd_sync() reads req_status in hci_cmd_work (workqueue) - hci_cmd_sync_complete() reads/writes from HCI event completion - hci_cmd_sync_cancel() / hci_cmd_sync_cancel_sync() read/write - hci_abort_conn() reads in connection abort path Since __hci_cmd_sync_sk() runs on hdev->req_workqueue while hci_send_cmd_sync() runs on hdev->workqueue, these are different workqueues that can execute concurrently on different CPUs. The plain C accesses constitute a data race. Add READ_ONCE()/WRITE_ONCE() annotations on all concurrent accesses to hdev->req_status to prevent potential compiler optimizations that could affect correctness (e.g., load fusing in the wait_event condition or store reordering). Signed-off-by: Cen Zhang Signed-off-by: Luiz Augusto von Dentz Stable-dep-of: 12917f591cea ("Bluetooth: hci_conn: Fix null ptr deref in hci_abort_conn()") Signed-off-by: Sasha Levin --- net/bluetooth/hci_core.c | 2 +- net/bluetooth/hci_sync.c | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index bc3230f59975ef..d9bb05f81f50e9 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -4060,7 +4060,7 @@ static void hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb) return; } - if (hci_req_status_pend(hdev) && + if (READ_ONCE(hdev->req_status) == HCI_REQ_PEND && !hci_dev_test_and_set_flag(hdev, HCI_CMD_PENDING)) { kfree_skb(hdev->req_skb); hdev->req_skb = skb_clone(hdev->sent_cmd, GFP_KERNEL); diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index 71a5346c38c1fd..6219c84b171b48 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -25,11 +25,11 @@ static void hci_cmd_sync_complete(struct hci_dev *hdev, u8 result, u16 opcode, { bt_dev_dbg(hdev, "result 0x%2.2x", result); - if (hdev->req_status != HCI_REQ_PEND) + if (READ_ONCE(hdev->req_status) != HCI_REQ_PEND) return; hdev->req_result = result; - hdev->req_status = HCI_REQ_DONE; + WRITE_ONCE(hdev->req_status, HCI_REQ_DONE); /* Free the request command so it is not used as response */ kfree_skb(hdev->req_skb); @@ -168,20 +168,20 @@ struct sk_buff *__hci_cmd_sync_sk(struct hci_dev *hdev, u16 opcode, u32 plen, hci_cmd_sync_add(&req, opcode, plen, param, event, sk); - hdev->req_status = HCI_REQ_PEND; + WRITE_ONCE(hdev->req_status, HCI_REQ_PEND); err = hci_req_sync_run(&req); if (err < 0) return ERR_PTR(err); err = wait_event_interruptible_timeout(hdev->req_wait_q, - hdev->req_status != HCI_REQ_PEND, + READ_ONCE(hdev->req_status) != HCI_REQ_PEND, timeout); if (err == -ERESTARTSYS) return ERR_PTR(-EINTR); - switch (hdev->req_status) { + switch (READ_ONCE(hdev->req_status)) { case HCI_REQ_DONE: err = -bt_to_errno(hdev->req_result); break; @@ -195,7 +195,7 @@ struct sk_buff *__hci_cmd_sync_sk(struct hci_dev *hdev, u16 opcode, u32 plen, break; } - hdev->req_status = 0; + WRITE_ONCE(hdev->req_status, 0); hdev->req_result = 0; skb = hdev->req_rsp; hdev->req_rsp = NULL; @@ -689,9 +689,9 @@ void hci_cmd_sync_cancel(struct hci_dev *hdev, int err) { bt_dev_dbg(hdev, "err 0x%2.2x", err); - if (hdev->req_status == HCI_REQ_PEND) { + if (READ_ONCE(hdev->req_status) == HCI_REQ_PEND) { hdev->req_result = err; - hdev->req_status = HCI_REQ_CANCELED; + WRITE_ONCE(hdev->req_status, HCI_REQ_CANCELED); queue_work(hdev->workqueue, &hdev->cmd_sync_cancel_work); } @@ -707,12 +707,12 @@ void hci_cmd_sync_cancel_sync(struct hci_dev *hdev, int err) { bt_dev_dbg(hdev, "err 0x%2.2x", err); - if (hdev->req_status == HCI_REQ_PEND) { + if (READ_ONCE(hdev->req_status) == HCI_REQ_PEND) { /* req_result is __u32 so error must be positive to be properly * propagated. */ hdev->req_result = err < 0 ? -err : err; - hdev->req_status = HCI_REQ_CANCELED; + WRITE_ONCE(hdev->req_status, HCI_REQ_CANCELED); wake_up_interruptible(&hdev->req_wait_q); } -- 2.53.0