diff options
author | Florian Westphal <fw@strlen.de> | 2016-05-05 18:51:47 -0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2016-05-06 05:50:01 -0400 |
commit | 03d7dc5cdfe6fd4e5bd04cfc2be7ae259f956428 (patch) | |
tree | 154c3f3f33680d9294dd10c50eb5217f2ace6887 | |
parent | cb39ad8b8ef224c544074962780bf763077d6141 (diff) |
netfilter: conntrack: check netns when walking expect hash
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c | 3 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_expect.c | 19 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_netlink.c | 12 |
3 files changed, 30 insertions, 4 deletions
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c index f8fc7ab201c9..2b4c729fcf8d 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c | |||
@@ -301,6 +301,9 @@ static int exp_seq_show(struct seq_file *s, void *v) | |||
301 | 301 | ||
302 | exp = hlist_entry(n, struct nf_conntrack_expect, hnode); | 302 | exp = hlist_entry(n, struct nf_conntrack_expect, hnode); |
303 | 303 | ||
304 | if (!net_eq(nf_ct_net(exp->master), seq_file_net(s))) | ||
305 | return 0; | ||
306 | |||
304 | if (exp->tuple.src.l3num != AF_INET) | 307 | if (exp->tuple.src.l3num != AF_INET) |
305 | return 0; | 308 | return 0; |
306 | 309 | ||
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index c2f7c4f475b1..da95d740e60b 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c | |||
@@ -86,6 +86,17 @@ static unsigned int nf_ct_expect_dst_hash(const struct nf_conntrack_tuple *tuple | |||
86 | return reciprocal_scale(hash, nf_ct_expect_hsize); | 86 | return reciprocal_scale(hash, nf_ct_expect_hsize); |
87 | } | 87 | } |
88 | 88 | ||
89 | static bool | ||
90 | nf_ct_exp_equal(const struct nf_conntrack_tuple *tuple, | ||
91 | const struct nf_conntrack_expect *i, | ||
92 | const struct nf_conntrack_zone *zone, | ||
93 | const struct net *net) | ||
94 | { | ||
95 | return nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask) && | ||
96 | net_eq(net, nf_ct_net(i->master)) && | ||
97 | nf_ct_zone_equal_any(i->master, zone); | ||
98 | } | ||
99 | |||
89 | struct nf_conntrack_expect * | 100 | struct nf_conntrack_expect * |
90 | __nf_ct_expect_find(struct net *net, | 101 | __nf_ct_expect_find(struct net *net, |
91 | const struct nf_conntrack_zone *zone, | 102 | const struct nf_conntrack_zone *zone, |
@@ -99,8 +110,7 @@ __nf_ct_expect_find(struct net *net, | |||
99 | 110 | ||
100 | h = nf_ct_expect_dst_hash(tuple); | 111 | h = nf_ct_expect_dst_hash(tuple); |
101 | hlist_for_each_entry_rcu(i, &net->ct.expect_hash[h], hnode) { | 112 | hlist_for_each_entry_rcu(i, &net->ct.expect_hash[h], hnode) { |
102 | if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask) && | 113 | if (nf_ct_exp_equal(tuple, i, zone, net)) |
103 | nf_ct_zone_equal_any(i->master, zone)) | ||
104 | return i; | 114 | return i; |
105 | } | 115 | } |
106 | return NULL; | 116 | return NULL; |
@@ -141,8 +151,7 @@ nf_ct_find_expectation(struct net *net, | |||
141 | h = nf_ct_expect_dst_hash(tuple); | 151 | h = nf_ct_expect_dst_hash(tuple); |
142 | hlist_for_each_entry(i, &net->ct.expect_hash[h], hnode) { | 152 | hlist_for_each_entry(i, &net->ct.expect_hash[h], hnode) { |
143 | if (!(i->flags & NF_CT_EXPECT_INACTIVE) && | 153 | if (!(i->flags & NF_CT_EXPECT_INACTIVE) && |
144 | nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask) && | 154 | nf_ct_exp_equal(tuple, i, zone, net)) { |
145 | nf_ct_zone_equal_any(i->master, zone)) { | ||
146 | exp = i; | 155 | exp = i; |
147 | break; | 156 | break; |
148 | } | 157 | } |
@@ -222,6 +231,7 @@ static inline int expect_clash(const struct nf_conntrack_expect *a, | |||
222 | } | 231 | } |
223 | 232 | ||
224 | return nf_ct_tuple_mask_cmp(&a->tuple, &b->tuple, &intersect_mask) && | 233 | return nf_ct_tuple_mask_cmp(&a->tuple, &b->tuple, &intersect_mask) && |
234 | net_eq(nf_ct_net(a->master), nf_ct_net(b->master)) && | ||
225 | nf_ct_zone_equal_any(a->master, nf_ct_zone(b->master)); | 235 | nf_ct_zone_equal_any(a->master, nf_ct_zone(b->master)); |
226 | } | 236 | } |
227 | 237 | ||
@@ -231,6 +241,7 @@ static inline int expect_matches(const struct nf_conntrack_expect *a, | |||
231 | return a->master == b->master && a->class == b->class && | 241 | return a->master == b->master && a->class == b->class && |
232 | nf_ct_tuple_equal(&a->tuple, &b->tuple) && | 242 | nf_ct_tuple_equal(&a->tuple, &b->tuple) && |
233 | nf_ct_tuple_mask_equal(&a->mask, &b->mask) && | 243 | nf_ct_tuple_mask_equal(&a->mask, &b->mask) && |
244 | net_eq(nf_ct_net(a->master), nf_ct_net(b->master)) && | ||
234 | nf_ct_zone_equal_any(a->master, nf_ct_zone(b->master)); | 245 | nf_ct_zone_equal_any(a->master, nf_ct_zone(b->master)); |
235 | } | 246 | } |
236 | 247 | ||
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index e00f178c48b0..5dfb84d86143 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -2636,6 +2636,10 @@ restart: | |||
2636 | hnode) { | 2636 | hnode) { |
2637 | if (l3proto && exp->tuple.src.l3num != l3proto) | 2637 | if (l3proto && exp->tuple.src.l3num != l3proto) |
2638 | continue; | 2638 | continue; |
2639 | |||
2640 | if (!net_eq(nf_ct_net(exp->master), net)) | ||
2641 | continue; | ||
2642 | |||
2639 | if (cb->args[1]) { | 2643 | if (cb->args[1]) { |
2640 | if (exp != last) | 2644 | if (exp != last) |
2641 | continue; | 2645 | continue; |
@@ -2888,6 +2892,10 @@ static int ctnetlink_del_expect(struct net *net, struct sock *ctnl, | |||
2888 | hlist_for_each_entry_safe(exp, next, | 2892 | hlist_for_each_entry_safe(exp, next, |
2889 | &net->ct.expect_hash[i], | 2893 | &net->ct.expect_hash[i], |
2890 | hnode) { | 2894 | hnode) { |
2895 | |||
2896 | if (!net_eq(nf_ct_exp_net(exp), net)) | ||
2897 | continue; | ||
2898 | |||
2891 | m_help = nfct_help(exp->master); | 2899 | m_help = nfct_help(exp->master); |
2892 | if (!strcmp(m_help->helper->name, name) && | 2900 | if (!strcmp(m_help->helper->name, name) && |
2893 | del_timer(&exp->timeout)) { | 2901 | del_timer(&exp->timeout)) { |
@@ -2906,6 +2914,10 @@ static int ctnetlink_del_expect(struct net *net, struct sock *ctnl, | |||
2906 | hlist_for_each_entry_safe(exp, next, | 2914 | hlist_for_each_entry_safe(exp, next, |
2907 | &net->ct.expect_hash[i], | 2915 | &net->ct.expect_hash[i], |
2908 | hnode) { | 2916 | hnode) { |
2917 | |||
2918 | if (!net_eq(nf_ct_exp_net(exp), net)) | ||
2919 | continue; | ||
2920 | |||
2909 | if (del_timer(&exp->timeout)) { | 2921 | if (del_timer(&exp->timeout)) { |
2910 | nf_ct_unlink_expect_report(exp, | 2922 | nf_ct_unlink_expect_report(exp, |
2911 | NETLINK_CB(skb).portid, | 2923 | NETLINK_CB(skb).portid, |