Skip to content

Commit 779328c

Browse files
committed
netfilter: nf_tables: fix memleak when more than 255 elements expired
jira VUlN-597 cve CVE-2023-52581 commit-author Florian Westphal <[email protected]> commit cf5000a upstream-diff We had to pull in a piece of upstream commit 6001a93 "netfilter: nftables: introduce table ownership". Red Hat pulled in some code that uses NFT_TABLE_F_MASK but they didn't want the full commit so they just redefined NFT_TABLE_F_MASK as NFT_TABLE_F_DORMANT. 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 <[email protected]> Signed-off-by: Florian Westphal <[email protected]> (cherry picked from commit cf5000a) Signed-off-by: Greg Rose <[email protected]> squash
1 parent d1dccb9 commit 779328c

File tree

3 files changed

+10
-3
lines changed

3 files changed

+10
-3
lines changed

include/net/netfilter/nf_tables.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1494,7 +1494,7 @@ struct nft_trans_gc {
14941494
struct net *net;
14951495
struct nft_set *set;
14961496
u32 seq;
1497-
u8 count;
1497+
u16 count;
14981498
void *priv[NFT_TRANS_GC_BATCHCOUNT];
14991499
struct rcu_head rcu;
15001500
};

include/uapi/linux/netfilter/nf_tables.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ enum nft_hook_attributes {
164164
enum nft_table_flags {
165165
NFT_TABLE_F_DORMANT = 0x1,
166166
};
167+
#define NFT_TABLE_F_MASK (NFT_TABLE_F_DORMANT)
167168

168169
/**
169170
* enum nft_table_attributes - nf_tables table netlink attributes

net/netfilter/nf_tables_api.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7955,12 +7955,15 @@ static int nft_trans_gc_space(struct nft_trans_gc *trans)
79557955
struct nft_trans_gc *nft_trans_gc_queue_async(struct nft_trans_gc *gc,
79567956
unsigned int gc_seq, gfp_t gfp)
79577957
{
7958+
struct nft_set *set;
7959+
79587960
if (nft_trans_gc_space(gc))
79597961
return gc;
79607962

7963+
set = gc->set;
79617964
nft_trans_gc_queue_work(gc);
79627965

7963-
return nft_trans_gc_alloc(gc->set, gc_seq, gfp);
7966+
return nft_trans_gc_alloc(set, gc_seq, gfp);
79647967
}
79657968
EXPORT_SYMBOL_GPL(nft_trans_gc_queue_async);
79667969

@@ -7977,15 +7980,18 @@ EXPORT_SYMBOL_GPL(nft_trans_gc_queue_async_done);
79777980

79787981
struct nft_trans_gc *nft_trans_gc_queue_sync(struct nft_trans_gc *gc, gfp_t gfp)
79797982
{
7983+
struct nft_set *set;
7984+
79807985
if (WARN_ON_ONCE(!lockdep_commit_lock_is_held(gc->net)))
79817986
return NULL;
79827987

79837988
if (nft_trans_gc_space(gc))
79847989
return gc;
79857990

7991+
set = gc->set;
79867992
call_rcu(&gc->rcu, nft_trans_gc_trans_free);
79877993

7988-
return nft_trans_gc_alloc(gc->set, 0, gfp);
7994+
return nft_trans_gc_alloc(set, 0, gfp);
79897995
}
79907996
EXPORT_SYMBOL_GPL(nft_trans_gc_queue_sync);
79917997

0 commit comments

Comments
 (0)