From c3ae82ed488b7fcfee531a667fb76b15068bfaa7 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Wed, 22 Nov 2023 16:53:43 -0500 Subject: [PATCH] Fixes for 6.5 Signed-off-by: Sasha Levin --- ...les-remove-catchall-element-in-gc-sy.patch | 86 ++++++++++++ ...les-split-async-and-sync-catchall-in.patch | 122 ++++++++++++++++++ queue-6.5/series | 2 + 3 files changed, 210 insertions(+) create mode 100644 queue-6.5/netfilter-nf_tables-remove-catchall-element-in-gc-sy.patch create mode 100644 queue-6.5/netfilter-nf_tables-split-async-and-sync-catchall-in.patch diff --git a/queue-6.5/netfilter-nf_tables-remove-catchall-element-in-gc-sy.patch b/queue-6.5/netfilter-nf_tables-remove-catchall-element-in-gc-sy.patch new file mode 100644 index 00000000000..550481e845f --- /dev/null +++ b/queue-6.5/netfilter-nf_tables-remove-catchall-element-in-gc-sy.patch @@ -0,0 +1,86 @@ +From 3b2e05e30cbbf59a1056bdeba1cf272315ed7f10 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Nov 2023 13:14:21 +0100 +Subject: netfilter: nf_tables: remove catchall element in GC sync path + +From: Pablo Neira Ayuso + +[ 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 +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + 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 398a1bcc6ea61..d676c87411dc1 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -6461,6 +6461,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) +@@ -6469,8 +6475,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; + } + } +@@ -9636,11 +9641,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)) +@@ -9658,7 +9664,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.5/netfilter-nf_tables-split-async-and-sync-catchall-in.patch b/queue-6.5/netfilter-nf_tables-split-async-and-sync-catchall-in.patch new file mode 100644 index 00000000000..7406395b750 --- /dev/null +++ b/queue-6.5/netfilter-nf_tables-split-async-and-sync-catchall-in.patch @@ -0,0 +1,122 @@ +From a698f39732a5f908c01f44a9f311263fb56a61f6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + 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 d676c87411dc1..db582c8d25f00 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -9637,16 +9637,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)) +@@ -9656,39 +9654,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 + diff --git a/queue-6.5/series b/queue-6.5/series index e156e7dbe01..d21ffa29ba4 100644 --- a/queue-6.5/series +++ b/queue-6.5/series @@ -324,3 +324,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 -- 2.47.3