]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
drop some netfilter patches from 5.15
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 21 Sep 2023 09:28:36 +0000 (11:28 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 21 Sep 2023 09:28:36 +0000 (11:28 +0200)
queue-5.15/netfilter-nf_tables-adapt-set-backend-to-use-gc-tran.patch [deleted file]
queue-5.15/netfilter-nf_tables-fix-gc-transaction-races-with-ne.patch [deleted file]
queue-5.15/netfilter-nf_tables-fix-kdoc-warnings-after-gc-rewor.patch [deleted file]
queue-5.15/netfilter-nf_tables-gc-transaction-api-to-avoid-race.patch [deleted file]
queue-5.15/netfilter-nf_tables-gc-transaction-race-with-netns-d.patch [deleted file]
queue-5.15/netfilter-nf_tables-make-validation-state-per-table.patch [deleted file]
queue-5.15/netfilter-nf_tables-remove-busy-mark-and-gc-batch-ap.patch [deleted file]
queue-5.15/netfilter-nft_set_hash-mark-set-element-as-dead-when.patch [deleted file]
queue-5.15/series

diff --git a/queue-5.15/netfilter-nf_tables-adapt-set-backend-to-use-gc-tran.patch b/queue-5.15/netfilter-nf_tables-adapt-set-backend-to-use-gc-tran.patch
deleted file mode 100644 (file)
index cde6381..0000000
+++ /dev/null
@@ -1,557 +0,0 @@
-From 48cf24f34ae00731911dd80cb9e9d11b774ec428 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 9 Aug 2023 14:54:23 +0200
-Subject: netfilter: nf_tables: adapt set backend to use GC transaction API
-
-From: Pablo Neira Ayuso <pablo@netfilter.org>
-
-[ Upstream commit f6c383b8c31a93752a52697f8430a71dcbc46adf ]
-
-Use the GC transaction API to replace the old and buggy gc API and the
-busy mark approach.
-
-No set elements are removed from async garbage collection anymore,
-instead the _DEAD bit is set on so the set element is not visible from
-lookup path anymore. Async GC enqueues transaction work that might be
-aborted and retried later.
-
-rbtree and pipapo set backends does not set on the _DEAD bit from the
-sync GC path since this runs in control plane path where mutex is held.
-In this case, set elements are deactivated, removed and then released
-via RCU callback, sync GC never fails.
-
-Fixes: 3c4287f62044 ("nf_tables: Add set type for arbitrary concatenation of ranges")
-Fixes: 8d8540c4f5e0 ("netfilter: nft_set_rbtree: add timeout support")
-Fixes: 9d0982927e79 ("netfilter: nft_hash: add support for timeouts")
-Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/netfilter/nf_tables_api.c  |   7 +-
- net/netfilter/nft_set_hash.c   |  77 +++++++++++-------
- net/netfilter/nft_set_pipapo.c |  48 ++++++++---
- net/netfilter/nft_set_rbtree.c | 144 ++++++++++++++++++++-------------
- 4 files changed, 173 insertions(+), 103 deletions(-)
-
-diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
-index 2333f5da1eb97..616fd19d5cedc 100644
---- a/net/netfilter/nf_tables_api.c
-+++ b/net/netfilter/nf_tables_api.c
-@@ -6003,7 +6003,6 @@ static void nft_setelem_activate(struct net *net, struct nft_set *set,
-       if (nft_setelem_is_catchall(set, elem)) {
-               nft_set_elem_change_active(net, set, ext);
--              nft_set_elem_clear_busy(ext);
-       } else {
-               set->ops->activate(net, set, elem);
-       }
-@@ -6018,8 +6017,7 @@ static int nft_setelem_catchall_deactivate(const struct net *net,
-       list_for_each_entry(catchall, &set->catchall_list, list) {
-               ext = nft_set_elem_ext(set, catchall->elem);
--              if (!nft_is_active(net, ext) ||
--                  nft_set_elem_mark_busy(ext))
-+              if (!nft_is_active(net, ext))
-                       continue;
-               kfree(elem->priv);
-@@ -6719,8 +6717,7 @@ static int nft_set_catchall_flush(const struct nft_ctx *ctx,
-       list_for_each_entry_rcu(catchall, &set->catchall_list, list) {
-               ext = nft_set_elem_ext(set, catchall->elem);
--              if (!nft_set_elem_active(ext, genmask) ||
--                  nft_set_elem_mark_busy(ext))
-+              if (!nft_set_elem_active(ext, genmask))
-                       continue;
-               elem.priv = catchall->elem;
-diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c
-index 0b73cb0e752f7..960cbd56c0406 100644
---- a/net/netfilter/nft_set_hash.c
-+++ b/net/netfilter/nft_set_hash.c
-@@ -59,6 +59,8 @@ static inline int nft_rhash_cmp(struct rhashtable_compare_arg *arg,
-       if (memcmp(nft_set_ext_key(&he->ext), x->key, x->set->klen))
-               return 1;
-+      if (nft_set_elem_is_dead(&he->ext))
-+              return 1;
-       if (nft_set_elem_expired(&he->ext))
-               return 1;
-       if (!nft_set_elem_active(&he->ext, x->genmask))
-@@ -188,7 +190,6 @@ static void nft_rhash_activate(const struct net *net, const struct nft_set *set,
-       struct nft_rhash_elem *he = elem->priv;
-       nft_set_elem_change_active(net, set, &he->ext);
--      nft_set_elem_clear_busy(&he->ext);
- }
- static bool nft_rhash_flush(const struct net *net,
-@@ -196,12 +197,9 @@ static bool nft_rhash_flush(const struct net *net,
- {
-       struct nft_rhash_elem *he = priv;
--      if (!nft_set_elem_mark_busy(&he->ext) ||
--          !nft_is_active(net, &he->ext)) {
--              nft_set_elem_change_active(net, set, &he->ext);
--              return true;
--      }
--      return false;
-+      nft_set_elem_change_active(net, set, &he->ext);
-+
-+      return true;
- }
- static void *nft_rhash_deactivate(const struct net *net,
-@@ -218,9 +216,8 @@ static void *nft_rhash_deactivate(const struct net *net,
-       rcu_read_lock();
-       he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params);
--      if (he != NULL &&
--          !nft_rhash_flush(net, set, he))
--              he = NULL;
-+      if (he)
-+              nft_set_elem_change_active(net, set, &he->ext);
-       rcu_read_unlock();
-@@ -314,25 +311,48 @@ static bool nft_rhash_expr_needs_gc_run(const struct nft_set *set,
- static void nft_rhash_gc(struct work_struct *work)
- {
-+      struct nftables_pernet *nft_net;
-       struct nft_set *set;
-       struct nft_rhash_elem *he;
-       struct nft_rhash *priv;
--      struct nft_set_gc_batch *gcb = NULL;
-       struct rhashtable_iter hti;
-+      struct nft_trans_gc *gc;
-+      struct net *net;
-+      u32 gc_seq;
-       priv = container_of(work, struct nft_rhash, gc_work.work);
-       set  = nft_set_container_of(priv);
-+      net  = read_pnet(&set->net);
-+      nft_net = nft_pernet(net);
-+      gc_seq = READ_ONCE(nft_net->gc_seq);
-+
-+      gc = nft_trans_gc_alloc(set, gc_seq, GFP_KERNEL);
-+      if (!gc)
-+              goto done;
-       rhashtable_walk_enter(&priv->ht, &hti);
-       rhashtable_walk_start(&hti);
-       while ((he = rhashtable_walk_next(&hti))) {
-               if (IS_ERR(he)) {
--                      if (PTR_ERR(he) != -EAGAIN)
--                              break;
-+                      if (PTR_ERR(he) != -EAGAIN) {
-+                              nft_trans_gc_destroy(gc);
-+                              gc = NULL;
-+                              goto try_later;
-+                      }
-                       continue;
-               }
-+              /* Ruleset has been updated, try later. */
-+              if (READ_ONCE(nft_net->gc_seq) != gc_seq) {
-+                      nft_trans_gc_destroy(gc);
-+                      gc = NULL;
-+                      goto try_later;
-+              }
-+
-+              if (nft_set_elem_is_dead(&he->ext))
-+                      goto dead_elem;
-+
-               if (nft_set_ext_exists(&he->ext, NFT_SET_EXT_EXPRESSIONS) &&
-                   nft_rhash_expr_needs_gc_run(set, &he->ext))
-                       goto needs_gc_run;
-@@ -340,26 +360,26 @@ static void nft_rhash_gc(struct work_struct *work)
-               if (!nft_set_elem_expired(&he->ext))
-                       continue;
- needs_gc_run:
--              if (nft_set_elem_mark_busy(&he->ext))
--                      continue;
-+              nft_set_elem_dead(&he->ext);
-+dead_elem:
-+              gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
-+              if (!gc)
-+                      goto try_later;
--              gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC);
--              if (gcb == NULL)
--                      break;
--              rhashtable_remove_fast(&priv->ht, &he->node, nft_rhash_params);
--              atomic_dec(&set->nelems);
--              nft_set_gc_batch_add(gcb, he);
-+              nft_trans_gc_elem_add(gc, he);
-       }
-+
-+      gc = nft_trans_gc_catchall(gc, gc_seq);
-+
-+try_later:
-+      /* catchall list iteration requires rcu read side lock. */
-       rhashtable_walk_stop(&hti);
-       rhashtable_walk_exit(&hti);
--      he = nft_set_catchall_gc(set);
--      if (he) {
--              gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC);
--              if (gcb)
--                      nft_set_gc_batch_add(gcb, he);
--      }
--      nft_set_gc_batch_complete(gcb);
-+      if (gc)
-+              nft_trans_gc_queue_async_done(gc);
-+
-+done:
-       queue_delayed_work(system_power_efficient_wq, &priv->gc_work,
-                          nft_set_gc_interval(set));
- }
-@@ -422,7 +442,6 @@ static void nft_rhash_destroy(const struct nft_ctx *ctx,
-       };
-       cancel_delayed_work_sync(&priv->gc_work);
--      rcu_barrier();
-       rhashtable_free_and_destroy(&priv->ht, nft_rhash_elem_destroy,
-                                   (void *)&rhash_ctx);
- }
-diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c
-index 8c16681884b7e..0a49c59a22dbd 100644
---- a/net/netfilter/nft_set_pipapo.c
-+++ b/net/netfilter/nft_set_pipapo.c
-@@ -1536,16 +1536,34 @@ static void pipapo_drop(struct nft_pipapo_match *m,
-       }
- }
-+static void nft_pipapo_gc_deactivate(struct net *net, struct nft_set *set,
-+                                   struct nft_pipapo_elem *e)
-+
-+{
-+      struct nft_set_elem elem = {
-+              .priv   = e,
-+      };
-+
-+      nft_setelem_data_deactivate(net, set, &elem);
-+}
-+
- /**
-  * pipapo_gc() - Drop expired entries from set, destroy start and end elements
-  * @set:      nftables API set representation
-  * @m:                Matching data
-  */
--static void pipapo_gc(const struct nft_set *set, struct nft_pipapo_match *m)
-+static void pipapo_gc(const struct nft_set *_set, struct nft_pipapo_match *m)
- {
-+      struct nft_set *set = (struct nft_set *) _set;
-       struct nft_pipapo *priv = nft_set_priv(set);
-+      struct net *net = read_pnet(&set->net);
-       int rules_f0, first_rule = 0;
-       struct nft_pipapo_elem *e;
-+      struct nft_trans_gc *gc;
-+
-+      gc = nft_trans_gc_alloc(set, 0, GFP_KERNEL);
-+      if (!gc)
-+              return;
-       while ((rules_f0 = pipapo_rules_same_key(m->f, first_rule))) {
-               union nft_pipapo_map_bucket rulemap[NFT_PIPAPO_MAX_FIELDS];
-@@ -1569,13 +1587,20 @@ static void pipapo_gc(const struct nft_set *set, struct nft_pipapo_match *m)
-               f--;
-               i--;
-               e = f->mt[rulemap[i].to].e;
--              if (nft_set_elem_expired(&e->ext) &&
--                  !nft_set_elem_mark_busy(&e->ext)) {
-+
-+              /* synchronous gc never fails, there is no need to set on
-+               * NFT_SET_ELEM_DEAD_BIT.
-+               */
-+              if (nft_set_elem_expired(&e->ext)) {
-                       priv->dirty = true;
--                      pipapo_drop(m, rulemap);
--                      rcu_barrier();
--                      nft_set_elem_destroy(set, e, true);
-+                      gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC);
-+                      if (!gc)
-+                              break;
-+
-+                      nft_pipapo_gc_deactivate(net, set, e);
-+                      pipapo_drop(m, rulemap);
-+                      nft_trans_gc_elem_add(gc, e);
-                       /* And check again current first rule, which is now the
-                        * first we haven't checked.
-@@ -1585,11 +1610,11 @@ static void pipapo_gc(const struct nft_set *set, struct nft_pipapo_match *m)
-               }
-       }
--      e = nft_set_catchall_gc(set);
--      if (e)
--              nft_set_elem_destroy(set, e, true);
--
--      priv->last_gc = jiffies;
-+      gc = nft_trans_gc_catchall(gc, 0);
-+      if (gc) {
-+              nft_trans_gc_queue_sync_done(gc);
-+              priv->last_gc = jiffies;
-+      }
- }
- /**
-@@ -1725,7 +1750,6 @@ static void nft_pipapo_activate(const struct net *net,
-               return;
-       nft_set_elem_change_active(net, set, &e->ext);
--      nft_set_elem_clear_busy(&e->ext);
- }
- /**
-diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
-index 8d73fffd2d09d..7015153b7be18 100644
---- a/net/netfilter/nft_set_rbtree.c
-+++ b/net/netfilter/nft_set_rbtree.c
-@@ -46,6 +46,12 @@ static int nft_rbtree_cmp(const struct nft_set *set,
-                     set->klen);
- }
-+static bool nft_rbtree_elem_expired(const struct nft_rbtree_elem *rbe)
-+{
-+      return nft_set_elem_expired(&rbe->ext) ||
-+             nft_set_elem_is_dead(&rbe->ext);
-+}
-+
- static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set,
-                               const u32 *key, const struct nft_set_ext **ext,
-                               unsigned int seq)
-@@ -80,7 +86,7 @@ static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set
-                               continue;
-                       }
--                      if (nft_set_elem_expired(&rbe->ext))
-+                      if (nft_rbtree_elem_expired(rbe))
-                               return false;
-                       if (nft_rbtree_interval_end(rbe)) {
-@@ -98,7 +104,7 @@ static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set
-       if (set->flags & NFT_SET_INTERVAL && interval != NULL &&
-           nft_set_elem_active(&interval->ext, genmask) &&
--          !nft_set_elem_expired(&interval->ext) &&
-+          !nft_rbtree_elem_expired(interval) &&
-           nft_rbtree_interval_start(interval)) {
-               *ext = &interval->ext;
-               return true;
-@@ -215,6 +221,18 @@ static void *nft_rbtree_get(const struct net *net, const struct nft_set *set,
-       return rbe;
- }
-+static void nft_rbtree_gc_remove(struct net *net, struct nft_set *set,
-+                               struct nft_rbtree *priv,
-+                               struct nft_rbtree_elem *rbe)
-+{
-+      struct nft_set_elem elem = {
-+              .priv   = rbe,
-+      };
-+
-+      nft_setelem_data_deactivate(net, set, &elem);
-+      rb_erase(&rbe->node, &priv->root);
-+}
-+
- static int nft_rbtree_gc_elem(const struct nft_set *__set,
-                             struct nft_rbtree *priv,
-                             struct nft_rbtree_elem *rbe,
-@@ -222,11 +240,12 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set,
- {
-       struct nft_set *set = (struct nft_set *)__set;
-       struct rb_node *prev = rb_prev(&rbe->node);
-+      struct net *net = read_pnet(&set->net);
-       struct nft_rbtree_elem *rbe_prev;
--      struct nft_set_gc_batch *gcb;
-+      struct nft_trans_gc *gc;
--      gcb = nft_set_gc_batch_check(set, NULL, GFP_ATOMIC);
--      if (!gcb)
-+      gc = nft_trans_gc_alloc(set, 0, GFP_ATOMIC);
-+      if (!gc)
-               return -ENOMEM;
-       /* search for end interval coming before this element.
-@@ -244,17 +263,28 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set,
-       if (prev) {
-               rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node);
-+              nft_rbtree_gc_remove(net, set, priv, rbe_prev);
--              rb_erase(&rbe_prev->node, &priv->root);
--              atomic_dec(&set->nelems);
--              nft_set_gc_batch_add(gcb, rbe_prev);
-+              /* There is always room in this trans gc for this element,
-+               * memory allocation never actually happens, hence, the warning
-+               * splat in such case. No need to set NFT_SET_ELEM_DEAD_BIT,
-+               * this is synchronous gc which never fails.
-+               */
-+              gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC);
-+              if (WARN_ON_ONCE(!gc))
-+                      return -ENOMEM;
-+
-+              nft_trans_gc_elem_add(gc, rbe_prev);
-       }
--      rb_erase(&rbe->node, &priv->root);
--      atomic_dec(&set->nelems);
-+      nft_rbtree_gc_remove(net, set, priv, rbe);
-+      gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC);
-+      if (WARN_ON_ONCE(!gc))
-+              return -ENOMEM;
-+
-+      nft_trans_gc_elem_add(gc, rbe);
--      nft_set_gc_batch_add(gcb, rbe);
--      nft_set_gc_batch_complete(gcb);
-+      nft_trans_gc_queue_sync_done(gc);
-       return 0;
- }
-@@ -482,7 +512,6 @@ static void nft_rbtree_activate(const struct net *net,
-       struct nft_rbtree_elem *rbe = elem->priv;
-       nft_set_elem_change_active(net, set, &rbe->ext);
--      nft_set_elem_clear_busy(&rbe->ext);
- }
- static bool nft_rbtree_flush(const struct net *net,
-@@ -490,12 +519,9 @@ static bool nft_rbtree_flush(const struct net *net,
- {
-       struct nft_rbtree_elem *rbe = priv;
--      if (!nft_set_elem_mark_busy(&rbe->ext) ||
--          !nft_is_active(net, &rbe->ext)) {
--              nft_set_elem_change_active(net, set, &rbe->ext);
--              return true;
--      }
--      return false;
-+      nft_set_elem_change_active(net, set, &rbe->ext);
-+
-+      return true;
- }
- static void *nft_rbtree_deactivate(const struct net *net,
-@@ -572,26 +598,40 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx,
- static void nft_rbtree_gc(struct work_struct *work)
- {
--      struct nft_rbtree_elem *rbe, *rbe_end = NULL, *rbe_prev = NULL;
--      struct nft_set_gc_batch *gcb = NULL;
-+      struct nft_rbtree_elem *rbe, *rbe_end = NULL;
-+      struct nftables_pernet *nft_net;
-       struct nft_rbtree *priv;
-+      struct nft_trans_gc *gc;
-       struct rb_node *node;
-       struct nft_set *set;
-+      unsigned int gc_seq;
-       struct net *net;
--      u8 genmask;
-       priv = container_of(work, struct nft_rbtree, gc_work.work);
-       set  = nft_set_container_of(priv);
-       net  = read_pnet(&set->net);
--      genmask = nft_genmask_cur(net);
-+      nft_net = nft_pernet(net);
-+      gc_seq  = READ_ONCE(nft_net->gc_seq);
-+
-+      gc = nft_trans_gc_alloc(set, gc_seq, GFP_KERNEL);
-+      if (!gc)
-+              goto done;
-       write_lock_bh(&priv->lock);
-       write_seqcount_begin(&priv->count);
-       for (node = rb_first(&priv->root); node != NULL; node = rb_next(node)) {
-+
-+              /* Ruleset has been updated, try later. */
-+              if (READ_ONCE(nft_net->gc_seq) != gc_seq) {
-+                      nft_trans_gc_destroy(gc);
-+                      gc = NULL;
-+                      goto try_later;
-+              }
-+
-               rbe = rb_entry(node, struct nft_rbtree_elem, node);
--              if (!nft_set_elem_active(&rbe->ext, genmask))
--                      continue;
-+              if (nft_set_elem_is_dead(&rbe->ext))
-+                      goto dead_elem;
-               /* elements are reversed in the rbtree for historical reasons,
-                * from highest to lowest value, that is why end element is
-@@ -604,46 +644,36 @@ static void nft_rbtree_gc(struct work_struct *work)
-               if (!nft_set_elem_expired(&rbe->ext))
-                       continue;
--              if (nft_set_elem_mark_busy(&rbe->ext)) {
--                      rbe_end = NULL;
-+              nft_set_elem_dead(&rbe->ext);
-+
-+              if (!rbe_end)
-                       continue;
--              }
--              if (rbe_prev) {
--                      rb_erase(&rbe_prev->node, &priv->root);
--                      rbe_prev = NULL;
--              }
--              gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC);
--              if (!gcb)
--                      break;
-+              nft_set_elem_dead(&rbe_end->ext);
--              atomic_dec(&set->nelems);
--              nft_set_gc_batch_add(gcb, rbe);
--              rbe_prev = rbe;
-+              gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
-+              if (!gc)
-+                      goto try_later;
--              if (rbe_end) {
--                      atomic_dec(&set->nelems);
--                      nft_set_gc_batch_add(gcb, rbe_end);
--                      rb_erase(&rbe_end->node, &priv->root);
--                      rbe_end = NULL;
--              }
--              node = rb_next(node);
--              if (!node)
--                      break;
-+              nft_trans_gc_elem_add(gc, rbe_end);
-+              rbe_end = NULL;
-+dead_elem:
-+              gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
-+              if (!gc)
-+                      goto try_later;
-+
-+              nft_trans_gc_elem_add(gc, rbe);
-       }
--      if (rbe_prev)
--              rb_erase(&rbe_prev->node, &priv->root);
-+
-+      gc = nft_trans_gc_catchall(gc, gc_seq);
-+
-+try_later:
-       write_seqcount_end(&priv->count);
-       write_unlock_bh(&priv->lock);
--      rbe = nft_set_catchall_gc(set);
--      if (rbe) {
--              gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC);
--              if (gcb)
--                      nft_set_gc_batch_add(gcb, rbe);
--      }
--      nft_set_gc_batch_complete(gcb);
--
-+      if (gc)
-+              nft_trans_gc_queue_async_done(gc);
-+done:
-       queue_delayed_work(system_power_efficient_wq, &priv->gc_work,
-                          nft_set_gc_interval(set));
- }
--- 
-2.40.1
-
diff --git a/queue-5.15/netfilter-nf_tables-fix-gc-transaction-races-with-ne.patch b/queue-5.15/netfilter-nf_tables-fix-gc-transaction-races-with-ne.patch
deleted file mode 100644 (file)
index 411578a..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-From cca7d158a67d5df21dd05e4de7d05eb7734ed59b Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 15 Aug 2023 15:39:00 +0200
-Subject: netfilter: nf_tables: fix GC transaction races with netns and netlink
- event exit path
-
-From: Pablo Neira Ayuso <pablo@netfilter.org>
-
-[ Upstream commit 6a33d8b73dfac0a41f3877894b38082bd0c9a5bc ]
-
-Netlink event path is missing a synchronization point with GC
-transactions. Add GC sequence number update to netns release path and
-netlink event path, any GC transaction losing race will be discarded.
-
-Fixes: 5f68718b34a5 ("netfilter: nf_tables: GC transaction API to avoid race with control plane")
-Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-Signed-off-by: Florian Westphal <fw@strlen.de>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/netfilter/nf_tables_api.c | 36 +++++++++++++++++++++++++++++++----
- 1 file changed, 32 insertions(+), 4 deletions(-)
-
-diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
-index 75b04c01f7b81..3e17d2403d899 100644
---- a/net/netfilter/nf_tables_api.c
-+++ b/net/netfilter/nf_tables_api.c
-@@ -9202,6 +9202,22 @@ static void nft_set_commit_update(struct list_head *set_update_list)
-       }
- }
-+static unsigned int nft_gc_seq_begin(struct nftables_pernet *nft_net)
-+{
-+      unsigned int gc_seq;
-+
-+      /* Bump gc counter, it becomes odd, this is the busy mark. */
-+      gc_seq = READ_ONCE(nft_net->gc_seq);
-+      WRITE_ONCE(nft_net->gc_seq, ++gc_seq);
-+
-+      return gc_seq;
-+}
-+
-+static void nft_gc_seq_end(struct nftables_pernet *nft_net, unsigned int gc_seq)
-+{
-+      WRITE_ONCE(nft_net->gc_seq, ++gc_seq);
-+}
-+
- static int nf_tables_commit(struct net *net, struct sk_buff *skb)
- {
-       struct nftables_pernet *nft_net = nft_pernet(net);
-@@ -9287,9 +9303,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
-       WRITE_ONCE(nft_net->base_seq, base_seq);
--      /* Bump gc counter, it becomes odd, this is the busy mark. */
--      gc_seq = READ_ONCE(nft_net->gc_seq);
--      WRITE_ONCE(nft_net->gc_seq, ++gc_seq);
-+      gc_seq = nft_gc_seq_begin(nft_net);
-       /* step 3. Start new generation, rules_gen_X now in use. */
-       net->nft.gencursor = nft_gencursor_next(net);
-@@ -9480,7 +9494,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
-       nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN);
-       nf_tables_commit_audit_log(&adl, nft_net->base_seq);
--      WRITE_ONCE(nft_net->gc_seq, ++gc_seq);
-+      nft_gc_seq_end(nft_net, gc_seq);
-       nf_tables_commit_release(net);
-       return 0;
-@@ -10463,6 +10477,7 @@ static int nft_rcv_nl_event(struct notifier_block *this, unsigned long event,
-       struct net *net = n->net;
-       unsigned int deleted;
-       bool restart = false;
-+      unsigned int gc_seq;
-       if (event != NETLINK_URELEASE || n->protocol != NETLINK_NETFILTER)
-               return NOTIFY_DONE;
-@@ -10470,6 +10485,9 @@ static int nft_rcv_nl_event(struct notifier_block *this, unsigned long event,
-       nft_net = nft_pernet(net);
-       deleted = 0;
-       mutex_lock(&nft_net->commit_mutex);
-+
-+      gc_seq = nft_gc_seq_begin(nft_net);
-+
-       if (!list_empty(&nf_tables_destroy_list))
-               nf_tables_trans_destroy_flush_work();
- again:
-@@ -10492,6 +10510,8 @@ static int nft_rcv_nl_event(struct notifier_block *this, unsigned long event,
-               if (restart)
-                       goto again;
-       }
-+      nft_gc_seq_end(nft_net, gc_seq);
-+
-       mutex_unlock(&nft_net->commit_mutex);
-       return NOTIFY_DONE;
-@@ -10529,12 +10549,20 @@ static void __net_exit nf_tables_pre_exit_net(struct net *net)
- static void __net_exit nf_tables_exit_net(struct net *net)
- {
-       struct nftables_pernet *nft_net = nft_pernet(net);
-+      unsigned int gc_seq;
-       mutex_lock(&nft_net->commit_mutex);
-+
-+      gc_seq = nft_gc_seq_begin(nft_net);
-+
-       if (!list_empty(&nft_net->commit_list) ||
-           !list_empty(&nft_net->module_list))
-               __nf_tables_abort(net, NFNL_ABORT_NONE);
-+
-       __nft_release_tables(net);
-+
-+      nft_gc_seq_end(nft_net, gc_seq);
-+
-       mutex_unlock(&nft_net->commit_mutex);
-       WARN_ON_ONCE(!list_empty(&nft_net->tables));
-       WARN_ON_ONCE(!list_empty(&nft_net->module_list));
--- 
-2.40.1
-
diff --git a/queue-5.15/netfilter-nf_tables-fix-kdoc-warnings-after-gc-rewor.patch b/queue-5.15/netfilter-nf_tables-fix-kdoc-warnings-after-gc-rewor.patch
deleted file mode 100644 (file)
index ade4f90..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-From e815552d39d047879f8453c5a1007dc4be47bbf3 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 10 Aug 2023 23:59:03 +0200
-Subject: netfilter: nf_tables: fix kdoc warnings after gc rework
-
-From: Florian Westphal <fw@strlen.de>
-
-[ Upstream commit 08713cb006b6f07434f276c5ee214fb20c7fd965 ]
-
-Jakub Kicinski says:
-  We've got some new kdoc warnings here:
-  net/netfilter/nft_set_pipapo.c:1557: warning: Function parameter or member '_set' not described in 'pipapo_gc'
-  net/netfilter/nft_set_pipapo.c:1557: warning: Excess function parameter 'set' description in 'pipapo_gc'
-  include/net/netfilter/nf_tables.h:577: warning: Function parameter or member 'dead' not described in 'nft_set'
-
-Fixes: 5f68718b34a5 ("netfilter: nf_tables: GC transaction API to avoid race with control plane")
-Fixes: f6c383b8c31a ("netfilter: nf_tables: adapt set backend to use GC transaction API")
-Reported-by: Jakub Kicinski <kuba@kernel.org>
-Closes: https://lore.kernel.org/netdev/20230810104638.746e46f1@kernel.org/
-Signed-off-by: Florian Westphal <fw@strlen.de>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- include/net/netfilter/nf_tables.h | 1 +
- net/netfilter/nft_set_pipapo.c    | 2 +-
- 2 files changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
-index cd3b5b9db8890..86ffb222f4d74 100644
---- a/include/net/netfilter/nf_tables.h
-+++ b/include/net/netfilter/nf_tables.h
-@@ -499,6 +499,7 @@ struct nft_set_elem_expr {
-  *    @expr: stateful expression
-  *    @ops: set ops
-  *    @flags: set flags
-+ *    @dead: set will be freed, never cleared
-  *    @genmask: generation mask
-  *    @klen: key length
-  *    @dlen: data length
-diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c
-index 0a49c59a22dbd..03472c1d9d548 100644
---- a/net/netfilter/nft_set_pipapo.c
-+++ b/net/netfilter/nft_set_pipapo.c
-@@ -1549,7 +1549,7 @@ static void nft_pipapo_gc_deactivate(struct net *net, struct nft_set *set,
- /**
-  * pipapo_gc() - Drop expired entries from set, destroy start and end elements
-- * @set:      nftables API set representation
-+ * @_set:     nftables API set representation
-  * @m:                Matching data
-  */
- static void pipapo_gc(const struct nft_set *_set, struct nft_pipapo_match *m)
--- 
-2.40.1
-
diff --git a/queue-5.15/netfilter-nf_tables-gc-transaction-api-to-avoid-race.patch b/queue-5.15/netfilter-nf_tables-gc-transaction-api-to-avoid-race.patch
deleted file mode 100644 (file)
index 06dd390..0000000
+++ /dev/null
@@ -1,574 +0,0 @@
-From 96c686573801202fe04d4ebce7e3cf7aa8caea2a Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 9 Aug 2023 14:31:54 +0200
-Subject: netfilter: nf_tables: GC transaction API to avoid race with control
- plane
-
-From: Pablo Neira Ayuso <pablo@netfilter.org>
-
-[ Upstream commit 5f68718b34a531a556f2f50300ead2862278da26 ]
-
-The set types rhashtable and rbtree use a GC worker to reclaim memory.
-From system work queue, in periodic intervals, a scan of the table is
-done.
-
-The major caveat here is that the nft transaction mutex is not held.
-This causes a race between control plane and GC when they attempt to
-delete the same element.
-
-We cannot grab the netlink mutex from the work queue, because the
-control plane has to wait for the GC work queue in case the set is to be
-removed, so we get following deadlock:
-
-   cpu 1                                cpu2
-     GC work                            transaction comes in , lock nft mutex
-       `acquire nft mutex // BLOCKS
-                                        transaction asks to remove the set
-                                        set destruction calls cancel_work_sync()
-
-cancel_work_sync will now block forever, because it is waiting for the
-mutex the caller already owns.
-
-This patch adds a new API that deals with garbage collection in two
-steps:
-
-1) Lockless GC of expired elements sets on the NFT_SET_ELEM_DEAD_BIT
-   so they are not visible via lookup. Annotate current GC sequence in
-   the GC transaction. Enqueue GC transaction work as soon as it is
-   full. If ruleset is updated, then GC transaction is aborted and
-   retried later.
-
-2) GC work grabs the mutex. If GC sequence has changed then this GC
-   transaction lost race with control plane, abort it as it contains
-   stale references to objects and let GC try again later. If the
-   ruleset is intact, then this GC transaction deactivates and removes
-   the elements and it uses call_rcu() to destroy elements.
-
-Note that no elements are removed from GC lockless path, the _DEAD bit
-is set and pointers are collected. GC catchall does not remove the
-elements anymore too. There is a new set->dead flag that is set on to
-abort the GC transaction to deal with set->ops->destroy() path which
-removes the remaining elements in the set from commit_release, where no
-mutex is held.
-
-To deal with GC when mutex is held, which allows safe deactivate and
-removal, add sync GC API which releases the set element object via
-call_rcu(). This is used by rbtree and pipapo backends which also
-perform garbage collection from control plane path.
-
-Since element removal from sets can happen from control plane and
-element garbage collection/timeout, it is necessary to keep the set
-structure alive until all elements have been deactivated and destroyed.
-
-We cannot do a cancel_work_sync or flush_work in nft_set_destroy because
-its called with the transaction mutex held, but the aforementioned async
-work queue might be blocked on the very mutex that nft_set_destroy()
-callchain is sitting on.
-
-This gives us the choice of ABBA deadlock or UaF.
-
-To avoid both, add set->refs refcount_t member. The GC API can then
-increment the set refcount and release it once the elements have been
-free'd.
-
-Set backends are adapted to use the GC transaction API in a follow up
-patch entitled:
-
-  ("netfilter: nf_tables: use gc transaction API in set backends")
-
-This is joint work with Florian Westphal.
-
-Fixes: cfed7e1b1f8e ("netfilter: nf_tables: add set garbage collection helpers")
-Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- include/net/netfilter/nf_tables.h |  64 +++++++-
- net/netfilter/nf_tables_api.c     | 248 ++++++++++++++++++++++++++++--
- 2 files changed, 300 insertions(+), 12 deletions(-)
-
-diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
-index b8d967e0eb1e2..a6bf58316a5d8 100644
---- a/include/net/netfilter/nf_tables.h
-+++ b/include/net/netfilter/nf_tables.h
-@@ -477,6 +477,7 @@ struct nft_set_elem_expr {
-  *
-  *    @list: table set list node
-  *    @bindings: list of set bindings
-+ *    @refs: internal refcounting for async set destruction
-  *    @table: table this set belongs to
-  *    @net: netnamespace this set belongs to
-  *    @name: name of the set
-@@ -506,6 +507,7 @@ struct nft_set_elem_expr {
- struct nft_set {
-       struct list_head                list;
-       struct list_head                bindings;
-+      refcount_t                      refs;
-       struct nft_table                *table;
-       possible_net_t                  net;
-       char                            *name;
-@@ -527,7 +529,8 @@ struct nft_set {
-       struct list_head                pending_update;
-       /* runtime data below here */
-       const struct nft_set_ops        *ops ____cacheline_aligned;
--      u16                             flags:14,
-+      u16                             flags:13,
-+                                      dead:1,
-                                       genmask:2;
-       u8                              klen;
-       u8                              dlen;
-@@ -1527,6 +1530,32 @@ static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext)
-       clear_bit(NFT_SET_ELEM_BUSY_BIT, word);
- }
-+#define NFT_SET_ELEM_DEAD_MASK        (1 << 3)
-+
-+#if defined(__LITTLE_ENDIAN_BITFIELD)
-+#define NFT_SET_ELEM_DEAD_BIT 3
-+#elif defined(__BIG_ENDIAN_BITFIELD)
-+#define NFT_SET_ELEM_DEAD_BIT (BITS_PER_LONG - BITS_PER_BYTE + 3)
-+#else
-+#error
-+#endif
-+
-+static inline void nft_set_elem_dead(struct nft_set_ext *ext)
-+{
-+      unsigned long *word = (unsigned long *)ext;
-+
-+      BUILD_BUG_ON(offsetof(struct nft_set_ext, genmask) != 0);
-+      set_bit(NFT_SET_ELEM_DEAD_BIT, word);
-+}
-+
-+static inline int nft_set_elem_is_dead(const struct nft_set_ext *ext)
-+{
-+      unsigned long *word = (unsigned long *)ext;
-+
-+      BUILD_BUG_ON(offsetof(struct nft_set_ext, genmask) != 0);
-+      return test_bit(NFT_SET_ELEM_DEAD_BIT, word);
-+}
-+
- /**
-  *    struct nft_trans - nf_tables object update in transaction
-  *
-@@ -1658,6 +1687,38 @@ struct nft_trans_flowtable {
- #define nft_trans_flowtable_flags(trans)      \
-       (((struct nft_trans_flowtable *)trans->data)->flags)
-+#define NFT_TRANS_GC_BATCHCOUNT       256
-+
-+struct nft_trans_gc {
-+      struct list_head        list;
-+      struct net              *net;
-+      struct nft_set          *set;
-+      u32                     seq;
-+      u8                      count;
-+      void                    *priv[NFT_TRANS_GC_BATCHCOUNT];
-+      struct rcu_head         rcu;
-+};
-+
-+struct nft_trans_gc *nft_trans_gc_alloc(struct nft_set *set,
-+                                      unsigned int gc_seq, gfp_t gfp);
-+void nft_trans_gc_destroy(struct nft_trans_gc *trans);
-+
-+struct nft_trans_gc *nft_trans_gc_queue_async(struct nft_trans_gc *gc,
-+                                            unsigned int gc_seq, gfp_t gfp);
-+void nft_trans_gc_queue_async_done(struct nft_trans_gc *gc);
-+
-+struct nft_trans_gc *nft_trans_gc_queue_sync(struct nft_trans_gc *gc, gfp_t gfp);
-+void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans);
-+
-+void nft_trans_gc_elem_add(struct nft_trans_gc *gc, void *priv);
-+
-+struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
-+                                         unsigned int gc_seq);
-+
-+void nft_setelem_data_deactivate(const struct net *net,
-+                               const struct nft_set *set,
-+                               struct nft_set_elem *elem);
-+
- int __init nft_chain_filter_init(void);
- void nft_chain_filter_fini(void);
-@@ -1684,6 +1745,7 @@ struct nftables_pernet {
-       struct mutex            commit_mutex;
-       u64                     table_handle;
-       unsigned int            base_seq;
-+      unsigned int            gc_seq;
- };
- extern unsigned int nf_tables_net_id;
-diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
-index dde19be41610d..2333f5da1eb97 100644
---- a/net/netfilter/nf_tables_api.c
-+++ b/net/netfilter/nf_tables_api.c
-@@ -31,7 +31,9 @@ static LIST_HEAD(nf_tables_expressions);
- static LIST_HEAD(nf_tables_objects);
- static LIST_HEAD(nf_tables_flowtables);
- static LIST_HEAD(nf_tables_destroy_list);
-+static LIST_HEAD(nf_tables_gc_list);
- static DEFINE_SPINLOCK(nf_tables_destroy_list_lock);
-+static DEFINE_SPINLOCK(nf_tables_gc_list_lock);
- enum {
-       NFT_VALIDATE_SKIP       = 0,
-@@ -120,6 +122,9 @@ static void nft_validate_state_update(struct nft_table *table, u8 new_validate_s
- static void nf_tables_trans_destroy_work(struct work_struct *w);
- static DECLARE_WORK(trans_destroy_work, nf_tables_trans_destroy_work);
-+static void nft_trans_gc_work(struct work_struct *work);
-+static DECLARE_WORK(trans_gc_work, nft_trans_gc_work);
-+
- static void nft_ctx_init(struct nft_ctx *ctx,
-                        struct net *net,
-                        const struct sk_buff *skb,
-@@ -581,10 +586,6 @@ static int nft_trans_set_add(const struct nft_ctx *ctx, int msg_type,
-       return __nft_trans_set_add(ctx, msg_type, set, NULL);
- }
--static void nft_setelem_data_deactivate(const struct net *net,
--                                      const struct nft_set *set,
--                                      struct nft_set_elem *elem);
--
- static int nft_mapelem_deactivate(const struct nft_ctx *ctx,
-                                 struct nft_set *set,
-                                 const struct nft_set_iter *iter,
-@@ -4756,6 +4757,7 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
-       INIT_LIST_HEAD(&set->bindings);
-       INIT_LIST_HEAD(&set->catchall_list);
-+      refcount_set(&set->refs, 1);
-       set->table = table;
-       write_pnet(&set->net, net);
-       set->ops = ops;
-@@ -4823,6 +4825,14 @@ static void nft_set_catchall_destroy(const struct nft_ctx *ctx,
-       }
- }
-+static void nft_set_put(struct nft_set *set)
-+{
-+      if (refcount_dec_and_test(&set->refs)) {
-+              kfree(set->name);
-+              kvfree(set);
-+      }
-+}
-+
- static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set)
- {
-       int i;
-@@ -4835,8 +4845,7 @@ static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set)
-       set->ops->destroy(ctx, set);
-       nft_set_catchall_destroy(ctx, set);
--      kfree(set->name);
--      kvfree(set);
-+      nft_set_put(set);
- }
- static int nf_tables_delset(struct sk_buff *skb, const struct nfnl_info *info,
-@@ -5901,7 +5910,8 @@ struct nft_set_ext *nft_set_catchall_lookup(const struct net *net,
-       list_for_each_entry_rcu(catchall, &set->catchall_list, list) {
-               ext = nft_set_elem_ext(set, catchall->elem);
-               if (nft_set_elem_active(ext, genmask) &&
--                  !nft_set_elem_expired(ext))
-+                  !nft_set_elem_expired(ext) &&
-+                  !nft_set_elem_is_dead(ext))
-                       return ext;
-       }
-@@ -6545,9 +6555,9 @@ static void nft_setelem_data_activate(const struct net *net,
-               nft_use_inc_restore(&(*nft_set_ext_obj(ext))->use);
- }
--static void nft_setelem_data_deactivate(const struct net *net,
--                                      const struct nft_set *set,
--                                      struct nft_set_elem *elem)
-+void nft_setelem_data_deactivate(const struct net *net,
-+                               const struct nft_set *set,
-+                               struct nft_set_elem *elem)
- {
-       const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
-@@ -8882,6 +8892,207 @@ void nft_chain_del(struct nft_chain *chain)
-       list_del_rcu(&chain->list);
- }
-+static void nft_trans_gc_setelem_remove(struct nft_ctx *ctx,
-+                                      struct nft_trans_gc *trans)
-+{
-+      void **priv = trans->priv;
-+      unsigned int i;
-+
-+      for (i = 0; i < trans->count; i++) {
-+              struct nft_set_elem elem = {
-+                      .priv = priv[i],
-+              };
-+
-+              nft_setelem_data_deactivate(ctx->net, trans->set, &elem);
-+              nft_setelem_remove(ctx->net, trans->set, &elem);
-+      }
-+}
-+
-+void nft_trans_gc_destroy(struct nft_trans_gc *trans)
-+{
-+      nft_set_put(trans->set);
-+      put_net(trans->net);
-+      kfree(trans);
-+}
-+
-+static void nft_trans_gc_trans_free(struct rcu_head *rcu)
-+{
-+      struct nft_set_elem elem = {};
-+      struct nft_trans_gc *trans;
-+      struct nft_ctx ctx = {};
-+      unsigned int i;
-+
-+      trans = container_of(rcu, struct nft_trans_gc, rcu);
-+      ctx.net = read_pnet(&trans->set->net);
-+
-+      for (i = 0; i < trans->count; i++) {
-+              elem.priv = trans->priv[i];
-+              if (!nft_setelem_is_catchall(trans->set, &elem))
-+                      atomic_dec(&trans->set->nelems);
-+
-+              nf_tables_set_elem_destroy(&ctx, trans->set, elem.priv);
-+      }
-+
-+      nft_trans_gc_destroy(trans);
-+}
-+
-+static bool nft_trans_gc_work_done(struct nft_trans_gc *trans)
-+{
-+      struct nftables_pernet *nft_net;
-+      struct nft_ctx ctx = {};
-+
-+      nft_net = nft_pernet(trans->net);
-+
-+      mutex_lock(&nft_net->commit_mutex);
-+
-+      /* Check for race with transaction, otherwise this batch refers to
-+       * stale objects that might not be there anymore. Skip transaction if
-+       * set has been destroyed from control plane transaction in case gc
-+       * worker loses race.
-+       */
-+      if (READ_ONCE(nft_net->gc_seq) != trans->seq || trans->set->dead) {
-+              mutex_unlock(&nft_net->commit_mutex);
-+              return false;
-+      }
-+
-+      ctx.net = trans->net;
-+      ctx.table = trans->set->table;
-+
-+      nft_trans_gc_setelem_remove(&ctx, trans);
-+      mutex_unlock(&nft_net->commit_mutex);
-+
-+      return true;
-+}
-+
-+static void nft_trans_gc_work(struct work_struct *work)
-+{
-+      struct nft_trans_gc *trans, *next;
-+      LIST_HEAD(trans_gc_list);
-+
-+      spin_lock(&nf_tables_destroy_list_lock);
-+      list_splice_init(&nf_tables_gc_list, &trans_gc_list);
-+      spin_unlock(&nf_tables_destroy_list_lock);
-+
-+      list_for_each_entry_safe(trans, next, &trans_gc_list, list) {
-+              list_del(&trans->list);
-+              if (!nft_trans_gc_work_done(trans)) {
-+                      nft_trans_gc_destroy(trans);
-+                      continue;
-+              }
-+              call_rcu(&trans->rcu, nft_trans_gc_trans_free);
-+      }
-+}
-+
-+struct nft_trans_gc *nft_trans_gc_alloc(struct nft_set *set,
-+                                      unsigned int gc_seq, gfp_t gfp)
-+{
-+      struct net *net = read_pnet(&set->net);
-+      struct nft_trans_gc *trans;
-+
-+      trans = kzalloc(sizeof(*trans), gfp);
-+      if (!trans)
-+              return NULL;
-+
-+      refcount_inc(&set->refs);
-+      trans->set = set;
-+      trans->net = get_net(net);
-+      trans->seq = gc_seq;
-+
-+      return trans;
-+}
-+
-+void nft_trans_gc_elem_add(struct nft_trans_gc *trans, void *priv)
-+{
-+      trans->priv[trans->count++] = priv;
-+}
-+
-+static void nft_trans_gc_queue_work(struct nft_trans_gc *trans)
-+{
-+      spin_lock(&nf_tables_gc_list_lock);
-+      list_add_tail(&trans->list, &nf_tables_gc_list);
-+      spin_unlock(&nf_tables_gc_list_lock);
-+
-+      schedule_work(&trans_gc_work);
-+}
-+
-+static int nft_trans_gc_space(struct nft_trans_gc *trans)
-+{
-+      return NFT_TRANS_GC_BATCHCOUNT - trans->count;
-+}
-+
-+struct nft_trans_gc *nft_trans_gc_queue_async(struct nft_trans_gc *gc,
-+                                            unsigned int gc_seq, gfp_t gfp)
-+{
-+      if (nft_trans_gc_space(gc))
-+              return gc;
-+
-+      nft_trans_gc_queue_work(gc);
-+
-+      return nft_trans_gc_alloc(gc->set, gc_seq, gfp);
-+}
-+
-+void nft_trans_gc_queue_async_done(struct nft_trans_gc *trans)
-+{
-+      if (trans->count == 0) {
-+              nft_trans_gc_destroy(trans);
-+              return;
-+      }
-+
-+      nft_trans_gc_queue_work(trans);
-+}
-+
-+struct nft_trans_gc *nft_trans_gc_queue_sync(struct nft_trans_gc *gc, gfp_t gfp)
-+{
-+      if (WARN_ON_ONCE(!lockdep_commit_lock_is_held(gc->net)))
-+              return NULL;
-+
-+      if (nft_trans_gc_space(gc))
-+              return gc;
-+
-+      call_rcu(&gc->rcu, nft_trans_gc_trans_free);
-+
-+      return nft_trans_gc_alloc(gc->set, 0, gfp);
-+}
-+
-+void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans)
-+{
-+      WARN_ON_ONCE(!lockdep_commit_lock_is_held(trans->net));
-+
-+      if (trans->count == 0) {
-+              nft_trans_gc_destroy(trans);
-+              return;
-+      }
-+
-+      call_rcu(&trans->rcu, nft_trans_gc_trans_free);
-+}
-+
-+struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
-+                                         unsigned int gc_seq)
-+{
-+      struct nft_set_elem_catchall *catchall;
-+      const struct nft_set *set = gc->set;
-+      struct nft_set_ext *ext;
-+
-+      list_for_each_entry_rcu(catchall, &set->catchall_list, list) {
-+              ext = nft_set_elem_ext(set, catchall->elem);
-+
-+              if (!nft_set_elem_expired(ext))
-+                      continue;
-+              if (nft_set_elem_is_dead(ext))
-+                      goto dead_elem;
-+
-+              nft_set_elem_dead(ext);
-+dead_elem:
-+              gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
-+              if (!gc)
-+                      return NULL;
-+
-+              nft_trans_gc_elem_add(gc, catchall->elem);
-+      }
-+
-+      return gc;
-+}
-+
- static void nf_tables_module_autoload_cleanup(struct net *net)
- {
-       struct nftables_pernet *nft_net = nft_pernet(net);
-@@ -9044,11 +9255,11 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
- {
-       struct nftables_pernet *nft_net = nft_pernet(net);
-       struct nft_trans *trans, *next;
-+      unsigned int base_seq, gc_seq;
-       LIST_HEAD(set_update_list);
-       struct nft_trans_elem *te;
-       struct nft_chain *chain;
-       struct nft_table *table;
--      unsigned int base_seq;
-       LIST_HEAD(adl);
-       int err;
-@@ -9125,6 +9336,10 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
-       WRITE_ONCE(nft_net->base_seq, base_seq);
-+      /* Bump gc counter, it becomes odd, this is the busy mark. */
-+      gc_seq = READ_ONCE(nft_net->gc_seq);
-+      WRITE_ONCE(nft_net->gc_seq, ++gc_seq);
-+
-       /* step 3. Start new generation, rules_gen_X now in use. */
-       net->nft.gencursor = nft_gencursor_next(net);
-@@ -9213,6 +9428,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
-                       nft_trans_destroy(trans);
-                       break;
-               case NFT_MSG_DELSET:
-+                      nft_trans_set(trans)->dead = 1;
-                       list_del_rcu(&nft_trans_set(trans)->list);
-                       nf_tables_set_notify(&trans->ctx, nft_trans_set(trans),
-                                            NFT_MSG_DELSET, GFP_KERNEL);
-@@ -9312,6 +9528,8 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
-       nft_commit_notify(net, NETLINK_CB(skb).portid);
-       nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN);
-       nf_tables_commit_audit_log(&adl, nft_net->base_seq);
-+
-+      WRITE_ONCE(nft_net->gc_seq, ++gc_seq);
-       nf_tables_commit_release(net);
-       return 0;
-@@ -10343,6 +10561,7 @@ static int __net_init nf_tables_init_net(struct net *net)
-       INIT_LIST_HEAD(&nft_net->notify_list);
-       mutex_init(&nft_net->commit_mutex);
-       nft_net->base_seq = 1;
-+      nft_net->gc_seq = 0;
-       return 0;
- }
-@@ -10371,10 +10590,16 @@ static void __net_exit nf_tables_exit_net(struct net *net)
-       WARN_ON_ONCE(!list_empty(&nft_net->notify_list));
- }
-+static void nf_tables_exit_batch(struct list_head *net_exit_list)
-+{
-+      flush_work(&trans_gc_work);
-+}
-+
- static struct pernet_operations nf_tables_net_ops = {
-       .init           = nf_tables_init_net,
-       .pre_exit       = nf_tables_pre_exit_net,
-       .exit           = nf_tables_exit_net,
-+      .exit_batch     = nf_tables_exit_batch,
-       .id             = &nf_tables_net_id,
-       .size           = sizeof(struct nftables_pernet),
- };
-@@ -10446,6 +10671,7 @@ static void __exit nf_tables_module_exit(void)
-       nft_chain_filter_fini();
-       nft_chain_route_fini();
-       unregister_pernet_subsys(&nf_tables_net_ops);
-+      cancel_work_sync(&trans_gc_work);
-       cancel_work_sync(&trans_destroy_work);
-       rcu_barrier();
-       rhltable_destroy(&nft_objname_ht);
--- 
-2.40.1
-
diff --git a/queue-5.15/netfilter-nf_tables-gc-transaction-race-with-netns-d.patch b/queue-5.15/netfilter-nf_tables-gc-transaction-race-with-netns-d.patch
deleted file mode 100644 (file)
index d446956..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-From 253a905cb384b9233d3d834adcc1469af2019946 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 15 Aug 2023 15:39:01 +0200
-Subject: netfilter: nf_tables: GC transaction race with netns dismantle
-
-From: Pablo Neira Ayuso <pablo@netfilter.org>
-
-[ Upstream commit 02c6c24402bf1c1e986899c14ba22a10b510916b ]
-
-Use maybe_get_net() since GC workqueue might race with netns exit path.
-
-Fixes: 5f68718b34a5 ("netfilter: nf_tables: GC transaction API to avoid race with control plane")
-Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-Signed-off-by: Florian Westphal <fw@strlen.de>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/netfilter/nf_tables_api.c | 7 ++++++-
- 1 file changed, 6 insertions(+), 1 deletion(-)
-
-diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
-index 3e17d2403d899..33023b42698bb 100644
---- a/net/netfilter/nf_tables_api.c
-+++ b/net/netfilter/nf_tables_api.c
-@@ -8944,9 +8944,14 @@ struct nft_trans_gc *nft_trans_gc_alloc(struct nft_set *set,
-       if (!trans)
-               return NULL;
-+      trans->net = maybe_get_net(net);
-+      if (!trans->net) {
-+              kfree(trans);
-+              return NULL;
-+      }
-+
-       refcount_inc(&set->refs);
-       trans->set = set;
--      trans->net = get_net(net);
-       trans->seq = gc_seq;
-       return trans;
--- 
-2.40.1
-
diff --git a/queue-5.15/netfilter-nf_tables-make-validation-state-per-table.patch b/queue-5.15/netfilter-nf_tables-make-validation-state-per-table.patch
deleted file mode 100644 (file)
index ce15993..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-From b03c5ec538908fb0c7547a140322500dd34ff912 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 13 Apr 2023 17:13:20 +0200
-Subject: netfilter: nf_tables: make validation state per table
-
-From: Florian Westphal <fw@strlen.de>
-
-[ Upstream commit 00c320f9b75560628e840bef027a27c746706759 ]
-
-We only need to validate tables that saw changes in the current
-transaction.
-
-The existing code revalidates all tables, but this isn't needed as
-cross-table jumps are not allowed (chains have table scope).
-
-Signed-off-by: Florian Westphal <fw@strlen.de>
-Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-Stable-dep-of: 5f68718b34a5 ("netfilter: nf_tables: GC transaction API to avoid race with control plane")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- include/net/netfilter/nf_tables.h |  3 ++-
- net/netfilter/nf_tables_api.c     | 38 +++++++++++++++----------------
- 2 files changed, 20 insertions(+), 21 deletions(-)
-
-diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
-index 1458b3eae8ada..b8d967e0eb1e2 100644
---- a/include/net/netfilter/nf_tables.h
-+++ b/include/net/netfilter/nf_tables.h
-@@ -1183,6 +1183,7 @@ static inline void nft_use_inc_restore(u32 *use)
-  *    @genmask: generation mask
-  *    @afinfo: address family info
-  *    @name: name of the table
-+ *    @validate_state: internal, set when transaction adds jumps
-  */
- struct nft_table {
-       struct list_head                list;
-@@ -1201,6 +1202,7 @@ struct nft_table {
-       char                            *name;
-       u16                             udlen;
-       u8                              *udata;
-+      u8                              validate_state;
- };
- static inline bool nft_table_has_owner(const struct nft_table *table)
-@@ -1682,7 +1684,6 @@ struct nftables_pernet {
-       struct mutex            commit_mutex;
-       u64                     table_handle;
-       unsigned int            base_seq;
--      u8                      validate_state;
- };
- extern unsigned int nf_tables_net_id;
-diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
-index d84da11aaee5c..dde19be41610d 100644
---- a/net/netfilter/nf_tables_api.c
-+++ b/net/netfilter/nf_tables_api.c
-@@ -102,11 +102,9 @@ static const u8 nft2audit_op[NFT_MSG_MAX] = { // enum nf_tables_msg_types
-       [NFT_MSG_DELFLOWTABLE]  = AUDIT_NFT_OP_FLOWTABLE_UNREGISTER,
- };
--static void nft_validate_state_update(struct net *net, u8 new_validate_state)
-+static void nft_validate_state_update(struct nft_table *table, u8 new_validate_state)
- {
--      struct nftables_pernet *nft_net = nft_pernet(net);
--
--      switch (nft_net->validate_state) {
-+      switch (table->validate_state) {
-       case NFT_VALIDATE_SKIP:
-               WARN_ON_ONCE(new_validate_state == NFT_VALIDATE_DO);
-               break;
-@@ -117,7 +115,7 @@ static void nft_validate_state_update(struct net *net, u8 new_validate_state)
-                       return;
-       }
--      nft_net->validate_state = new_validate_state;
-+      table->validate_state = new_validate_state;
- }
- static void nf_tables_trans_destroy_work(struct work_struct *w);
- static DECLARE_WORK(trans_destroy_work, nf_tables_trans_destroy_work);
-@@ -1286,6 +1284,7 @@ static int nf_tables_newtable(struct sk_buff *skb, const struct nfnl_info *info,
-       if (table == NULL)
-               goto err_kzalloc;
-+      table->validate_state = NFT_VALIDATE_SKIP;
-       table->name = nla_strdup(attr, GFP_KERNEL);
-       if (table->name == NULL)
-               goto err_strdup;
-@@ -3650,7 +3649,7 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
-               }
-               if (expr_info[i].ops->validate)
--                      nft_validate_state_update(net, NFT_VALIDATE_NEED);
-+                      nft_validate_state_update(table, NFT_VALIDATE_NEED);
-               expr_info[i].ops = NULL;
-               expr = nft_expr_next(expr);
-@@ -3704,7 +3703,7 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
-       if (flow)
-               nft_trans_flow_rule(trans) = flow;
--      if (nft_net->validate_state == NFT_VALIDATE_DO)
-+      if (table->validate_state == NFT_VALIDATE_DO)
-               return nft_table_validate(net, table);
-       return 0;
-@@ -6347,7 +6346,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
-                       if (desc.type == NFT_DATA_VERDICT &&
-                           (elem.data.val.verdict.code == NFT_GOTO ||
-                            elem.data.val.verdict.code == NFT_JUMP))
--                              nft_validate_state_update(ctx->net,
-+                              nft_validate_state_update(ctx->table,
-                                                         NFT_VALIDATE_NEED);
-               }
-@@ -6465,7 +6464,6 @@ static int nf_tables_newsetelem(struct sk_buff *skb,
-                               const struct nfnl_info *info,
-                               const struct nlattr * const nla[])
- {
--      struct nftables_pernet *nft_net = nft_pernet(info->net);
-       struct netlink_ext_ack *extack = info->extack;
-       u8 genmask = nft_genmask_next(info->net);
-       u8 family = info->nfmsg->nfgen_family;
-@@ -6503,7 +6501,7 @@ static int nf_tables_newsetelem(struct sk_buff *skb,
-                       return err;
-       }
--      if (nft_net->validate_state == NFT_VALIDATE_DO)
-+      if (table->validate_state == NFT_VALIDATE_DO)
-               return nft_table_validate(net, table);
-       return 0;
-@@ -8600,19 +8598,20 @@ static int nf_tables_validate(struct net *net)
-       struct nftables_pernet *nft_net = nft_pernet(net);
-       struct nft_table *table;
--      switch (nft_net->validate_state) {
--      case NFT_VALIDATE_SKIP:
--              break;
--      case NFT_VALIDATE_NEED:
--              nft_validate_state_update(net, NFT_VALIDATE_DO);
--              fallthrough;
--      case NFT_VALIDATE_DO:
--              list_for_each_entry(table, &nft_net->tables, list) {
-+      list_for_each_entry(table, &nft_net->tables, list) {
-+              switch (table->validate_state) {
-+              case NFT_VALIDATE_SKIP:
-+                      continue;
-+              case NFT_VALIDATE_NEED:
-+                      nft_validate_state_update(table, NFT_VALIDATE_DO);
-+                      fallthrough;
-+              case NFT_VALIDATE_DO:
-                       if (nft_table_validate(net, table) < 0)
-                               return -EAGAIN;
-+
-+                      nft_validate_state_update(table, NFT_VALIDATE_SKIP);
-               }
--              nft_validate_state_update(net, NFT_VALIDATE_SKIP);
-               break;
-       }
-@@ -10344,7 +10343,6 @@ static int __net_init nf_tables_init_net(struct net *net)
-       INIT_LIST_HEAD(&nft_net->notify_list);
-       mutex_init(&nft_net->commit_mutex);
-       nft_net->base_seq = 1;
--      nft_net->validate_state = NFT_VALIDATE_SKIP;
-       return 0;
- }
--- 
-2.40.1
-
diff --git a/queue-5.15/netfilter-nf_tables-remove-busy-mark-and-gc-batch-ap.patch b/queue-5.15/netfilter-nf_tables-remove-busy-mark-and-gc-batch-ap.patch
deleted file mode 100644 (file)
index b10f919..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-From 7be3a56c7758beebca3e24138a8ac8af23300285 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 9 Aug 2023 15:00:36 +0200
-Subject: netfilter: nf_tables: remove busy mark and gc batch API
-
-From: Pablo Neira Ayuso <pablo@netfilter.org>
-
-[ Upstream commit a2dd0233cbc4d8a0abb5f64487487ffc9265beb5 ]
-
-Ditch it, it has been replace it by the GC transaction API and it has no
-clients anymore.
-
-Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- include/net/netfilter/nf_tables.h | 98 +------------------------------
- net/netfilter/nf_tables_api.c     | 48 +--------------
- 2 files changed, 4 insertions(+), 142 deletions(-)
-
-diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
-index a6bf58316a5d8..cd3b5b9db8890 100644
---- a/include/net/netfilter/nf_tables.h
-+++ b/include/net/netfilter/nf_tables.h
-@@ -564,7 +564,6 @@ struct nft_set *nft_set_lookup_global(const struct net *net,
- struct nft_set_ext *nft_set_catchall_lookup(const struct net *net,
-                                           const struct nft_set *set);
--void *nft_set_catchall_gc(const struct nft_set *set);
- static inline unsigned long nft_set_gc_interval(const struct nft_set *set)
- {
-@@ -779,62 +778,6 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem,
- void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
-                               const struct nft_set *set, void *elem);
--/**
-- *    struct nft_set_gc_batch_head - nf_tables set garbage collection batch
-- *
-- *    @rcu: rcu head
-- *    @set: set the elements belong to
-- *    @cnt: count of elements
-- */
--struct nft_set_gc_batch_head {
--      struct rcu_head                 rcu;
--      const struct nft_set            *set;
--      unsigned int                    cnt;
--};
--
--#define NFT_SET_GC_BATCH_SIZE ((PAGE_SIZE -                             \
--                                sizeof(struct nft_set_gc_batch_head)) / \
--                               sizeof(void *))
--
--/**
-- *    struct nft_set_gc_batch - nf_tables set garbage collection batch
-- *
-- *    @head: GC batch head
-- *    @elems: garbage collection elements
-- */
--struct nft_set_gc_batch {
--      struct nft_set_gc_batch_head    head;
--      void                            *elems[NFT_SET_GC_BATCH_SIZE];
--};
--
--struct nft_set_gc_batch *nft_set_gc_batch_alloc(const struct nft_set *set,
--                                              gfp_t gfp);
--void nft_set_gc_batch_release(struct rcu_head *rcu);
--
--static inline void nft_set_gc_batch_complete(struct nft_set_gc_batch *gcb)
--{
--      if (gcb != NULL)
--              call_rcu(&gcb->head.rcu, nft_set_gc_batch_release);
--}
--
--static inline struct nft_set_gc_batch *
--nft_set_gc_batch_check(const struct nft_set *set, struct nft_set_gc_batch *gcb,
--                     gfp_t gfp)
--{
--      if (gcb != NULL) {
--              if (gcb->head.cnt + 1 < ARRAY_SIZE(gcb->elems))
--                      return gcb;
--              nft_set_gc_batch_complete(gcb);
--      }
--      return nft_set_gc_batch_alloc(set, gfp);
--}
--
--static inline void nft_set_gc_batch_add(struct nft_set_gc_batch *gcb,
--                                      void *elem)
--{
--      gcb->elems[gcb->head.cnt++] = elem;
--}
--
- struct nft_expr_ops;
- /**
-  *    struct nft_expr_type - nf_tables expression type
-@@ -1495,47 +1438,12 @@ static inline void nft_set_elem_change_active(const struct net *net,
- #endif /* IS_ENABLED(CONFIG_NF_TABLES) */
--/*
-- * We use a free bit in the genmask field to indicate the element
-- * is busy, meaning it is currently being processed either by
-- * the netlink API or GC.
-- *
-- * Even though the genmask is only a single byte wide, this works
-- * because the extension structure if fully constant once initialized,
-- * so there are no non-atomic write accesses unless it is already
-- * marked busy.
-- */
--#define NFT_SET_ELEM_BUSY_MASK        (1 << 2)
--
--#if defined(__LITTLE_ENDIAN_BITFIELD)
--#define NFT_SET_ELEM_BUSY_BIT 2
--#elif defined(__BIG_ENDIAN_BITFIELD)
--#define NFT_SET_ELEM_BUSY_BIT (BITS_PER_LONG - BITS_PER_BYTE + 2)
--#else
--#error
--#endif
--
--static inline int nft_set_elem_mark_busy(struct nft_set_ext *ext)
--{
--      unsigned long *word = (unsigned long *)ext;
--
--      BUILD_BUG_ON(offsetof(struct nft_set_ext, genmask) != 0);
--      return test_and_set_bit(NFT_SET_ELEM_BUSY_BIT, word);
--}
--
--static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext)
--{
--      unsigned long *word = (unsigned long *)ext;
--
--      clear_bit(NFT_SET_ELEM_BUSY_BIT, word);
--}
--
--#define NFT_SET_ELEM_DEAD_MASK        (1 << 3)
-+#define NFT_SET_ELEM_DEAD_MASK        (1 << 2)
- #if defined(__LITTLE_ENDIAN_BITFIELD)
--#define NFT_SET_ELEM_DEAD_BIT 3
-+#define NFT_SET_ELEM_DEAD_BIT 2
- #elif defined(__BIG_ENDIAN_BITFIELD)
--#define NFT_SET_ELEM_DEAD_BIT (BITS_PER_LONG - BITS_PER_BYTE + 3)
-+#define NFT_SET_ELEM_DEAD_BIT (BITS_PER_LONG - BITS_PER_BYTE + 2)
- #else
- #error
- #endif
-diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
-index 616fd19d5cedc..75b04c01f7b81 100644
---- a/net/netfilter/nf_tables_api.c
-+++ b/net/netfilter/nf_tables_api.c
-@@ -5919,29 +5919,6 @@ struct nft_set_ext *nft_set_catchall_lookup(const struct net *net,
- }
- EXPORT_SYMBOL_GPL(nft_set_catchall_lookup);
--void *nft_set_catchall_gc(const struct nft_set *set)
--{
--      struct nft_set_elem_catchall *catchall, *next;
--      struct nft_set_ext *ext;
--      void *elem = NULL;
--
--      list_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
--              ext = nft_set_elem_ext(set, catchall->elem);
--
--              if (!nft_set_elem_expired(ext) ||
--                  nft_set_elem_mark_busy(ext))
--                      continue;
--
--              elem = catchall->elem;
--              list_del_rcu(&catchall->list);
--              kfree_rcu(catchall, rcu);
--              break;
--      }
--
--      return elem;
--}
--EXPORT_SYMBOL_GPL(nft_set_catchall_gc);
--
- static int nft_setelem_catchall_insert(const struct net *net,
-                                      struct nft_set *set,
-                                      const struct nft_set_elem *elem,
-@@ -6406,7 +6383,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
-               goto err_elem_expr;
-       }
--      ext->genmask = nft_genmask_cur(ctx->net) | NFT_SET_ELEM_BUSY_MASK;
-+      ext->genmask = nft_genmask_cur(ctx->net);
-       err = nft_setelem_insert(ctx->net, set, &elem, &ext2, flags);
-       if (err) {
-@@ -6786,29 +6763,6 @@ static int nf_tables_delsetelem(struct sk_buff *skb,
-       return err;
- }
--void nft_set_gc_batch_release(struct rcu_head *rcu)
--{
--      struct nft_set_gc_batch *gcb;
--      unsigned int i;
--
--      gcb = container_of(rcu, struct nft_set_gc_batch, head.rcu);
--      for (i = 0; i < gcb->head.cnt; i++)
--              nft_set_elem_destroy(gcb->head.set, gcb->elems[i], true);
--      kfree(gcb);
--}
--
--struct nft_set_gc_batch *nft_set_gc_batch_alloc(const struct nft_set *set,
--                                              gfp_t gfp)
--{
--      struct nft_set_gc_batch *gcb;
--
--      gcb = kzalloc(sizeof(*gcb), gfp);
--      if (gcb == NULL)
--              return gcb;
--      gcb->head.set = set;
--      return gcb;
--}
--
- /*
-  * Stateful objects
-  */
--- 
-2.40.1
-
diff --git a/queue-5.15/netfilter-nft_set_hash-mark-set-element-as-dead-when.patch b/queue-5.15/netfilter-nft_set_hash-mark-set-element-as-dead-when.patch
deleted file mode 100644 (file)
index caac51f..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-From 46c14671cf0c641c8bd41ccc54019a08e2b0d04a Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 9 Aug 2023 15:00:06 +0200
-Subject: netfilter: nft_set_hash: mark set element as dead when deleting from
- packet path
-
-From: Pablo Neira Ayuso <pablo@netfilter.org>
-
-[ Upstream commit c92db3030492b8ad1d0faace7a93bbcf53850d0c ]
-
-Set on the NFT_SET_ELEM_DEAD_BIT flag on this element, instead of
-performing element removal which might race with an ongoing transaction.
-Enable gc when dynamic flag is set on since dynset deletion requires
-garbage collection after this patch.
-
-Fixes: d0a8d877da97 ("netfilter: nft_dynset: support for element deletion")
-Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/netfilter/nft_set_hash.c | 6 ++++--
- 1 file changed, 4 insertions(+), 2 deletions(-)
-
-diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c
-index 960cbd56c0406..8dfa97105d8a3 100644
---- a/net/netfilter/nft_set_hash.c
-+++ b/net/netfilter/nft_set_hash.c
-@@ -249,7 +249,9 @@ static bool nft_rhash_delete(const struct nft_set *set,
-       if (he == NULL)
-               return false;
--      return rhashtable_remove_fast(&priv->ht, &he->node, nft_rhash_params) == 0;
-+      nft_set_elem_dead(&he->ext);
-+
-+      return true;
- }
- static void nft_rhash_walk(const struct nft_ctx *ctx, struct nft_set *set,
-@@ -414,7 +416,7 @@ static int nft_rhash_init(const struct nft_set *set,
-               return err;
-       INIT_DEFERRABLE_WORK(&priv->gc_work, nft_rhash_gc);
--      if (set->flags & NFT_SET_TIMEOUT)
-+      if (set->flags & (NFT_SET_TIMEOUT | NFT_SET_EVAL))
-               nft_rhash_gc_init(set);
-       return 0;
--- 
-2.40.1
-
index 675a193acf756b66fde5dda9053ceba6cda3e447..e24e9816fcd99d522c42b489c6b7f1db8326eb34 100644 (file)
@@ -79,14 +79,6 @@ selftests-tracing-fix-to-unmount-tracefs-for-recover.patch
 scsi-lpfc-fix-the-null-vs-is_err-bug-for-debugfs_cre.patch
 x86-boot-compressed-reserve-more-memory-for-page-tab.patch
 x86-purgatory-remove-lto-flags.patch
-netfilter-nf_tables-make-validation-state-per-table.patch
-netfilter-nf_tables-gc-transaction-api-to-avoid-race.patch
-netfilter-nf_tables-adapt-set-backend-to-use-gc-tran.patch
-netfilter-nft_set_hash-mark-set-element-as-dead-when.patch
-netfilter-nf_tables-remove-busy-mark-and-gc-batch-ap.patch
-netfilter-nf_tables-fix-kdoc-warnings-after-gc-rewor.patch
-netfilter-nf_tables-fix-gc-transaction-races-with-ne.patch
-netfilter-nf_tables-gc-transaction-race-with-netns-d.patch
 samples-hw_breakpoint-fix-building-without-module-un.patch
 md-raid1-fix-error-iso-c90-forbids-mixed-declaration.patch
 attr-block-mode-changes-of-symlinks.patch