dm-crypt: use __bio_add_page to add single page to clone bio
[linux-block.git] / net / netfilter / nf_tables_core.c
CommitLineData
d2912cb1 1// SPDX-License-Identifier: GPL-2.0-only
96518518
PM
2/*
3 * Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
4 *
96518518
PM
5 * Development of this code funded by Astaro AG (http://www.astaro.com/)
6 */
7
a81b2ce8 8#include <linux/kernel.h>
96518518
PM
9#include <linux/module.h>
10#include <linux/init.h>
11#include <linux/list.h>
12#include <linux/rculist.h>
13#include <linux/skbuff.h>
14#include <linux/netlink.h>
15#include <linux/netfilter.h>
e639f7ab 16#include <linux/static_key.h>
96518518
PM
17#include <linux/netfilter/nfnetlink.h>
18#include <linux/netfilter/nf_tables.h>
19#include <net/netfilter/nf_tables_core.h>
20#include <net/netfilter/nf_tables.h>
b5bc89bf 21#include <net/netfilter/nf_log.h>
30e103fe 22#include <net/netfilter/nft_meta.h>
96518518 23
d8d76062
FW
24#if defined(CONFIG_RETPOLINE) && defined(CONFIG_X86)
25
26static struct static_key_false nf_tables_skip_direct_calls;
27
28static bool nf_skip_indirect_calls(void)
29{
30 return static_branch_likely(&nf_tables_skip_direct_calls);
31}
32
33static void __init nf_skip_indirect_calls_enable(void)
34{
35 if (!cpu_feature_enabled(X86_FEATURE_RETPOLINE))
36 static_branch_enable(&nf_tables_skip_direct_calls);
37}
38#else
39static inline bool nf_skip_indirect_calls(void) { return false; }
40
41static inline void nf_skip_indirect_calls_enable(void) { }
42#endif
43
698bb828 44static noinline void __nft_trace_packet(const struct nft_pktinfo *pkt,
0a202145 45 const struct nft_verdict *verdict,
46df4175 46 const struct nft_rule_dp *rule,
698bb828 47 struct nft_traceinfo *info,
e65eebec 48 enum nft_trace_types type)
01ef16c2 49{
e34b9ed9 50 if (!info->trace || !info->nf_trace)
33d5a7b1
FW
51 return;
52
33d5a7b1
FW
53 info->type = type;
54
46df4175 55 nft_trace_notify(pkt, verdict, rule, info);
01ef16c2
PM
56}
57
399a14ec 58static inline void nft_trace_packet(const struct nft_pktinfo *pkt,
0a202145 59 struct nft_verdict *verdict,
399a14ec 60 struct nft_traceinfo *info,
2c865a8a 61 const struct nft_rule_dp *rule,
33d5a7b1 62 enum nft_trace_types type)
01ef16c2 63{
e639f7ab 64 if (static_branch_unlikely(&nft_trace_enabled)) {
e34b9ed9 65 info->nf_trace = pkt->skb->nf_trace;
46df4175 66 __nft_trace_packet(pkt, verdict, rule, info, type);
33d5a7b1 67 }
01ef16c2
PM
68}
69
399a14ec
FW
70static inline void nft_trace_copy_nftrace(const struct nft_pktinfo *pkt,
71 struct nft_traceinfo *info)
e34b9ed9 72{
2a1d6abd
FW
73 if (static_branch_unlikely(&nft_trace_enabled))
74 info->nf_trace = pkt->skb->nf_trace;
e34b9ed9
FW
75}
76
10fdd6d8
PS
77static void nft_bitwise_fast_eval(const struct nft_expr *expr,
78 struct nft_regs *regs)
79{
80 const struct nft_bitwise_fast_expr *priv = nft_expr_priv(expr);
81 u32 *src = &regs->data[priv->sreg];
82 u32 *dst = &regs->data[priv->dreg];
83
84 *dst = (*src & priv->mask) ^ priv->xor;
85}
86
cb7dbfd0 87static void nft_cmp_fast_eval(const struct nft_expr *expr,
a55e22e9 88 struct nft_regs *regs)
cb7dbfd0
PM
89{
90 const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr);
cb7dbfd0 91
5f48846d 92 if (((regs->data[priv->sreg] & priv->mask) == priv->data) ^ priv->inv)
cb7dbfd0 93 return;
a55e22e9 94 regs->verdict.code = NFT_BREAK;
cb7dbfd0
PM
95}
96
23f68d46
PNA
97static void nft_cmp16_fast_eval(const struct nft_expr *expr,
98 struct nft_regs *regs)
99{
100 const struct nft_cmp16_fast_expr *priv = nft_expr_priv(expr);
101 const u64 *reg_data = (const u64 *)&regs->data[priv->sreg];
102 const u64 *mask = (const u64 *)&priv->mask;
103 const u64 *data = (const u64 *)&priv->data;
104
105 if (((reg_data[0] & mask[0]) == data[0] &&
106 ((reg_data[1] & mask[1]) == data[1])) ^ priv->inv)
107 return;
108 regs->verdict.code = NFT_BREAK;
109}
110
698bb828
FW
111static noinline void __nft_trace_verdict(const struct nft_pktinfo *pkt,
112 struct nft_traceinfo *info,
46df4175 113 const struct nft_rule_dp *rule,
4765473f
PNA
114 const struct nft_regs *regs)
115{
116 enum nft_trace_types type;
117
118 switch (regs->verdict.code) {
119 case NFT_CONTINUE:
120 case NFT_RETURN:
121 type = NFT_TRACETYPE_RETURN;
122 break;
e34b9ed9
FW
123 case NF_STOLEN:
124 type = NFT_TRACETYPE_RULE;
125 /* can't access skb->nf_trace; use copy */
126 break;
4765473f
PNA
127 default:
128 type = NFT_TRACETYPE_RULE;
399a14ec
FW
129
130 if (info->trace)
698bb828 131 info->nf_trace = pkt->skb->nf_trace;
4765473f
PNA
132 break;
133 }
134
46df4175 135 __nft_trace_packet(pkt, &regs->verdict, rule, info, type);
4765473f
PNA
136}
137
698bb828
FW
138static inline void nft_trace_verdict(const struct nft_pktinfo *pkt,
139 struct nft_traceinfo *info,
2c865a8a 140 const struct nft_rule_dp *rule,
4765473f
PNA
141 const struct nft_regs *regs)
142{
46df4175
FW
143 if (static_branch_unlikely(&nft_trace_enabled))
144 __nft_trace_verdict(pkt, info, rule, regs);
4765473f
PNA
145}
146
c29b72e0 147static bool nft_payload_fast_eval(const struct nft_expr *expr,
a55e22e9 148 struct nft_regs *regs,
c29b72e0
PM
149 const struct nft_pktinfo *pkt)
150{
151 const struct nft_payload *priv = nft_expr_priv(expr);
152 const struct sk_buff *skb = pkt->skb;
49499c3e 153 u32 *dest = &regs->data[priv->dreg];
c29b72e0
PM
154 unsigned char *ptr;
155
156 if (priv->base == NFT_PAYLOAD_NETWORK_HEADER)
157 ptr = skb_network_header(skb);
a20877b5 158 else {
b5bdc6f9 159 if (!(pkt->flags & NFT_PKTINFO_L4PROTO))
a20877b5 160 return false;
2d7b4ace 161 ptr = skb_network_header(skb) + nft_thoff(pkt);
a20877b5 162 }
c29b72e0
PM
163
164 ptr += priv->offset;
165
8dc3c2b8 166 if (unlikely(ptr + priv->len > skb_tail_pointer(skb)))
c29b72e0
PM
167 return false;
168
49499c3e 169 *dest = 0;
c29b72e0 170 if (priv->len == 2)
fad136ea 171 *(u16 *)dest = *(u16 *)ptr;
c29b72e0 172 else if (priv->len == 4)
fad136ea 173 *(u32 *)dest = *(u32 *)ptr;
c29b72e0 174 else
fad136ea 175 *(u8 *)dest = *(u8 *)ptr;
c29b72e0
PM
176 return true;
177}
178
9f08ea84
PNA
179DEFINE_STATIC_KEY_FALSE(nft_counters_enabled);
180
181static noinline void nft_update_chain_stats(const struct nft_chain *chain,
182 const struct nft_pktinfo *pkt)
183{
00924094 184 struct nft_base_chain *base_chain;
a9f5e78c 185 struct nft_stats __percpu *pstats;
9f08ea84
PNA
186 struct nft_stats *stats;
187
00924094 188 base_chain = nft_base_chain(chain);
00924094 189
a9f5e78c
LR
190 pstats = READ_ONCE(base_chain->stats);
191 if (pstats) {
192 local_bh_disable();
193 stats = this_cpu_ptr(pstats);
00924094
FW
194 u64_stats_update_begin(&stats->syncp);
195 stats->pkts++;
196 stats->bytes += pkt->skb->len;
197 u64_stats_update_end(&stats->syncp);
a9f5e78c 198 local_bh_enable();
00924094 199 }
9f08ea84
PNA
200}
201
0ca743a5 202struct nft_jumpstack {
2c865a8a 203 const struct nft_rule_dp *rule;
0ca743a5
PNA
204};
205
222440b4
FW
206static void expr_call_ops_eval(const struct nft_expr *expr,
207 struct nft_regs *regs,
208 struct nft_pktinfo *pkt)
209{
10870dd8 210#ifdef CONFIG_RETPOLINE
d8d76062
FW
211 unsigned long e;
212
213 if (nf_skip_indirect_calls())
214 goto indirect_call;
215
216 e = (unsigned long)expr->ops->eval;
10870dd8
FW
217#define X(e, fun) \
218 do { if ((e) == (unsigned long)(fun)) \
219 return fun(expr, regs, pkt); } while (0)
220
221 X(e, nft_payload_eval);
222 X(e, nft_cmp_eval);
023223df 223 X(e, nft_counter_eval);
10870dd8
FW
224 X(e, nft_meta_get_eval);
225 X(e, nft_lookup_eval);
d9e78914
FW
226#if IS_ENABLED(CONFIG_NFT_CT)
227 X(e, nft_ct_get_fast_eval);
228#endif
10870dd8
FW
229 X(e, nft_range_eval);
230 X(e, nft_immediate_eval);
231 X(e, nft_byteorder_eval);
232 X(e, nft_dynset_eval);
233 X(e, nft_rt_get_eval);
234 X(e, nft_bitwise_eval);
2032e907
FW
235 X(e, nft_objref_eval);
236 X(e, nft_objref_map_eval);
10870dd8 237#undef X
d8d76062 238indirect_call:
10870dd8
FW
239#endif /* CONFIG_RETPOLINE */
240 expr->ops->eval(expr, regs, pkt);
222440b4
FW
241}
242
2c865a8a
PNA
243#define nft_rule_expr_first(rule) (struct nft_expr *)&rule->data[0]
244#define nft_rule_expr_next(expr) ((void *)expr) + expr->ops->size
245#define nft_rule_expr_last(rule) (struct nft_expr *)&rule->data[rule->dlen]
2c865a8a
PNA
246
247#define nft_rule_dp_for_each_expr(expr, last, rule) \
248 for ((expr) = nft_rule_expr_first(rule), (last) = nft_rule_expr_last(rule); \
249 (expr) != (last); \
250 (expr) = nft_rule_expr_next(expr))
251
0ca743a5 252unsigned int
06198b34 253nft_do_chain(struct nft_pktinfo *pkt, void *priv)
96518518 254{
06198b34 255 const struct nft_chain *chain = priv, *basechain = chain;
0e5a1c7e 256 const struct net *net = nft_net(pkt);
96518518 257 const struct nft_expr *expr, *last;
d4d89e65 258 const struct nft_rule_dp *rule;
4c905f67 259 struct nft_regs regs = {};
96518518 260 unsigned int stackptr = 0;
0ca743a5 261 struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE];
0cbc06b3 262 bool genbit = READ_ONCE(net->nft.gencursor);
2c865a8a 263 struct nft_rule_blob *blob;
33d5a7b1 264 struct nft_traceinfo info;
96518518 265
e639f7ab
FW
266 info.trace = false;
267 if (static_branch_unlikely(&nft_trace_enabled))
0a202145 268 nft_trace_init(&info, pkt, basechain);
96518518 269do_chain:
0cbc06b3 270 if (genbit)
2c865a8a 271 blob = rcu_dereference(chain->blob_gen_1);
0cbc06b3 272 else
2c865a8a 273 blob = rcu_dereference(chain->blob_gen_0);
0cbc06b3 274
2c865a8a 275 rule = (struct nft_rule_dp *)blob->data;
96518518 276next_rule:
a55e22e9 277 regs.verdict.code = NFT_CONTINUE;
d4d89e65 278 for (; !rule->is_last ; rule = nft_rule_next(rule)) {
2c865a8a 279 nft_rule_dp_for_each_expr(expr, last, rule) {
cb7dbfd0 280 if (expr->ops == &nft_cmp_fast_ops)
a55e22e9 281 nft_cmp_fast_eval(expr, &regs);
23f68d46
PNA
282 else if (expr->ops == &nft_cmp16_fast_ops)
283 nft_cmp16_fast_eval(expr, &regs);
10fdd6d8
PS
284 else if (expr->ops == &nft_bitwise_fast_ops)
285 nft_bitwise_fast_eval(expr, &regs);
c29b72e0 286 else if (expr->ops != &nft_payload_fast_ops ||
a55e22e9 287 !nft_payload_fast_eval(expr, &regs, pkt))
222440b4 288 expr_call_ops_eval(expr, &regs, pkt);
cb7dbfd0 289
a55e22e9 290 if (regs.verdict.code != NFT_CONTINUE)
96518518
PM
291 break;
292 }
293
a55e22e9 294 switch (regs.verdict.code) {
96518518 295 case NFT_BREAK:
a55e22e9 296 regs.verdict.code = NFT_CONTINUE;
399a14ec 297 nft_trace_copy_nftrace(pkt, &info);
3b084e99 298 continue;
96518518 299 case NFT_CONTINUE:
0a202145 300 nft_trace_packet(pkt, &regs.verdict, &info, rule,
e65eebec 301 NFT_TRACETYPE_RULE);
96518518
PM
302 continue;
303 }
304 break;
305 }
306
698bb828 307 nft_trace_verdict(pkt, &info, rule, &regs);
4765473f 308
a55e22e9 309 switch (regs.verdict.code & NF_VERDICT_MASK) {
96518518
PM
310 case NF_ACCEPT:
311 case NF_DROP:
312 case NF_QUEUE:
5efa0fc6 313 case NF_STOLEN:
a55e22e9 314 return regs.verdict.code;
e569bdab
EL
315 }
316
a55e22e9 317 switch (regs.verdict.code) {
96518518 318 case NFT_JUMP:
adc972c5
TY
319 if (WARN_ON_ONCE(stackptr >= NFT_JUMP_STACK_SIZE))
320 return NF_DROP;
2c865a8a 321 jumpstack[stackptr].rule = nft_rule_next(rule);
96518518 322 stackptr++;
954d8297 323 fallthrough;
96518518 324 case NFT_GOTO:
a55e22e9 325 chain = regs.verdict.chain;
96518518 326 goto do_chain;
354bf5a0 327 case NFT_CONTINUE:
96518518 328 case NFT_RETURN:
7e9bc10d 329 break;
96518518 330 default:
690d5417 331 WARN_ON_ONCE(1);
96518518
PM
332 }
333
334 if (stackptr > 0) {
335 stackptr--;
2c865a8a 336 rule = jumpstack[stackptr].rule;
96518518
PM
337 goto next_rule;
338 }
339
0a202145 340 nft_trace_packet(pkt, &regs.verdict, &info, NULL, NFT_TRACETYPE_POLICY);
5467a512 341
9f08ea84
PNA
342 if (static_branch_unlikely(&nft_counters_enabled))
343 nft_update_chain_stats(basechain, pkt);
b5bc89bf 344
5467a512 345 return nft_base_chain(basechain)->policy;
96518518 346}
3876d22d 347EXPORT_SYMBOL_GPL(nft_do_chain);
96518518 348
4e24877e
LZ
349static struct nft_expr_type *nft_basic_types[] = {
350 &nft_imm_type,
351 &nft_cmp_type,
352 &nft_lookup_type,
353 &nft_bitwise_type,
354 &nft_byteorder_type,
355 &nft_payload_type,
356 &nft_dynset_type,
357 &nft_range_type,
8a22543c 358 &nft_meta_type,
ae1bc6a9 359 &nft_rt_type,
d0103158 360 &nft_exthdr_type,
836382dc 361 &nft_last_type,
023223df 362 &nft_counter_type,
d037abc2 363 &nft_objref_type,
3a07327d 364 &nft_inner_type,
4e24877e
LZ
365};
366
fb961945
CG
367static struct nft_object_type *nft_basic_objects[] = {
368#ifdef CONFIG_NETWORK_SECMARK
369 &nft_secmark_obj_type,
370#endif
023223df 371 &nft_counter_obj_type,
fb961945
CG
372};
373
96518518
PM
374int __init nf_tables_core_module_init(void)
375{
fb961945
CG
376 int err, i, j = 0;
377
023223df
PNA
378 nft_counter_init_seqcount();
379
fb961945
CG
380 for (i = 0; i < ARRAY_SIZE(nft_basic_objects); i++) {
381 err = nft_register_obj(nft_basic_objects[i]);
382 if (err)
383 goto err;
384 }
96518518 385
fb961945
CG
386 for (j = 0; j < ARRAY_SIZE(nft_basic_types); j++) {
387 err = nft_register_expr(nft_basic_types[j]);
4e24877e
LZ
388 if (err)
389 goto err;
390 }
96518518 391
d8d76062
FW
392 nf_skip_indirect_calls_enable();
393
0f3cd9b3 394 return 0;
4e24877e
LZ
395
396err:
fb961945
CG
397 while (j-- > 0)
398 nft_unregister_expr(nft_basic_types[j]);
399
4e24877e 400 while (i-- > 0)
fb961945
CG
401 nft_unregister_obj(nft_basic_objects[i]);
402
96518518
PM
403 return err;
404}
405
406void nf_tables_core_module_exit(void)
407{
4e24877e
LZ
408 int i;
409
410 i = ARRAY_SIZE(nft_basic_types);
411 while (i-- > 0)
412 nft_unregister_expr(nft_basic_types[i]);
fb961945
CG
413
414 i = ARRAY_SIZE(nft_basic_objects);
415 while (i-- > 0)
416 nft_unregister_obj(nft_basic_objects[i]);
96518518 417}