diff options
author | David S. Miller <davem@davemloft.net> | 2013-09-17 20:22:53 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-09-17 20:22:53 -0400 |
commit | 61c5923a2f2d8ab98a1e3c76f17e0f4a871ec75b (patch) | |
tree | 0bcacd43538e7e1952f7e8696e48f9ffdbb1e0d0 /net | |
parent | 2936b6ab455433a5ad14c7a1d2473afe1fa3faa7 (diff) | |
parent | 0a0d80eb39aa465b7bdf6f7754d0ba687eb3d2a7 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says:
====================
The following patchset contains Netfilter fixes for you net tree,
mostly targeted to ipset, they are:
* Fix ICMPv6 NAT due to wrong comparison, code instead of type, from
Phil Oester.
* Fix RCU race in conntrack extensions release path, from Michal Kubecek.
* Fix missing inversion in the userspace ipset test command match if
the nomatch option is specified, from Jozsef Kadlecsik.
* Skip layer 4 protocol matching in ipset in case of IPv6 fragments,
also from Jozsef Kadlecsik.
* Fix sequence adjustment in nfnetlink_queue due to using the netlink
skb instead of the network skb, from Gao feng.
* Make sure we cannot swap of sets with different layer 3 family in
ipset, from Jozsef Kadlecsik.
* Fix possible bogus matching in ipset if hash sets with net elements
are used, from Oliver Smith.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/netfilter/nf_nat_proto_icmpv6.c | 4 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_core.c | 5 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_getport.c | 4 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_hash_gen.h | 28 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_hash_ipportnet.c | 4 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_hash_net.c | 4 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_hash_netiface.c | 4 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_hash_netport.c | 4 | ||||
-rw-r--r-- | net/netfilter/nfnetlink_queue_core.c | 2 |
9 files changed, 31 insertions, 28 deletions
diff --git a/net/ipv6/netfilter/nf_nat_proto_icmpv6.c b/net/ipv6/netfilter/nf_nat_proto_icmpv6.c index 61aaf70f376e..2205e8eeeacf 100644 --- a/net/ipv6/netfilter/nf_nat_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_nat_proto_icmpv6.c | |||
@@ -69,8 +69,8 @@ icmpv6_manip_pkt(struct sk_buff *skb, | |||
69 | hdr = (struct icmp6hdr *)(skb->data + hdroff); | 69 | hdr = (struct icmp6hdr *)(skb->data + hdroff); |
70 | l3proto->csum_update(skb, iphdroff, &hdr->icmp6_cksum, | 70 | l3proto->csum_update(skb, iphdroff, &hdr->icmp6_cksum, |
71 | tuple, maniptype); | 71 | tuple, maniptype); |
72 | if (hdr->icmp6_code == ICMPV6_ECHO_REQUEST || | 72 | if (hdr->icmp6_type == ICMPV6_ECHO_REQUEST || |
73 | hdr->icmp6_code == ICMPV6_ECHO_REPLY) { | 73 | hdr->icmp6_type == ICMPV6_ECHO_REPLY) { |
74 | inet_proto_csum_replace2(&hdr->icmp6_cksum, skb, | 74 | inet_proto_csum_replace2(&hdr->icmp6_cksum, skb, |
75 | hdr->icmp6_identifier, | 75 | hdr->icmp6_identifier, |
76 | tuple->src.u.icmp.id, 0); | 76 | tuple->src.u.icmp.id, 0); |
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index f77139007983..f2e30fb31e78 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c | |||
@@ -1052,7 +1052,7 @@ ip_set_swap(struct sock *ctnl, struct sk_buff *skb, | |||
1052 | * Not an artificial restriction anymore, as we must prevent | 1052 | * Not an artificial restriction anymore, as we must prevent |
1053 | * possible loops created by swapping in setlist type of sets. */ | 1053 | * possible loops created by swapping in setlist type of sets. */ |
1054 | if (!(from->type->features == to->type->features && | 1054 | if (!(from->type->features == to->type->features && |
1055 | from->type->family == to->type->family)) | 1055 | from->family == to->family)) |
1056 | return -IPSET_ERR_TYPE_MISMATCH; | 1056 | return -IPSET_ERR_TYPE_MISMATCH; |
1057 | 1057 | ||
1058 | strncpy(from_name, from->name, IPSET_MAXNAMELEN); | 1058 | strncpy(from_name, from->name, IPSET_MAXNAMELEN); |
@@ -1489,8 +1489,7 @@ ip_set_utest(struct sock *ctnl, struct sk_buff *skb, | |||
1489 | if (ret == -EAGAIN) | 1489 | if (ret == -EAGAIN) |
1490 | ret = 1; | 1490 | ret = 1; |
1491 | 1491 | ||
1492 | return (ret < 0 && ret != -ENOTEMPTY) ? ret : | 1492 | return ret > 0 ? 0 : -IPSET_ERR_EXIST; |
1493 | ret > 0 ? 0 : -IPSET_ERR_EXIST; | ||
1494 | } | 1493 | } |
1495 | 1494 | ||
1496 | /* Get headed data of a set */ | 1495 | /* Get headed data of a set */ |
diff --git a/net/netfilter/ipset/ip_set_getport.c b/net/netfilter/ipset/ip_set_getport.c index 6fdf88ae2353..dac156f819ac 100644 --- a/net/netfilter/ipset/ip_set_getport.c +++ b/net/netfilter/ipset/ip_set_getport.c | |||
@@ -116,12 +116,12 @@ ip_set_get_ip6_port(const struct sk_buff *skb, bool src, | |||
116 | { | 116 | { |
117 | int protoff; | 117 | int protoff; |
118 | u8 nexthdr; | 118 | u8 nexthdr; |
119 | __be16 frag_off; | 119 | __be16 frag_off = 0; |
120 | 120 | ||
121 | nexthdr = ipv6_hdr(skb)->nexthdr; | 121 | nexthdr = ipv6_hdr(skb)->nexthdr; |
122 | protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr, | 122 | protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr, |
123 | &frag_off); | 123 | &frag_off); |
124 | if (protoff < 0) | 124 | if (protoff < 0 || (frag_off & htons(~0x7)) != 0) |
125 | return false; | 125 | return false; |
126 | 126 | ||
127 | return get_port(skb, nexthdr, protoff, src, port, proto); | 127 | return get_port(skb, nexthdr, protoff, src, port, proto); |
diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h index 57beb1762b2d..707bc520d629 100644 --- a/net/netfilter/ipset/ip_set_hash_gen.h +++ b/net/netfilter/ipset/ip_set_hash_gen.h | |||
@@ -325,18 +325,22 @@ mtype_add_cidr(struct htype *h, u8 cidr, u8 nets_length) | |||
325 | static void | 325 | static void |
326 | mtype_del_cidr(struct htype *h, u8 cidr, u8 nets_length) | 326 | mtype_del_cidr(struct htype *h, u8 cidr, u8 nets_length) |
327 | { | 327 | { |
328 | u8 i, j; | 328 | u8 i, j, net_end = nets_length - 1; |
329 | 329 | ||
330 | for (i = 0; i < nets_length - 1 && h->nets[i].cidr != cidr; i++) | 330 | for (i = 0; i < nets_length; i++) { |
331 | ; | 331 | if (h->nets[i].cidr != cidr) |
332 | h->nets[i].nets--; | 332 | continue; |
333 | 333 | if (h->nets[i].nets > 1 || i == net_end || | |
334 | if (h->nets[i].nets != 0) | 334 | h->nets[i + 1].nets == 0) { |
335 | return; | 335 | h->nets[i].nets--; |
336 | 336 | return; | |
337 | for (j = i; j < nets_length - 1 && h->nets[j].nets; j++) { | 337 | } |
338 | h->nets[j].cidr = h->nets[j + 1].cidr; | 338 | for (j = i; j < net_end && h->nets[j].nets; j++) { |
339 | h->nets[j].nets = h->nets[j + 1].nets; | 339 | h->nets[j].cidr = h->nets[j + 1].cidr; |
340 | h->nets[j].nets = h->nets[j + 1].nets; | ||
341 | } | ||
342 | h->nets[j].nets = 0; | ||
343 | return; | ||
340 | } | 344 | } |
341 | } | 345 | } |
342 | #endif | 346 | #endif |
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c index c6a525373be4..f15f3e28b9c3 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportnet.c +++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c | |||
@@ -260,7 +260,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
260 | e.ip = htonl(ip); | 260 | e.ip = htonl(ip); |
261 | e.ip2 = htonl(ip2_from & ip_set_hostmask(e.cidr + 1)); | 261 | e.ip2 = htonl(ip2_from & ip_set_hostmask(e.cidr + 1)); |
262 | ret = adtfn(set, &e, &ext, &ext, flags); | 262 | ret = adtfn(set, &e, &ext, &ext, flags); |
263 | return ip_set_enomatch(ret, flags, adt) ? 1 : | 263 | return ip_set_enomatch(ret, flags, adt, set) ? -ret : |
264 | ip_set_eexist(ret, flags) ? 0 : ret; | 264 | ip_set_eexist(ret, flags) ? 0 : ret; |
265 | } | 265 | } |
266 | 266 | ||
@@ -544,7 +544,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
544 | 544 | ||
545 | if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { | 545 | if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { |
546 | ret = adtfn(set, &e, &ext, &ext, flags); | 546 | ret = adtfn(set, &e, &ext, &ext, flags); |
547 | return ip_set_enomatch(ret, flags, adt) ? 1 : | 547 | return ip_set_enomatch(ret, flags, adt, set) ? -ret : |
548 | ip_set_eexist(ret, flags) ? 0 : ret; | 548 | ip_set_eexist(ret, flags) ? 0 : ret; |
549 | } | 549 | } |
550 | 550 | ||
diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c index da740ceb56ae..223e9f546d0f 100644 --- a/net/netfilter/ipset/ip_set_hash_net.c +++ b/net/netfilter/ipset/ip_set_hash_net.c | |||
@@ -199,7 +199,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
199 | if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) { | 199 | if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) { |
200 | e.ip = htonl(ip & ip_set_hostmask(e.cidr)); | 200 | e.ip = htonl(ip & ip_set_hostmask(e.cidr)); |
201 | ret = adtfn(set, &e, &ext, &ext, flags); | 201 | ret = adtfn(set, &e, &ext, &ext, flags); |
202 | return ip_set_enomatch(ret, flags, adt) ? 1 : | 202 | return ip_set_enomatch(ret, flags, adt, set) ? -ret: |
203 | ip_set_eexist(ret, flags) ? 0 : ret; | 203 | ip_set_eexist(ret, flags) ? 0 : ret; |
204 | } | 204 | } |
205 | 205 | ||
@@ -396,7 +396,7 @@ hash_net6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
396 | 396 | ||
397 | ret = adtfn(set, &e, &ext, &ext, flags); | 397 | ret = adtfn(set, &e, &ext, &ext, flags); |
398 | 398 | ||
399 | return ip_set_enomatch(ret, flags, adt) ? 1 : | 399 | return ip_set_enomatch(ret, flags, adt, set) ? -ret : |
400 | ip_set_eexist(ret, flags) ? 0 : ret; | 400 | ip_set_eexist(ret, flags) ? 0 : ret; |
401 | } | 401 | } |
402 | 402 | ||
diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c index 84ae6f6ce624..7d798d5d5cd3 100644 --- a/net/netfilter/ipset/ip_set_hash_netiface.c +++ b/net/netfilter/ipset/ip_set_hash_netiface.c | |||
@@ -368,7 +368,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
368 | if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) { | 368 | if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) { |
369 | e.ip = htonl(ip & ip_set_hostmask(e.cidr)); | 369 | e.ip = htonl(ip & ip_set_hostmask(e.cidr)); |
370 | ret = adtfn(set, &e, &ext, &ext, flags); | 370 | ret = adtfn(set, &e, &ext, &ext, flags); |
371 | return ip_set_enomatch(ret, flags, adt) ? 1 : | 371 | return ip_set_enomatch(ret, flags, adt, set) ? -ret : |
372 | ip_set_eexist(ret, flags) ? 0 : ret; | 372 | ip_set_eexist(ret, flags) ? 0 : ret; |
373 | } | 373 | } |
374 | 374 | ||
@@ -634,7 +634,7 @@ hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
634 | 634 | ||
635 | ret = adtfn(set, &e, &ext, &ext, flags); | 635 | ret = adtfn(set, &e, &ext, &ext, flags); |
636 | 636 | ||
637 | return ip_set_enomatch(ret, flags, adt) ? 1 : | 637 | return ip_set_enomatch(ret, flags, adt, set) ? -ret : |
638 | ip_set_eexist(ret, flags) ? 0 : ret; | 638 | ip_set_eexist(ret, flags) ? 0 : ret; |
639 | } | 639 | } |
640 | 640 | ||
diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c index 9a0869853be5..09d6690bee6f 100644 --- a/net/netfilter/ipset/ip_set_hash_netport.c +++ b/net/netfilter/ipset/ip_set_hash_netport.c | |||
@@ -244,7 +244,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
244 | if (adt == IPSET_TEST || !(with_ports || tb[IPSET_ATTR_IP_TO])) { | 244 | if (adt == IPSET_TEST || !(with_ports || tb[IPSET_ATTR_IP_TO])) { |
245 | e.ip = htonl(ip & ip_set_hostmask(e.cidr + 1)); | 245 | e.ip = htonl(ip & ip_set_hostmask(e.cidr + 1)); |
246 | ret = adtfn(set, &e, &ext, &ext, flags); | 246 | ret = adtfn(set, &e, &ext, &ext, flags); |
247 | return ip_set_enomatch(ret, flags, adt) ? 1 : | 247 | return ip_set_enomatch(ret, flags, adt, set) ? -ret : |
248 | ip_set_eexist(ret, flags) ? 0 : ret; | 248 | ip_set_eexist(ret, flags) ? 0 : ret; |
249 | } | 249 | } |
250 | 250 | ||
@@ -489,7 +489,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
489 | 489 | ||
490 | if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { | 490 | if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { |
491 | ret = adtfn(set, &e, &ext, &ext, flags); | 491 | ret = adtfn(set, &e, &ext, &ext, flags); |
492 | return ip_set_enomatch(ret, flags, adt) ? 1 : | 492 | return ip_set_enomatch(ret, flags, adt, set) ? -ret : |
493 | ip_set_eexist(ret, flags) ? 0 : ret; | 493 | ip_set_eexist(ret, flags) ? 0 : ret; |
494 | } | 494 | } |
495 | 495 | ||
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index 95a98c8c1da6..ae2e5c11d01a 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c | |||
@@ -1009,7 +1009,7 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, | |||
1009 | verdict = NF_DROP; | 1009 | verdict = NF_DROP; |
1010 | 1010 | ||
1011 | if (ct) | 1011 | if (ct) |
1012 | nfqnl_ct_seq_adjust(skb, ct, ctinfo, diff); | 1012 | nfqnl_ct_seq_adjust(entry->skb, ct, ctinfo, diff); |
1013 | } | 1013 | } |
1014 | 1014 | ||
1015 | if (nfqa[NFQA_MARK]) | 1015 | if (nfqa[NFQA_MARK]) |