diff options
author | David S. Miller <davem@davemloft.net> | 2015-02-20 17:36:20 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-02-20 17:36:20 -0500 |
commit | ee92259849b1616e4c23121f78eb1342d2b1ce1e (patch) | |
tree | 3f9b59862131aeee98552048d8ac67be0ede6cf8 /net | |
parent | 278f7b4fffce9ad267406cf8800df271d14f4a16 (diff) | |
parent | 78296c97ca1fd3b104f12e1f1fbc06c46635990b (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says:
====================
Netfilter/IPVS fixes for net
The following patchset contains updates for your net tree, they are:
1) Fix removal of destination in IPVS when the new mixed family support
is used, from Alexey Andriyanov via Simon Horman.
2) Fix module refcount undeflow in nft_compat when reusing a match /
target.
3) Fix iptables-restore when the recent match is used with a new hitcount
that exceeds threshold, from Florian Westphal.
4) Fix stack corruption in xt_socket due to using stack storage to save
the inner IPv6 header, from Eric Dumazet.
I'll follow up soon with another batch with more fixes that are still
cooking.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/ipvs/ip_vs_ctl.c | 2 | ||||
-rw-r--r-- | net/netfilter/nft_compat.c | 12 | ||||
-rw-r--r-- | net/netfilter/xt_recent.c | 11 | ||||
-rw-r--r-- | net/netfilter/xt_socket.c | 21 |
4 files changed, 28 insertions, 18 deletions
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index e55759056361..ed99448671c3 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c | |||
@@ -3402,7 +3402,7 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info) | |||
3402 | if (udest.af == 0) | 3402 | if (udest.af == 0) |
3403 | udest.af = svc->af; | 3403 | udest.af = svc->af; |
3404 | 3404 | ||
3405 | if (udest.af != svc->af) { | 3405 | if (udest.af != svc->af && cmd != IPVS_CMD_DEL_DEST) { |
3406 | /* The synchronization protocol is incompatible | 3406 | /* The synchronization protocol is incompatible |
3407 | * with mixed family services | 3407 | * with mixed family services |
3408 | */ | 3408 | */ |
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c index c598f74063a1..1279cd85663e 100644 --- a/net/netfilter/nft_compat.c +++ b/net/netfilter/nft_compat.c | |||
@@ -625,8 +625,12 @@ nft_match_select_ops(const struct nft_ctx *ctx, | |||
625 | struct xt_match *match = nft_match->ops.data; | 625 | struct xt_match *match = nft_match->ops.data; |
626 | 626 | ||
627 | if (strcmp(match->name, mt_name) == 0 && | 627 | if (strcmp(match->name, mt_name) == 0 && |
628 | match->revision == rev && match->family == family) | 628 | match->revision == rev && match->family == family) { |
629 | if (!try_module_get(match->me)) | ||
630 | return ERR_PTR(-ENOENT); | ||
631 | |||
629 | return &nft_match->ops; | 632 | return &nft_match->ops; |
633 | } | ||
630 | } | 634 | } |
631 | 635 | ||
632 | match = xt_request_find_match(family, mt_name, rev); | 636 | match = xt_request_find_match(family, mt_name, rev); |
@@ -695,8 +699,12 @@ nft_target_select_ops(const struct nft_ctx *ctx, | |||
695 | struct xt_target *target = nft_target->ops.data; | 699 | struct xt_target *target = nft_target->ops.data; |
696 | 700 | ||
697 | if (strcmp(target->name, tg_name) == 0 && | 701 | if (strcmp(target->name, tg_name) == 0 && |
698 | target->revision == rev && target->family == family) | 702 | target->revision == rev && target->family == family) { |
703 | if (!try_module_get(target->me)) | ||
704 | return ERR_PTR(-ENOENT); | ||
705 | |||
699 | return &nft_target->ops; | 706 | return &nft_target->ops; |
707 | } | ||
700 | } | 708 | } |
701 | 709 | ||
702 | target = xt_request_find_target(family, tg_name, rev); | 710 | target = xt_request_find_target(family, tg_name, rev); |
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index 30dbe34915ae..45e1b30e4fb2 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c | |||
@@ -378,12 +378,11 @@ static int recent_mt_check(const struct xt_mtchk_param *par, | |||
378 | mutex_lock(&recent_mutex); | 378 | mutex_lock(&recent_mutex); |
379 | t = recent_table_lookup(recent_net, info->name); | 379 | t = recent_table_lookup(recent_net, info->name); |
380 | if (t != NULL) { | 380 | if (t != NULL) { |
381 | if (info->hit_count > t->nstamps_max_mask) { | 381 | if (nstamp_mask > t->nstamps_max_mask) { |
382 | pr_info("hitcount (%u) is larger than packets to be remembered (%u) for table %s\n", | 382 | spin_lock_bh(&recent_lock); |
383 | info->hit_count, t->nstamps_max_mask + 1, | 383 | recent_table_flush(t); |
384 | info->name); | 384 | t->nstamps_max_mask = nstamp_mask; |
385 | ret = -EINVAL; | 385 | spin_unlock_bh(&recent_lock); |
386 | goto out; | ||
387 | } | 386 | } |
388 | 387 | ||
389 | t->refcnt++; | 388 | t->refcnt++; |
diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c index 1ba67931eb1b..13332dbf291d 100644 --- a/net/netfilter/xt_socket.c +++ b/net/netfilter/xt_socket.c | |||
@@ -243,12 +243,13 @@ static int | |||
243 | extract_icmp6_fields(const struct sk_buff *skb, | 243 | extract_icmp6_fields(const struct sk_buff *skb, |
244 | unsigned int outside_hdrlen, | 244 | unsigned int outside_hdrlen, |
245 | int *protocol, | 245 | int *protocol, |
246 | struct in6_addr **raddr, | 246 | const struct in6_addr **raddr, |
247 | struct in6_addr **laddr, | 247 | const struct in6_addr **laddr, |
248 | __be16 *rport, | 248 | __be16 *rport, |
249 | __be16 *lport) | 249 | __be16 *lport, |
250 | struct ipv6hdr *ipv6_var) | ||
250 | { | 251 | { |
251 | struct ipv6hdr *inside_iph, _inside_iph; | 252 | const struct ipv6hdr *inside_iph; |
252 | struct icmp6hdr *icmph, _icmph; | 253 | struct icmp6hdr *icmph, _icmph; |
253 | __be16 *ports, _ports[2]; | 254 | __be16 *ports, _ports[2]; |
254 | u8 inside_nexthdr; | 255 | u8 inside_nexthdr; |
@@ -263,12 +264,14 @@ extract_icmp6_fields(const struct sk_buff *skb, | |||
263 | if (icmph->icmp6_type & ICMPV6_INFOMSG_MASK) | 264 | if (icmph->icmp6_type & ICMPV6_INFOMSG_MASK) |
264 | return 1; | 265 | return 1; |
265 | 266 | ||
266 | inside_iph = skb_header_pointer(skb, outside_hdrlen + sizeof(_icmph), sizeof(_inside_iph), &_inside_iph); | 267 | inside_iph = skb_header_pointer(skb, outside_hdrlen + sizeof(_icmph), |
268 | sizeof(*ipv6_var), ipv6_var); | ||
267 | if (inside_iph == NULL) | 269 | if (inside_iph == NULL) |
268 | return 1; | 270 | return 1; |
269 | inside_nexthdr = inside_iph->nexthdr; | 271 | inside_nexthdr = inside_iph->nexthdr; |
270 | 272 | ||
271 | inside_hdrlen = ipv6_skip_exthdr(skb, outside_hdrlen + sizeof(_icmph) + sizeof(_inside_iph), | 273 | inside_hdrlen = ipv6_skip_exthdr(skb, outside_hdrlen + sizeof(_icmph) + |
274 | sizeof(*ipv6_var), | ||
272 | &inside_nexthdr, &inside_fragoff); | 275 | &inside_nexthdr, &inside_fragoff); |
273 | if (inside_hdrlen < 0) | 276 | if (inside_hdrlen < 0) |
274 | return 1; /* hjm: Packet has no/incomplete transport layer headers. */ | 277 | return 1; /* hjm: Packet has no/incomplete transport layer headers. */ |
@@ -315,10 +318,10 @@ xt_socket_get_sock_v6(struct net *net, const u8 protocol, | |||
315 | static bool | 318 | static bool |
316 | socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par) | 319 | socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par) |
317 | { | 320 | { |
318 | struct ipv6hdr *iph = ipv6_hdr(skb); | 321 | struct ipv6hdr ipv6_var, *iph = ipv6_hdr(skb); |
319 | struct udphdr _hdr, *hp = NULL; | 322 | struct udphdr _hdr, *hp = NULL; |
320 | struct sock *sk = skb->sk; | 323 | struct sock *sk = skb->sk; |
321 | struct in6_addr *daddr = NULL, *saddr = NULL; | 324 | const struct in6_addr *daddr = NULL, *saddr = NULL; |
322 | __be16 uninitialized_var(dport), uninitialized_var(sport); | 325 | __be16 uninitialized_var(dport), uninitialized_var(sport); |
323 | int thoff = 0, uninitialized_var(tproto); | 326 | int thoff = 0, uninitialized_var(tproto); |
324 | const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo; | 327 | const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo; |
@@ -342,7 +345,7 @@ socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par) | |||
342 | 345 | ||
343 | } else if (tproto == IPPROTO_ICMPV6) { | 346 | } else if (tproto == IPPROTO_ICMPV6) { |
344 | if (extract_icmp6_fields(skb, thoff, &tproto, &saddr, &daddr, | 347 | if (extract_icmp6_fields(skb, thoff, &tproto, &saddr, &daddr, |
345 | &sport, &dport)) | 348 | &sport, &dport, &ipv6_var)) |
346 | return false; | 349 | return false; |
347 | } else { | 350 | } else { |
348 | return false; | 351 | return false; |