Skip to content

Commit ecf4392

Browse files
author
Paolo Abeni
committed
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>
2 parents fc21f08 + 7433b6d commit ecf4392

File tree

3 files changed

+23
-5
lines changed

3 files changed

+23
-5
lines changed

include/net/netfilter/nf_tables.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1682,7 +1682,7 @@ struct nft_trans_gc {
16821682
struct net *net;
16831683
struct nft_set *set;
16841684
u32 seq;
1685-
u8 count;
1685+
u16 count;
16861686
void *priv[NFT_TRANS_GC_BATCHCOUNT];
16871687
struct rcu_head rcu;
16881688
};

net/netfilter/ipset/ip_set_core.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,14 @@ __ip_set_put(struct ip_set *set)
682682
/* set->ref can be swapped out by ip_set_swap, netlink events (like dump) need
683683
* a separate reference counter
684684
*/
685+
static void
686+
__ip_set_get_netlink(struct ip_set *set)
687+
{
688+
write_lock_bh(&ip_set_ref_lock);
689+
set->ref_netlink++;
690+
write_unlock_bh(&ip_set_ref_lock);
691+
}
692+
685693
static void
686694
__ip_set_put_netlink(struct ip_set *set)
687695
{
@@ -1693,11 +1701,11 @@ call_ad(struct net *net, struct sock *ctnl, struct sk_buff *skb,
16931701

16941702
do {
16951703
if (retried) {
1696-
__ip_set_get(set);
1704+
__ip_set_get_netlink(set);
16971705
nfnl_unlock(NFNL_SUBSYS_IPSET);
16981706
cond_resched();
16991707
nfnl_lock(NFNL_SUBSYS_IPSET);
1700-
__ip_set_put(set);
1708+
__ip_set_put_netlink(set);
17011709
}
17021710

17031711
ip_set_lock(set);

net/netfilter/nf_tables_api.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,6 +1219,10 @@ static int nf_tables_updtable(struct nft_ctx *ctx)
12191219
flags & NFT_TABLE_F_OWNER))
12201220
return -EOPNOTSUPP;
12211221

1222+
/* No dormant off/on/off/on games in single transaction */
1223+
if (ctx->table->flags & __NFT_TABLE_F_UPDATE)
1224+
return -EINVAL;
1225+
12221226
trans = nft_trans_alloc(ctx, NFT_MSG_NEWTABLE,
12231227
sizeof(struct nft_trans_table));
12241228
if (trans == NULL)
@@ -9575,12 +9579,15 @@ static int nft_trans_gc_space(struct nft_trans_gc *trans)
95759579
struct nft_trans_gc *nft_trans_gc_queue_async(struct nft_trans_gc *gc,
95769580
unsigned int gc_seq, gfp_t gfp)
95779581
{
9582+
struct nft_set *set;
9583+
95789584
if (nft_trans_gc_space(gc))
95799585
return gc;
95809586

9587+
set = gc->set;
95819588
nft_trans_gc_queue_work(gc);
95829589

9583-
return nft_trans_gc_alloc(gc->set, gc_seq, gfp);
9590+
return nft_trans_gc_alloc(set, gc_seq, gfp);
95849591
}
95859592

95869593
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)
95959602

95969603
struct nft_trans_gc *nft_trans_gc_queue_sync(struct nft_trans_gc *gc, gfp_t gfp)
95979604
{
9605+
struct nft_set *set;
9606+
95989607
if (WARN_ON_ONCE(!lockdep_commit_lock_is_held(gc->net)))
95999608
return NULL;
96009609

96019610
if (nft_trans_gc_space(gc))
96029611
return gc;
96039612

9613+
set = gc->set;
96049614
call_rcu(&gc->rcu, nft_trans_gc_trans_free);
96059615

9606-
return nft_trans_gc_alloc(gc->set, 0, gfp);
9616+
return nft_trans_gc_alloc(set, 0, gfp);
96079617
}
96089618

96099619
void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans)

0 commit comments

Comments
 (0)