Skip to content

Commit a995a68

Browse files
ummakynesgregkh
authored andcommitted
netfilter: nf_tables: fix memleak when more than 255 elements expired
commit cf5000a upstream. 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> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent b95d7af commit a995a68

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
@@ -1440,7 +1440,7 @@ struct nft_trans_gc {
14401440
struct net *net;
14411441
struct nft_set *set;
14421442
u32 seq;
1443-
u8 count;
1443+
u16 count;
14441444
void *priv[NFT_TRANS_GC_BATCHCOUNT];
14451445
struct rcu_head rcu;
14461446
};

net/netfilter/nf_tables_api.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7089,12 +7089,15 @@ static int nft_trans_gc_space(struct nft_trans_gc *trans)
70897089
struct nft_trans_gc *nft_trans_gc_queue_async(struct nft_trans_gc *gc,
70907090
unsigned int gc_seq, gfp_t gfp)
70917091
{
7092+
struct nft_set *set;
7093+
70927094
if (nft_trans_gc_space(gc))
70937095
return gc;
70947096

7097+
set = gc->set;
70957098
nft_trans_gc_queue_work(gc);
70967099

7097-
return nft_trans_gc_alloc(gc->set, gc_seq, gfp);
7100+
return nft_trans_gc_alloc(set, gc_seq, gfp);
70987101
}
70997102
EXPORT_SYMBOL_GPL(nft_trans_gc_queue_async);
71007103

@@ -7111,15 +7114,18 @@ EXPORT_SYMBOL_GPL(nft_trans_gc_queue_async_done);
71117114

71127115
struct nft_trans_gc *nft_trans_gc_queue_sync(struct nft_trans_gc *gc, gfp_t gfp)
71137116
{
7117+
struct nft_set *set;
7118+
71147119
if (WARN_ON_ONCE(!lockdep_commit_lock_is_held(gc->net)))
71157120
return NULL;
71167121

71177122
if (nft_trans_gc_space(gc))
71187123
return gc;
71197124

7125+
set = gc->set;
71207126
call_rcu(&gc->rcu, nft_trans_gc_trans_free);
71217127

7122-
return nft_trans_gc_alloc(gc->set, 0, gfp);
7128+
return nft_trans_gc_alloc(set, 0, gfp);
71237129
}
71247130
EXPORT_SYMBOL_GPL(nft_trans_gc_queue_sync);
71257131

0 commit comments

Comments
 (0)