Skip to content

Commit 5165cc4

Browse files
committed
netfilter: nf_tables: split async and sync catchall in two functions
jira VULN-430 subsystem-update netfilter: centos-stream-9 cfd9694 commit-author Pablo Neira Ayuso <pablo@netfilter.org> commit 8837ba3 upstream-diff Used the cleanly applying 9.4 backport 45aad05 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: 93995bf ("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> (cherry picked from commit 8837ba3) Signed-off-by: Marcin Wcisło <marcin.wcislo@conclusive.pl>
1 parent fd5ce20 commit 5165cc4

File tree

1 file changed

+34
-28
lines changed

1 file changed

+34
-28
lines changed

net/netfilter/nf_tables_api.c

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9164,16 +9164,14 @@ void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans)
91649164
call_rcu(&trans->rcu, nft_trans_gc_trans_free);
91659165
}
91669166

9167-
static struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
9168-
unsigned int gc_seq,
9169-
bool sync)
9167+
struct nft_trans_gc *nft_trans_gc_catchall_async(struct nft_trans_gc *gc,
9168+
unsigned int gc_seq)
91709169
{
9171-
struct nft_set_elem_catchall *catchall, *next;
9170+
struct nft_set_elem_catchall *catchall;
91729171
const struct nft_set *set = gc->set;
9173-
struct nft_elem_priv *elem_priv;
91749172
struct nft_set_ext *ext;
91759173

9176-
list_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
9174+
list_for_each_entry_rcu(catchall, &set->catchall_list, list) {
91779175
ext = nft_set_elem_ext(set, catchall->elem);
91789176

91799177
if (!nft_set_elem_expired(ext))
@@ -9183,41 +9181,49 @@ static struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
91839181

91849182
nft_set_elem_dead(ext);
91859183
dead_elem:
9186-
if (sync)
9187-
gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC);
9188-
else
9189-
gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
9184+
gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
9185+
if (!gc)
9186+
return NULL;
9187+
9188+
nft_trans_gc_elem_add(gc, catchall->elem);
9189+
}
9190+
9191+
return gc;
9192+
}
91909193

9194+
struct nft_trans_gc *nft_trans_gc_catchall_sync(struct nft_trans_gc *gc)
9195+
{
9196+
struct nft_set_elem_catchall *catchall, *next;
9197+
const struct nft_set *set = gc->set;
9198+
struct nft_elem_priv *elem_priv;
9199+
struct nft_set_elem elem;
9200+
struct nft_set_ext *ext;
9201+
9202+
WARN_ON_ONCE(!lockdep_commit_lock_is_held(gc->net));
9203+
9204+
list_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
9205+
ext = nft_set_elem_ext(set, catchall->elem);
9206+
9207+
if (!nft_set_elem_expired(ext))
9208+
continue;
9209+
9210+
gc = nft_trans_gc_queue_sync(gc, GFP_KERNEL);
91919211
if (!gc)
91929212
return NULL;
91939213

91949214
elem_priv = catchall->elem;
9195-
if (sync) {
9196-
struct nft_set_elem elem = {
9197-
.priv = elem_priv,
9198-
};
91999215

9200-
nft_setelem_data_deactivate(gc->net, gc->set, &elem);
9201-
nft_setelem_catchall_destroy(catchall);
9202-
}
9216+
memset(&elem, 0, sizeof(elem));
9217+
elem.priv = catchall->elem;
92039218

9219+
nft_setelem_data_deactivate(gc->net, gc->set, &elem);
9220+
nft_setelem_catchall_destroy(catchall);
92049221
nft_trans_gc_elem_add(gc, elem_priv);
92059222
}
92069223

92079224
return gc;
92089225
}
92099226

9210-
struct nft_trans_gc *nft_trans_gc_catchall_async(struct nft_trans_gc *gc,
9211-
unsigned int gc_seq)
9212-
{
9213-
return nft_trans_gc_catchall(gc, gc_seq, false);
9214-
}
9215-
9216-
struct nft_trans_gc *nft_trans_gc_catchall_sync(struct nft_trans_gc *gc)
9217-
{
9218-
return nft_trans_gc_catchall(gc, 0, true);
9219-
}
9220-
92219227
static void nf_tables_module_autoload_cleanup(struct net *net)
92229228
{
92239229
struct nftables_pernet *nft_net = nft_pernet(net);

0 commit comments

Comments
 (0)