From: Florian Westphal <fw@strlen.de>
To: Jenny Guanni Qu <qguanni@gmail.com>
Cc: edumazet@google.com, pablo@netfilter.org, netdev@vger.kernel.org,
davem@davemloft.net, netfilter-devel@vger.kernel.org,
pabeni@redhat.com, Jakub Kicinski <kuba@kernel.org>
Subject: Re: [net,06/11] netfilter: nf_conntrack_h323: fix OOB read in decode_int() CONS case
Date: Sat, 14 Mar 2026 19:31:35 +0100 [thread overview]
Message-ID: <abWph_Nu9TBQ4r6I@strlen.de> (raw)
In-Reply-To: <20260314161236.2454291-1-kuba@kernel.org>
Jakub Kicinski <kuba@kernel.org> wrote:
> This is an AI-generated review of your patch. The human sending this
> email has considered the AI review valid, or at least plausible.
Jenny, could you please double-check?
I don't think this report is right.
> netfilter: nf_conntrack_h323: fix OOB read in decode_int() CONS case
>
> This patch adds a boundary check in the CONS case of decode_int() to
> prevent reading beyond the buffer after get_bits() returns a length
> value. The fix validates that len bytes remain before calling
> get_uint().
SO far I can follow LLM response.
> > diff --git a/net/netfilter/nf_conntrack_h323_asn1.c b/net/netfilter/nf_conntrack_h323_asn1.c
> > index 62aa22a07876..c972e9488e16 100644
> > --- a/net/netfilter/nf_conntrack_h323_asn1.c
> > +++ b/net/netfilter/nf_conntrack_h323_asn1.c
> > @@ -331,6 +331,8 @@ static int decode_int(struct bitstr *bs, const struct field_t *f,
> > if (nf_h323_error_boundary(bs, 0, 2))
> > return H323_ERROR_BOUND;
> > len = get_bits(bs, 2) + 1;
> > + if (nf_h323_error_boundary(bs, len, 0))
> > + return H323_ERROR_BOUND;
> > BYTE_ALIGN(bs);
> > if (base && (f->attr & DECODE)) { /* timeToLive */
> > unsigned int v = get_uint(bs, len) + f->lb;
>
> This patch fixes the CONS case, but the UNCO case in the same function
> has the same vulnerability. In the UNCO case, get_len(bs) can return up
> to 0x3FFF (16383 bytes), and the code advances bs->cur by that amount
> without checking that len bytes remain:
>
> case UNCO:
> BYTE_ALIGN(bs);
> if (nf_h323_error_boundary(bs, 2, 0))
> return H323_ERROR_BOUND;
> len = get_len(bs);
> bs->cur += len;
> break;
>
> The check only validates 2 bytes for get_len() itself, not the
> subsequent len bytes that will be skipped. Does this need the same fix
> pattern?
I don't think so. Pointer can advance, but right after the swtich/case
there is:
358 if (nf_h323_error_boundary(bs, 0, 0))
359 return H323_ERROR_BOUND;
360 return H323_ERROR_NONE;
So bs->cur can advance past cur->end, but then the function
returns ERROR_BOUND.
> The decode_bitstr() function has a similar issue. In the SEMI case, it
> calls get_len(bs) which can return up to 0x3FFF bits, then advances the
> buffer by len >> 3 bytes plus partial bits without checking that
> sufficient buffer space exists:
>
> case SEMI:
> if (nf_h323_error_boundary(bs, 2, 0))
> return H323_ERROR_BOUND;
> len = get_len(bs);
AFAICS we've checked get_len() doesn't cause oob access.
> break;
> }
>
> bs->cur += len >> 3;
> bs->bit = len & 7;
>
> The check at the top only validates 2 bytes for the get_len() call. The
> actual advance at the bottom can be up to 2047 bytes. Should this be
> checked as well?
AFAICS it is, right after there is:
410 if (nf_h323_error_boundary(bs, 0, 0))
411 return H323_ERROR_BOUND;
> The decode_octstr() function has the same pattern in both the SEMI case
> and the default case:
>
> case SEMI:
> BYTE_ALIGN(bs);
> if (nf_h323_error_boundary(bs, 2, 0))
> return H323_ERROR_BOUND;
> len = get_len(bs) + f->lb;
> break;
> default: /* 2 <= Range <= 255 */
> if (nf_h323_error_boundary(bs, 0, f->sz))
> return H323_ERROR_BOUND;
> len = get_bits(bs, f->sz) + f->lb;
> BYTE_ALIGN(bs);
> break;
> }
>
> bs->cur += len;
Pointer increment, right after there is:
483 if (nf_h323_error_boundary(bs, 0, 0))
484 return H323_ERROR_BOUND;
> len bytes without checking. The existing checks only validate the bytes
> needed to READ the length value, not the len bytes that will be
> consumed. Should boundary checks be added after both break statements?
AFAICS there are such checks... :-/
> Similarly, decode_bmpstr() (which handles 2-byte character strings) has
> the same issue in both the BYTE case and default case:
>
> case BYTE: /* Range == 256 */
> BYTE_ALIGN(bs);
> if (nf_h323_error_boundary(bs, 1, 0))
> return H323_ERROR_BOUND;
> len = (*bs->cur++) + f->lb;
> break;
We write to bs->cur, but AFAICS the write has been vetted for.
> default: /* 2 <= Range <= 255 */
> if (nf_h323_error_boundary(bs, 0, f->sz))
> return H323_ERROR_BOUND;
> len = get_bits(bs, f->sz) + f->lb;
> BYTE_ALIGN(bs);
> break;
> }
>
> bs->cur += len << 1;
>
> After computing len from packet data plus f->lb, the function advances
> by len << 1 bytes (doubling for 2-byte characters) without verifying
> that len << 1 bytes are available. Should this also be checked?
AFAICS it is...
510 bs->cur += len << 1;
511
512 if (nf_h323_error_boundary(bs, 0, 0))
513 return H323_ERROR_BOUND;
So AFAICS this LLM response is bunk.
next prev parent reply other threads:[~2026-03-14 18:31 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-13 15:06 [PATCH net 00/11] netfilter: updates for net Florian Westphal
2026-03-13 15:06 ` [PATCH net 01/11] netfilter: ctnetlink: fix use-after-free in ctnetlink_dump_exp_ct() Florian Westphal
2026-03-14 16:20 ` patchwork-bot+netdevbpf
2026-03-13 15:06 ` [PATCH net 02/11] netfilter: conntrack: add missing netlink policy validations Florian Westphal
2026-03-13 15:06 ` [PATCH net 03/11] netfilter: nf_conntrack_sip: fix Content-Length u32 truncation in sip_help_tcp() Florian Westphal
2026-03-13 15:06 ` [PATCH net 04/11] netfilter: revert nft_set_rbtree: validate open interval overlap Florian Westphal
2026-03-16 8:14 ` [PATCH net 04/11] netfilter: revert nft_set_rbtree: validate open interval overlap: manual merge Matthieu Baerts
2026-03-13 15:06 ` [PATCH net 05/11] netfilter: nf_flow_table_ip: reset mac header before vlan push Florian Westphal
2026-03-13 15:06 ` [PATCH net 06/11] netfilter: nf_conntrack_h323: fix OOB read in decode_int() CONS case Florian Westphal
2026-03-14 16:12 ` [net,06/11] " Jakub Kicinski
2026-03-14 18:31 ` Florian Westphal [this message]
2026-03-14 22:16 ` Guanni Qu
2026-03-15 1:23 ` Jakub Kicinski
2026-03-13 15:06 ` [PATCH net 07/11] nf_tables: nft_dynset: fix possible stateful expression memleak in error path Florian Westphal
2026-03-13 15:06 ` [PATCH net 08/11] netfilter: nft_ct: drop pending enqueued packets on removal Florian Westphal
2026-03-13 15:06 ` [PATCH net 09/11] netfilter: xt_CT: drop pending enqueued packets on template removal Florian Westphal
2026-03-13 15:06 ` [PATCH net 10/11] netfilter: xt_time: use unsigned int for monthday bit shift Florian Westphal
2026-03-13 15:06 ` [PATCH net 11/11] netfilter: nf_conntrack_h323: check for zero length in DecodeQ931() Florian Westphal
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=abWph_Nu9TBQ4r6I@strlen.de \
--to=fw@strlen.de \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=netfilter-devel@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=pablo@netfilter.org \
--cc=qguanni@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 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.