Commit 1b54f4fa 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) Fix gcc-10 compilation warning in nf_conntrack, from Arnd Bergmann.

2) Add NF_FLOW_HW_PENDING to avoid races between stats and deletion
   commands, from Paul Blakey.

3) Remove WQ_MEM_RECLAIM from the offload workqueue, from Roi Dayan.

4) Infinite loop when removing nf_conntrack module, from Florian Westphal.

5) Set NF_FLOW_TEARDOWN bit on expiration to avoid races when refreshing
   the timeout from the software path.

6) Missing nft_set_elem_expired() check in the rbtree, from Phil Sutter.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c9e2053d 340eaff6
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -87,7 +87,7 @@ struct nf_conn {
	struct hlist_node	nat_bysource;
#endif
	/* all members below initialized via memset */
	u8 __nfct_init_offset[0];
	struct { } __nfct_init_offset;

	/* If we were expected by an expectation, this will be it */
	struct nf_conn *master;
+1 −0
Original line number Diff line number Diff line
@@ -127,6 +127,7 @@ enum nf_flow_flags {
	NF_FLOW_HW_DYING,
	NF_FLOW_HW_DEAD,
	NF_FLOW_HW_REFRESH,
	NF_FLOW_HW_PENDING,
};

enum flow_offload_type {
+14 −3
Original line number Diff line number Diff line
@@ -1519,9 +1519,9 @@ __nf_conntrack_alloc(struct net *net,
	ct->status = 0;
	ct->timeout = 0;
	write_pnet(&ct->ct_net, net);
	memset(&ct->__nfct_init_offset[0], 0,
	memset(&ct->__nfct_init_offset, 0,
	       offsetof(struct nf_conn, proto) -
	       offsetof(struct nf_conn, __nfct_init_offset[0]));
	       offsetof(struct nf_conn, __nfct_init_offset));

	nf_ct_zone_add(ct, zone);

@@ -2139,8 +2139,19 @@ get_next_corpse(int (*iter)(struct nf_conn *i, void *data),
		nf_conntrack_lock(lockp);
		if (*bucket < nf_conntrack_htable_size) {
			hlist_nulls_for_each_entry(h, n, &nf_conntrack_hash[*bucket], hnnode) {
				if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL)
				if (NF_CT_DIRECTION(h) != IP_CT_DIR_REPLY)
					continue;
				/* All nf_conn objects are added to hash table twice, one
				 * for original direction tuple, once for the reply tuple.
				 *
				 * Exception: In the IPS_NAT_CLASH case, only the reply
				 * tuple is added (the original tuple already existed for
				 * a different object).
				 *
				 * We only need to call the iterator once for each
				 * conntrack, so we just use the 'reply' direction
				 * tuple while iterating.
				 */
				ct = nf_ct_tuplehash_to_ctrack(h);
				if (iter(ct, data))
					goto found;
+5 −3
Original line number Diff line number Diff line
@@ -284,7 +284,7 @@ static void flow_offload_del(struct nf_flowtable *flow_table,

	if (nf_flow_has_expired(flow))
		flow_offload_fixup_ct(flow->ct);
	else if (test_bit(NF_FLOW_TEARDOWN, &flow->flags))
	else
		flow_offload_fixup_ct_timeout(flow->ct);

	flow_offload_free(flow);
@@ -361,8 +361,10 @@ static void nf_flow_offload_gc_step(struct flow_offload *flow, void *data)
{
	struct nf_flowtable *flow_table = data;

	if (nf_flow_has_expired(flow) || nf_ct_is_dying(flow->ct) ||
	    test_bit(NF_FLOW_TEARDOWN, &flow->flags)) {
	if (nf_flow_has_expired(flow) || nf_ct_is_dying(flow->ct))
		set_bit(NF_FLOW_TEARDOWN, &flow->flags);

	if (test_bit(NF_FLOW_TEARDOWN, &flow->flags)) {
		if (test_bit(NF_FLOW_HW, &flow->flags)) {
			if (!test_bit(NF_FLOW_HW_DYING, &flow->flags))
				nf_flow_offload_del(flow_table, flow);
+8 −2
Original line number Diff line number Diff line
@@ -817,6 +817,7 @@ static void flow_offload_work_handler(struct work_struct *work)
			WARN_ON_ONCE(1);
	}

	clear_bit(NF_FLOW_HW_PENDING, &offload->flow->flags);
	kfree(offload);
}

@@ -831,9 +832,14 @@ nf_flow_offload_work_alloc(struct nf_flowtable *flowtable,
{
	struct flow_offload_work *offload;

	if (test_and_set_bit(NF_FLOW_HW_PENDING, &flow->flags))
		return NULL;

	offload = kmalloc(sizeof(struct flow_offload_work), GFP_ATOMIC);
	if (!offload)
	if (!offload) {
		clear_bit(NF_FLOW_HW_PENDING, &flow->flags);
		return NULL;
	}

	offload->cmd = cmd;
	offload->flow = flow;
@@ -1056,7 +1062,7 @@ static struct flow_indr_block_entry block_ing_entry = {
int nf_flow_table_offload_init(void)
{
	nf_flow_offload_wq  = alloc_workqueue("nf_flow_table_offload",
					      WQ_UNBOUND | WQ_MEM_RECLAIM, 0);
					      WQ_UNBOUND, 0);
	if (!nf_flow_offload_wq)
		return -ENOMEM;

Loading