]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
netfilter: nf_conntrack_sip: widen NAT rewrite delta to s32 in sip_help_tcp()
authorXiang Mei <xmei5@asu.edu>
Sun, 12 Jul 2026 23:42:01 +0000 (16:42 -0700)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 22 Jul 2026 17:47:17 +0000 (19:47 +0200)
sip_help_tcp() stores the size change of each NAT-rewritten SIP message
in s16 diff and accumulates it in s16 tdiff, but a single message can
grow by more than S16_MAX while the packet stays under the 65535
enlarge_skb() limit: nf_nat_sip() rewrites every matching URI, and a long
Contact list expands the message by tens of kilobytes. diff then wraps,
and "datalen = datalen + diff - msglen" yields a huge unsigned datalen,
so the next iteration's ct_sip_get_header() reads past the linearized skb
tail.

Widen diff, tdiff and the seq_adjust hook to s32. Both are bounded by the
65535 byte packet limit, and the seqadj core is already s32
(nf_ct_seqadj_set() takes s32), so no previously accepted input is
rejected.

  BUG: KASAN: use-after-free in ct_sip_get_header (net/netfilter/nf_conntrack_sip.c:464)
  Read of size 1 at addr ffff888010800000 by task ksoftirqd/1/25
   ct_sip_get_header (net/netfilter/nf_conntrack_sip.c:464)
   sip_help_tcp (net/netfilter/nf_conntrack_sip.c:1694)
   nf_confirm (net/netfilter/nf_conntrack_proto.c:183)
   nf_hook_slow (net/netfilter/core.c:619)
   ip6_output (net/ipv6/ip6_output.c:246)
   ip6_forward (net/ipv6/ip6_output.c:690)
   ipv6_rcv (net/ipv6/ip6_input.c:351)
   __netif_receive_skb_one_core (net/core/dev.c:6212)
   process_backlog (net/core/dev.c:6676)
   __napi_poll (net/core/dev.c:7735)
   net_rx_action (net/core/dev.c:7955)
   handle_softirqs (kernel/softirq.c:622)
   run_ksoftirqd (kernel/softirq.c:1076)
   ...

Fixes: f5b321bd37fb ("netfilter: nf_conntrack_sip: add TCP support")
Reported-by: Weiming Shi <bestswngs@gmail.com>
Link: https://patch.msgid.link/netfilter-devel/20260712234201.3213635-1-xmei5@asu.edu
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Xiang Mei <xmei5@asu.edu>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/linux/netfilter/nf_conntrack_sip.h
net/netfilter/nf_conntrack_sip.c
net/netfilter/nf_nat_sip.c

index dbc614dfe0d5652f4de9594a3327c9bfabfc4eed..aafa0c04f917ebec565be614e226aaeee96934c4 100644 (file)
@@ -115,7 +115,7 @@ struct nf_nat_sip_hooks {
                            unsigned int *datalen);
 
        void (*seq_adjust)(struct sk_buff *skb,
-                          unsigned int protoff, s16 off);
+                          unsigned int protoff, s32 off);
 
        unsigned int (*expect)(struct sk_buff *skb,
                               unsigned int protoff,
index f3f90a866338940b29b141e21624b2a16334836f..e4a70d1d77b0b9a4e59fb696ed9034e067f0bea4 100644 (file)
@@ -1663,7 +1663,7 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff,
        unsigned int matchoff, matchlen;
        unsigned int msglen, origlen;
        const char *dptr, *end;
-       s16 diff, tdiff = 0;
+       s32 diff, tdiff = 0;
        int ret = NF_ACCEPT;
        unsigned long clen;
        bool term;
index aea02f6aff092aa7200772f9e2b8dbbffb259da8..a93eaf0f7d305e0828bec7323354ed1438c4f0df 100644 (file)
@@ -321,7 +321,7 @@ next:
 }
 
 static void nf_nat_sip_seq_adjust(struct sk_buff *skb, unsigned int protoff,
-                                 s16 off)
+                                 s32 off)
 {
        enum ip_conntrack_info ctinfo;
        struct nf_conn *ct = nf_ct_get(skb, &ctinfo);