aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-02-20 17:36:20 -0500
committerDavid S. Miller <davem@davemloft.net>2015-02-20 17:36:20 -0500
commitee92259849b1616e4c23121f78eb1342d2b1ce1e (patch)
tree3f9b59862131aeee98552048d8ac67be0ede6cf8 /net
parent278f7b4fffce9ad267406cf8800df271d14f4a16 (diff)
parent78296c97ca1fd3b104f12e1f1fbc06c46635990b (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.c2
-rw-r--r--net/netfilter/nft_compat.c12
-rw-r--r--net/netfilter/xt_recent.c11
-rw-r--r--net/netfilter/xt_socket.c21
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
243extract_icmp6_fields(const struct sk_buff *skb, 243extract_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,
315static bool 318static bool
316socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par) 319socket_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;