Skip to content

Commit 82e5ca7

Browse files
committed
netfilter: nftables: add nft_pernet() helper function
jira VULN-429 pre-cve CVE-2023-4244 commit-author Pablo Neira Ayuso <pablo@netfilter.org> commit d59d2f8 upstream-diff So many conflicts when trying to cherry pick this but they're all very similar and didn't have much trouble picking them out. As per previous commits in this series I've used rocky8_10 branch as the source of truth when resolving conflicts. Consolidate call to net_generic(net, nf_tables_net_id) in this wrapper function. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> (cherry picked from commit d59d2f8) Signed-off-by: Greg Rose <g.v.rose@ciq.com>
1 parent e32fc00 commit 82e5ca7

File tree

2 files changed

+61
-5
lines changed

2 files changed

+61
-5
lines changed

include/net/netfilter/nf_tables.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <net/netfilter/nf_flow_table.h>
1414
#include <net/netlink.h>
1515
#include <net/flow_offload.h>
16+
#include <net/netns/generic.h>
1617

1718
struct module;
1819

@@ -1561,4 +1562,17 @@ __printf(2, 3) int nft_request_module(struct net *net, const char *fmt, ...);
15611562
#else
15621563
static inline int nft_request_module(struct net *net, const char *fmt, ...) { return -ENOENT; }
15631564
#endif
1565+
1566+
struct nftables_pernet {
1567+
u64 tstamp;
1568+
unsigned int gc_seq;
1569+
};
1570+
1571+
extern unsigned int nf_tables_net_id;
1572+
1573+
static inline struct nftables_pernet *nft_pernet(const struct net *net)
1574+
{
1575+
return net_generic(net, nf_tables_net_id);
1576+
}
1577+
15641578
#endif /* _NET_NF_TABLES_H */

net/netfilter/nf_tables_api.c

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828

2929
#define NFT_MODULE_AUTOLOAD_LIMIT (MODULE_NAME_LEN - sizeof("nft-expr-255-"))
3030

31+
unsigned int nf_tables_net_id __read_mostly;
32+
EXPORT_SYMBOL_GPL(nf_tables_net_id);
33+
3134
static LIST_HEAD(nf_tables_expressions);
3235
static LIST_HEAD(nf_tables_objects);
3336
static LIST_HEAD(nf_tables_flowtables);
@@ -3593,8 +3596,8 @@ static struct nft_set *nft_set_lookup_byid(const struct net *net,
35933596
const struct nft_table *table,
35943597
const struct nlattr *nla, u8 genmask)
35953598
{
3596-
struct nft_trans *trans;
35973599
u32 id = ntohl(nla_get_be32(nla));
3600+
struct nft_trans *trans;
35983601

35993602
list_for_each_entry(trans, &net->nft.commit_list, list) {
36003603
if (trans->msg_type == NFT_MSG_NEWSET) {
@@ -3837,8 +3840,8 @@ static void nf_tables_set_notify(const struct nft_ctx *ctx,
38373840
const struct nft_set *set, int event,
38383841
gfp_t gfp_flags)
38393842
{
3840-
u32 portid = ctx->portid;
38413843
struct sk_buff *skb;
3844+
u32 portid = ctx->portid;
38423845
u16 flags = 0;
38433846
int err;
38443847

@@ -4786,7 +4789,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
47864789
rcu_read_lock();
47874790
cb->seq = READ_ONCE(net->nft.base_seq);
47884791

4789-
list_for_each_entry_rcu(table, &net->nft.tables, list) {
4792+
list_for_each_entry_rcu(table, &net->nft.tables, list) {
47904793
if (dump_ctx->ctx.family != NFPROTO_UNSPEC &&
47914794
dump_ctx->ctx.family != table->family)
47924795
continue;
@@ -7955,14 +7958,31 @@ static void nft_set_commit_update(struct list_head *set_update_list)
79557958
}
79567959
}
79577960

7961+
static unsigned int nft_gc_seq_begin(struct nftables_pernet *nft_net)
7962+
{
7963+
unsigned int gc_seq;
7964+
7965+
/* Bump gc counter, it becomes odd, this is the busy mark. */
7966+
gc_seq = READ_ONCE(nft_net->gc_seq);
7967+
WRITE_ONCE(nft_net->gc_seq, ++gc_seq);
7968+
7969+
return gc_seq;
7970+
}
7971+
7972+
static void nft_gc_seq_end(struct nftables_pernet *nft_net, unsigned int gc_seq)
7973+
{
7974+
WRITE_ONCE(nft_net->gc_seq, ++gc_seq);
7975+
}
7976+
79587977
static int nf_tables_commit(struct net *net, struct sk_buff *skb)
79597978
{
7979+
struct nftables_pernet *nft_net = nft_pernet(net);
79607980
struct nft_trans *trans, *next;
7981+
unsigned int base_seq, gc_seq;
79617982
LIST_HEAD(set_update_list);
79627983
struct nft_trans_elem *te;
79637984
struct nft_chain *chain;
79647985
struct nft_table *table;
7965-
unsigned int base_seq;
79667986
LIST_HEAD(adl);
79677987
int err;
79687988

@@ -8013,6 +8033,8 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
80138033

80148034
WRITE_ONCE(net->nft.base_seq, base_seq);
80158035

8036+
gc_seq = nft_gc_seq_begin(nft_net);
8037+
80168038
/* step 3. Start new generation, rules_gen_X now in use. */
80178039
net->nft.gencursor = nft_gencursor_next(net);
80188040

@@ -8391,18 +8413,25 @@ static void nf_tables_cleanup(struct net *net)
83918413
static int nf_tables_abort(struct net *net, struct sk_buff *skb,
83928414
enum nfnl_abort_action action)
83938415
{
8394-
int ret = __nf_tables_abort(net, action);
8416+
struct nftables_pernet *nft_net = nft_pernet(net);
8417+
unsigned int gc_seq;
8418+
int ret;
83958419

8420+
gc_seq = nft_gc_seq_begin(nft_net);
8421+
ret = __nf_tables_abort(net, action);
8422+
nft_gc_seq_end(nft_net, gc_seq);
83968423
mutex_unlock(&net->nft_commit_mutex);
83978424

83988425
return ret;
83998426
}
84008427

84018428
static bool nf_tables_valid_genid(struct net *net, u32 genid)
84028429
{
8430+
struct nftables_pernet *nft_net = nft_pernet(net);
84038431
bool genid_ok;
84048432

84058433
mutex_lock(&net->nft_commit_mutex);
8434+
nft_net->tstamp = get_jiffies_64();
84068435

84078436
genid_ok = genid == 0 || net->nft.base_seq == genid;
84088437
if (!genid_ok)
@@ -9012,13 +9041,16 @@ static void __nft_release_tables(struct net *net)
90129041

90139042
static int __net_init nf_tables_init_net(struct net *net)
90149043
{
9044+
struct nftables_pernet *nft_net = nft_pernet(net);
9045+
90159046
INIT_LIST_HEAD(&net->nft.tables);
90169047
INIT_LIST_HEAD(&net->nft.commit_list);
90179048
INIT_LIST_HEAD(&net->nft_module_list);
90189049
INIT_LIST_HEAD(&net->nft_notify_list);
90199050
mutex_init(&net->nft_commit_mutex);
90209051
net->nft.base_seq = 1;
90219052
net->nft.validate_state = NFT_VALIDATE_SKIP;
9053+
nft_net->gc_seq = 0;
90229054

90239055
return 0;
90249056
}
@@ -9032,11 +9064,21 @@ static void __net_exit nf_tables_pre_exit_net(struct net *net)
90329064

90339065
static void __net_exit nf_tables_exit_net(struct net *net)
90349066
{
9067+
struct nftables_pernet *nft_net = nft_pernet(net);
9068+
unsigned int gc_seq;
9069+
90359070
mutex_lock(&net->nft_commit_mutex);
9071+
9072+
gc_seq = nft_gc_seq_begin(nft_net);
9073+
90369074
if (!list_empty(&net->nft.commit_list) ||
90379075
!list_empty(&net->nft_module_list))
90389076
__nf_tables_abort(net, NFNL_ABORT_NONE);
9077+
90399078
__nft_release_tables(net);
9079+
9080+
nft_gc_seq_end(nft_net, gc_seq);
9081+
90409082
mutex_unlock(&net->nft_commit_mutex);
90419083
WARN_ON_ONCE(!list_empty(&net->nft.tables));
90429084
WARN_ON_ONCE(!list_empty(&net->nft_module_list));

0 commit comments

Comments
 (0)