Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+28 -18
+1 -1
net/netfilter/ipvs/ip_vs_ctl.c
··· 3402 3402 if (udest.af == 0) 3403 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 3406 /* The synchronization protocol is incompatible 3407 3407 * with mixed family services 3408 3408 */
+10 -2
net/netfilter/nft_compat.c
··· 625 625 struct xt_match *match = nft_match->ops.data; 626 626 627 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 632 return &nft_match->ops; 633 + } 630 634 } 631 635 632 636 match = xt_request_find_match(family, mt_name, rev); ··· 699 695 struct xt_target *target = nft_target->ops.data; 700 696 701 697 if (strcmp(target->name, tg_name) == 0 && 702 - target->revision == rev && target->family == family) 698 + target->revision == rev && target->family == family) { 699 + if (!try_module_get(target->me)) 700 + return ERR_PTR(-ENOENT); 701 + 703 702 return &nft_target->ops; 703 + } 704 704 } 705 705 706 706 target = xt_request_find_target(family, tg_name, rev);
+5 -6
net/netfilter/xt_recent.c
··· 378 378 mutex_lock(&recent_mutex); 379 379 t = recent_table_lookup(recent_net, info->name); 380 380 if (t != NULL) { 381 - if (info->hit_count > t->nstamps_max_mask) { 382 - pr_info("hitcount (%u) is larger than packets to be remembered (%u) for table %s\n", 383 - info->hit_count, t->nstamps_max_mask + 1, 384 - info->name); 385 - ret = -EINVAL; 386 - goto out; 381 + if (nstamp_mask > t->nstamps_max_mask) { 382 + spin_lock_bh(&recent_lock); 383 + recent_table_flush(t); 384 + t->nstamps_max_mask = nstamp_mask; 385 + spin_unlock_bh(&recent_lock); 387 386 } 388 387 389 388 t->refcnt++;
+12 -9
net/netfilter/xt_socket.c
··· 243 243 extract_icmp6_fields(const struct sk_buff *skb, 244 244 unsigned int outside_hdrlen, 245 245 int *protocol, 246 - struct in6_addr **raddr, 247 - struct in6_addr **laddr, 246 + const struct in6_addr **raddr, 247 + const struct in6_addr **laddr, 248 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 253 struct icmp6hdr *icmph, _icmph; 253 254 __be16 *ports, _ports[2]; 254 255 u8 inside_nexthdr; ··· 264 263 if (icmph->icmp6_type & ICMPV6_INFOMSG_MASK) 265 264 return 1; 266 265 267 - inside_iph = skb_header_pointer(skb, outside_hdrlen + sizeof(_icmph), sizeof(_inside_iph), &_inside_iph); 266 + inside_iph = skb_header_pointer(skb, outside_hdrlen + sizeof(_icmph), 267 + sizeof(*ipv6_var), ipv6_var); 268 268 if (inside_iph == NULL) 269 269 return 1; 270 270 inside_nexthdr = inside_iph->nexthdr; 271 271 272 - inside_hdrlen = ipv6_skip_exthdr(skb, outside_hdrlen + sizeof(_icmph) + sizeof(_inside_iph), 272 + inside_hdrlen = ipv6_skip_exthdr(skb, outside_hdrlen + sizeof(_icmph) + 273 + sizeof(*ipv6_var), 273 274 &inside_nexthdr, &inside_fragoff); 274 275 if (inside_hdrlen < 0) 275 276 return 1; /* hjm: Packet has no/incomplete transport layer headers. */ ··· 318 315 static bool 319 316 socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par) 320 317 { 321 - struct ipv6hdr *iph = ipv6_hdr(skb); 318 + struct ipv6hdr ipv6_var, *iph = ipv6_hdr(skb); 322 319 struct udphdr _hdr, *hp = NULL; 323 320 struct sock *sk = skb->sk; 324 - struct in6_addr *daddr = NULL, *saddr = NULL; 321 + const struct in6_addr *daddr = NULL, *saddr = NULL; 325 322 __be16 uninitialized_var(dport), uninitialized_var(sport); 326 323 int thoff = 0, uninitialized_var(tproto); 327 324 const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo; ··· 345 342 346 343 } else if (tproto == IPPROTO_ICMPV6) { 347 344 if (extract_icmp6_fields(skb, thoff, &tproto, &saddr, &daddr, 348 - &sport, &dport)) 345 + &sport, &dport, &ipv6_var)) 349 346 return false; 350 347 } else { 351 348 return false;