--- /dev/null
+From 4cb8df396e0c661a6b4180e402e83aa8422f5df7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Sep 2023 18:02:56 +0200
+Subject: netfilter: nf_tables: fix memleak when more than 255 elements expired
+
+From: Florian Westphal <fw@strlen.de>
+
+commit cf5000a7787cbc10341091d37245a42c119d26c5 upstream.
+
+When more than 255 elements expired we're supposed to switch to a new gc
+container structure.
+
+This never happens: u8 type will wrap before reaching the boundary
+and nft_trans_gc_space() always returns true.
+
+This means we recycle the initial gc container structure and
+lose track of the elements that came before.
+
+While at it, don't deref 'gc' after we've passed it to call_rcu.
+
+Fixes: 5f68718b34a5 ("netfilter: nf_tables: GC transaction API to avoid race with control plane")
+Reported-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/netfilter/nf_tables.h | 2 +-
+ net/netfilter/nf_tables_api.c | 10 ++++++++--
+ 2 files changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
+index a4455f4995abf..7c816359d5a98 100644
+--- a/include/net/netfilter/nf_tables.h
++++ b/include/net/netfilter/nf_tables.h
+@@ -1682,7 +1682,7 @@ struct nft_trans_gc {
+ struct net *net;
+ struct nft_set *set;
+ u32 seq;
+- u8 count;
++ u16 count;
+ void *priv[NFT_TRANS_GC_BATCHCOUNT];
+ struct rcu_head rcu;
+ };
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index bba8042f721a5..1c2fb32bfa5f6 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -9559,12 +9559,15 @@ static int nft_trans_gc_space(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)
+ {
++ struct nft_set *set;
++
+ if (nft_trans_gc_space(gc))
+ return gc;
+
++ set = gc->set;
+ nft_trans_gc_queue_work(gc);
+
+- return nft_trans_gc_alloc(gc->set, gc_seq, gfp);
++ return nft_trans_gc_alloc(set, gc_seq, gfp);
+ }
+
+ void nft_trans_gc_queue_async_done(struct nft_trans_gc *trans)
+@@ -9579,15 +9582,18 @@ void nft_trans_gc_queue_async_done(struct nft_trans_gc *trans)
+
+ struct nft_trans_gc *nft_trans_gc_queue_sync(struct nft_trans_gc *gc, gfp_t gfp)
+ {
++ struct nft_set *set;
++
+ if (WARN_ON_ONCE(!lockdep_commit_lock_is_held(gc->net)))
+ return NULL;
+
+ if (nft_trans_gc_space(gc))
+ return gc;
+
++ set = gc->set;
+ call_rcu(&gc->rcu, nft_trans_gc_trans_free);
+
+- return nft_trans_gc_alloc(gc->set, 0, gfp);
++ return nft_trans_gc_alloc(set, 0, gfp);
+ }
+
+ void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans)
+--
+2.40.1
+
--- /dev/null
+From c69e067c343b03010f7a36ea1514c3637b39cab2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Sep 2023 18:02:55 +0200
+Subject: netfilter: nft_set_hash: try later when GC hits EAGAIN on iteration
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+commit b079155faae94e9b3ab9337e82100a914ebb4e8d upstream.
+
+Skip GC run if iterator rewinds to the beginning with EAGAIN, otherwise GC
+might collect the same element more than once.
+
+Fixes: f6c383b8c31a ("netfilter: nf_tables: adapt set backend to use GC transaction API")
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nft_set_hash.c | 9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c
+index eca20dc601384..2013de934cef0 100644
+--- a/net/netfilter/nft_set_hash.c
++++ b/net/netfilter/nft_set_hash.c
+@@ -338,12 +338,9 @@ static void nft_rhash_gc(struct work_struct *work)
+
+ while ((he = rhashtable_walk_next(&hti))) {
+ if (IS_ERR(he)) {
+- if (PTR_ERR(he) != -EAGAIN) {
+- nft_trans_gc_destroy(gc);
+- gc = NULL;
+- goto try_later;
+- }
+- continue;
++ nft_trans_gc_destroy(gc);
++ gc = NULL;
++ goto try_later;
+ }
+
+ /* Ruleset has been updated, try later. */
+--
+2.40.1
+
--- /dev/null
+From f267b48f5272db451fe84c2f1530184d9d87feef Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Sep 2023 18:02:53 +0200
+Subject: netfilter: nft_set_pipapo: call nft_trans_gc_queue_sync() in catchall
+ GC
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+commit 4a9e12ea7e70223555ec010bec9f711089ce96f6 upstream.
+
+pipapo needs to enqueue GC transactions for catchall elements through
+nft_trans_gc_queue_sync(). Add nft_trans_gc_catchall_sync() and
+nft_trans_gc_catchall_async() to handle GC transaction queueing
+accordingly.
+
+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")
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/netfilter/nf_tables.h | 5 +++--
+ net/netfilter/nf_tables_api.c | 22 +++++++++++++++++++---
+ net/netfilter/nft_set_hash.c | 2 +-
+ net/netfilter/nft_set_pipapo.c | 2 +-
+ net/netfilter/nft_set_rbtree.c | 2 +-
+ 5 files changed, 25 insertions(+), 8 deletions(-)
+
+diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
+index dd40c75011d25..a4455f4995abf 100644
+--- a/include/net/netfilter/nf_tables.h
++++ b/include/net/netfilter/nf_tables.h
+@@ -1700,8 +1700,9 @@ 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);
++struct nft_trans_gc *nft_trans_gc_catchall_async(struct nft_trans_gc *gc,
++ unsigned int gc_seq);
++struct nft_trans_gc *nft_trans_gc_catchall_sync(struct nft_trans_gc *gc);
+
+ void nft_setelem_data_deactivate(const struct net *net,
+ const struct nft_set *set,
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index a72934f00804e..bba8042f721a5 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -9602,8 +9602,9 @@ void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans)
+ 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)
++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;
+ const struct nft_set *set = gc->set;
+@@ -9619,7 +9620,11 @@ struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
+
+ nft_set_elem_dead(ext);
+ dead_elem:
+- gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
++ if (sync)
++ gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC);
++ else
++ gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
++
+ if (!gc)
+ return NULL;
+
+@@ -9629,6 +9634,17 @@ struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
+ 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);
++}
++
+ static void nf_tables_module_autoload_cleanup(struct net *net)
+ {
+ struct nftables_pernet *nft_net = nft_pernet(net);
+diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c
+index 524763659f251..eca20dc601384 100644
+--- a/net/netfilter/nft_set_hash.c
++++ b/net/netfilter/nft_set_hash.c
+@@ -372,7 +372,7 @@ static void nft_rhash_gc(struct work_struct *work)
+ nft_trans_gc_elem_add(gc, he);
+ }
+
+- gc = nft_trans_gc_catchall(gc, gc_seq);
++ gc = nft_trans_gc_catchall_async(gc, gc_seq);
+
+ try_later:
+ /* catchall list iteration requires rcu read side lock. */
+diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c
+index 6af9c9ed4b5c3..10b89ac74476b 100644
+--- a/net/netfilter/nft_set_pipapo.c
++++ b/net/netfilter/nft_set_pipapo.c
+@@ -1610,7 +1610,7 @@ static void pipapo_gc(const struct nft_set *_set, struct nft_pipapo_match *m)
+ }
+ }
+
+- gc = nft_trans_gc_catchall(gc, 0);
++ gc = nft_trans_gc_catchall_sync(gc);
+ if (gc) {
+ nft_trans_gc_queue_sync_done(gc);
+ priv->last_gc = jiffies;
+diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
+index 70491ba98decb..487572dcd6144 100644
+--- a/net/netfilter/nft_set_rbtree.c
++++ b/net/netfilter/nft_set_rbtree.c
+@@ -669,7 +669,7 @@ static void nft_rbtree_gc(struct work_struct *work)
+ nft_trans_gc_elem_add(gc, rbe);
+ }
+
+- gc = nft_trans_gc_catchall(gc, gc_seq);
++ gc = nft_trans_gc_catchall_async(gc, gc_seq);
+
+ try_later:
+ read_unlock_bh(&priv->lock);
+--
+2.40.1
+
--- /dev/null
+From 57a544945fe0427deb8d1e08f8e757c11d36a88f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Sep 2023 18:02:54 +0200
+Subject: netfilter: nft_set_pipapo: stop GC iteration if GC transaction
+ allocation fails
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+commit 6d365eabce3c018a80f6e0379b17df2abb17405e upstream.
+
+nft_trans_gc_queue_sync() enqueues the GC transaction and it allocates a
+new one. If this allocation fails, then stop this GC sync run and retry
+later.
+
+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: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nft_set_pipapo.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c
+index 10b89ac74476b..c0dcc40de358f 100644
+--- a/net/netfilter/nft_set_pipapo.c
++++ b/net/netfilter/nft_set_pipapo.c
+@@ -1596,7 +1596,7 @@ static void pipapo_gc(const struct nft_set *_set, struct nft_pipapo_match *m)
+
+ gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC);
+ if (!gc)
+- break;
++ return;
+
+ nft_pipapo_gc_deactivate(net, set, e);
+ pipapo_drop(m, rulemap);
+--
+2.40.1
+
--- /dev/null
+From 8c36ca0bb937c96cd0e7a1f817b68da087167299 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Sep 2023 18:02:52 +0200
+Subject: netfilter: nft_set_rbtree: use read spinlock to avoid datapath
+ contention
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+commit 96b33300fba880ec0eafcf3d82486f3463b4b6da upstream.
+
+rbtree GC does not modify the datastructure, instead it collects expired
+elements and it enqueues a GC transaction. Use a read spinlock instead
+to avoid data contention while GC worker is running.
+
+Fixes: f6c383b8c31a ("netfilter: nf_tables: adapt set backend to use GC transaction API")
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nft_set_rbtree.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
+index f250b5399344a..70491ba98decb 100644
+--- a/net/netfilter/nft_set_rbtree.c
++++ b/net/netfilter/nft_set_rbtree.c
+@@ -622,8 +622,7 @@ static void nft_rbtree_gc(struct work_struct *work)
+ if (!gc)
+ goto done;
+
+- write_lock_bh(&priv->lock);
+- write_seqcount_begin(&priv->count);
++ read_lock_bh(&priv->lock);
+ for (node = rb_first(&priv->root); node != NULL; node = rb_next(node)) {
+
+ /* Ruleset has been updated, try later. */
+@@ -673,8 +672,7 @@ static void nft_rbtree_gc(struct work_struct *work)
+ gc = nft_trans_gc_catchall(gc, gc_seq);
+
+ try_later:
+- write_seqcount_end(&priv->count);
+- write_unlock_bh(&priv->lock);
++ read_unlock_bh(&priv->lock);
+
+ if (gc)
+ nft_trans_gc_queue_async_done(gc);
+--
+2.40.1
+
ext4-replace-the-traditional-ternary-conditional-ope.patch
ext4-move-setting-of-trimmed-bit-into-ext4_try_to_tr.patch
ext4-do-not-let-fstrim-block-system-suspend.patch
+netfilter-nft_set_rbtree-use-read-spinlock-to-avoid-.patch
+netfilter-nft_set_pipapo-call-nft_trans_gc_queue_syn.patch
+netfilter-nft_set_pipapo-stop-gc-iteration-if-gc-tra.patch
+netfilter-nft_set_hash-try-later-when-gc-hits-eagain.patch
+netfilter-nf_tables-fix-memleak-when-more-than-255-e.patch