* [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