* [PATCH net] nfc: hci: add bounds checking in nfc_hci_create_pipe()
@ 2026-09-12 11:57 Liu Chao
2026-09-16 1:00 ` netdev-bot+sashiko
0 siblings, 1 reply; 3+ messages in thread
From: Liu Chao @ 2026-09-12 11:57 UTC (permalink / raw)
To: David Heidelberg
Cc: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Dan Carpenter, oe-linux-nfc, netdev, linux-kernel,
Liu Chao, stable
The "pipe" value comes from the controller ADM_CREATE_PIPE response
and can be anything in the 0-255 range, while hdev->pipes[] only has
NFC_HCI_MAX_PIPES (128) entries. A response carrying a pipe id above
127 makes the caller, nfc_hci_connect_gate(), write past the end of
hdev->pipes[].
The response length is also not validated before the cast to struct
hci_create_pipe_resp, so a short response leads to reading past the
end of the received data.
The notification path in nfc_hci_cmd_received() already validates both
the length and the pipe id for the very same structure; do the same
for the command response path. Set *result so that the caller does
not mistake a rejected pipe for success, which is why this differs
slightly from the NCI side fix, commit 110b43ef0534 ("NFC: nci: Add
bounds checking in nci_hci_create_pipe()").
Fixes: 118278f20aa8 ("NFC: hci: Add pipes table to reference them with a tuple {gate, host}")
Cc: stable@vger.kernel.org
Signed-off-by: Liu Chao <liuc63@xiaopeng.com>
---
net/nfc/hci/command.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/net/nfc/hci/command.c b/net/nfc/hci/command.c
index af6bacb3b..9c8bcb98b 100644
--- a/net/nfc/hci/command.c
+++ b/net/nfc/hci/command.c
@@ -225,10 +225,19 @@ static u8 nfc_hci_create_pipe(struct nfc_hci_dev *hdev, u8 dest_host,
if (*result < 0)
return NFC_HCI_INVALID_PIPE;
+ if (skb->len < sizeof(*resp)) {
+ kfree_skb(skb);
+ *result = -EPROTO;
+ return NFC_HCI_INVALID_PIPE;
+ }
resp = (struct hci_create_pipe_resp *)skb->data;
pipe = resp->pipe;
kfree_skb(skb);
+ if (pipe >= NFC_HCI_MAX_PIPES) {
+ *result = -EINVAL;
+ return NFC_HCI_INVALID_PIPE;
+ }
pr_debug("pipe created=%d\n", pipe);
return pipe;
base-commit: e6b6078ea1731b05b3b552497b3bce4bf8b014ae
--
2.50.1
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH net] nfc: hci: add bounds checking in nfc_hci_create_pipe() 2026-09-12 11:57 [PATCH net] nfc: hci: add bounds checking in nfc_hci_create_pipe() Liu Chao @ 2026-09-16 1:00 ` netdev-bot+sashiko 2026-09-18 12:38 ` Simon Horman 0 siblings, 1 reply; 3+ messages in thread From: netdev-bot+sashiko @ 2026-09-16 1:00 UTC (permalink / raw) To: liuc63 Cc: david, davem, edumazet, kuba, pabeni, horms, dan.carpenter, oe-linux-nfc, netdev, linux-kernel, stable Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: Critical: 0 · High: 1 (1) · Medium: 0 (1) · Low: 0 - [High] The patch validates the pipe id inside nfc_hci_create_pipe() only, but the out-of-bounds store the commit message names as the… Pre-existing issues: - [High] Incomplete fix for the same bug class: the ST NFC drivers still index hdev->pipes[NFC_HCI_MAX_PIPES] (128 entries) with a raw… - [Medium] hdev->pipes[] and hdev->gate2pipe[] are mutated from two contexts with no lock in common. -- nfc: hci: add bounds checking in nfc_hci_create_pipe() This adds a length check on the ADM_CREATE_PIPE response before casting it to struct hci_create_pipe_resp, and rejects pipe ids at or above NFC_HCI_MAX_PIPES in nfc_hci_create_pipe(). The result code is set so the caller does not treat a rejected pipe as success. > diff --git a/net/nfc/hci/command.c b/net/nfc/hci/command.c > index af6bacb3ba986..9c8bcb98b9677 100644 > --- a/net/nfc/hci/command.c > +++ b/net/nfc/hci/command.c > @@ -225,10 +225,19 @@ static u8 nfc_hci_create_pipe(struct nfc_hci_dev *hdev, u8 dest_host, > if (*result < 0) > return NFC_HCI_INVALID_PIPE; > > + if (skb->len < sizeof(*resp)) { > + kfree_skb(skb); > + *result = -EPROTO; > + return NFC_HCI_INVALID_PIPE; > + } > resp = (struct hci_create_pipe_resp *)skb->data; > pipe = resp->pipe; > kfree_skb(skb); > > + if (pipe >= NFC_HCI_MAX_PIPES) { > + *result = -EINVAL; > + return NFC_HCI_INVALID_PIPE; > + } [Severity: High] Does this placement actually cover the store named in the commit message? The changelog says: "A response carrying a pipe id above 127 makes the caller, nfc_hci_connect_gate(), write past the end of hdev->pipes[]." But nfc_hci_connect_gate() also receives a pipe id directly as an argument, and in that case nfc_hci_create_pipe() is never called: net/nfc/hci/command.c:nfc_hci_connect_gate() { if (pipe == NFC_HCI_DO_NOT_CREATE_PIPE) return 0; ... if (pipe != NFC_HCI_INVALID_PIPE) goto open_pipe; ... open_pipe: r = nfc_hci_open_pipe(hdev, pipe); ... hdev->pipes[pipe].gate = dest_gate; hdev->pipes[pipe].dest_host = dest_host; hdev->gate2pipe[dest_gate] = pipe; } Only 0x81 (NFC_HCI_DO_NOT_CREATE_PIPE) returns early and 0x80 (NFC_HCI_INVALID_PIPE) falls into the create path, so any value in 0x82..0xff takes the goto open_pipe branch and, once the controller ACKs ANY_OPEN_PIPE, writes two bytes at offset 2 * pipe in the 256-byte hdev->pipes[] array. Can that argument hold an out-of-range value? The ST driver stores the raw controller byte into init_data: drivers/nfc/st21nfca/core.c:st21nfca_hci_load_session() { ... hdev->init_data.gates[j].pipe = pipe_info[2]; ... } hdev->init_data is assigned once in nfc_hci_allocate_device() and is never re-initialized, and the session-id-mismatch branch of hci_dev_session_init() calls nfc_hci_disconnect_all_gates() (which resets gate2pipe[], removing the -EADDRINUSE early return) before replaying those ids: net/nfc/hci/core.c:hci_dev_session_init() { ... r = nfc_hci_disconnect_all_gates(hdev); if (r < 0) goto exit; r = hci_dev_connect_gates(hdev, hdev->init_data.gate_count, hdev->init_data.gates); ... } net/nfc/hci/core.c:hci_dev_connect_gates() { ... r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID, gates->gate, gates->pipe); ... } Would it be better to validate at the write site in nfc_hci_connect_gate(), or in a single helper used by both paths, so the out-of-bounds store the changelog describes is actually closed? [Severity: High] This isn't a bug introduced by this patch, but the same two defect classes still exist in the ST NFC drivers, which index the same 128-entry hdev->pipes[] array with a raw controller byte. In st21nfca_hci_load_session(), the index comes straight from the ST21NFCA_DM_GETINFO pipe list: drivers/nfc/st21nfca/core.c:st21nfca_hci_load_session() { ... pipe_info[2] = skb_pipe_list->data[i]; ... hdev->pipes[pipe_info[2]].gate = st21nfca_gates[j].gate; hdev->pipes[pipe_info[2]].dest_host = info->src_host_id; ... } struct nfc_hci_pipe is two bytes, so an index of 128..255 stores at byte offset 256..510 in a 256-byte array, first overwriting the sw_/hw_ version fields and the async_cb / async_cb_context function pointers of the kzalloc()'d struct nfc_hci_dev and then running past the allocation. st_nci_hci_load_session() has the identical pattern writing ndev->hci_dev->pipes[pipe_info[2]]. The missing length check is there too. Both drivers cast the DM_GETINFO response to a five-byte struct and read all five fields without requiring skb_pipe_info->len >= sizeof(*info): drivers/nfc/st21nfca/core.c:st21nfca_hci_load_session() { ... info = (struct st21nfca_pipe_info *) skb_pipe_info->data; ... } drivers/nfc/st-nci/se.c:st_nci_hci_load_session() { ... dm_pipe_info = (struct st_nci_pipe_info *) skb_pipe_info->data; ... } Since this series is fixing exactly these two problems for the ADM_CREATE_PIPE response, would it make sense to cover the load_session paths as well? [Severity: Medium] This is a pre-existing issue and not something this patch changes, but hdev->pipes[] and hdev->gate2pipe[] are updated from two contexts with no lock in common, which is worth noting since the newly validated pipe id feeds one of them. The command path writes them from process context after nfc_hci_execute_cmd() has already dropped msg_tx_mutex: net/nfc/hci/command.c:nfc_hci_connect_gate() { ... hdev->pipes[pipe].gate = dest_gate; hdev->pipes[pipe].dest_host = dest_host; hdev->gate2pipe[dest_gate] = pipe; ... } The notification path writes and clears the same entries from the nfc_hci_msg_rx_work work item without taking any lock: net/nfc/hci/core.c:nfc_hci_cmd_received() { ... hdev->gate2pipe[create_info->dest_gate] = create_info->pipe; hdev->pipes[create_info->pipe].gate = create_info->dest_gate; hdev->pipes[create_info->pipe].dest_host = create_info->src_host; ... } With an empty lockset intersection, can a controller-driven ADM_NOTIFY_PIPE_DELETED or ADM_NOTIFY_ALL_PIPE_CLEARED interleave with the three-field update above and leave gate2pipe[] pointing at an entry marked NFC_HCI_INVALID_GATE, or a live pipes[] entry with no gate mapping? Later dispatch reads gate = hdev->pipes[pipe].gate in nfc_hci_event_received(), so the effect would be mis-routed or dropped events and leaked pipe state rather than memory corruption, since both writers do bound their indices. > pr_debug("pipe created=%d\n", pipe); > > return pipe; -- Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260912115720.530715-1-liuc63%40xiaopeng.com ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH net] nfc: hci: add bounds checking in nfc_hci_create_pipe() 2026-09-16 1:00 ` netdev-bot+sashiko @ 2026-09-18 12:38 ` Simon Horman 0 siblings, 0 replies; 3+ messages in thread From: Simon Horman @ 2026-09-18 12:38 UTC (permalink / raw) To: netdev-bot+sashiko Cc: liuc63, david, davem, edumazet, kuba, pabeni, dan.carpenter, oe-linux-nfc, netdev, linux-kernel, stable On Wed, Sep 16, 2026 at 01:00:25AM +0000, netdev-bot+sashiko@kernel.org wrote: > Thank you for your contribution! Sashiko AI review found 1 potential > issue(s) to consider: Hi Liu, There is an expectation that AI-generated reviews forwarded to the netdev ML are responded to. That can take a variety of forms including an email response that agrees with or refutes the review, or an updated version of the patch with an appropriate changelog. The expectation is the patch author or submitter handles this. But in order to move things along, in this case I've taken a look over it. > > Critical: 0 · High: 1 (1) · Medium: 0 (1) · Low: 0 > > - [High] The patch validates the pipe id inside nfc_hci_create_pipe() > only, but the out-of-bounds store the commit message names as the… > > Pre-existing issues: > - [High] Incomplete fix for the same bug class: the ST NFC drivers still > index hdev->pipes[NFC_HCI_MAX_PIPES] (128 entries) with a raw… > - [Medium] hdev->pipes[] and hdev->gate2pipe[] are mutated from two > contexts with no lock in common. > > -- > > nfc: hci: add bounds checking in nfc_hci_create_pipe() > > This adds a length check on the ADM_CREATE_PIPE response before casting it > to struct hci_create_pipe_resp, and rejects pipe ids at or above > NFC_HCI_MAX_PIPES in nfc_hci_create_pipe(). The result code is set so the > caller does not treat a rejected pipe as success. > > > diff --git a/net/nfc/hci/command.c b/net/nfc/hci/command.c > > index af6bacb3ba986..9c8bcb98b9677 100644 > > --- a/net/nfc/hci/command.c > > +++ b/net/nfc/hci/command.c > > @@ -225,10 +225,19 @@ static u8 nfc_hci_create_pipe(struct nfc_hci_dev *hdev, u8 dest_host, > > if (*result < 0) > > return NFC_HCI_INVALID_PIPE; > > > > + if (skb->len < sizeof(*resp)) { > > + kfree_skb(skb); > > + *result = -EPROTO; > > + return NFC_HCI_INVALID_PIPE; > > + } > > resp = (struct hci_create_pipe_resp *)skb->data; > > pipe = resp->pipe; > > kfree_skb(skb); > > > > + if (pipe >= NFC_HCI_MAX_PIPES) { > > + *result = -EINVAL; > > + return NFC_HCI_INVALID_PIPE; > > + } > > [Severity: High] > > Does this placement actually cover the store named in the commit message? > The changelog says: > > "A response carrying a pipe id above 127 makes the caller, > nfc_hci_connect_gate(), write past the end of hdev->pipes[]." > > But nfc_hci_connect_gate() also receives a pipe id directly as an argument, > and in that case nfc_hci_create_pipe() is never called: > > net/nfc/hci/command.c:nfc_hci_connect_gate() { > if (pipe == NFC_HCI_DO_NOT_CREATE_PIPE) > return 0; > ... > if (pipe != NFC_HCI_INVALID_PIPE) > goto open_pipe; > ... > open_pipe: > r = nfc_hci_open_pipe(hdev, pipe); > ... > hdev->pipes[pipe].gate = dest_gate; > hdev->pipes[pipe].dest_host = dest_host; > hdev->gate2pipe[dest_gate] = pipe; > } > > Only 0x81 (NFC_HCI_DO_NOT_CREATE_PIPE) returns early and 0x80 > (NFC_HCI_INVALID_PIPE) falls into the create path, so any value in > 0x82..0xff takes the goto open_pipe branch and, once the controller ACKs > ANY_OPEN_PIPE, writes two bytes at offset 2 * pipe in the 256-byte > hdev->pipes[] array. > > Can that argument hold an out-of-range value? The ST driver stores the raw > controller byte into init_data: > > drivers/nfc/st21nfca/core.c:st21nfca_hci_load_session() { > ... > hdev->init_data.gates[j].pipe = pipe_info[2]; > ... > } > > hdev->init_data is assigned once in nfc_hci_allocate_device() and is never > re-initialized, and the session-id-mismatch branch of > hci_dev_session_init() calls nfc_hci_disconnect_all_gates() (which resets > gate2pipe[], removing the -EADDRINUSE early return) before replaying those > ids: > > net/nfc/hci/core.c:hci_dev_session_init() { > ... > r = nfc_hci_disconnect_all_gates(hdev); > if (r < 0) > goto exit; > > r = hci_dev_connect_gates(hdev, hdev->init_data.gate_count, > hdev->init_data.gates); > ... > } > > net/nfc/hci/core.c:hci_dev_connect_gates() { > ... > r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID, > gates->gate, gates->pipe); > ... > } > > Would it be better to validate at the write site in nfc_hci_connect_gate(), > or in a single helper used by both paths, so the out-of-bounds store the > changelog describes is actually closed? This does seem to be a valid concern and I suggest handling it by add validation to nfc_hci_connect_gate() rather than nfc_hci_create_pipe(). > > [Severity: High] > > This isn't a bug introduced by this patch, but the same two defect classes > still exist in the ST NFC drivers, which index the same 128-entry > hdev->pipes[] array with a raw controller byte. I think that this is orthogonal to the purpose of this patch and should be treated as a separate issue; I don't think it needs to affect progress of this patch. ... > [Severity: Medium] > > This is a pre-existing issue and not something this patch changes, but > hdev->pipes[] and hdev->gate2pipe[] are updated from two contexts with no > lock in common, which is worth noting since the newly validated pipe id > feeds one of them. Ditto. ... -- pw-bot: changes-requested ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-09-18 12:38 UTC | newest] Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-09-12 11:57 [PATCH net] nfc: hci: add bounds checking in nfc_hci_create_pipe() Liu Chao 2026-09-16 1:00 ` netdev-bot+sashiko 2026-09-18 12:38 ` Simon Horman
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®