f9bb0e2cc39066c3b4cb1381ccea10017fed477c
[openwrt/staging/stintel.git] /
1 From: Pablo Neira Ayuso <pablo@netfilter.org>
2 Date: Tue, 23 Mar 2021 00:56:28 +0100
3 Subject: [PATCH] netfilter: nftables: update table flags from the commit
4 phase
5
6 Do not update table flags from the preparation phase. Store the flags
7 update into the transaction, then update the flags from the commit
8 phase.
9
10 Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
11 ---
12
13 --- a/include/net/netfilter/nf_tables.h
14 +++ b/include/net/netfilter/nf_tables.h
15 @@ -1474,13 +1474,16 @@ struct nft_trans_chain {
16
17 struct nft_trans_table {
18 bool update;
19 - bool enable;
20 + u8 state;
21 + u32 flags;
22 };
23
24 #define nft_trans_table_update(trans) \
25 (((struct nft_trans_table *)trans->data)->update)
26 -#define nft_trans_table_enable(trans) \
27 - (((struct nft_trans_table *)trans->data)->enable)
28 +#define nft_trans_table_state(trans) \
29 + (((struct nft_trans_table *)trans->data)->state)
30 +#define nft_trans_table_flags(trans) \
31 + (((struct nft_trans_table *)trans->data)->flags)
32
33 struct nft_trans_elem {
34 struct nft_set *set;
35 --- a/net/netfilter/nf_tables_api.c
36 +++ b/net/netfilter/nf_tables_api.c
37 @@ -917,6 +917,12 @@ static void nf_tables_table_disable(stru
38 nft_table_disable(net, table, 0);
39 }
40
41 +enum {
42 + NFT_TABLE_STATE_UNCHANGED = 0,
43 + NFT_TABLE_STATE_DORMANT,
44 + NFT_TABLE_STATE_WAKEUP
45 +};
46 +
47 static int nf_tables_updtable(struct nft_ctx *ctx)
48 {
49 struct nft_trans *trans;
50 @@ -940,19 +946,17 @@ static int nf_tables_updtable(struct nft
51
52 if ((flags & NFT_TABLE_F_DORMANT) &&
53 !(ctx->table->flags & NFT_TABLE_F_DORMANT)) {
54 - nft_trans_table_enable(trans) = false;
55 + nft_trans_table_state(trans) = NFT_TABLE_STATE_DORMANT;
56 } else if (!(flags & NFT_TABLE_F_DORMANT) &&
57 ctx->table->flags & NFT_TABLE_F_DORMANT) {
58 - ctx->table->flags &= ~NFT_TABLE_F_DORMANT;
59 ret = nf_tables_table_enable(ctx->net, ctx->table);
60 if (ret >= 0)
61 - nft_trans_table_enable(trans) = true;
62 - else
63 - ctx->table->flags |= NFT_TABLE_F_DORMANT;
64 + nft_trans_table_state(trans) = NFT_TABLE_STATE_WAKEUP;
65 }
66 if (ret < 0)
67 goto err;
68
69 + nft_trans_table_flags(trans) = flags;
70 nft_trans_table_update(trans) = true;
71 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
72 return 0;
73 @@ -7919,11 +7923,10 @@ static int nf_tables_commit(struct net *
74 switch (trans->msg_type) {
75 case NFT_MSG_NEWTABLE:
76 if (nft_trans_table_update(trans)) {
77 - if (!nft_trans_table_enable(trans)) {
78 - nf_tables_table_disable(net,
79 - trans->ctx.table);
80 - trans->ctx.table->flags |= NFT_TABLE_F_DORMANT;
81 - }
82 + if (nft_trans_table_state(trans) == NFT_TABLE_STATE_DORMANT)
83 + nf_tables_table_disable(net, trans->ctx.table);
84 +
85 + trans->ctx.table->flags = nft_trans_table_flags(trans);
86 } else {
87 nft_clear(net, trans->ctx.table);
88 }
89 @@ -8137,11 +8140,9 @@ static int __nf_tables_abort(struct net
90 switch (trans->msg_type) {
91 case NFT_MSG_NEWTABLE:
92 if (nft_trans_table_update(trans)) {
93 - if (nft_trans_table_enable(trans)) {
94 - nf_tables_table_disable(net,
95 - trans->ctx.table);
96 - trans->ctx.table->flags |= NFT_TABLE_F_DORMANT;
97 - }
98 + if (nft_trans_table_state(trans) == NFT_TABLE_STATE_WAKEUP)
99 + nf_tables_table_disable(net, trans->ctx.table);
100 +
101 nft_trans_destroy(trans);
102 } else {
103 list_del_rcu(&trans->ctx.table->list);