hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/net/netfilter/nft_immediate.c
....@@ -76,11 +76,9 @@
7676 switch (priv->data.verdict.code) {
7777 case NFT_JUMP:
7878 case NFT_GOTO:
79
- if (nft_chain_is_bound(chain)) {
80
- err = -EBUSY;
81
- goto err1;
82
- }
83
- chain->bound = true;
79
+ err = nf_tables_bind_chain(ctx, chain);
80
+ if (err < 0)
81
+ return err;
8482 break;
8583 default:
8684 break;
....@@ -98,8 +96,47 @@
9896 const struct nft_expr *expr)
9997 {
10098 const struct nft_immediate_expr *priv = nft_expr_priv(expr);
99
+ const struct nft_data *data = &priv->data;
100
+ struct nft_ctx chain_ctx;
101
+ struct nft_chain *chain;
102
+ struct nft_rule *rule;
103
+
104
+ if (priv->dreg == NFT_REG_VERDICT) {
105
+ switch (data->verdict.code) {
106
+ case NFT_JUMP:
107
+ case NFT_GOTO:
108
+ chain = data->verdict.chain;
109
+ if (!nft_chain_binding(chain))
110
+ break;
111
+
112
+ chain_ctx = *ctx;
113
+ chain_ctx.chain = chain;
114
+
115
+ list_for_each_entry(rule, &chain->rules, list)
116
+ nft_rule_expr_activate(&chain_ctx, rule);
117
+
118
+ nft_clear(ctx->net, chain);
119
+ break;
120
+ default:
121
+ break;
122
+ }
123
+ }
101124
102125 return nft_data_hold(&priv->data, nft_dreg_to_type(priv->dreg));
126
+}
127
+
128
+static void nft_immediate_chain_deactivate(const struct nft_ctx *ctx,
129
+ struct nft_chain *chain,
130
+ enum nft_trans_phase phase)
131
+{
132
+ struct nft_ctx chain_ctx;
133
+ struct nft_rule *rule;
134
+
135
+ chain_ctx = *ctx;
136
+ chain_ctx.chain = chain;
137
+
138
+ list_for_each_entry(rule, &chain->rules, list)
139
+ nft_rule_expr_deactivate(&chain_ctx, rule, phase);
103140 }
104141
105142 static void nft_immediate_deactivate(const struct nft_ctx *ctx,
....@@ -107,6 +144,38 @@
107144 enum nft_trans_phase phase)
108145 {
109146 const struct nft_immediate_expr *priv = nft_expr_priv(expr);
147
+ const struct nft_data *data = &priv->data;
148
+ struct nft_chain *chain;
149
+
150
+ if (priv->dreg == NFT_REG_VERDICT) {
151
+ switch (data->verdict.code) {
152
+ case NFT_JUMP:
153
+ case NFT_GOTO:
154
+ chain = data->verdict.chain;
155
+ if (!nft_chain_binding(chain))
156
+ break;
157
+
158
+ switch (phase) {
159
+ case NFT_TRANS_PREPARE_ERROR:
160
+ nf_tables_unbind_chain(ctx, chain);
161
+ nft_deactivate_next(ctx->net, chain);
162
+ break;
163
+ case NFT_TRANS_PREPARE:
164
+ nft_immediate_chain_deactivate(ctx, chain, phase);
165
+ nft_deactivate_next(ctx->net, chain);
166
+ break;
167
+ default:
168
+ nft_immediate_chain_deactivate(ctx, chain, phase);
169
+ nft_chain_del(chain);
170
+ chain->bound = false;
171
+ nft_use_dec(&chain->table->use);
172
+ break;
173
+ }
174
+ break;
175
+ default:
176
+ break;
177
+ }
178
+ }
110179
111180 if (phase == NFT_TRANS_COMMIT)
112181 return;
....@@ -131,15 +200,27 @@
131200 case NFT_GOTO:
132201 chain = data->verdict.chain;
133202
134
- if (!nft_chain_is_bound(chain))
203
+ if (!nft_chain_binding(chain))
135204 break;
136205
206
+ /* Rule construction failed, but chain is already bound:
207
+ * let the transaction records release this chain and its rules.
208
+ */
209
+ if (chain->bound) {
210
+ nft_use_dec(&chain->use);
211
+ break;
212
+ }
213
+
214
+ /* Rule has been deleted, release chain and its rules. */
137215 chain_ctx = *ctx;
138216 chain_ctx.chain = chain;
139217
140
- list_for_each_entry_safe(rule, n, &chain->rules, list)
141
- nf_tables_rule_release(&chain_ctx, rule);
142
-
218
+ nft_use_dec(&chain->use);
219
+ list_for_each_entry_safe(rule, n, &chain->rules, list) {
220
+ nft_use_dec(&chain->use);
221
+ list_del(&rule->list);
222
+ nf_tables_rule_destroy(&chain_ctx, rule);
223
+ }
143224 nf_tables_chain_destroy(&chain_ctx);
144225 break;
145226 default: