Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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


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
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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
			 */
+10 −2
Original line number Diff line number Diff line
@@ -625,9 +625,13 @@ 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);
	if (IS_ERR(match))
@@ -695,9 +699,13 @@ 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);
	if (IS_ERR(target))
+5 −6
Original line number Diff line number Diff line
@@ -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++;
+12 −9
Original line number Diff line number Diff line
@@ -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;