* [PATCH] netfilter: nf_conntrack_sip: fix OOB read in SIP URI port parsing
@ 2026-03-12 14:55 Jenny Guanni Qu
2026-03-12 15:37 ` Florian Westphal
0 siblings, 1 reply; 4+ messages in thread
From: Jenny Guanni Qu @ 2026-03-12 14:55 UTC (permalink / raw)
To: pablo, kadlec; +Cc: netfilter-devel, fw, klaudia, dawid, Jenny Guanni Qu
In epaddr_len() and ct_sip_parse_header_uri(), after sip_parse_addr()
parses an IP address, the pointer (dptr or c) may point at or past
limit. The subsequent check for a ':' port separator dereferences the
pointer without a bounds check, causing a 1-byte out-of-bounds read.
Add bounds checks before the dereference in both locations.
Fixes: 05e3ced297fe ("[NETFILTER]: nf_conntrack_sip: introduce SIP-URI parsing helper")
Reported-by: Klaudia Kloc <klaudia@vidocsecurity.com>
Reported-by: Dawid Moczadło <dawid@vidocsecurity.com>
Tested-by: Jenny Guanni Qu <qguanni@gmail.com>
Signed-off-by: Jenny Guanni Qu <qguanni@gmail.com>
---
net/netfilter/nf_conntrack_sip.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index d0eac27f6ba0..a232054d7919 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -194,7 +194,7 @@ static int epaddr_len(const struct nf_conn *ct, const char *dptr,
}
/* Port number */
- if (*dptr == ':') {
+ if (dptr < limit && *dptr == ':') {
dptr++;
dptr += digits_len(ct, dptr, limit, shift);
}
@@ -520,7 +520,7 @@ int ct_sip_parse_header_uri(const struct nf_conn *ct, const char *dptr,
if (!sip_parse_addr(ct, dptr + *matchoff, &c, addr, limit, true))
return -1;
- if (*c == ':') {
+ if (c < limit && *c == ':') {
c++;
p = simple_strtoul(c, (char **)&c, 10);
if (p < 1024 || p > 65535)
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] netfilter: nf_conntrack_sip: fix OOB read in SIP URI port parsing
2026-03-12 14:55 [PATCH] netfilter: nf_conntrack_sip: fix OOB read in SIP URI port parsing Jenny Guanni Qu
@ 2026-03-12 15:37 ` Florian Westphal
2026-03-12 22:39 ` Guanni Qu
0 siblings, 1 reply; 4+ messages in thread
From: Florian Westphal @ 2026-03-12 15:37 UTC (permalink / raw)
To: Jenny Guanni Qu; +Cc: pablo, kadlec, netfilter-devel, klaudia, dawid
Jenny Guanni Qu <qguanni@gmail.com> wrote:
> In epaddr_len() and ct_sip_parse_header_uri(), after sip_parse_addr()
> parses an IP address, the pointer (dptr or c) may point at or past
> limit. The subsequent check for a ':' port separator dereferences the
> pointer without a bounds check, causing a 1-byte out-of-bounds read.
>
> Add bounds checks before the dereference in both locations.
I'm not sure.
This bug is real, but I suspect there are many many more bugs in this
code.
> Fixes: 05e3ced297fe ("[NETFILTER]: nf_conntrack_sip: introduce SIP-URI parsing helper")
> Reported-by: Klaudia Kloc <klaudia@vidocsecurity.com>
> Reported-by: Dawid Moczadło <dawid@vidocsecurity.com>
> Tested-by: Jenny Guanni Qu <qguanni@gmail.com>
> Signed-off-by: Jenny Guanni Qu <qguanni@gmail.com>
> ---
> net/netfilter/nf_conntrack_sip.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
> index d0eac27f6ba0..a232054d7919 100644
> --- a/net/netfilter/nf_conntrack_sip.c
> +++ b/net/netfilter/nf_conntrack_sip.c
> @@ -194,7 +194,7 @@ static int epaddr_len(const struct nf_conn *ct, const char *dptr,
> }
>
> /* Port number */
> - if (*dptr == ':') {
> + if (dptr < limit && *dptr == ':') {
> dptr++;
> dptr += digits_len(ct, dptr, limit, shift);
> }
> @@ -520,7 +520,7 @@ int ct_sip_parse_header_uri(const struct nf_conn *ct, const char *dptr,
>
> if (!sip_parse_addr(ct, dptr + *matchoff, &c, addr, limit, true))
> return -1;
> - if (*c == ':') {
> + if (c < limit && *c == ':') {
> c++;
> p = simple_strtoul(c, (char **)&c, 10);
I'm not sure this check is enough. simple_strtoul() assumes
a c-string. Are we dealing with a c-string here?
I suspect the anser is: 'no' and that we depend on 0 bytes appearing in
skb_shinfo at end of network buffer for this to 'work'.
I would prefer to add much stricter constraints everywhere.
Untested example:
static bool sip_parse_port(const char *dptr, const char **endp, const char *limit)
{
static const unsigned int max = strlen("65535");
int len = 0;
/* port is optional, but dptr >= limit indicates malformed
* sip message.
*/
if (dptr >= limit)
return false;
if (*dptr != ':') /* this is fine, no port provided. */
return true;
while (dptr < limit && isdigit(*dptr)) {
dptr++;
len++;
if (len > max)
return false;
}
/* reached limit while parsing port */
if (dptr >= limit)
return false;
if (endp)
*endp = dptr;
return true;
}
@@ -193,11 +225,9 @@ static int epaddr_len(const struct nf_conn *ct, const char *dptr,
return 0;
}
- /* Port number */
- if (*dptr == ':') {
- dptr++;
- dptr += digits_len(ct, dptr, limit, shift);
- }
+ if (!sip_parse_port(dptr, &dptr, limit))
+ return 0;
+
return dptr - aux;
}
Whats your take?
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] netfilter: nf_conntrack_sip: fix OOB read in SIP URI port parsing
2026-03-12 15:37 ` Florian Westphal
@ 2026-03-12 22:39 ` Guanni Qu
2026-03-12 23:07 ` Florian Westphal
0 siblings, 1 reply; 4+ messages in thread
From: Guanni Qu @ 2026-03-12 22:39 UTC (permalink / raw)
To: Florian Westphal; +Cc: pablo, kadlec, netfilter-devel, klaudia, dawid
Hi Florian,
You're right, the minimal bounds check isn't enough. The simple_strtoul()
call assumes a NUL-terminated string, and the SIP packet data in the skb
is not guaranteed to be NUL-terminated. The current code relies on
incidental zero bytes in skb_shinfo.
I like your sip_parse_port() approach. I'll take it, wire it into
both call sites, and send a v2. While I'm in there I'll audit the
rest of nf_conntrack_sip for similar limit violations and send
anything I find as part of the same series.
Jenny
On Thu, Mar 12, 2026 at 8:37 AM Florian Westphal <fw@strlen.de> wrote:
>
> Jenny Guanni Qu <qguanni@gmail.com> wrote:
> > In epaddr_len() and ct_sip_parse_header_uri(), after sip_parse_addr()
> > parses an IP address, the pointer (dptr or c) may point at or past
> > limit. The subsequent check for a ':' port separator dereferences the
> > pointer without a bounds check, causing a 1-byte out-of-bounds read.
> >
> > Add bounds checks before the dereference in both locations.
>
> I'm not sure.
>
> This bug is real, but I suspect there are many many more bugs in this
> code.
>
> > Fixes: 05e3ced297fe ("[NETFILTER]: nf_conntrack_sip: introduce SIP-URI parsing helper")
> > Reported-by: Klaudia Kloc <klaudia@vidocsecurity.com>
> > Reported-by: Dawid Moczadło <dawid@vidocsecurity.com>
> > Tested-by: Jenny Guanni Qu <qguanni@gmail.com>
> > Signed-off-by: Jenny Guanni Qu <qguanni@gmail.com>
> > ---
> > net/netfilter/nf_conntrack_sip.c | 4 ++--
> > 1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
> > index d0eac27f6ba0..a232054d7919 100644
> > --- a/net/netfilter/nf_conntrack_sip.c
> > +++ b/net/netfilter/nf_conntrack_sip.c
> > @@ -194,7 +194,7 @@ static int epaddr_len(const struct nf_conn *ct, const char *dptr,
> > }
> >
> > /* Port number */
> > - if (*dptr == ':') {
> > + if (dptr < limit && *dptr == ':') {
> > dptr++;
> > dptr += digits_len(ct, dptr, limit, shift);
> > }
> > @@ -520,7 +520,7 @@ int ct_sip_parse_header_uri(const struct nf_conn *ct, const char *dptr,
> >
> > if (!sip_parse_addr(ct, dptr + *matchoff, &c, addr, limit, true))
> > return -1;
> > - if (*c == ':') {
> > + if (c < limit && *c == ':') {
> > c++;
> > p = simple_strtoul(c, (char **)&c, 10);
>
> I'm not sure this check is enough. simple_strtoul() assumes
> a c-string. Are we dealing with a c-string here?
>
> I suspect the anser is: 'no' and that we depend on 0 bytes appearing in
> skb_shinfo at end of network buffer for this to 'work'.
>
> I would prefer to add much stricter constraints everywhere.
>
> Untested example:
> static bool sip_parse_port(const char *dptr, const char **endp, const char *limit)
> {
> static const unsigned int max = strlen("65535");
> int len = 0;
>
> /* port is optional, but dptr >= limit indicates malformed
> * sip message.
> */
> if (dptr >= limit)
> return false;
>
> if (*dptr != ':') /* this is fine, no port provided. */
> return true;
>
> while (dptr < limit && isdigit(*dptr)) {
> dptr++;
> len++;
>
> if (len > max)
> return false;
> }
>
> /* reached limit while parsing port */
> if (dptr >= limit)
> return false;
>
> if (endp)
> *endp = dptr;
>
> return true;
> }
>
> @@ -193,11 +225,9 @@ static int epaddr_len(const struct nf_conn *ct, const char *dptr,
> return 0;
> }
>
> - /* Port number */
> - if (*dptr == ':') {
> - dptr++;
> - dptr += digits_len(ct, dptr, limit, shift);
> - }
> + if (!sip_parse_port(dptr, &dptr, limit))
> + return 0;
> +
> return dptr - aux;
> }
>
> Whats your take?
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] netfilter: nf_conntrack_sip: fix OOB read in SIP URI port parsing
2026-03-12 22:39 ` Guanni Qu
@ 2026-03-12 23:07 ` Florian Westphal
0 siblings, 0 replies; 4+ messages in thread
From: Florian Westphal @ 2026-03-12 23:07 UTC (permalink / raw)
To: Guanni Qu; +Cc: pablo, kadlec, netfilter-devel, klaudia, dawid
Guanni Qu <qguanni@gmail.com> wrote:
> You're right, the minimal bounds check isn't enough. The simple_strtoul()
> call assumes a NUL-terminated string, and the SIP packet data in the skb
> is not guaranteed to be NUL-terminated. The current code relies on
> incidental zero bytes in skb_shinfo.
>
> I like your sip_parse_port() approach. I'll take it, wire it into
> both call sites, and send a v2. While I'm in there I'll audit the
> rest of nf_conntrack_sip for similar limit violations and send
> anything I find as part of the same series.
Thats great, thanks a lot!
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-03-12 23:07 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-12 14:55 [PATCH] netfilter: nf_conntrack_sip: fix OOB read in SIP URI port parsing Jenny Guanni Qu
2026-03-12 15:37 ` Florian Westphal
2026-03-12 22:39 ` Guanni Qu
2026-03-12 23:07 ` Florian Westphal
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox