Commit 4761df52 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files
Pablo Neira Ayuso says:

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

1) Use kfree_rcu(ptr, rcu) variant, using kfree_rcu(ptr) was not
   intentional. From Eric Dumazet.

2) Use-after-free in netfilter hook core, from Eric Dumazet.

3) Missing rcu read lock side for netfilter egress hook,
   from Florian Westphal.

4) nf_queue assume state->sk is full socket while it might not be.
   Invoke sock_gen_put(), from Florian Westphal.

5) Add selftest to exercise the reported KASAN splat in 4)

6) Fix possible use-after-free in nf_queue in case sk_refcnt is 0.
   Also from Florian.

7) Use input interface index only for hardware offload, not for
   the software plane. This breaks tc ct action. Patch from Paul Blakey.

* git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf:
  net/sched: act_ct: Fix flow table lookup failure with no originating ifindex
  netfilter: nf_queue: handle socket prefetch
  netfilter: nf_queue: fix possible use-after-free
  selftests: netfilter: add nfqueue TCP_NEW_SYN_RECV socket race test
  netfilter: nf_queue: don't assume sk is full socket
  netfilter: egress: silence egress hook lockdep splats
  netfilter: fix use-after-free in __nf_register_net_hook()
  netfilter: nf_tables: prefer kfree_rcu(ptr, rcu) variant
====================

Link: https://lore.kernel.org/r/20220301215337.378405-1-pablo@netfilter.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents b8d06ce7 db6140e5
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -101,7 +101,11 @@ static inline struct sk_buff *nf_hook_egress(struct sk_buff *skb, int *rc,
	nf_hook_state_init(&state, NF_NETDEV_EGRESS,
			   NFPROTO_NETDEV, dev, NULL, NULL,
			   dev_net(dev), NULL);

	/* nf assumes rcu_read_lock, not just read_lock_bh */
	rcu_read_lock();
	ret = nf_hook_slow(skb, &state, e, 0);
	rcu_read_unlock();

	if (ret == 1) {
		return skb;
+5 −1
Original line number Diff line number Diff line
@@ -96,6 +96,7 @@ enum flow_offload_xmit_type {
	FLOW_OFFLOAD_XMIT_NEIGH,
	FLOW_OFFLOAD_XMIT_XFRM,
	FLOW_OFFLOAD_XMIT_DIRECT,
	FLOW_OFFLOAD_XMIT_TC,
};

#define NF_FLOW_TABLE_ENCAP_MAX		2
@@ -127,7 +128,7 @@ struct flow_offload_tuple {
	struct { }			__hash;

	u8				dir:2,
					xmit_type:2,
					xmit_type:3,
					encap_num:2,
					in_vlan_ingress:2;
	u16				mtu;
@@ -142,6 +143,9 @@ struct flow_offload_tuple {
			u8		h_source[ETH_ALEN];
			u8		h_dest[ETH_ALEN];
		} out;
		struct {
			u32		iifidx;
		} tc;
	};
};

+1 −1
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ void nf_register_queue_handler(const struct nf_queue_handler *qh);
void nf_unregister_queue_handler(void);
void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);

void nf_queue_entry_get_refs(struct nf_queue_entry *entry);
bool nf_queue_entry_get_refs(struct nf_queue_entry *entry);
void nf_queue_entry_free(struct nf_queue_entry *entry);

static inline void init_hashrandom(u32 *jhash_initval)
+3 −2
Original line number Diff line number Diff line
@@ -428,14 +428,15 @@ static int __nf_register_net_hook(struct net *net, int pf,
	p = nf_entry_dereference(*pp);
	new_hooks = nf_hook_entries_grow(p, reg);

	if (!IS_ERR(new_hooks))
	if (!IS_ERR(new_hooks)) {
		hooks_validate(new_hooks);
		rcu_assign_pointer(*pp, new_hooks);
	}

	mutex_unlock(&nf_hook_mutex);
	if (IS_ERR(new_hooks))
		return PTR_ERR(new_hooks);

	hooks_validate(new_hooks);
#ifdef CONFIG_NETFILTER_INGRESS
	if (nf_ingress_hook(reg, pf))
		net_inc_ingress_queue();
+5 −1
Original line number Diff line number Diff line
@@ -110,7 +110,11 @@ static int nf_flow_rule_match(struct nf_flow_match *match,
		nf_flow_rule_lwt_match(match, tun_info);
	}

	if (tuple->xmit_type == FLOW_OFFLOAD_XMIT_TC)
		key->meta.ingress_ifindex = tuple->tc.iifidx;
	else
		key->meta.ingress_ifindex = tuple->iifidx;

	mask->meta.ingress_ifindex = 0xffffffff;

	if (tuple->encap_num > 0 && !(tuple->in_vlan_ingress & BIT(0)) &&
Loading