mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: netdev-bot+sashiko@kernel.org
To: joasantonio108@gmail.com
Cc: david@ixit.cz, davem@davemloft.net, edumazet@kernel.org,
	kuba@kernel.org, pabeni@redhat.com, horms@kernel.org,
	kipreyyy@gmail.com, sanghyun.park.cnu@gmail.com,
	oe-linux-nfc@lists.linux.dev, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH net 3/5] nfc: nci: consume the loopback response exactly once
Date: Mon, 02 Nov 2026 23:43:45 +0000	[thread overview]
Message-ID: <179366302585.488856.12804499169587262096@kernel.org> (raw)
In-Reply-To: <179331585573.30322.5511229003943288914@gmail.com>

Thank you for your contribution! Sashiko AI review found 3 potential
issue(s) to consider.

Critical: 0 · High: 1 · Medium: 2 · Low: 0

If you believe none of the issues are legitimate, please reply to each
issue of Medium severity or higher and explain why the AI is wrong.
If any of them are legitimate and you plan to respin, please let patchwork
know by including "pw-bot: cr" as a separate line at the end of your reply
(one such reply per series is enough).

- [High] nci_nfcc_loopback() (net/nfc/nci/core.c) can still use or write
  freed memory.
- [Medium] The patch consumes conn_info->rx_skb only when nci_request()
  returns NCI_STATUS_OK.
- [Medium] The read-then-clear the patch adds to nci_nfcc_loopback()
  (core.c:471-472, `rx_skb = conn_info->rx_skb; conn_info->rx_skb =…

--

nfc: nci: consume the loopback response exactly once

This patch changes nci_nfcc_loopback() so that, after a successful
nci_request(), it detaches conn_info->rx_skb before using it. The skb is
freed if the caller passed no resp pointer, and -EPROTO is returned if the
request completed without a data packet. The goal is to fix a
use-after-free and double free that happen when a stray zero-status NCI
response completes a loopback request.

> diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
> index 73e3a96470ace..8e2a755ce2555 100644
> --- a/net/nfc/nci/core.c
> +++ b/net/nfc/nci/core.c

[ ... ]

> @@ -464,8 +464,20 @@ int nci_nfcc_loopback(struct nci_dev *ndev, const void *data, size_t data_len,
>  	ndev->cur_conn_id = conn_id;
>  	r = nci_request(ndev, nci_send_data_req, &loopback_data,
>  			msecs_to_jiffies(NCI_DATA_TIMEOUT));
> -	if (r == NCI_STATUS_OK && resp)
> -		*resp = conn_info->rx_skb;
> +	if (r == NCI_STATUS_OK) {

[Severity: Medium]
Can a stale rx_skb from an earlier loopback still be returned here?

The rx_skb is only consumed when nci_request() returns NCI_STATUS_OK.
Nothing clears or frees conn_info->rx_skb before the new request is sent.
The same is true on the -ETIMEDOUT, -ERESTARTSYS and non-zero status
paths.

data_exchange_cb is never cleared. nci_data_exchange_complete() checks
NCI_DATA_EXCHANGE only for the static RF connection:

net/nfc/nci/data.c:nci_data_exchange_complete() {
    ...
	if (conn_id == NCI_STATIC_RF_CONN_ID &&
	    !test_and_clear_bit(NCI_DATA_EXCHANGE, &ndev->flags)) {
    ...
}

Suppose loopback #1 times out and its data packet arrives late.
nci_nfcc_loopback_cb() still stores the packet:

	conn_info->rx_skb = skb;

Suppose loopback #2 is then completed by a stray zero-status response,
like the CORE_SET_CONFIG_RSP in the commit message. Wouldn't this code
return the skb from loopback #1 as the reply to loopback #2?
st_nci_loopback() would then copy that skb's data to userspace.

If the real data for loopback #2 arrives instead, nci_nfcc_loopback_cb()
overwrites rx_skb without freeing it. Does that leak the late skb?

nci_core_conn_close_rsp_packet() and nci_unregister_device() also drop
conn_info without freeing any skb still stored in rx_skb.

st21nfca_hci_loopback(), by comparison, clears its rx_skb before it sends.
Could conn_info->rx_skb be freed and cleared before nci_request() here,
and on the error paths too?

> +		/* Consume the stored data packet exactly once, see
> +		 * nci_nfcc_loopback_cb().
> +		 */
> +		rx_skb = conn_info->rx_skb;
> +		conn_info->rx_skb = NULL;

[Severity: High]
Is conn_info still valid at this point?

conn_info is looked up before the blocking nci_request() call, and
ndev->cur_conn_id is set to the loopback conn_id. While the request is
pending, the NFCC can send an unsolicited CORE_CONN_CLOSE_RSP with
status 0. nci_rsp_packet() picks the handler by opcode only, and the
handler does:

net/nfc/nci/rsp.c:nci_core_conn_close_rsp_packet() {
    ...
	if (status == NCI_STATUS_OK) {
		conn_info = nci_get_conn_info_by_conn_id(ndev,
							 ndev->cur_conn_id);
		if (conn_info) {
			list_del(&conn_info->list);
			...
			devm_kfree(&ndev->nfc_dev->dev, conn_info->dest_params);
			devm_kfree(&ndev->nfc_dev->dev, conn_info);
		}
	}
	nci_req_complete(ndev, status);
}

That completes the loopback request with NCI_STATUS_OK. The code above then
reads rx_skb from freed memory, and with this patch it also writes NULL
into that memory.

If the slab object has been reused, could the new NULL store corrupt the
new owner? If the read returns a non-NULL value, st_nci_loopback() would
read skb->len and skb->data and then call kfree_skb() on it. That is the
same skb use-after-free and double free the commit message describes.

Would it be safer to look up conn_info again after nci_request() returns,
or to check that the completing response belongs to this request?

[Severity: Medium]
Can this read-then-clear race with nci_nfcc_loopback_cb()?

These are two plain accesses, and they share no lock with the code that
stores rx_skb. nci_nfcc_loopback_cb() runs from rx_work and doesn't take
req_lock:

	conn_info->rx_skb = skb;

	nci_req_complete(ndev, NCI_STATUS_OK);

In the case this patch targets, a stray zero-status response completes
the request first. rx_work can then handle the real loopback data packet
while the woken caller is in this code:

caller                                rx_work
rx_skb = conn_info->rx_skb; /* NULL */
                                      conn_info->rx_skb = skb;
conn_info->rx_skb = NULL;
return -EPROTO;

Does that leak the skb stored by the callback? This is also an unlocked
race on a plain pointer, which KCSAN would report.

> +		if (!rx_skb)
> +			return -EPROTO;

[ ... ]

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/179331585573.30322.4049957541187612575%40gmail.com

  reply	other threads:[~2026-11-02 23:43 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-29 23:17 [PATCH net 0/5] nfc: fix HCI over NCI and NFCC loopback response handling Joas Antonio dos Santos
2026-10-29 23:17 ` [PATCH net 4/5] nfc: st21nfca: validate pipe ids in st21nfca_hci_load_session() Joas Antonio dos Santos
2026-10-29 23:17 ` [PATCH net 5/5] nfc: st-nci: validate pipe ids in st_nci_hci_load_session() Joas Antonio dos Santos
2026-10-29 23:17 ` [PATCH net 3/5] nfc: nci: consume the loopback response exactly once Joas Antonio dos Santos
2026-11-02 23:43   ` netdev-bot+sashiko [this message]
2026-10-29 23:17 ` [PATCH net 2/5] nfc: nci: hci: consume the HCP " Joas Antonio dos Santos
2026-11-02 23:43   ` netdev-bot+sashiko
2026-10-29 23:17 ` [PATCH net 1/5] nfc: nci: don't drop data received on HCI and loopback connections Joas Antonio dos Santos
2026-11-02 23:43   ` netdev-bot+sashiko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=179366302585.488856.12804499169587262096@kernel.org \
    --to=netdev-bot+sashiko@kernel.org \
    --cc=davem@davemloft.net \
    --cc=david@ixit.cz \
    --cc=edumazet@kernel.org \
    --cc=horms@kernel.org \
    --cc=joasantonio108@gmail.com \
    --cc=kipreyyy@gmail.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=oe-linux-nfc@lists.linux.dev \
    --cc=pabeni@redhat.com \
    --cc=sanghyun.park.cnu@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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®