mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
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>
This commit is contained in:
commit
ee92259849
4 changed files with 28 additions and 18 deletions
|
@ -3402,7 +3402,7 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info)
|
|||
if (udest.af == 0)
|
||||
udest.af = svc->af;
|
||||
|
||||
if (udest.af != svc->af) {
|
||||
if (udest.af != svc->af && cmd != IPVS_CMD_DEL_DEST) {
|
||||
/* The synchronization protocol is incompatible
|
||||
* with mixed family services
|
||||
*/
|
||||
|
|
|
@ -625,8 +625,12 @@ nft_match_select_ops(const struct nft_ctx *ctx,
|
|||
struct xt_match *match = nft_match->ops.data;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
match = xt_request_find_match(family, mt_name, rev);
|
||||
|
@ -695,8 +699,12 @@ nft_target_select_ops(const struct nft_ctx *ctx,
|
|||
struct xt_target *target = nft_target->ops.data;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
target = xt_request_find_target(family, tg_name, rev);
|
||||
|
|
|
@ -378,12 +378,11 @@ static int recent_mt_check(const struct xt_mtchk_param *par,
|
|||
mutex_lock(&recent_mutex);
|
||||
t = recent_table_lookup(recent_net, info->name);
|
||||
if (t != NULL) {
|
||||
if (info->hit_count > t->nstamps_max_mask) {
|
||||
pr_info("hitcount (%u) is larger than packets to be remembered (%u) for table %s\n",
|
||||
info->hit_count, t->nstamps_max_mask + 1,
|
||||
info->name);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
if (nstamp_mask > t->nstamps_max_mask) {
|
||||
spin_lock_bh(&recent_lock);
|
||||
recent_table_flush(t);
|
||||
t->nstamps_max_mask = nstamp_mask;
|
||||
spin_unlock_bh(&recent_lock);
|
||||
}
|
||||
|
||||
t->refcnt++;
|
||||
|
|
|
@ -243,12 +243,13 @@ static int
|
|||
extract_icmp6_fields(const struct sk_buff *skb,
|
||||
unsigned int outside_hdrlen,
|
||||
int *protocol,
|
||||
struct in6_addr **raddr,
|
||||
struct in6_addr **laddr,
|
||||
const struct in6_addr **raddr,
|
||||
const struct in6_addr **laddr,
|
||||
__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;
|
||||
__be16 *ports, _ports[2];
|
||||
u8 inside_nexthdr;
|
||||
|
@ -263,12 +264,14 @@ extract_icmp6_fields(const struct sk_buff *skb,
|
|||
if (icmph->icmp6_type & ICMPV6_INFOMSG_MASK)
|
||||
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)
|
||||
return 1;
|
||||
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);
|
||||
if (inside_hdrlen < 0)
|
||||
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,
|
|||
static bool
|
||||
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 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);
|
||||
int thoff = 0, uninitialized_var(tproto);
|
||||
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)
|
|||
|
||||
} else if (tproto == IPPROTO_ICMPV6) {
|
||||
if (extract_icmp6_fields(skb, thoff, &tproto, &saddr, &daddr,
|
||||
&sport, &dport))
|
||||
&sport, &dport, &ipv6_var))
|
||||
return false;
|
||||
} else {
|
||||
return false;
|
||||
|
|
Loading…
Reference in a new issue