Commit ee922598 authored by David S. Miller's avatar David S. Miller

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 278f7b4f 78296c97
...@@ -3402,7 +3402,7 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info) ...@@ -3402,7 +3402,7 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info)
if (udest.af == 0) if (udest.af == 0)
udest.af = svc->af; udest.af = svc->af;
if (udest.af != svc->af) { if (udest.af != svc->af && cmd != IPVS_CMD_DEL_DEST) {
/* The synchronization protocol is incompatible /* The synchronization protocol is incompatible
* with mixed family services * with mixed family services
*/ */
......
...@@ -625,8 +625,12 @@ nft_match_select_ops(const struct nft_ctx *ctx, ...@@ -625,8 +625,12 @@ nft_match_select_ops(const struct nft_ctx *ctx,
struct xt_match *match = nft_match->ops.data; struct xt_match *match = nft_match->ops.data;
if (strcmp(match->name, mt_name) == 0 && if (strcmp(match->name, mt_name) == 0 &&
match->revision == rev && match->family == family) match->revision == rev && match->family == family) {
if (!try_module_get(match->me))
return ERR_PTR(-ENOENT);
return &nft_match->ops; return &nft_match->ops;
}
} }
match = xt_request_find_match(family, mt_name, rev); match = xt_request_find_match(family, mt_name, rev);
...@@ -695,8 +699,12 @@ nft_target_select_ops(const struct nft_ctx *ctx, ...@@ -695,8 +699,12 @@ nft_target_select_ops(const struct nft_ctx *ctx,
struct xt_target *target = nft_target->ops.data; struct xt_target *target = nft_target->ops.data;
if (strcmp(target->name, tg_name) == 0 && if (strcmp(target->name, tg_name) == 0 &&
target->revision == rev && target->family == family) target->revision == rev && target->family == family) {
if (!try_module_get(target->me))
return ERR_PTR(-ENOENT);
return &nft_target->ops; return &nft_target->ops;
}
} }
target = xt_request_find_target(family, tg_name, rev); target = xt_request_find_target(family, tg_name, rev);
......
...@@ -378,12 +378,11 @@ static int recent_mt_check(const struct xt_mtchk_param *par, ...@@ -378,12 +378,11 @@ static int recent_mt_check(const struct xt_mtchk_param *par,
mutex_lock(&recent_mutex); mutex_lock(&recent_mutex);
t = recent_table_lookup(recent_net, info->name); t = recent_table_lookup(recent_net, info->name);
if (t != NULL) { if (t != NULL) {
if (info->hit_count > t->nstamps_max_mask) { if (nstamp_mask > t->nstamps_max_mask) {
pr_info("hitcount (%u) is larger than packets to be remembered (%u) for table %s\n", spin_lock_bh(&recent_lock);
info->hit_count, t->nstamps_max_mask + 1, recent_table_flush(t);
info->name); t->nstamps_max_mask = nstamp_mask;
ret = -EINVAL; spin_unlock_bh(&recent_lock);
goto out;
} }
t->refcnt++; t->refcnt++;
......
...@@ -243,12 +243,13 @@ static int ...@@ -243,12 +243,13 @@ static int
extract_icmp6_fields(const struct sk_buff *skb, extract_icmp6_fields(const struct sk_buff *skb,
unsigned int outside_hdrlen, unsigned int outside_hdrlen,
int *protocol, int *protocol,
struct in6_addr **raddr, const struct in6_addr **raddr,
struct in6_addr **laddr, const struct in6_addr **laddr,
__be16 *rport, __be16 *rport,
__be16 *lport) __be16 *lport,
struct ipv6hdr *ipv6_var)
{ {
struct ipv6hdr *inside_iph, _inside_iph; const struct ipv6hdr *inside_iph;
struct icmp6hdr *icmph, _icmph; struct icmp6hdr *icmph, _icmph;
__be16 *ports, _ports[2]; __be16 *ports, _ports[2];
u8 inside_nexthdr; u8 inside_nexthdr;
...@@ -263,12 +264,14 @@ extract_icmp6_fields(const struct sk_buff *skb, ...@@ -263,12 +264,14 @@ extract_icmp6_fields(const struct sk_buff *skb,
if (icmph->icmp6_type & ICMPV6_INFOMSG_MASK) if (icmph->icmp6_type & ICMPV6_INFOMSG_MASK)
return 1; return 1;
inside_iph = skb_header_pointer(skb, outside_hdrlen + sizeof(_icmph), sizeof(_inside_iph), &_inside_iph); inside_iph = skb_header_pointer(skb, outside_hdrlen + sizeof(_icmph),
sizeof(*ipv6_var), ipv6_var);
if (inside_iph == NULL) if (inside_iph == NULL)
return 1; return 1;
inside_nexthdr = inside_iph->nexthdr; inside_nexthdr = inside_iph->nexthdr;
inside_hdrlen = ipv6_skip_exthdr(skb, outside_hdrlen + sizeof(_icmph) + sizeof(_inside_iph), inside_hdrlen = ipv6_skip_exthdr(skb, outside_hdrlen + sizeof(_icmph) +
sizeof(*ipv6_var),
&inside_nexthdr, &inside_fragoff); &inside_nexthdr, &inside_fragoff);
if (inside_hdrlen < 0) if (inside_hdrlen < 0)
return 1; /* hjm: Packet has no/incomplete transport layer headers. */ 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,10 +318,10 @@ xt_socket_get_sock_v6(struct net *net, const u8 protocol,
static bool static bool
socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par) socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par)
{ {
struct ipv6hdr *iph = ipv6_hdr(skb); struct ipv6hdr ipv6_var, *iph = ipv6_hdr(skb);
struct udphdr _hdr, *hp = NULL; struct udphdr _hdr, *hp = NULL;
struct sock *sk = skb->sk; struct sock *sk = skb->sk;
struct in6_addr *daddr = NULL, *saddr = NULL; const struct in6_addr *daddr = NULL, *saddr = NULL;
__be16 uninitialized_var(dport), uninitialized_var(sport); __be16 uninitialized_var(dport), uninitialized_var(sport);
int thoff = 0, uninitialized_var(tproto); int thoff = 0, uninitialized_var(tproto);
const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo; 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,7 +345,7 @@ socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par)
} else if (tproto == IPPROTO_ICMPV6) { } else if (tproto == IPPROTO_ICMPV6) {
if (extract_icmp6_fields(skb, thoff, &tproto, &saddr, &daddr, if (extract_icmp6_fields(skb, thoff, &tproto, &saddr, &daddr,
&sport, &dport)) &sport, &dport, &ipv6_var))
return false; return false;
} else { } else {
return false; return false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment