mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: netdev-bot+sashiko@kernel.org
To: liuc63@xiaopeng.com
Cc: david@ixit.cz, edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, horms@kernel.org, davem@davemloft.net,
	oe-linux-nfc@lists.linux.dev, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, stable@vger.kernel.org
Subject: Re: [PATCH net 2/2] nfc: digital: check resp length in digital_tg_send_atr_res_complete()
Date: Wed, 16 Sep 2026 12:19:54 +0000	[thread overview]
Message-ID: <178956119445.22033.18320417961342899452@kernel.org> (raw)
In-Reply-To: <20260912131852.1651462-3-liuc63@xiaopeng.com>

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

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

- [Medium] The commit message's justification ("The downstream handlers
  (digital_tg_recv_psl_req, digital_tg_recv_dep_req) each have their own…

Pre-existing issues:
- [Medium] Sibling instance of the same unchecked-length read remains in
  the same file: digital_in_recv_dep_res() reads resp->data[0] as the…
- [Medium] Frame-format disagreement kept (and re-written) by the patch:
  digital_tg_send_atr_res_complete() derives the SoD presence from the…

--

nfc: digital: check resp length in digital_tg_send_atr_res_complete()

This adds a resp->len check to digital_tg_send_atr_res_complete() before
reading resp->data[0] and resp->data[offset], and frees the skb and
restarts polling when the frame is too short.

A few questions below.

> nfc: digital: check resp length in digital_tg_send_atr_res_complete()
>
>     The downstream handlers (digital_tg_recv_psl_req, digital_tg_recv_dep_req)
>     each have their own length checks, so the consequence is a misdirected
>     dispatch on stale data rather than memory corruption.

[Severity: Medium]
Is this statement accurate for digital_tg_recv_dep_req()?  That handler
validates only resp->len >= sizeof(struct digital_dep_req_res), i.e. 3
bytes (dir, cmd, pfb), and then reads byte 3 before any further length
test:

net/nfc/digital_dep.c:digital_tg_recv_dep_req() {
	...
	size = sizeof(struct digital_dep_req_res);
	dep_req = (struct digital_dep_req_res *)resp->data;

	if (resp->len < size || dep_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
	    dep_req->cmd != DIGITAL_CMD_DEP_REQ) {
		rc = -EIO;
		goto exit;
	}

	pfb = dep_req->pfb;

	if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb)) {
		if (ddev->did && (ddev->did == resp->data[3])) {
	...
}

The "if (size > resp->len)" test that would cover byte 3 runs only after
that comparison, so it does not guard the read.

The precondition is a nonzero ddev->did, which the remote peer sets in
digital_tg_recv_atr_req():

	ddev->did = atr_req->did;

so a peer that negotiates a DID and then sends a 3-byte DEP_REQ payload
with the DID bit set in PFB makes digital_tg_recv_dep_req() read
resp->data[3] one byte past resp->len.  Should the check also be extended
there, or should the changelog drop the claim that the downstream handlers
cover this?

> diff --git a/net/nfc/digital_dep.c b/net/nfc/digital_dep.c
> index 6d8e662a3819a..5093b7b817202 100644
> --- a/net/nfc/digital_dep.c
> +++ b/net/nfc/digital_dep.c
> @@ -1467,16 +1467,19 @@ static void digital_tg_recv_psl_req(struct nfc_digital_dev *ddev, void *arg,
>  static void digital_tg_send_atr_res_complete(struct nfc_digital_dev *ddev,
>  					     void *arg, struct sk_buff *resp)
>  {
> -	int offset;
> +	unsigned int offset;
>  
>  	if (IS_ERR(resp)) {
>  		digital_poll_next_tech(ddev);
>  		return;
>  	}
>  
> -	offset = 2;
> -	if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB)
> -		offset++;
> +	if (!resp->len)
> +		goto bad_frame;
> +
> +	offset = (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB) ? 3 : 2;
> +	if (resp->len <= offset)
> +		goto bad_frame;

[Severity: Medium]
This isn't a bug introduced by this patch, since the byte-value heuristic
is only reformatted into a ternary here, but while this offset computation
is being rewritten, would it be better to derive the SoD presence from
ddev->curr_rf_tech the way the encoder/decoder pair does?

net/nfc/digital_dep.c:digital_skb_push_dep_sod() {
	if (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A)
		*(u8 *)skb_push(skb, sizeof(u8)) = DIGITAL_NFC_DEP_NFCA_SOD_SB;
}

net/nfc/digital_dep.c:digital_skb_pull_dep_sod() {
	if (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A)
		skb_pull(skb, sizeof(u8));
}

In 212F/424F target mode there is no SB byte, so data[0] is the LEN byte.
Can a LEN of 0xF0 (240, legal since local_payload_max is
DIGITAL_PAYLOAD_SIZE_MAX) make this pick offset 3 and read the PFB byte as
the command byte?

DIGITAL_CMD_PSL_REQ is 0x04 and DIGITAL_NFC_DEP_PFB_DID_BIT is also 0x04,
so a first DEP_REQ (I-PDU, PNI 0, DID in use) of exactly that size would
have PFB == 0x04 and be dispatched to digital_tg_recv_psl_req(), which
then drops it:

net/nfc/digital_dep.c:digital_tg_recv_psl_req() {
	if (resp->len != sizeof(struct digital_psl_req) ||
	...
		rc = -EIO;
		goto exit;
	}
}

Does that stall the DEP session, since the frame is freed with no reply?
The new bounds check is computed from the same offset, so it inherits the
disagreement.

>  
>  	ddev->atn_count = 0;
>  
> @@ -1484,6 +1487,12 @@ static void digital_tg_recv_psl_req(struct nfc_digital_dev *ddev, void *arg,
>  		digital_tg_recv_psl_req(ddev, arg, resp);
>  	else
>  		digital_tg_recv_dep_req(ddev, arg, resp);
> +
> +	return;
> +
> +bad_frame:
> +	kfree_skb(resp);
> +	digital_poll_next_tech(ddev);
>  }

[Severity: Medium]
This is a pre-existing issue and not introduced by this patch, but there
is a sibling unchecked read of the same kind in the same file, in
digital_in_recv_dep_res().  Would it make sense to cover it in the same
series?

net/nfc/digital_dep.c:digital_in_recv_dep_res() {
	...
	if (size > resp->len) {
		rc = -EIO;
		goto error;
	}

	skb_pull(resp, size);
	...
	case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
	...
		rtox = DIGITAL_NFC_DEP_RTOX_VALUE(resp->data[0]);
}

With a 3-byte DEP_RES payload (dir, cmd, pfb and no DID/NAD bit), size is
3, so both "resp->len < size" and "size > resp->len" pass, and the
skb_pull() leaves resp->len == 0.  The SUPERVISOR_PDU plus timeout-bit
branch then reads resp->data[0] one byte past resp->len and feeds the
masked value to digital_in_send_rtox() as a timeout.  Both ddev->atn_count
and ddev->nack_count are zeroed just above, so the branch is reachable.

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260912131852.1651462-1-liuc63%40xiaopeng.com

      reply	other threads:[~2026-09-16 12:19 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-12 13:18 [PATCH net 0/2] nfc: digital: fix two bugs in NFC-DEP chaining and frame handling Liu Chao
2026-09-12 13:18 ` [PATCH net 1/2] nfc: digital: reserve proper headroom for chaining_skb Liu Chao
2026-09-16 12:19   ` netdev-bot+sashiko
2026-09-12 13:18 ` [PATCH net 2/2] nfc: digital: check resp length in digital_tg_send_atr_res_complete() Liu Chao
2026-09-16 12:19   ` netdev-bot+sashiko [this message]

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=178956119445.22033.18320417961342899452@kernel.org \
    --to=netdev-bot+sashiko@kernel.org \
    --cc=davem@davemloft.net \
    --cc=david@ixit.cz \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=liuc63@xiaopeng.com \
    --cc=netdev@vger.kernel.org \
    --cc=oe-linux-nfc@lists.linux.dev \
    --cc=pabeni@redhat.com \
    --cc=stable@vger.kernel.org \
    /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®