Commit ace53fdc authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso
Browse files

netfilter: conntrack: remove __nf_ct_unconfirmed_destroy



Its not needed anymore:

A. If entry is totally new, then the rcu-protected resource
must already have been removed from global visibility before call
to nf_ct_iterate_destroy.

B. If entry was allocated before, but is not yet in the hash table
   (uncofirmed case), genid gets incremented and synchronize_rcu() call
   makes sure access has completed.

C. Next attempt to peek at extension area will fail for unconfirmed
  conntracks, because ext->genid != genid.

D. Conntracks in the hash are iterated as before.

Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 42df4fb9
Loading
Loading
Loading
Loading
+13 −33
Original line number Diff line number Diff line
@@ -2457,34 +2457,6 @@ static int iter_net_only(struct nf_conn *i, void *data)
	return d->iter(i, d->data);
}

static void
__nf_ct_unconfirmed_destroy(struct net *net)
{
	int cpu;

	for_each_possible_cpu(cpu) {
		struct nf_conntrack_tuple_hash *h;
		struct hlist_nulls_node *n;
		struct ct_pcpu *pcpu;

		pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu);

		spin_lock_bh(&pcpu->lock);
		hlist_nulls_for_each_entry(h, n, &pcpu->unconfirmed, hnnode) {
			struct nf_conn *ct;

			ct = nf_ct_tuplehash_to_ctrack(h);

			/* we cannot call iter() on unconfirmed list, the
			 * owning cpu can reallocate ct->ext at any time.
			 */
			set_bit(IPS_DYING_BIT, &ct->status);
		}
		spin_unlock_bh(&pcpu->lock);
		cond_resched();
	}
}

void nf_ct_iterate_cleanup_net(struct net *net,
			       int (*iter)(struct nf_conn *i, void *data),
			       void *data, u32 portid, int report)
@@ -2527,26 +2499,34 @@ nf_ct_iterate_destroy(int (*iter)(struct nf_conn *i, void *data), void *data)

		if (atomic_read(&cnet->count) == 0)
			continue;
		__nf_ct_unconfirmed_destroy(net);
		nf_queue_nf_hook_drop(net);
	}
	up_read(&net_rwsem);

	/* Need to wait for netns cleanup worker to finish, if its
	 * running -- it might have deleted a net namespace from
	 * the global list, so our __nf_ct_unconfirmed_destroy() might
	 * not have affected all namespaces.
	 * the global list, so hook drop above might not have
	 * affected all namespaces.
	 */
	net_ns_barrier();

	/* a conntrack could have been unlinked from unconfirmed list
	 * before we grabbed pcpu lock in __nf_ct_unconfirmed_destroy().
	/* a skb w. unconfirmed conntrack could have been reinjected just
	 * before we called nf_queue_nf_hook_drop().
	 *
	 * This makes sure its inserted into conntrack table.
	 */
	synchronize_net();

	nf_ct_ext_bump_genid();
	nf_ct_iterate_cleanup(iter, data, 0, 0);

	/* Another cpu might be in a rcu read section with
	 * rcu protected pointer cleared in iter callback
	 * or hidden via nf_ct_ext_bump_genid() above.
	 *
	 * Wait until those are done.
	 */
	synchronize_rcu();
}
EXPORT_SYMBOL_GPL(nf_ct_iterate_destroy);

+0 −5
Original line number Diff line number Diff line
@@ -468,11 +468,6 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)

	nf_ct_expect_iterate_destroy(expect_iter_me, NULL);
	nf_ct_iterate_destroy(unhelp, me);

	/* Maybe someone has gotten the helper already when unhelp above.
	 * So need to wait it.
	 */
	synchronize_rcu();
}
EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister);

+0 −1
Original line number Diff line number Diff line
@@ -674,7 +674,6 @@ static void __exit cttimeout_exit(void)
	RCU_INIT_POINTER(nf_ct_timeout_hook, NULL);

	nf_ct_iterate_destroy(untimeout, NULL);
	synchronize_rcu();
}

module_init(cttimeout_init);