Skip to content

Commit 25dfead

Browse files
committed
netfilter: nf_tables: fix memleak when more than 255 elements expired
jira VULN-598 cve CVE-2023-52581 commit-author Florian Westphal <fw@strlen.de> commit cf5000a When more than 255 elements expired we're supposed to switch to a new gc container structure. This never happens: u8 type will wrap before reaching the boundary and nft_trans_gc_space() always returns true. This means we recycle the initial gc container structure and lose track of the elements that came before. While at it, don't deref 'gc' after we've passed it to call_rcu. Fixes: 5f68718 ("netfilter: nf_tables: GC transaction API to avoid race with control plane") Reported-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Florian Westphal <fw@strlen.de> (cherry picked from commit cf5000a) Signed-off-by: Marcin Wcisło <marcin.wcislo@conclusive.pl>
1 parent 29b8b9a commit 25dfead

File tree

2 files changed

+9
-3
lines changed

2 files changed

+9
-3
lines changed

include/net/netfilter/nf_tables.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1611,7 +1611,7 @@ struct nft_trans_gc {
16111611
struct net *net;
16121612
struct nft_set *set;
16131613
u32 seq;
1614-
u8 count;
1614+
u16 count;
16151615
void *priv[NFT_TRANS_GC_BATCHCOUNT];
16161616
struct rcu_head rcu;
16171617
};

net/netfilter/nf_tables_api.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9218,12 +9218,15 @@ static int nft_trans_gc_space(struct nft_trans_gc *trans)
92189218
struct nft_trans_gc *nft_trans_gc_queue_async(struct nft_trans_gc *gc,
92199219
unsigned int gc_seq, gfp_t gfp)
92209220
{
9221+
struct nft_set *set;
9222+
92219223
if (nft_trans_gc_space(gc))
92229224
return gc;
92239225

9226+
set = gc->set;
92249227
nft_trans_gc_queue_work(gc);
92259228

9226-
return nft_trans_gc_alloc(gc->set, gc_seq, gfp);
9229+
return nft_trans_gc_alloc(set, gc_seq, gfp);
92279230
}
92289231

92299232
void nft_trans_gc_queue_async_done(struct nft_trans_gc *trans)
@@ -9238,15 +9241,18 @@ void nft_trans_gc_queue_async_done(struct nft_trans_gc *trans)
92389241

92399242
struct nft_trans_gc *nft_trans_gc_queue_sync(struct nft_trans_gc *gc, gfp_t gfp)
92409243
{
9244+
struct nft_set *set;
9245+
92419246
if (WARN_ON_ONCE(!lockdep_commit_lock_is_held(gc->net)))
92429247
return NULL;
92439248

92449249
if (nft_trans_gc_space(gc))
92459250
return gc;
92469251

9252+
set = gc->set;
92479253
call_rcu(&gc->rcu, nft_trans_gc_trans_free);
92489254

9249-
return nft_trans_gc_alloc(gc->set, 0, gfp);
9255+
return nft_trans_gc_alloc(set, 0, gfp);
92509256
}
92519257

92529258
void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans)

0 commit comments

Comments
 (0)