All of lore.kernel.org
 help / color / mirror / Atom feed
From: Simon Horman <horms@kernel.org>
To: doruk@0sec.ai
Cc: Simon Horman <horms@kernel.org>,
	david@ixit.cz, oe-linux-nfc@lists.linux.dev,
	david.laight.linux@gmail.com, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, stable@vger.kernel.org
Subject: Re: [PATCH net] nfc: llcp: bound the remaining LLCP TLV parsers to their buffers
Date: Fri, 10 Jul 2026 14:48:50 +0100	[thread overview]
Message-ID: <20260710134850.1615092-1-horms@kernel.org> (raw)
In-Reply-To: <20260705115607.60844-1-doruk@0sec.ai>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://netdev-ai.bots.linux.dev/sashiko/
---
nfc: llcp: bound the remaining LLCP TLV parsers to their buffers

The commit adds pointer-based bounds to nfc_llcp_parse_gb_tlv(),
nfc_llcp_parse_connection_tlv() and nfc_llcp_connect_sn(), replacing
the previous u8 offset walk which could wrap and produce an unbounded
TLV loop. It cites the size_t underflow of "skb->len - LLCP_HEADER_SIZE"
as one of the failure modes it wants to close.

> diff --git a/net/nfc/llcp_commands.c b/net/nfc/llcp_commands.c
> index 291f26facbf3..1a0a2f4aca70 100644
> --- a/net/nfc/llcp_commands.c
> +++ b/net/nfc/llcp_commands.c

[ ... ]

> @@ -243,17 +246,21 @@ int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock,
>  				  const u8 *tlv_array, u16 tlv_array_len)
>  {
>  	const u8 *tlv = tlv_array;
> -	u8 type, length, offset = 0;
> +	const u8 *tlv_end = tlv_array + tlv_array_len;
> +	u8 type, length;
>  
>  	pr_debug("TLV array length %d\n", tlv_array_len);
>  
>  	if (sock == NULL)
>  		return -ENOTCONN;
>  
> -	while (offset < tlv_array_len) {
> +	while (tlv + 2 < tlv_end) {
>  		type = tlv[0];
>  		length = tlv[1];
>  
> +		if (tlv + 2 + length > tlv_end)
> +			break;
> +

[High]
Is the size_t underflow the commit message mentions actually addressed
for nfc_llcp_parse_connection_tlv()?

The two callers, nfc_llcp_recv_connect() and nfc_llcp_recv_cc() in
net/nfc/llcp_core.c, still compute the length at the call site as
skb->len - LLCP_HEADER_SIZE and hand it to the parser:

    nfc_llcp_parse_connection_tlv(new_sock, &skb->data[LLCP_HEADER_SIZE],
                                  skb->len - LLCP_HEADER_SIZE);

and

    nfc_llcp_parse_connection_tlv(llcp_sock, &skb->data[LLCP_HEADER_SIZE],
                                  skb->len - LLCP_HEADER_SIZE);

If skb->len is 0 or 1, that subtraction (size_t at the call site,
truncated to the u16 tlv_array_len parameter) becomes 0xFFFE or 0xFFFF.

Inside the parser, that value now feeds:

    const u8 *tlv_end = tlv_array + tlv_array_len;

    while (tlv + 2 < tlv_end) {
            ...
            if (tlv + 2 + length > tlv_end)
                    break;

so tlv_end points roughly 64 KiB past &skb->data[LLCP_HEADER_SIZE] and
neither the loop condition nor the per-TLV check catches the walk
leaving the skb.

The commit message calls this out as one of the motivations:

    "Dropping the u8 offset also removes the wrap, and for very short
    connect frames this avoids the size_t underflow of
    'skb->len - LLCP_HEADER_SIZE'."

That mitigation is applied inside nfc_llcp_connect_sn() by using
skb_tail_pointer(skb) directly, but the equivalent change is not made
for the connection TLV path. nfc_llcp_rx_skb() has no minimum-length
guard, so a received CONNECT or CC PDU with skb->len < LLCP_HEADER_SIZE
still reaches these callers.

Would it make sense to either guard skb->len >= LLCP_HEADER_SIZE
before the two call sites, or take the same skb_tail_pointer() based
approach used in nfc_llcp_connect_sn() so the parser derives its bound
from the skb rather than from an untrusted subtraction?

> diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c
> index dc65c719f35f..5e1881199238 100644
> --- a/net/nfc/llcp_core.c
> +++ b/net/nfc/llcp_core.c
> @@ -849,13 +849,16 @@ static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local,
>  static const u8 *nfc_llcp_connect_sn(const struct sk_buff *skb, size_t *sn_len)
>  {
>  	u8 type, length;
> -	const u8 *tlv = &skb->data[2];
> -	size_t tlv_array_len = skb->len - LLCP_HEADER_SIZE, offset = 0;
> +	const u8 *tlv = &skb->data[LLCP_HEADER_SIZE];
> +	const u8 *tlv_end = skb_tail_pointer(skb);
>  
> -	while (offset < tlv_array_len) {
> +	while (tlv + 2 < tlv_end) {

  reply	other threads:[~2026-07-10 13:49 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-05 11:56 [PATCH net] nfc: llcp: bound the remaining LLCP TLV parsers to their buffers Doruk Tan Ozturk
2026-07-10 13:48 ` Simon Horman [this message]
2026-07-11 13:42   ` Doruk (0sec)
2026-07-13 15:34     ` Simon Horman

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=20260710134850.1615092-1-horms@kernel.org \
    --to=horms@kernel.org \
    --cc=david.laight.linux@gmail.com \
    --cc=david@ixit.cz \
    --cc=doruk@0sec.ai \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=oe-linux-nfc@lists.linux.dev \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.