Merge tag 'nf-23-09-20' of https://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf
Florian Westphal says: ==================== netfilter updates for net The following three patches fix regressions in the netfilter subsystem: 1. Reject attempts to repeatedly toggle the 'dormant' flag in a single transaction. Doing so makes nf_tables lose track of the real state vs. the desired state. This ends with an attempt to unregister hooks that were never registered in the first place, which yields a splat. 2. Fix element counting in the new nftables garbage collection infra that came with 6.5: More than 255 expired elements wraps a counter which results in memory leak. 3. Since 6.4 ipset can BUG when a set is renamed while a CREATE command is in progress, fix from Jozsef Kadlecsik. * tag 'nf-23-09-20' of https://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf: netfilter: ipset: Fix race between IPSET_CMD_CREATE and IPSET_CMD_SWAP netfilter: nf_tables: fix memleak when more than 255 elements expired netfilter: nf_tables: disable toggling dormant table state more than once ==================== Link: https://lore.kernel.org/r/20230920084156.4192-1-fw@strlen.de Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
||||
@@ -682,6 +682,14 @@ __ip_set_put(struct ip_set *set)
|
||||
/* set->ref can be swapped out by ip_set_swap, netlink events (like dump) need
|
||||
* a separate reference counter
|
||||
*/
|
||||
static void
|
||||
__ip_set_get_netlink(struct ip_set *set)
|
||||
{
|
||||
write_lock_bh(&ip_set_ref_lock);
|
||||
set->ref_netlink++;
|
||||
write_unlock_bh(&ip_set_ref_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
__ip_set_put_netlink(struct ip_set *set)
|
||||
{
|
||||
@@ -1693,11 +1701,11 @@ call_ad(struct net *net, struct sock *ctnl, struct sk_buff *skb,
|
||||
|
||||
do {
|
||||
if (retried) {
|
||||
__ip_set_get(set);
|
||||
__ip_set_get_netlink(set);
|
||||
nfnl_unlock(NFNL_SUBSYS_IPSET);
|
||||
cond_resched();
|
||||
nfnl_lock(NFNL_SUBSYS_IPSET);
|
||||
__ip_set_put(set);
|
||||
__ip_set_put_netlink(set);
|
||||
}
|
||||
|
||||
ip_set_lock(set);
|
||||
|
||||
@@ -1219,6 +1219,10 @@ static int nf_tables_updtable(struct nft_ctx *ctx)
|
||||
flags & NFT_TABLE_F_OWNER))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* No dormant off/on/off/on games in single transaction */
|
||||
if (ctx->table->flags & __NFT_TABLE_F_UPDATE)
|
||||
return -EINVAL;
|
||||
|
||||
trans = nft_trans_alloc(ctx, NFT_MSG_NEWTABLE,
|
||||
sizeof(struct nft_trans_table));
|
||||
if (trans == NULL)
|
||||
@@ -9575,12 +9579,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)
|
||||
@@ -9595,15 +9602,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)
|
||||
|
||||
Reference in New Issue
Block a user