]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
netfilter: conntrack: check NULL when retrieving ct extension
authorPablo Neira Ayuso <pablo@netfilter.org>
Mon, 8 Jun 2026 16:14:36 +0000 (18:14 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Sun, 14 Jun 2026 10:51:55 +0000 (12:51 +0200)
nf_ct_ext_find() might return NULL if ct extension is not found.

Add also the null checks to:

- nfct_help()
- nfct_help_data()
- nfct_seqadj()
- nfct_nat()

This is defensive, for safety reasons.

nf_ct_ext_find() used to return NULL if the extension is stale for
unconfirmed conntracks if the genid validation fails.

Skip NULL check in nf_nat_inet_fn() given this is valid to be NULL
for non-initialized ct nat extensions.

While at it, fetch ct helper area in nf_ct_expect_related_report() only
once and pass it on to other ancilliary functions. Replace WARN_ON()
by WARN_ON_ONCE() in nf_ct_unlink_expect_report().

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
14 files changed:
include/net/netfilter/nf_conntrack_helper.h
net/ipv4/netfilter/nf_nat_h323.c
net/ipv4/netfilter/nf_nat_pptp.c
net/netfilter/nf_conntrack_broadcast.c
net/netfilter/nf_conntrack_expect.c
net/netfilter/nf_conntrack_ftp.c
net/netfilter/nf_conntrack_h323_main.c
net/netfilter/nf_conntrack_pptp.c
net/netfilter/nf_conntrack_proto_gre.c
net/netfilter/nf_conntrack_sane.c
net/netfilter/nf_conntrack_seqadj.c
net/netfilter/nf_conntrack_sip.c
net/netfilter/nf_nat_sip.c
net/netfilter/nfnetlink_cthelper.c

index ed93a5a1adc873784ed36a5a0a6f22b2c3a0335a..93207de4f2c8bcfab5e606a4236d6cc971eeb9cb 100644 (file)
@@ -136,6 +136,8 @@ static inline void *nfct_help_data(const struct nf_conn *ct)
        struct nf_conn_help *help;
 
        help = nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
+       if (!help)
+               return NULL;
 
        return (void *)help->data;
 }
index faee20af485613132c874442fa3942018e3f3ecb..19dad54ada098ece80ff94ecf618610b02058ecf 100644 (file)
@@ -100,6 +100,9 @@ static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct,
        __be16 port;
        union nf_inet_addr addr;
 
+       if (!info)
+               return -1;
+
        for (i = 0; i < count; i++) {
                if (get_h225_addr(ct, *data, &taddr[i], &addr, &port)) {
                        if (addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
@@ -184,6 +187,9 @@ static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
        int i;
        u_int16_t nated_port;
 
+       if (!info)
+               return -1;
+
        /* Set expectations for NAT */
        rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
        rtp_exp->expectfn = nf_nat_follow_master;
@@ -325,6 +331,9 @@ static int nat_h245(struct sk_buff *skb, struct nf_conn *ct,
        int dir = CTINFO2DIR(ctinfo);
        u_int16_t nated_port = ntohs(port);
 
+       if (!info)
+               return -1;
+
        /* Set expectations for NAT */
        exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
        exp->expectfn = nf_nat_follow_master;
@@ -404,6 +413,9 @@ static int nat_q931(struct sk_buff *skb, struct nf_conn *ct,
        u_int16_t nated_port = ntohs(port);
        union nf_inet_addr addr;
 
+       if (!info)
+               return -1;
+
        /* Set expectations for NAT */
        exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
        exp->expectfn = ip_nat_q931_expect;
index fab357cc85594472caa69f971d73cb7ef88af9cf..fed5249001a498979872ab001062b6f43d588d34 100644 (file)
@@ -53,11 +53,13 @@ static void pptp_nat_expected(struct nf_conn *ct,
        struct nf_conn_nat *nat;
 
        nat = nf_ct_nat_ext_add(ct);
-       if (WARN_ON_ONCE(!nat))
+       if (!nat)
                return;
 
        nat_pptp_info = &nat->help.nat_pptp_info;
        ct_pptp_info = nfct_help_data(master);
+       if (!ct_pptp_info)
+               return;
 
        /* And here goes the grand finale of corrosion... */
        if (exp->dir == IP_CT_DIR_ORIGINAL) {
@@ -132,11 +134,13 @@ pptp_outbound_pkt(struct sk_buff *skb,
        __be16 new_callid;
        unsigned int cid_off;
 
-       if (WARN_ON_ONCE(!nat))
+       if (!nat)
                return NF_DROP;
 
        nat_pptp_info = &nat->help.nat_pptp_info;
        ct_pptp_info = nfct_help_data(ct);
+       if (!ct_pptp_info)
+               return NF_DROP;
 
        new_callid = ct_pptp_info->pns_call_id;
 
@@ -204,11 +208,13 @@ pptp_exp_gre(struct nf_conntrack_expect *expect_orig,
        struct nf_ct_pptp_master *ct_pptp_info;
        struct nf_nat_pptp *nat_pptp_info;
 
-       if (WARN_ON_ONCE(!nat))
+       if (!nat)
                return;
 
        nat_pptp_info = &nat->help.nat_pptp_info;
        ct_pptp_info = nfct_help_data(ct);
+       if (!ct_pptp_info)
+               return;
 
        /* save original PAC call ID in nat_info */
        nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id;
@@ -241,7 +247,7 @@ pptp_inbound_pkt(struct sk_buff *skb,
        __be16 new_pcid;
        unsigned int pcid_off;
 
-       if (WARN_ON_ONCE(!nat))
+       if (!nat)
                return NF_DROP;
 
        nat_pptp_info = &nat->help.nat_pptp_info;
index 75e53fde6b29748dc75c4d3a5cd5f16e3021c064..400119b6320e727460c2e2ab0b660f7f50fdfbcb 100644 (file)
@@ -29,6 +29,9 @@ int nf_conntrack_broadcast_help(struct sk_buff *skb,
        struct nf_conn_help *help = nfct_help(ct);
        __be32 mask = 0;
 
+       if (!help)
+               goto out;
+
        /* we're only interested in locally generated packets */
        if (skb->sk == NULL || !net_eq(nf_ct_net(ct), sock_net(skb->sk)))
                goto out;
index 8e943efbdf0a5292b0dc202f901eeecab7c66ccb..5c9b17835c280b262e89c152104b77e9e7ec1fa1 100644 (file)
@@ -52,8 +52,7 @@ void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp,
        struct nf_conntrack_net *cnet;
 
        lockdep_nfct_expect_lock_held();
-       WARN_ON(!master_help);
-       WARN_ON(timer_pending(&exp->timeout));
+       WARN_ON_ONCE(timer_pending(&exp->timeout));
 
        hlist_del_rcu(&exp->hnode);
 
@@ -61,7 +60,8 @@ void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp,
        cnet->expect_count--;
 
        hlist_del_rcu(&exp->lnode);
-       master_help->expecting[exp->class]--;
+       if (master_help)
+               master_help->expecting[exp->class]--;
 
        nf_ct_expect_event_report(IPEXP_DESTROY, exp, portid, report);
        nf_ct_expect_put(exp);
@@ -405,10 +405,10 @@ void nf_ct_expect_put(struct nf_conntrack_expect *exp)
 }
 EXPORT_SYMBOL_GPL(nf_ct_expect_put);
 
-static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
+static void nf_ct_expect_insert(struct nf_conntrack_expect *exp,
+                               struct nf_conn_help *master_help)
 {
        struct nf_conntrack_net *cnet;
-       struct nf_conn_help *master_help = nfct_help(exp->master);
        struct nf_conntrack_helper *helper;
        struct net *net = nf_ct_exp_net(exp);
        unsigned int h = nf_ct_expect_dst_hash(net, &exp->tuple);
@@ -436,10 +436,9 @@ static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
 }
 
 /* Race with expectations being used means we could have none to find; OK. */
-static void evict_oldest_expect(struct nf_conn *master,
+static void evict_oldest_expect(struct nf_conn_help *master_help,
                                struct nf_conntrack_expect *new)
 {
-       struct nf_conn_help *master_help = nfct_help(master);
        struct nf_conntrack_expect *exp, *last = NULL;
 
        hlist_for_each_entry(exp, &master_help->expectations, lnode) {
@@ -452,13 +451,12 @@ static void evict_oldest_expect(struct nf_conn *master,
 }
 
 static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect,
+                                      struct nf_conn_help *master_help,
                                       unsigned int flags)
 {
        const struct nf_conntrack_expect_policy *p;
        struct nf_conntrack_expect *i;
        struct nf_conntrack_net *cnet;
-       struct nf_conn *master = expect->master;
-       struct nf_conn_help *master_help = nfct_help(master);
        struct nf_conntrack_helper *helper;
        struct net *net = nf_ct_exp_net(expect);
        struct hlist_node *next;
@@ -467,10 +465,6 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect,
 
        lockdep_nfct_expect_lock_held();
 
-       if (!master_help) {
-               ret = -ESHUTDOWN;
-               goto out;
-       }
        h = nf_ct_expect_dst_hash(net, &expect->tuple);
        hlist_for_each_entry_safe(i, next, &nf_ct_expect_hash[h], hnode) {
                if (master_matches(i, expect, flags) &&
@@ -493,7 +487,7 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect,
                p = &helper->expect_policy[expect->class];
                if (p->max_expected &&
                    master_help->expecting[expect->class] >= p->max_expected) {
-                       evict_oldest_expect(master, expect);
+                       evict_oldest_expect(master_help, expect);
                        if (master_help->expecting[expect->class]
                                                >= p->max_expected) {
                                ret = -EMFILE;
@@ -514,14 +508,21 @@ out:
 int nf_ct_expect_related_report(struct nf_conntrack_expect *expect,
                                u32 portid, int report, unsigned int flags)
 {
+       struct nf_conn_help *master_help;
        int ret;
 
        spin_lock_bh(&nf_conntrack_expect_lock);
-       ret = __nf_ct_expect_check(expect, flags);
+       master_help = nfct_help(expect->master);
+       if (!master_help) {
+               ret = -ESHUTDOWN;
+               goto out;
+       }
+
+       ret = __nf_ct_expect_check(expect, master_help, flags);
        if (ret < 0)
                goto out;
 
-       nf_ct_expect_insert(expect);
+       nf_ct_expect_insert(expect, master_help);
 
        nf_ct_expect_event_report(IPEXP_NEW, expect, portid, report);
        spin_unlock_bh(&nf_conntrack_expect_lock);
index c7777f37371ac239e0988b5b1cae9156a1e87475..0847f845613d6a0103b98e5c5b206c55438f427f 100644 (file)
@@ -384,6 +384,9 @@ static int help(struct sk_buff *skb,
        int found = 0, ends_in_nl;
        nf_nat_ftp_hook_fn *nf_nat_ftp;
 
+       if (!ct_ftp_info)
+               return NF_DROP;
+
        /* Until there's been traffic both ways, don't look in packets. */
        if (ctinfo != IP_CT_ESTABLISHED &&
            ctinfo != IP_CT_ESTABLISHED_REPLY) {
@@ -545,6 +548,9 @@ static int nf_ct_ftp_from_nlattr(struct nlattr *attr, struct nf_conn *ct)
 {
        struct nf_ct_ftp_master *ftp = nfct_help_data(ct);
 
+       if (!ftp)
+               return -ENOENT;
+
        /* This conntrack has been injected from user-space, always pick up
         * sequence tracking. Otherwise, the first FTP command after the
         * failover breaks.
index ebae9fdab89780b4e480e439622827d23d884c9b..7f189dceb3c4d79dfb4e77772af3c97d96c627f6 100644 (file)
@@ -76,6 +76,9 @@ static int get_tpkt_data(struct sk_buff *skb, unsigned int protoff,
        int tpktlen;
        int tpktoff;
 
+       if (!info)
+               return 0;
+
        /* Get TCP header */
        th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
        if (th == NULL)
@@ -1191,6 +1194,9 @@ static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,
        union nf_inet_addr addr;
        struct nf_conntrack_expect *exp;
 
+       if (!info)
+               return -1;
+
        /* Look for the first related address */
        for (i = 0; i < count; i++) {
                if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) &&
@@ -1307,6 +1313,9 @@ static int process_rrq(struct sk_buff *skb, struct nf_conn *ct,
        const struct nfct_h323_nat_hooks *nathook;
        int ret;
 
+       if (!info)
+               return -1;
+
        pr_debug("nf_ct_ras: RRQ\n");
 
        ret = expect_q931(skb, ct, ctinfo, protoff, data,
@@ -1345,6 +1354,9 @@ static int process_rcf(struct sk_buff *skb, struct nf_conn *ct,
        int ret;
        struct nf_conntrack_expect *exp;
 
+       if (!info)
+               return -1;
+
        pr_debug("nf_ct_ras: RCF\n");
 
        nathook = rcu_dereference(nfct_h323_nat_hook);
@@ -1395,6 +1407,9 @@ static int process_urq(struct sk_buff *skb, struct nf_conn *ct,
        int dir = CTINFO2DIR(ctinfo);
        int ret;
 
+       if (!info)
+               return -1;
+
        pr_debug("nf_ct_ras: URQ\n");
 
        nathook = rcu_dereference(nfct_h323_nat_hook);
@@ -1429,6 +1444,9 @@ static int process_arq(struct sk_buff *skb, struct nf_conn *ct,
        __be16 port;
        union nf_inet_addr addr;
 
+       if (!info)
+               return 0;
+
        pr_debug("nf_ct_ras: ARQ\n");
 
        nathook = rcu_dereference(nfct_h323_nat_hook);
index ed567a1cf7fd7e2916fd19d776edf95cf3224183..776505a78e645606bae9cebb63cb4664b1623925 100644 (file)
@@ -198,6 +198,9 @@ pptp_inbound_pkt(struct sk_buff *skb, unsigned int protoff,
        u_int16_t msg;
        __be16 cid = 0, pcid = 0;
 
+       if (!info)
+               return NF_DROP;
+
        msg = ntohs(ctlh->messageType);
        pr_debug("inbound control message %s\n", pptp_msg_name(msg));
 
@@ -325,6 +328,9 @@ pptp_outbound_pkt(struct sk_buff *skb, unsigned int protoff,
        u_int16_t msg;
        __be16 cid = 0, pcid = 0;
 
+       if (!info)
+               return NF_DROP;
+
        msg = ntohs(ctlh->messageType);
        pr_debug("outbound control message %s\n", pptp_msg_name(msg));
 
@@ -443,6 +449,9 @@ conntrack_pptp_help(struct sk_buff *skb, unsigned int protoff,
        int ret;
        u_int16_t msg;
 
+       if (!info)
+               return NF_DROP;
+
 #if IS_ENABLED(CONFIG_NF_NAT)
        if (!nf_ct_is_confirmed(ct) && (ct->status & IPS_NAT_MASK)) {
                struct nf_conn_nat *nat = nf_ct_ext_find(ct, NF_CT_EXT_NAT);
index 473658259f1a2b14895e6e6c896bfa4328b1cc87..616ab1e2fc5edc30bcb5501f8a40d316cb00681f 100644 (file)
@@ -131,6 +131,9 @@ bool nf_ct_gre_keymap_add(struct nf_conn *ct,
        struct nf_ct_gre_keymap *km_orig, *km_repl;
        bool ret = false;
 
+       if (!ct_pptp_info)
+               return false;
+
        km_orig = kmalloc_obj(*km_orig, GFP_ATOMIC);
        if (!km_orig)
                return false;
@@ -187,6 +190,9 @@ void nf_ct_gre_keymap_destroy(struct nf_conn *ct)
        struct nf_ct_pptp_master *ct_pptp_info = nfct_help_data(ct);
        enum ip_conntrack_dir dir;
 
+       if (!ct_pptp_info)
+               return;
+
        pr_debug("entering for ct %p\n", ct);
 
        spin_lock_bh(&keymap_lock);
@@ -389,6 +395,9 @@ void gre_pptp_destroy_siblings(struct nf_conn *ct)
        const struct nf_ct_pptp_master *ct_pptp_info = nfct_help_data(ct);
        struct nf_conntrack_tuple t;
 
+       if (!ct_pptp_info)
+               return;
+
        nf_ct_gre_keymap_destroy(ct);
 
        /* try original (pns->pac) tuple */
index a7f7b07ba0c2b75e0bcc99c284b08ecc8a604aa5..39085acf7a718575451825ba7ea1d913b69df6a7 100644 (file)
@@ -74,6 +74,9 @@ static int help(struct sk_buff *skb,
                struct sane_reply_net_start repl;
        } buf;
 
+       if (!ct_sane_info)
+               return NF_DROP;
+
        /* Until there's been traffic both ways, don't look in packets. */
        if (ctinfo != IP_CT_ESTABLISHED &&
            ctinfo != IP_CT_ESTABLISHED_REPLY)
index b7e99f34dfce86daef377b8939cb6f4bd28af38f..220216a4edc513bdef9fe4ca7dcfb0759ba85df8 100644 (file)
@@ -18,9 +18,12 @@ int nf_ct_seqadj_init(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
                return 0;
 
        spin_lock_bh(&ct->lock);
-       set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
-
        seqadj = nfct_seqadj(ct);
+       if (!seqadj) {
+               spin_unlock_bh(&ct->lock);
+               return 0;
+       }
+       set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
        this_way = &seqadj->seq[dir];
        this_way->offset_before  = off;
        this_way->offset_after   = off;
@@ -39,10 +42,8 @@ int nf_ct_seqadj_set(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
        if (off == 0)
                return 0;
 
-       if (unlikely(!seqadj)) {
-               WARN_ONCE(1, "Missing nfct_seqadj_ext_add() setup call\n");
+       if (unlikely(!seqadj))
                return 0;
-       }
 
        set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
 
@@ -125,6 +126,9 @@ static unsigned int nf_ct_sack_adjust(struct sk_buff *skb,
        struct nf_conn_seqadj *seqadj = nfct_seqadj(ct);
        unsigned int dir, optoff, optend;
 
+       if (!seqadj)
+               return 0;
+
        optoff = protoff + sizeof(struct tcphdr);
        optend = protoff + tcph->doff * 4;
 
@@ -175,6 +179,9 @@ int nf_ct_seq_adjust(struct sk_buff *skb,
        struct nf_ct_seqadj *this_way, *other_way;
        int res = 1;
 
+       if (!seqadj)
+               return 0;
+
        this_way  = &seqadj->seq[dir];
        other_way = &seqadj->seq[!dir];
 
index 2c78a3e1dab5e5359e72e72cd94fd8ed693ab752..c606d1f60b5895c91c95f01b262d3f537798802f 100644 (file)
@@ -887,6 +887,9 @@ static int refresh_signalling_expectation(struct nf_conn *ct,
        struct hlist_node *next;
        int found = 0;
 
+       if (!help)
+               return 0;
+
        spin_lock_bh(&nf_conntrack_expect_lock);
        hlist_for_each_entry_safe(exp, next, &help->expectations, lnode) {
                if (exp->class != SIP_EXPECT_SIGNALLING ||
@@ -910,6 +913,9 @@ static void flush_expectations(struct nf_conn *ct, bool media)
        struct nf_conntrack_expect *exp;
        struct hlist_node *next;
 
+       if (!help)
+               return;
+
        spin_lock_bh(&nf_conntrack_expect_lock);
        hlist_for_each_entry_safe(exp, next, &help->expectations, lnode) {
                if ((exp->class != SIP_EXPECT_SIGNALLING) ^ media)
@@ -940,6 +946,11 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int protoff,
        u_int16_t base_port;
        __be16 rtp_port, rtcp_port;
        const struct nf_nat_sip_hooks *hooks;
+       struct nf_conn_help *help;
+
+       help = nfct_help(ct);
+       if (!help)
+               return NF_DROP;
 
        saddr = NULL;
        if (sip_direct_media) {
@@ -1002,7 +1013,7 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int protoff,
                exp = __nf_ct_expect_find(net, nf_ct_zone(ct), &tuple);
 
                if (!exp || exp->master == ct ||
-                   exp->helper != nfct_help(ct)->helper ||
+                   exp->helper != help->helper ||
                    exp->class != class)
                        break;
 #if IS_ENABLED(CONFIG_NF_NAT)
@@ -1227,6 +1238,9 @@ static int process_invite_response(struct sk_buff *skb, unsigned int protoff,
        struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
        struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct);
 
+       if (!ct_sip_info)
+               return NF_DROP;
+
        if ((code >= 100 && code <= 199) ||
            (code >= 200 && code <= 299))
                return process_sdp(skb, protoff, dataoff, dptr, datalen, cseq);
@@ -1244,6 +1258,9 @@ static int process_update_response(struct sk_buff *skb, unsigned int protoff,
        struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
        struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct);
 
+       if (!ct_sip_info)
+               return NF_DROP;
+
        if ((code >= 100 && code <= 199) ||
            (code >= 200 && code <= 299))
                return process_sdp(skb, protoff, dataoff, dptr, datalen, cseq);
@@ -1261,6 +1278,9 @@ static int process_prack_response(struct sk_buff *skb, unsigned int protoff,
        struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
        struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct);
 
+       if (!ct_sip_info)
+               return NF_DROP;
+
        if ((code >= 100 && code <= 199) ||
            (code >= 200 && code <= 299))
                return process_sdp(skb, protoff, dataoff, dptr, datalen, cseq);
@@ -1279,6 +1299,9 @@ static int process_invite_request(struct sk_buff *skb, unsigned int protoff,
        struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct);
        unsigned int ret;
 
+       if (!ct_sip_info)
+               return NF_DROP;
+
        flush_expectations(ct, true);
        ret = process_sdp(skb, protoff, dataoff, dptr, datalen, cseq);
        if (ret == NF_ACCEPT)
@@ -1316,11 +1339,15 @@ static int process_register_request(struct sk_buff *skb, unsigned int protoff,
        union nf_inet_addr *saddr, daddr;
        const struct nf_nat_sip_hooks *hooks;
        struct nf_conntrack_helper *helper;
+       struct nf_conn_help *help;
        __be16 port;
        u8 proto;
        unsigned int expires = 0;
        int ret;
 
+       if (!ct_sip_info)
+               return NF_DROP;
+
        /* Expected connections can not register again. */
        if (ct->status & IPS_EXPECTED)
                return NF_ACCEPT;
@@ -1366,7 +1393,11 @@ static int process_register_request(struct sk_buff *skb, unsigned int protoff,
                goto store_cseq;
        }
 
-       helper = rcu_dereference(nfct_help(ct)->helper);
+       help = nfct_help(ct);
+       if (!help)
+               return NF_DROP;
+
+       helper = rcu_dereference(help->helper);
        if (!helper)
                return NF_DROP;
 
@@ -1421,6 +1452,9 @@ static int process_register_response(struct sk_buff *skb, unsigned int protoff,
        unsigned int expires = 0;
        int in_contact = 0, ret;
 
+       if (!ct_sip_info)
+               return NF_DROP;
+
        /* According to RFC 3261, "UAs MUST NOT send a new registration until
         * they have received a final response from the registrar for the
         * previous one or the previous REGISTER request has timed out".
@@ -1550,6 +1584,9 @@ static int process_sip_request(struct sk_buff *skb, unsigned int protoff,
        union nf_inet_addr addr;
        __be16 port;
 
+       if (!ct_sip_info)
+               return NF_DROP;
+
        /* Many Cisco IP phones use a high source port for SIP requests, but
         * listen for the response on port 5060.  If we are the local
         * router for one of these phones, save the port number from the
index 9fbfc6bff0c2218aabcabf79b3891575e6bdda9b..7f29a6785327921d75596230a4718dd6d64bd2aa 100644 (file)
@@ -106,6 +106,9 @@ static int map_addr(struct sk_buff *skb, unsigned int protoff,
        union nf_inet_addr newaddr;
        __be16 newport;
 
+       if (!ct_sip_info)
+               return 0;
+
        if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, addr) &&
            ct->tuplehash[dir].tuple.src.u.udp.port == port) {
                newaddr = ct->tuplehash[!dir].tuple.dst.u3;
@@ -158,6 +161,9 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff,
        __be16 port;
        int request, in_header;
 
+       if (!ct_sip_info)
+               return NF_DROP;
+
        /* Basic rules: requests and responses. */
        if (strncasecmp(*dptr, "SIP/2.0", strlen("SIP/2.0")) != 0) {
                if (ct_sip_parse_request(ct, *dptr, *datalen,
@@ -326,6 +332,9 @@ static void nf_nat_sip_expected(struct nf_conn *ct,
        int range_set_for_snat = 0;
        struct nf_nat_range2 range;
 
+       if (!help)
+               return;
+
        /* This must be a fresh one. */
        BUG_ON(ct->status & IPS_NAT_DONE_MASK);
 
@@ -390,6 +399,9 @@ static unsigned int nf_nat_sip_expect(struct sk_buff *skb, unsigned int protoff,
        char buffer[INET6_ADDRSTRLEN + sizeof("[]:nnnnn")];
        unsigned int buflen;
 
+       if (!ct_sip_info)
+               return NF_DROP;
+
        /* Connection will come from reply */
        if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,
                             &ct->tuplehash[!dir].tuple.dst.u3))
index 033ea90c4401e92921dae6ff16d3bbd261d6437a..f1460b683d7af7e8f43336c46b99a5efe441fe11 100644 (file)
@@ -101,6 +101,9 @@ nfnl_cthelper_from_nlattr(struct nlattr *attr, struct nf_conn *ct)
        struct nf_conn_help *help = nfct_help(ct);
        const struct nf_conntrack_helper *helper;
 
+       if (!help)
+               return -EINVAL;
+
        if (attr == NULL)
                return -EINVAL;
 
@@ -118,6 +121,9 @@ nfnl_cthelper_to_nlattr(struct sk_buff *skb, const struct nf_conn *ct)
        const struct nf_conn_help *help = nfct_help(ct);
        const struct nf_conntrack_helper *helper;
 
+       if (!help)
+               return 0;
+
        helper = rcu_dereference(help->helper);
        if (helper && helper->data_len &&
            nla_put(skb, CTA_HELP_INFO, helper->data_len, &help->data))