netfilter: nf_tables: remove catchall element in GC sync path
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: 4a9e12ea7e
("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>
This commit is contained in:
parent
94090b23f3
commit
93995bf4af
1 changed files with 17 additions and 5 deletions
|
@ -6520,6 +6520,12 @@ static int nft_setelem_deactivate(const struct net *net,
|
||||||
return ret;
|
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,
|
static void nft_setelem_catchall_remove(const struct net *net,
|
||||||
const struct nft_set *set,
|
const struct nft_set *set,
|
||||||
struct nft_elem_priv *elem_priv)
|
struct nft_elem_priv *elem_priv)
|
||||||
|
@ -6528,8 +6534,7 @@ static void nft_setelem_catchall_remove(const struct net *net,
|
||||||
|
|
||||||
list_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
|
list_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
|
||||||
if (catchall->elem == elem_priv) {
|
if (catchall->elem == elem_priv) {
|
||||||
list_del_rcu(&catchall->list);
|
nft_setelem_catchall_destroy(catchall);
|
||||||
kfree_rcu(catchall, rcu);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9678,11 +9683,12 @@ static struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
|
||||||
unsigned int gc_seq,
|
unsigned int gc_seq,
|
||||||
bool sync)
|
bool sync)
|
||||||
{
|
{
|
||||||
struct nft_set_elem_catchall *catchall;
|
struct nft_set_elem_catchall *catchall, *next;
|
||||||
const struct nft_set *set = gc->set;
|
const struct nft_set *set = gc->set;
|
||||||
|
struct nft_elem_priv *elem_priv;
|
||||||
struct nft_set_ext *ext;
|
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);
|
ext = nft_set_elem_ext(set, catchall->elem);
|
||||||
|
|
||||||
if (!nft_set_elem_expired(ext))
|
if (!nft_set_elem_expired(ext))
|
||||||
|
@ -9700,7 +9706,13 @@ dead_elem:
|
||||||
if (!gc)
|
if (!gc)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
nft_trans_gc_elem_add(gc, catchall->elem);
|
elem_priv = catchall->elem;
|
||||||
|
if (sync) {
|
||||||
|
nft_setelem_data_deactivate(gc->net, gc->set, elem_priv);
|
||||||
|
nft_setelem_catchall_destroy(catchall);
|
||||||
|
}
|
||||||
|
|
||||||
|
nft_trans_gc_elem_add(gc, elem_priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
return gc;
|
return gc;
|
||||||
|
|
Loading…
Add table
Reference in a new issue