diff options
| -rw-r--r-- | net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 13 | ||||
| -rw-r--r-- | net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 9 | ||||
| -rw-r--r-- | net/netfilter/nf_conntrack_core.c | 26 | ||||
| -rw-r--r-- | net/netfilter/nf_conntrack_expect.c | 4 | ||||
| -rw-r--r-- | net/netfilter/nf_conntrack_helper.c | 2 | ||||
| -rw-r--r-- | net/netfilter/nf_conntrack_netlink.c | 34 | ||||
| -rw-r--r-- | net/netfilter/nf_conntrack_proto_gre.c | 2 |
7 files changed, 61 insertions, 29 deletions
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index fd62a41d69..6dc72a815f 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
| @@ -133,6 +133,7 @@ static unsigned int ipv4_conntrack_help(unsigned int hooknum, | |||
| 133 | struct nf_conn *ct; | 133 | struct nf_conn *ct; |
| 134 | enum ip_conntrack_info ctinfo; | 134 | enum ip_conntrack_info ctinfo; |
| 135 | struct nf_conn_help *help; | 135 | struct nf_conn_help *help; |
| 136 | struct nf_conntrack_helper *helper; | ||
| 136 | 137 | ||
| 137 | /* This is where we call the helper: as the packet goes out. */ | 138 | /* This is where we call the helper: as the packet goes out. */ |
| 138 | ct = nf_ct_get(*pskb, &ctinfo); | 139 | ct = nf_ct_get(*pskb, &ctinfo); |
| @@ -140,12 +141,14 @@ static unsigned int ipv4_conntrack_help(unsigned int hooknum, | |||
| 140 | return NF_ACCEPT; | 141 | return NF_ACCEPT; |
| 141 | 142 | ||
| 142 | help = nfct_help(ct); | 143 | help = nfct_help(ct); |
| 143 | if (!help || !help->helper) | 144 | if (!help) |
| 144 | return NF_ACCEPT; | 145 | return NF_ACCEPT; |
| 145 | 146 | /* rcu_read_lock()ed by nf_hook_slow */ | |
| 146 | return help->helper->help(pskb, | 147 | helper = rcu_dereference(help->helper); |
| 147 | skb_network_offset(*pskb) + ip_hdrlen(*pskb), | 148 | if (!helper) |
| 148 | ct, ctinfo); | 149 | return NF_ACCEPT; |
| 150 | return helper->help(pskb, skb_network_offset(*pskb) + ip_hdrlen(*pskb), | ||
| 151 | ct, ctinfo); | ||
| 149 | } | 152 | } |
| 150 | 153 | ||
| 151 | static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, | 154 | static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, |
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index dc442fb791..1b1797f1f3 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | |||
| @@ -160,6 +160,7 @@ static unsigned int ipv6_confirm(unsigned int hooknum, | |||
| 160 | { | 160 | { |
| 161 | struct nf_conn *ct; | 161 | struct nf_conn *ct; |
| 162 | struct nf_conn_help *help; | 162 | struct nf_conn_help *help; |
| 163 | struct nf_conntrack_helper *helper; | ||
| 163 | enum ip_conntrack_info ctinfo; | 164 | enum ip_conntrack_info ctinfo; |
| 164 | unsigned int ret, protoff; | 165 | unsigned int ret, protoff; |
| 165 | unsigned int extoff = (u8 *)(ipv6_hdr(*pskb) + 1) - (*pskb)->data; | 166 | unsigned int extoff = (u8 *)(ipv6_hdr(*pskb) + 1) - (*pskb)->data; |
| @@ -172,7 +173,11 @@ static unsigned int ipv6_confirm(unsigned int hooknum, | |||
| 172 | goto out; | 173 | goto out; |
| 173 | 174 | ||
| 174 | help = nfct_help(ct); | 175 | help = nfct_help(ct); |
| 175 | if (!help || !help->helper) | 176 | if (!help) |
| 177 | goto out; | ||
| 178 | /* rcu_read_lock()ed by nf_hook_slow */ | ||
| 179 | helper = rcu_dereference(help->helper); | ||
| 180 | if (!helper) | ||
| 176 | goto out; | 181 | goto out; |
| 177 | 182 | ||
| 178 | protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum, | 183 | protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum, |
| @@ -182,7 +187,7 @@ static unsigned int ipv6_confirm(unsigned int hooknum, | |||
| 182 | return NF_ACCEPT; | 187 | return NF_ACCEPT; |
| 183 | } | 188 | } |
| 184 | 189 | ||
| 185 | ret = help->helper->help(pskb, protoff, ct, ctinfo); | 190 | ret = helper->help(pskb, protoff, ct, ctinfo); |
| 186 | if (ret != NF_ACCEPT) | 191 | if (ret != NF_ACCEPT) |
| 187 | return ret; | 192 | return ret; |
| 188 | out: | 193 | out: |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 483e927a9c..7a15e30356 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
| @@ -350,9 +350,15 @@ static void death_by_timeout(unsigned long ul_conntrack) | |||
| 350 | { | 350 | { |
| 351 | struct nf_conn *ct = (void *)ul_conntrack; | 351 | struct nf_conn *ct = (void *)ul_conntrack; |
| 352 | struct nf_conn_help *help = nfct_help(ct); | 352 | struct nf_conn_help *help = nfct_help(ct); |
| 353 | struct nf_conntrack_helper *helper; | ||
| 353 | 354 | ||
| 354 | if (help && help->helper && help->helper->destroy) | 355 | if (help) { |
| 355 | help->helper->destroy(ct); | 356 | rcu_read_lock(); |
| 357 | helper = rcu_dereference(help->helper); | ||
| 358 | if (helper && helper->destroy) | ||
| 359 | helper->destroy(ct); | ||
| 360 | rcu_read_unlock(); | ||
| 361 | } | ||
| 356 | 362 | ||
| 357 | write_lock_bh(&nf_conntrack_lock); | 363 | write_lock_bh(&nf_conntrack_lock); |
| 358 | /* Inside lock so preempt is disabled on module removal path. | 364 | /* Inside lock so preempt is disabled on module removal path. |
| @@ -661,6 +667,7 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, | |||
| 661 | unsigned int dataoff) | 667 | unsigned int dataoff) |
| 662 | { | 668 | { |
| 663 | struct nf_conn *conntrack; | 669 | struct nf_conn *conntrack; |
| 670 | struct nf_conn_help *help; | ||
| 664 | struct nf_conntrack_tuple repl_tuple; | 671 | struct nf_conntrack_tuple repl_tuple; |
| 665 | struct nf_conntrack_expect *exp; | 672 | struct nf_conntrack_expect *exp; |
| 666 | u_int32_t features = 0; | 673 | u_int32_t features = 0; |
| @@ -691,6 +698,7 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, | |||
| 691 | write_lock_bh(&nf_conntrack_lock); | 698 | write_lock_bh(&nf_conntrack_lock); |
| 692 | exp = find_expectation(tuple); | 699 | exp = find_expectation(tuple); |
| 693 | 700 | ||
| 701 | help = nfct_help(conntrack); | ||
| 694 | if (exp) { | 702 | if (exp) { |
| 695 | DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n", | 703 | DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n", |
| 696 | conntrack, exp); | 704 | conntrack, exp); |
| @@ -698,7 +706,7 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, | |||
| 698 | __set_bit(IPS_EXPECTED_BIT, &conntrack->status); | 706 | __set_bit(IPS_EXPECTED_BIT, &conntrack->status); |
| 699 | conntrack->master = exp->master; | 707 | conntrack->master = exp->master; |
| 700 | if (exp->helper) | 708 | if (exp->helper) |
| 701 | nfct_help(conntrack)->helper = exp->helper; | 709 | rcu_assign_pointer(help->helper, exp->helper); |
| 702 | #ifdef CONFIG_NF_CONNTRACK_MARK | 710 | #ifdef CONFIG_NF_CONNTRACK_MARK |
| 703 | conntrack->mark = exp->master->mark; | 711 | conntrack->mark = exp->master->mark; |
| 704 | #endif | 712 | #endif |
| @@ -708,10 +716,11 @@ init_conntrack(const struct nf_conntrack_tuple *tuple, | |||
| 708 | nf_conntrack_get(&conntrack->master->ct_general); | 716 | nf_conntrack_get(&conntrack->master->ct_general); |
| 709 | NF_CT_STAT_INC(expect_new); | 717 | NF_CT_STAT_INC(expect_new); |
| 710 | } else { | 718 | } else { |
| 711 | struct nf_conn_help *help = nfct_help(conntrack); | 719 | if (help) { |
| 712 | 720 | /* not in hash table yet, so not strictly necessary */ | |
| 713 | if (help) | 721 | rcu_assign_pointer(help->helper, |
| 714 | help->helper = __nf_ct_helper_find(&repl_tuple); | 722 | __nf_ct_helper_find(&repl_tuple)); |
| 723 | } | ||
| 715 | NF_CT_STAT_INC(new); | 724 | NF_CT_STAT_INC(new); |
| 716 | } | 725 | } |
| 717 | 726 | ||
| @@ -893,7 +902,8 @@ void nf_conntrack_alter_reply(struct nf_conn *ct, | |||
| 893 | helper = __nf_ct_helper_find(newreply); | 902 | helper = __nf_ct_helper_find(newreply); |
| 894 | if (helper) | 903 | if (helper) |
| 895 | memset(&help->help, 0, sizeof(help->help)); | 904 | memset(&help->help, 0, sizeof(help->help)); |
| 896 | help->helper = helper; | 905 | /* not in hash table yet, so not strictly necessary */ |
| 906 | rcu_assign_pointer(help->helper, helper); | ||
| 897 | } | 907 | } |
| 898 | write_unlock_bh(&nf_conntrack_lock); | 908 | write_unlock_bh(&nf_conntrack_lock); |
| 899 | } | 909 | } |
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 117cbfdb91..504fb6c083 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c | |||
| @@ -337,6 +337,10 @@ int nf_conntrack_expect_related(struct nf_conntrack_expect *expect) | |||
| 337 | NF_CT_ASSERT(master_help); | 337 | NF_CT_ASSERT(master_help); |
| 338 | 338 | ||
| 339 | write_lock_bh(&nf_conntrack_lock); | 339 | write_lock_bh(&nf_conntrack_lock); |
| 340 | if (!master_help->helper) { | ||
| 341 | ret = -ESHUTDOWN; | ||
| 342 | goto out; | ||
| 343 | } | ||
| 340 | list_for_each_entry(i, &nf_conntrack_expect_list, list) { | 344 | list_for_each_entry(i, &nf_conntrack_expect_list, list) { |
| 341 | if (expect_matches(i, expect)) { | 345 | if (expect_matches(i, expect)) { |
| 342 | /* Refresh timer: if it's dying, ignore.. */ | 346 | /* Refresh timer: if it's dying, ignore.. */ |
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 0743be4434..f868b7fbd9 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c | |||
| @@ -93,7 +93,7 @@ static inline int unhelp(struct nf_conntrack_tuple_hash *i, | |||
| 93 | 93 | ||
| 94 | if (help && help->helper == me) { | 94 | if (help && help->helper == me) { |
| 95 | nf_conntrack_event(IPCT_HELPER, ct); | 95 | nf_conntrack_event(IPCT_HELPER, ct); |
| 96 | help->helper = NULL; | 96 | rcu_assign_pointer(help->helper, NULL); |
| 97 | } | 97 | } |
| 98 | return 0; | 98 | return 0; |
| 99 | } | 99 | } |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index d6d39e2413..3f73327794 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
| @@ -171,21 +171,29 @@ ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct) | |||
| 171 | { | 171 | { |
| 172 | struct nfattr *nest_helper; | 172 | struct nfattr *nest_helper; |
| 173 | const struct nf_conn_help *help = nfct_help(ct); | 173 | const struct nf_conn_help *help = nfct_help(ct); |
| 174 | struct nf_conntrack_helper *helper; | ||
| 174 | |||
