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


Pablo Neira Ayuso says:

====================
Netfilter fixes for net

The following patchset contains Netfilter fixes for net:

1) Missing netns context in arp_tables, from Florian Westphal.

2) Underflow in flowtable reference counter, from wenxu.

3) Fix incorrect ethernet destination address in flowtable offload,
   from wenxu.

4) Check for status of neighbour entry, from wenxu.

5) Fix NAT port mangling, from wenxu.

6) Unbind callbacks from destroy path to cleanup hardware properly
   on flowtable removal.

7) Fix missing casting statistics timestamp, add nf_flowtable_time_stamp
   and use it.

8) NULL pointer exception when timeout argument is null in conntrack
   dccp and sctp protocol helpers, from Florian Westphal.

9) Possible nul-dereference in ipset with IPSET_ATTR_LINENO, also from
   Florian.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 30780d08 22dad713
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -106,6 +106,12 @@ struct flow_offload {
};

#define NF_FLOW_TIMEOUT (30 * HZ)
#define nf_flowtable_time_stamp	(u32)jiffies

static inline __s32 nf_flow_timeout_delta(unsigned int timeout)
{
	return (__s32)(timeout - nf_flowtable_time_stamp);
}

struct nf_flow_route {
	struct {
+16 −11
Original line number Diff line number Diff line
@@ -384,10 +384,11 @@ next: ;
	return 1;
}

static inline int check_target(struct arpt_entry *e, const char *name)
static int check_target(struct arpt_entry *e, struct net *net, const char *name)
{
	struct xt_entry_target *t = arpt_get_target(e);
	struct xt_tgchk_param par = {
		.net       = net,
		.table     = name,
		.entryinfo = e,
		.target    = t->u.kernel.target,
@@ -399,8 +400,9 @@ static inline int check_target(struct arpt_entry *e, const char *name)
	return xt_check_target(&par, t->u.target_size - sizeof(*t), 0, false);
}

static inline int
find_check_entry(struct arpt_entry *e, const char *name, unsigned int size,
static int
find_check_entry(struct arpt_entry *e, struct net *net, const char *name,
		 unsigned int size,
		 struct xt_percpu_counter_alloc_state *alloc_state)
{
	struct xt_entry_target *t;
@@ -419,7 +421,7 @@ find_check_entry(struct arpt_entry *e, const char *name, unsigned int size,
	}
	t->u.kernel.target = target;

	ret = check_target(e, name);
	ret = check_target(e, net, name);
	if (ret)
		goto err;
	return 0;
@@ -512,7 +514,9 @@ static inline void cleanup_entry(struct arpt_entry *e)
/* Checks and translates the user-supplied table segment (held in
 * newinfo).
 */
static int translate_table(struct xt_table_info *newinfo, void *entry0,
static int translate_table(struct net *net,
			   struct xt_table_info *newinfo,
			   void *entry0,
			   const struct arpt_replace *repl)
{
	struct xt_percpu_counter_alloc_state alloc_state = { 0 };
@@ -569,7 +573,7 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0,
	/* Finally, each sanity check must pass */
	i = 0;
	xt_entry_foreach(iter, entry0, newinfo->size) {
		ret = find_check_entry(iter, repl->name, repl->size,
		ret = find_check_entry(iter, net, repl->name, repl->size,
				       &alloc_state);
		if (ret != 0)
			break;
@@ -974,7 +978,7 @@ static int do_replace(struct net *net, const void __user *user,
		goto free_newinfo;
	}

	ret = translate_table(newinfo, loc_cpu_entry, &tmp);
	ret = translate_table(net, newinfo, loc_cpu_entry, &tmp);
	if (ret != 0)
		goto free_newinfo;

@@ -1149,7 +1153,8 @@ compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr,
	}
}

static int translate_compat_table(struct xt_table_info **pinfo,
static int translate_compat_table(struct net *net,
				  struct xt_table_info **pinfo,
				  void **pentry0,
				  const struct compat_arpt_replace *compatr)
{
@@ -1217,7 +1222,7 @@ static int translate_compat_table(struct xt_table_info **pinfo,
	repl.num_counters = 0;
	repl.counters = NULL;
	repl.size = newinfo->size;
	ret = translate_table(newinfo, entry1, &repl);
	ret = translate_table(net, newinfo, entry1, &repl);
	if (ret)
		goto free_newinfo;

@@ -1270,7 +1275,7 @@ static int compat_do_replace(struct net *net, void __user *user,
		goto free_newinfo;
	}

	ret = translate_compat_table(&newinfo, &loc_cpu_entry, &tmp);
	ret = translate_compat_table(net, &newinfo, &loc_cpu_entry, &tmp);
	if (ret != 0)
		goto free_newinfo;

@@ -1546,7 +1551,7 @@ int arpt_register_table(struct net *net,
	loc_cpu_entry = newinfo->entries;
	memcpy(loc_cpu_entry, repl->entries, repl->size);

	ret = translate_table(newinfo, loc_cpu_entry, repl);
	ret = translate_table(net, newinfo, loc_cpu_entry, repl);
	if (ret != 0)
		goto out_free;

+2 −1
Original line number Diff line number Diff line
@@ -1848,6 +1848,7 @@ static int ip_set_utest(struct net *net, struct sock *ctnl, struct sk_buff *skb,
	struct ip_set *set;
	struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {};
	int ret = 0;
	u32 lineno;

	if (unlikely(protocol_min_failed(attr) ||
		     !attr[IPSET_ATTR_SETNAME] ||
@@ -1864,7 +1865,7 @@ static int ip_set_utest(struct net *net, struct sock *ctnl, struct sk_buff *skb,
		return -IPSET_ERR_PROTOCOL;

	rcu_read_lock_bh();
	ret = set->variant->uadt(set, tb, IPSET_TEST, NULL, 0, 0);
	ret = set->variant->uadt(set, tb, IPSET_TEST, &lineno, 0, 0);
	rcu_read_unlock_bh();
	/* Userspace can't trigger element to be re-added */
	if (ret == -EAGAIN)
+3 −0
Original line number Diff line number Diff line
@@ -677,6 +677,9 @@ static int dccp_timeout_nlattr_to_obj(struct nlattr *tb[],
	unsigned int *timeouts = data;
	int i;

	if (!timeouts)
		 timeouts = dn->dccp_timeout;

	/* set default DCCP timeouts. */
	for (i=0; i<CT_DCCP_MAX; i++)
		timeouts[i] = dn->dccp_timeout[i];
+3 −0
Original line number Diff line number Diff line
@@ -594,6 +594,9 @@ static int sctp_timeout_nlattr_to_obj(struct nlattr *tb[],
	struct nf_sctp_net *sn = nf_sctp_pernet(net);
	int i;

	if (!timeouts)
		timeouts = sn->timeouts;

	/* set default SCTP timeouts. */
	for (i=0; i<SCTP_CONNTRACK_MAX; i++)
		timeouts[i] = sn->timeouts[i];
Loading