netfilter: conntrack: remove __nf_ct_unconfirmed_destroy
authorFlorian Westphal <fw@strlen.de>
Mon, 11 Apr 2022 11:01:23 +0000 (13:01 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Fri, 13 May 2022 16:52:17 +0000 (18:52 +0200)
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: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_helper.c
net/netfilter/nfnetlink_cttimeout.c

index 7631094..7b4b3f5 100644 (file)
@@ -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);
 
index 8dec42e..c12a87e 100644 (file)
@@ -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);
 
index 9bc4ebe..f069c24 100644 (file)
@@ -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);