Skip to content

Commit fbad06a

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 0972124 commit fbad06a

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
@@ -7956,12 +7956,15 @@ static int nft_trans_gc_space(struct nft_trans_gc *trans)
79567956
struct nft_trans_gc *nft_trans_gc_queue_async(struct nft_trans_gc *gc,
79577957
unsigned int gc_seq, gfp_t gfp)
79587958
{
7959+
struct nft_set *set;
7960+
79597961
if (nft_trans_gc_space(gc))
79607962
return gc;
79617963

7964+
set = gc->set;
79627965
nft_trans_gc_queue_work(gc);
79637966

7964-
return nft_trans_gc_alloc(gc->set, gc_seq, gfp);
7967+
return nft_trans_gc_alloc(set, gc_seq, gfp);
79657968
}
79667969
EXPORT_SYMBOL_GPL(nft_trans_gc_queue_async);
79677970

@@ -7978,15 +7981,18 @@ EXPORT_SYMBOL_GPL(nft_trans_gc_queue_async_done);
79787981

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

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

7992+
set = gc->set;
79877993
call_rcu(&gc->rcu, nft_trans_gc_trans_free);
79887994

7989-
return nft_trans_gc_alloc(gc->set, 0, gfp);
7995+
return nft_trans_gc_alloc(set, 0, gfp);
79907996
}
79917997
EXPORT_SYMBOL_GPL(nft_trans_gc_queue_sync);
79927998

0 commit comments

Comments
 (0)