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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox