]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.6
authorSasha Levin <sashal@kernel.org>
Wed, 22 Nov 2023 21:53:42 +0000 (16:53 -0500)
committerSasha Levin <sashal@kernel.org>
Wed, 22 Nov 2023 21:53:42 +0000 (16:53 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-6.6/netfilter-nf_tables-remove-catchall-element-in-gc-sy.patch [new file with mode: 0644]
queue-6.6/netfilter-nf_tables-split-async-and-sync-catchall-in.patch [new file with mode: 0644]
queue-6.6/series

diff --git a/queue-6.6/netfilter-nf_tables-remove-catchall-element-in-gc-sy.patch b/queue-6.6/netfilter-nf_tables-remove-catchall-element-in-gc-sy.patch
new file mode 100644 (file)
index 0000000..4ed5854
--- /dev/null
@@ -0,0 +1,86 @@
+From c7e147bd4f689e9dc74ed0fbff207bb592b8d050 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Nov 2023 13:14:21 +0100
+Subject: netfilter: nf_tables: remove catchall element in GC sync path
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+[ Upstream commit 93995bf4af2c5a99e2a87f0cd5ce547d31eb7630 ]
+
+The expired catchall element is not deactivated and removed from GC sync
+path. This path holds mutex so just call nft_setelem_data_deactivate()
+and nft_setelem_catchall_remove() before queueing the GC work.
+
+Fixes: 4a9e12ea7e70 ("netfilter: nft_set_pipapo: call nft_trans_gc_queue_sync() in catchall GC")
+Reported-by: lonial con <kongln9170@gmail.com>
+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 | 26 +++++++++++++++++++++-----
+ 1 file changed, 21 insertions(+), 5 deletions(-)
+
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index 3807c6c1181fd..e6c52d417b6d0 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -6464,6 +6464,12 @@ static int nft_setelem_deactivate(const struct net *net,
+       return ret;
+ }
++static void nft_setelem_catchall_destroy(struct nft_set_elem_catchall *catchall)
++{
++      list_del_rcu(&catchall->list);
++      kfree_rcu(catchall, rcu);
++}
++
+ static void nft_setelem_catchall_remove(const struct net *net,
+                                       const struct nft_set *set,
+                                       const struct nft_set_elem *elem)
+@@ -6472,8 +6478,7 @@ static void nft_setelem_catchall_remove(const struct net *net,
+       list_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
+               if (catchall->elem == elem->priv) {
+-                      list_del_rcu(&catchall->list);
+-                      kfree_rcu(catchall, rcu);
++                      nft_setelem_catchall_destroy(catchall);
+                       break;
+               }
+       }
+@@ -9639,11 +9644,12 @@ static struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
+                                                 unsigned int gc_seq,
+                                                 bool sync)
+ {
+-      struct nft_set_elem_catchall *catchall;
++      struct nft_set_elem_catchall *catchall, *next;
+       const struct nft_set *set = gc->set;
++      struct nft_elem_priv *elem_priv;
+       struct nft_set_ext *ext;
+-      list_for_each_entry_rcu(catchall, &set->catchall_list, list) {
++      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))
+@@ -9661,7 +9667,17 @@ static struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
+               if (!gc)
+                       return NULL;
+-              nft_trans_gc_elem_add(gc, catchall->elem);
++              elem_priv = catchall->elem;
++              if (sync) {
++                      struct nft_set_elem elem = {
++                              .priv = elem_priv,
++                      };
++
++                      nft_setelem_data_deactivate(gc->net, gc->set, &elem);
++                      nft_setelem_catchall_destroy(catchall);
++              }
++
++              nft_trans_gc_elem_add(gc, elem_priv);
+       }
+       return gc;
+-- 
+2.42.0
+
diff --git a/queue-6.6/netfilter-nf_tables-split-async-and-sync-catchall-in.patch b/queue-6.6/netfilter-nf_tables-split-async-and-sync-catchall-in.patch
new file mode 100644 (file)
index 0000000..e1e8f05
--- /dev/null
@@ -0,0 +1,122 @@
+From e2af4888c8d88cd22724cdc52ab24f9591006ed8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Nov 2023 13:14:22 +0100
+Subject: netfilter: nf_tables: split async and sync catchall in two functions
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+[ Upstream commit 8837ba3e58ea1e3d09ae36db80b1e80853aada95 ]
+
+list_for_each_entry_safe() does not work for the async case which runs
+under RCU, therefore, split GC logic for catchall in two functions
+instead, one for each of the sync and async GC variants.
+
+The catchall sync GC variant never sees a _DEAD bit set on ever, thus,
+this handling is removed in such case, moreover, allocate GC sync batch
+via GFP_KERNEL.
+
+Fixes: 93995bf4af2c ("netfilter: nf_tables: remove catchall element in GC sync path")
+Reported-by: Florian Westphal <fw@strlen.de>
+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 | 61 ++++++++++++++++++-----------------
+ 1 file changed, 32 insertions(+), 29 deletions(-)
+
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index e6c52d417b6d0..4a450f6d12a59 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -9640,16 +9640,14 @@ void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans)
+       call_rcu(&trans->rcu, nft_trans_gc_trans_free);
+ }
+-static struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
+-                                                unsigned int gc_seq,
+-                                                bool sync)
++struct nft_trans_gc *nft_trans_gc_catchall_async(struct nft_trans_gc *gc,
++                                               unsigned int gc_seq)
+ {
+-      struct nft_set_elem_catchall *catchall, *next;
++      struct nft_set_elem_catchall *catchall;
+       const struct nft_set *set = gc->set;
+-      struct nft_elem_priv *elem_priv;
+       struct nft_set_ext *ext;
+-      list_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
++      list_for_each_entry_rcu(catchall, &set->catchall_list, list) {
+               ext = nft_set_elem_ext(set, catchall->elem);
+               if (!nft_set_elem_expired(ext))
+@@ -9659,39 +9657,44 @@ static struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
+               nft_set_elem_dead(ext);
+ dead_elem:
+-              if (sync)
+-                      gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC);
+-              else
+-                      gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
+-
++              gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
+               if (!gc)
+                       return NULL;
+-              elem_priv = catchall->elem;
+-              if (sync) {
+-                      struct nft_set_elem elem = {
+-                              .priv = elem_priv,
+-                      };
+-
+-                      nft_setelem_data_deactivate(gc->net, gc->set, &elem);
+-                      nft_setelem_catchall_destroy(catchall);
+-              }
+-
+-              nft_trans_gc_elem_add(gc, elem_priv);
++              nft_trans_gc_elem_add(gc, catchall->elem);
+       }
+       return gc;
+ }
+-struct nft_trans_gc *nft_trans_gc_catchall_async(struct nft_trans_gc *gc,
+-                                               unsigned int gc_seq)
+-{
+-      return nft_trans_gc_catchall(gc, gc_seq, false);
+-}
+-
+ struct nft_trans_gc *nft_trans_gc_catchall_sync(struct nft_trans_gc *gc)
+ {
+-      return nft_trans_gc_catchall(gc, 0, true);
++      struct nft_set_elem_catchall *catchall, *next;
++      const struct nft_set *set = gc->set;
++      struct nft_set_elem elem;
++      struct nft_set_ext *ext;
++
++      WARN_ON_ONCE(!lockdep_commit_lock_is_held(gc->net));
++
++      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))
++                      continue;
++
++              gc = nft_trans_gc_queue_sync(gc, GFP_KERNEL);
++              if (!gc)
++                      return NULL;
++
++              memset(&elem, 0, sizeof(elem));
++              elem.priv = catchall->elem;
++
++              nft_setelem_data_deactivate(gc->net, gc->set, &elem);
++              nft_setelem_catchall_destroy(catchall);
++              nft_trans_gc_elem_add(gc, elem.priv);
++      }
++
++      return gc;
+ }
+ static void nf_tables_module_autoload_cleanup(struct net *net)
+-- 
+2.42.0
+
index 75666994cda1dfa4fd138677fa9d3b05a68603c8..01b7695c20878410b6ed245b1db4640e77162899 100644 (file)
@@ -347,3 +347,5 @@ mfd-qcom-spmi-pmic-fix-reference-leaks-in-revid-helper.patch
 mfd-qcom-spmi-pmic-fix-revid-implementation.patch
 ima-annotate-iint-mutex-to-avoid-lockdep-false-positive-warnings.patch
 ima-detect-changes-to-the-backing-overlay-file.patch
+netfilter-nf_tables-remove-catchall-element-in-gc-sy.patch
+netfilter-nf_tables-split-async-and-sync-catchall-in.patch