Skip to content

Commit 664b0f8

Browse files
committed
netfilter: nf_tables: add generation mask to chains
Similar to ("netfilter: nf_tables: add generation mask to tables"). Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
1 parent f2a6d76 commit 664b0f8

File tree

2 files changed

+60
-33
lines changed

2 files changed

+60
-33
lines changed

include/net/netfilter/nf_tables.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -732,7 +732,6 @@ static inline struct nft_userdata *nft_userdata(const struct nft_rule *rule)
732732

733733
enum nft_chain_flags {
734734
NFT_BASE_CHAIN = 0x1,
735-
NFT_CHAIN_INACTIVE = 0x2,
736735
};
737736

738737
/**
@@ -754,7 +753,8 @@ struct nft_chain {
754753
u64 handle;
755754
u32 use;
756755
u16 level;
757-
u8 flags;
756+
u8 flags:6,
757+
genmask:2;
758758
char name[NFT_CHAIN_MAXNAMELEN];
759759
};
760760

net/netfilter/nf_tables_api.c

Lines changed: 58 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ static int nft_trans_chain_add(struct nft_ctx *ctx, int msg_type)
211211
return -ENOMEM;
212212

213213
if (msg_type == NFT_MSG_NEWCHAIN)
214-
ctx->chain->flags |= NFT_CHAIN_INACTIVE;
214+
nft_activate_next(ctx->net, ctx->chain);
215215

216216
list_add_tail(&trans->list, &ctx->net->nft.commit_list);
217217
return 0;
@@ -226,7 +226,7 @@ static int nft_delchain(struct nft_ctx *ctx)
226226
return err;
227227

228228
ctx->table->use--;
229-
list_del_rcu(&ctx->chain->list);
229+
nft_deactivate_next(ctx->net, ctx->chain);
230230

231231
return err;
232232
}
@@ -559,13 +559,16 @@ static int nf_tables_gettable(struct net *net, struct sock *nlsk,
559559
return err;
560560
}
561561

562-
static int nf_tables_table_enable(const struct nft_af_info *afi,
562+
static int nf_tables_table_enable(struct net *net,
563+
const struct nft_af_info *afi,
563564
struct nft_table *table)
564565
{
565566
struct nft_chain *chain;
566567
int err, i = 0;
567568

568569
list_for_each_entry(chain, &table->chains, list) {
570+
if (!nft_is_active_next(net, chain))
571+
continue;
569572
if (!(chain->flags & NFT_BASE_CHAIN))
570573
continue;
571574

@@ -578,6 +581,8 @@ static int nf_tables_table_enable(const struct nft_af_info *afi,
578581
return 0;
579582
err:
580583
list_for_each_entry(chain, &table->chains, list) {
584+
if (!nft_is_active_next(net, chain))
585+
continue;
581586
if (!(chain->flags & NFT_BASE_CHAIN))
582587
continue;
583588

@@ -589,12 +594,15 @@ static int nf_tables_table_enable(const struct nft_af_info *afi,
589594
return err;
590595
}
591596

592-
static void nf_tables_table_disable(const struct nft_af_info *afi,
597+
static void nf_tables_table_disable(struct net *net,
598+
const struct nft_af_info *afi,
593599
struct nft_table *table)
594600
{
595601
struct nft_chain *chain;
596602

597603
list_for_each_entry(chain, &table->chains, list) {
604+
if (!nft_is_active_next(net, chain))
605+
continue;
598606
if (chain->flags & NFT_BASE_CHAIN)
599607
nft_unregister_basechain(nft_base_chain(chain),
600608
afi->nops);
@@ -627,7 +635,7 @@ static int nf_tables_updtable(struct nft_ctx *ctx)
627635
nft_trans_table_enable(trans) = false;
628636
} else if (!(flags & NFT_TABLE_F_DORMANT) &&
629637
ctx->table->flags & NFT_TABLE_F_DORMANT) {
630-
ret = nf_tables_table_enable(ctx->afi, ctx->table);
638+
ret = nf_tables_table_enable(ctx->net, ctx->afi, ctx->table);
631639
if (ret >= 0) {
632640
ctx->table->flags &= ~NFT_TABLE_F_DORMANT;
633641
nft_trans_table_enable(trans) = true;
@@ -722,6 +730,9 @@ static int nft_flush_table(struct nft_ctx *ctx)
722730
struct nft_set *set, *ns;
723731

724732
list_for_each_entry(chain, &ctx->table->chains, list) {
733+
if (!nft_is_active_next(ctx->net, chain))
734+
continue;
735+
725736
ctx->chain = chain;
726737

727738
err = nft_delrule_by_chain(ctx);
@@ -740,6 +751,9 @@ static int nft_flush_table(struct nft_ctx *ctx)
740751
}
741752

742753
list_for_each_entry_safe(chain, nc, &ctx->table->chains, list) {
754+
if (!nft_is_active_next(ctx->net, chain))
755+
continue;
756+
743757
ctx->chain = chain;
744758

745759
err = nft_delchain(ctx);
@@ -849,28 +863,32 @@ EXPORT_SYMBOL_GPL(nft_unregister_chain_type);
849863
*/
850864

851865
static struct nft_chain *
852-
nf_tables_chain_lookup_byhandle(const struct nft_table *table, u64 handle)
866+
nf_tables_chain_lookup_byhandle(const struct nft_table *table, u64 handle,
867+
u8 genmask)
853868
{
854869
struct nft_chain *chain;
855870

856871
list_for_each_entry(chain, &table->chains, list) {
857-
if (chain->handle == handle)
872+
if (chain->handle == handle &&
873+
nft_active_genmask(chain, genmask))
858874
return chain;
859875
}
860876

861877
return ERR_PTR(-ENOENT);
862878
}
863879

864880
static struct nft_chain *nf_tables_chain_lookup(const struct nft_table *table,
865-
const struct nlattr *nla)
881+
const struct nlattr *nla,
882+
u8 genmask)
866883
{
867884
struct nft_chain *chain;
868885

869886
if (nla == NULL)
870887
return ERR_PTR(-EINVAL);
871888

872889
list_for_each_entry(chain, &table->chains, list) {
873-
if (!nla_strcmp(nla, chain->name))
890+
if (!nla_strcmp(nla, chain->name) &&
891+
nft_active_genmask(chain, genmask))
874892
return chain;
875893
}
876894

@@ -1053,6 +1071,8 @@ static int nf_tables_dump_chains(struct sk_buff *skb,
10531071
if (idx > s_idx)
10541072
memset(&cb->args[1], 0,
10551073
sizeof(cb->args) - sizeof(cb->args[0]));
1074+
if (!nft_is_active(net, chain))
1075+
continue;
10561076
if (nf_tables_fill_chain_info(skb, net,
10571077
NETLINK_CB(cb->skb).portid,
10581078
cb->nlh->nlmsg_seq,
@@ -1101,11 +1121,9 @@ static int nf_tables_getchain(struct net *net, struct sock *nlsk,
11011121
if (IS_ERR(table))
11021122
return PTR_ERR(table);
11031123

1104-
chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME]);
1124+
chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask);
11051125
if (IS_ERR(chain))
11061126
return PTR_ERR(chain);
1107-
if (chain->flags & NFT_CHAIN_INACTIVE)
1108-
return -ENOENT;
11091127

11101128
skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
11111129
if (!skb2)
@@ -1230,11 +1248,11 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
12301248

12311249
if (nla[NFTA_CHAIN_HANDLE]) {
12321250
handle = be64_to_cpu(nla_get_be64(nla[NFTA_CHAIN_HANDLE]));
1233-
chain = nf_tables_chain_lookup_byhandle(table, handle);
1251+
chain = nf_tables_chain_lookup_byhandle(table, handle, genmask);
12341252
if (IS_ERR(chain))
12351253
return PTR_ERR(chain);
12361254
} else {
1237-
chain = nf_tables_chain_lookup(table, name);
1255+
chain = nf_tables_chain_lookup(table, name, genmask);
12381256
if (IS_ERR(chain)) {
12391257
if (PTR_ERR(chain) != -ENOENT)
12401258
return PTR_ERR(chain);
@@ -1265,16 +1283,20 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
12651283
struct nft_stats *stats = NULL;
12661284
struct nft_trans *trans;
12671285

1268-
if (chain->flags & NFT_CHAIN_INACTIVE)
1269-
return -ENOENT;
12701286
if (nlh->nlmsg_flags & NLM_F_EXCL)
12711287
return -EEXIST;
12721288
if (nlh->nlmsg_flags & NLM_F_REPLACE)
12731289
return -EOPNOTSUPP;
12741290

1275-
if (nla[NFTA_CHAIN_HANDLE] && name &&
1276-
!IS_ERR(nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME])))
1277-
return -EEXIST;
1291+
if (nla[NFTA_CHAIN_HANDLE] && name) {
1292+
struct nft_chain *chain2;
1293+
1294+
chain2 = nf_tables_chain_lookup(table,
1295+
nla[NFTA_CHAIN_NAME],
1296+
genmask);
1297+
if (IS_ERR(chain2))
1298+
return PTR_ERR(chain2);
1299+
}
12781300

12791301
if (nla[NFTA_CHAIN_COUNTERS]) {
12801302
if (!(chain->flags & NFT_BASE_CHAIN))
@@ -1468,7 +1490,7 @@ static int nf_tables_delchain(struct net *net, struct sock *nlsk,
14681490
if (IS_ERR(table))
14691491
return PTR_ERR(table);
14701492

1471-
chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME]);
1493+
chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask);
14721494
if (IS_ERR(chain))
14731495
return PTR_ERR(chain);
14741496
if (chain->use > 0)
@@ -1930,11 +1952,9 @@ static int nf_tables_getrule(struct net *net, struct sock *nlsk,
19301952
if (IS_ERR(table))
19311953
return PTR_ERR(table);
19321954

1933-
chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN]);
1955+
chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN], genmask);
19341956
if (IS_ERR(chain))
19351957
return PTR_ERR(chain);
1936-
if (chain->flags & NFT_CHAIN_INACTIVE)
1937-
return -ENOENT;
19381958

19391959
rule = nf_tables_rule_lookup(chain, nla[NFTA_RULE_HANDLE]);
19401960
if (IS_ERR(rule))
@@ -2008,7 +2028,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
20082028
if (IS_ERR(table))
20092029
return PTR_ERR(table);
20102030

2011-
chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN]);
2031+
chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN], genmask);
20122032
if (IS_ERR(chain))
20132033
return PTR_ERR(chain);
20142034

@@ -2166,7 +2186,8 @@ static int nf_tables_delrule(struct net *net, struct sock *nlsk,
21662186
return PTR_ERR(table);
21672187

21682188
if (nla[NFTA_RULE_CHAIN]) {
2169-
chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN]);
2189+
chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN],
2190+
genmask);
21702191
if (IS_ERR(chain))
21712192
return PTR_ERR(chain);
21722193
}
@@ -2186,6 +2207,9 @@ static int nf_tables_delrule(struct net *net, struct sock *nlsk,
21862207
}
21872208
} else {
21882209
list_for_each_entry(chain, &table->chains, list) {
2210+
if (!nft_is_active_next(net, chain))
2211+
continue;
2212+
21892213
ctx.chain = chain;
21902214
err = nft_delrule_by_chain(&ctx);
21912215
if (err < 0)
@@ -3934,7 +3958,8 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
39343958
case NFT_MSG_NEWTABLE:
39353959
if (nft_trans_table_update(trans)) {
39363960
if (!nft_trans_table_enable(trans)) {
3937-
nf_tables_table_disable(trans->ctx.afi,
3961+
nf_tables_table_disable(net,
3962+
trans->ctx.afi,
39383963
trans->ctx.table);
39393964
trans->ctx.table->flags |= NFT_TABLE_F_DORMANT;
39403965
}
@@ -3952,12 +3977,13 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
39523977
if (nft_trans_chain_update(trans))
39533978
nft_chain_commit_update(trans);
39543979
else
3955-
trans->ctx.chain->flags &= ~NFT_CHAIN_INACTIVE;
3980+
nft_clear(net, trans->ctx.chain);
39563981

39573982
nf_tables_chain_notify(&trans->ctx, NFT_MSG_NEWCHAIN);
39583983
nft_trans_destroy(trans);
39593984
break;
39603985
case NFT_MSG_DELCHAIN:
3986+
list_del_rcu(&trans->ctx.chain->list);
39613987
nf_tables_chain_notify(&trans->ctx, NFT_MSG_DELCHAIN);
39623988
nf_tables_unregister_hooks(trans->ctx.table,
39633989
trans->ctx.chain,
@@ -4061,7 +4087,8 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb)
40614087
case NFT_MSG_NEWTABLE:
40624088
if (nft_trans_table_update(trans)) {
40634089
if (nft_trans_table_enable(trans)) {
4064-
nf_tables_table_disable(trans->ctx.afi,
4090+
nf_tables_table_disable(net,
4091+
trans->ctx.afi,
40654092
trans->ctx.table);
40664093
trans->ctx.table->flags |= NFT_TABLE_F_DORMANT;
40674094
}
@@ -4089,8 +4116,7 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb)
40894116
break;
40904117
case NFT_MSG_DELCHAIN:
40914118
trans->ctx.table->use++;
4092-
list_add_tail_rcu(&trans->ctx.chain->list,
4093-
&trans->ctx.table->chains);
4119+
nft_clear(trans->ctx.net, trans->ctx.chain);
40944120
nft_trans_destroy(trans);
40954121
break;
40964122
case NFT_MSG_NEWRULE:
@@ -4413,6 +4439,7 @@ static const struct nla_policy nft_verdict_policy[NFTA_VERDICT_MAX + 1] = {
44134439
static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
44144440
struct nft_data_desc *desc, const struct nlattr *nla)
44154441
{
4442+
u8 genmask = nft_genmask_next(ctx->net);
44164443
struct nlattr *tb[NFTA_VERDICT_MAX + 1];
44174444
struct nft_chain *chain;
44184445
int err;
@@ -4445,7 +4472,7 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
44454472
if (!tb[NFTA_VERDICT_CHAIN])
44464473
return -EINVAL;
44474474
chain = nf_tables_chain_lookup(ctx->table,
4448-
tb[NFTA_VERDICT_CHAIN]);
4475+
tb[NFTA_VERDICT_CHAIN], genmask);
44494476
if (IS_ERR(chain))
44504477
return PTR_ERR(chain);
44514478
if (chain->flags & NFT_BASE_CHAIN)

0 commit comments

Comments
 (0)