Skip to content

Commit 332c446

Browse files
committed
netfilter: nftables: add nft_pernet() helper function
jira VULN-429 pre-cve CVE-2023-4244 commit-author Pablo Neira Ayuso <[email protected]> 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 <[email protected]> (cherry picked from commit d59d2f8) Signed-off-by: Greg Rose <[email protected]>
1 parent 5e9f8e2 commit 332c446

File tree

2 files changed

+61
-5
lines changed

2 files changed

+61
-5
lines changed

include/net/netfilter/nf_tables.h

+14
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

+47-5
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

@@ -4783,7 +4786,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
47834786
rcu_read_lock();
47844787
cb->seq = READ_ONCE(net->nft.base_seq);
47854788

4786-
list_for_each_entry_rcu(table, &net->nft.tables, list) {
4789+
list_for_each_entry_rcu(table, &net->nft.tables, list) {
47874790
if (dump_ctx->ctx.family != NFPROTO_UNSPEC &&
47884791
dump_ctx->ctx.family != table->family)
47894792
continue;
@@ -7957,14 +7960,31 @@ static void nft_set_commit_update(struct list_head *set_update_list)
79577960
}
79587961
}
79597962

7963+
static unsigned int nft_gc_seq_begin(struct nftables_pernet *nft_net)
7964+
{
7965+
unsigned int gc_seq;
7966+
7967+
/* Bump gc counter, it becomes odd, this is the busy mark. */
7968+
gc_seq = READ_ONCE(nft_net->gc_seq);
7969+
WRITE_ONCE(nft_net->gc_seq, ++gc_seq);
7970+
7971+
return gc_seq;
7972+
}
7973+
7974+
static void nft_gc_seq_end(struct nftables_pernet *nft_net, unsigned int gc_seq)
7975+
{
7976+
WRITE_ONCE(nft_net->gc_seq, ++gc_seq);
7977+
}
7978+
79607979
static int nf_tables_commit(struct net *net, struct sk_buff *skb)
79617980
{
7981+
struct nftables_pernet *nft_net = nft_pernet(net);
79627982
struct nft_trans *trans, *next;
7983+
unsigned int base_seq, gc_seq;
79637984
LIST_HEAD(set_update_list);
79647985
struct nft_trans_elem *te;
79657986
struct nft_chain *chain;
79667987
struct nft_table *table;
7967-
unsigned int base_seq;
79687988
LIST_HEAD(adl);
79697989
int err;
79707990

@@ -8015,6 +8035,8 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
80158035

80168036
WRITE_ONCE(net->nft.base_seq, base_seq);
80178037

8038+
gc_seq = nft_gc_seq_begin(nft_net);
8039+
80188040
/* step 3. Start new generation, rules_gen_X now in use. */
80198041
net->nft.gencursor = nft_gencursor_next(net);
80208042

@@ -8393,18 +8415,25 @@ static void nf_tables_cleanup(struct net *net)
83938415
static int nf_tables_abort(struct net *net, struct sk_buff *skb,
83948416
enum nfnl_abort_action action)
83958417
{
8396-
int ret = __nf_tables_abort(net, action);
8418+
struct nftables_pernet *nft_net = nft_pernet(net);
8419+
unsigned int gc_seq;
8420+
int ret;
83978421

8422+
gc_seq = nft_gc_seq_begin(nft_net);
8423+
ret = __nf_tables_abort(net, action);
8424+
nft_gc_seq_end(nft_net, gc_seq);
83988425
mutex_unlock(&net->nft_commit_mutex);
83998426

84008427
return ret;
84018428
}
84028429

84038430
static bool nf_tables_valid_genid(struct net *net, u32 genid)
84048431
{
8432+
struct nftables_pernet *nft_net = nft_pernet(net);
84058433
bool genid_ok;
84068434

84078435
mutex_lock(&net->nft_commit_mutex);
8436+
nft_net->tstamp = get_jiffies_64();
84088437

84098438
genid_ok = genid == 0 || net->nft.base_seq == genid;
84108439
if (!genid_ok)
@@ -9014,13 +9043,16 @@ static void __nft_release_tables(struct net *net)
90149043

90159044
static int __net_init nf_tables_init_net(struct net *net)
90169045
{
9046+
struct nftables_pernet *nft_net = nft_pernet(net);
9047+
90179048
INIT_LIST_HEAD(&net->nft.tables);
90189049
INIT_LIST_HEAD(&net->nft.commit_list);
90199050
INIT_LIST_HEAD(&net->nft_module_list);
90209051
INIT_LIST_HEAD(&net->nft_notify_list);
90219052
mutex_init(&net->nft_commit_mutex);
90229053
net->nft.base_seq = 1;
90239054
net->nft.validate_state = NFT_VALIDATE_SKIP;
9055+
nft_net->gc_seq = 0;
90249056

90259057
return 0;
90269058
}
@@ -9034,11 +9066,21 @@ static void __net_exit nf_tables_pre_exit_net(struct net *net)
90349066

90359067
static void __net_exit nf_tables_exit_net(struct net *net)
90369068
{
9069+
struct nftables_pernet *nft_net = nft_pernet(net);
9070+
unsigned int gc_seq;
9071+
90379072
mutex_lock(&net->nft_commit_mutex);
9073+
9074+
gc_seq = nft_gc_seq_begin(nft_net);
9075+
90389076
if (!list_empty(&net->nft.commit_list) ||
90399077
!list_empty(&net->nft_module_list))
90409078
__nf_tables_abort(net, NFNL_ABORT_NONE);
9079+
90419080
__nft_release_tables(net);
9081+
9082+
nft_gc_seq_end(nft_net, gc_seq);
9083+
90429084
mutex_unlock(&net->nft_commit_mutex);
90439085
WARN_ON_ONCE(!list_empty(&net->nft.tables));
90449086
WARN_ON_ONCE(!list_empty(&net->nft_module_list));

0 commit comments

Comments
 (0)