1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2008 Patrick McHardy <kaber@trash.net> 4 * 5 * Development of this code funded by Astaro AG (http://www.astaro.com/) 6 */ 7 8 #include <linux/kernel.h> 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> 16 #include <linux/static_key.h> 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> 21 #include <net/netfilter/nf_log.h> 22 #include <net/netfilter/nft_meta.h> 23 24 static noinline void __nft_trace_packet(struct nft_traceinfo *info, 25 const struct nft_chain *chain, 26 enum nft_trace_types type) 27 { 28 if (!info->trace || !info->nf_trace) 29 return; 30 31 info->chain = chain; 32 info->type = type; 33 34 nft_trace_notify(info); 35 } 36 37 static inline void nft_trace_packet(const struct nft_pktinfo *pkt, 38 struct nft_traceinfo *info, 39 const struct nft_chain *chain, 40 const struct nft_rule_dp *rule, 41 enum nft_trace_types type) 42 { 43 if (static_branch_unlikely(&nft_trace_enabled)) { 44 info->nf_trace = pkt->skb->nf_trace; 45 info->rule = rule; 46 __nft_trace_packet(info, chain, type); 47 } 48 } 49 50 static inline void nft_trace_copy_nftrace(const struct nft_pktinfo *pkt, 51 struct nft_traceinfo *info) 52 { 53 if (static_branch_unlikely(&nft_trace_enabled)) { 54 if (info->trace) 55 info->nf_trace = pkt->skb->nf_trace; 56 } 57 } 58 59 static void nft_bitwise_fast_eval(const struct nft_expr *expr, 60 struct nft_regs *regs) 61 { 62 const struct nft_bitwise_fast_expr *priv = nft_expr_priv(expr); 63 u32 *src = ®s->data[priv->sreg]; 64 u32 *dst = ®s->data[priv->dreg]; 65 66 *dst = (*src & priv->mask) ^ priv->xor; 67 } 68 69 static void nft_cmp_fast_eval(const struct nft_expr *expr, 70 struct nft_regs *regs) 71 { 72 const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr); 73 74 if (((regs->data[priv->sreg] & priv->mask) == priv->data) ^ priv->inv) 75 return; 76 regs->verdict.code = NFT_BREAK; 77 } 78 79 static void nft_cmp16_fast_eval(const struct nft_expr *expr, 80 struct nft_regs *regs) 81 { 82 const struct nft_cmp16_fast_expr *priv = nft_expr_priv(expr); 83 const u64 *reg_data = (const u64 *)®s->data[priv->sreg]; 84 const u64 *mask = (const u64 *)&priv->mask; 85 const u64 *data = (const u64 *)&priv->data; 86 87 if (((reg_data[0] & mask[0]) == data[0] && 88 ((reg_data[1] & mask[1]) == data[1])) ^ priv->inv) 89 return; 90 regs->verdict.code = NFT_BREAK; 91 } 92 93 static noinline void __nft_trace_verdict(struct nft_traceinfo *info, 94 const struct nft_chain *chain, 95 const struct nft_regs *regs) 96 { 97 enum nft_trace_types type; 98 99 switch (regs->verdict.code) { 100 case NFT_CONTINUE: 101 case NFT_RETURN: 102 type = NFT_TRACETYPE_RETURN; 103 break; 104 case NF_STOLEN: 105 type = NFT_TRACETYPE_RULE; 106 /* can't access skb->nf_trace; use copy */ 107 break; 108 default: 109 type = NFT_TRACETYPE_RULE; 110 111 if (info->trace) 112 info->nf_trace = info->pkt->skb->nf_trace; 113 break; 114 } 115 116 __nft_trace_packet(info, chain, type); 117 } 118 119 static inline void nft_trace_verdict(struct nft_traceinfo *info, 120 const struct nft_chain *chain, 121 const struct nft_rule_dp *rule, 122 const struct nft_regs *regs) 123 { 124 if (static_branch_unlikely(&nft_trace_enabled)) { 125 info->rule = rule; 126 __nft_trace_verdict(info, chain, regs); 127 } 128 } 129 130 static bool nft_payload_fast_eval(const struct nft_expr *expr, 131 struct nft_regs *regs, 132 const struct nft_pktinfo *pkt) 133 { 134 const struct nft_payload *priv = nft_expr_priv(expr); 135 const struct sk_buff *skb = pkt->skb; 136 u32 *dest = ®s->data[priv->dreg]; 137 unsigned char *ptr; 138 139 if (priv->base == NFT_PAYLOAD_NETWORK_HEADER) 140 ptr = skb_network_header(skb); 141 else { 142 if (!(pkt->flags & NFT_PKTINFO_L4PROTO)) 143 return false; 144 ptr = skb_network_header(skb) + nft_thoff(pkt); 145 } 146 147 ptr += priv->offset; 148 149 if (unlikely(ptr + priv->len > skb_tail_pointer(skb))) 150 return false; 151 152 *dest = 0; 153 if (priv->len == 2) 154 *(u16 *)dest = *(u16 *)ptr; 155 else if (priv->len == 4) 156 *(u32 *)dest = *(u32 *)ptr; 157 else 158 *(u8 *)dest = *(u8 *)ptr; 159 return true; 160 } 161 162 DEFINE_STATIC_KEY_FALSE(nft_counters_enabled); 163 164 static noinline void nft_update_chain_stats(const struct nft_chain *chain, 165 const struct nft_pktinfo *pkt) 166 { 167 struct nft_base_chain *base_chain; 168 struct nft_stats __percpu *pstats; 169 struct nft_stats *stats; 170 171 base_chain = nft_base_chain(chain); 172 173 pstats = READ_ONCE(base_chain->stats); 174 if (pstats) { 175 local_bh_disable(); 176 stats = this_cpu_ptr(pstats); 177 u64_stats_update_begin(&stats->syncp); 178 stats->pkts++; 179 stats->bytes += pkt->skb->len; 180 u64_stats_update_end(&stats->syncp); 181 local_bh_enable(); 182 } 183 } 184 185 struct nft_jumpstack { 186 const struct nft_chain *chain; 187 const struct nft_rule_dp *rule; 188 const struct nft_rule_dp *last_rule; 189 }; 190 191 static void expr_call_ops_eval(const struct nft_expr *expr, 192 struct nft_regs *regs, 193 struct nft_pktinfo *pkt) 194 { 195 #ifdef CONFIG_RETPOLINE 196 unsigned long e = (unsigned long)expr->ops->eval; 197 #define X(e, fun) \ 198 do { if ((e) == (unsigned long)(fun)) \ 199 return fun(expr, regs, pkt); } while (0) 200 201 X(e, nft_payload_eval); 202 X(e, nft_cmp_eval); 203 X(e, nft_counter_eval); 204 X(e, nft_meta_get_eval); 205 X(e, nft_lookup_eval); 206 X(e, nft_range_eval); 207 X(e, nft_immediate_eval); 208 X(e, nft_byteorder_eval); 209 X(e, nft_dynset_eval); 210 X(e, nft_rt_get_eval); 211 X(e, nft_bitwise_eval); 212 #undef X 213 #endif /* CONFIG_RETPOLINE */ 214 expr->ops->eval(expr, regs, pkt); 215 } 216 217 #define nft_rule_expr_first(rule) (struct nft_expr *)&rule->data[0] 218 #define nft_rule_expr_next(expr) ((void *)expr) + expr->ops->size 219 #define nft_rule_expr_last(rule) (struct nft_expr *)&rule->data[rule->dlen] 220 #define nft_rule_next(rule) (void *)rule + sizeof(*rule) + rule->dlen 221 222 #define nft_rule_dp_for_each_expr(expr, last, rule) \ 223 for ((expr) = nft_rule_expr_first(rule), (last) = nft_rule_expr_last(rule); \ 224 (expr) != (last); \ 225 (expr) = nft_rule_expr_next(expr)) 226 227 unsigned int 228 nft_do_chain(struct nft_pktinfo *pkt, void *priv) 229 { 230 const struct nft_chain *chain = priv, *basechain = chain; 231 const struct nft_rule_dp *rule, *last_rule; 232 const struct net *net = nft_net(pkt); 233 const struct nft_expr *expr, *last; 234 struct nft_regs regs = {}; 235 unsigned int stackptr = 0; 236 struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE]; 237 bool genbit = READ_ONCE(net->nft.gencursor); 238 struct nft_rule_blob *blob; 239 struct nft_traceinfo info; 240 241 info.trace = false; 242 if (static_branch_unlikely(&nft_trace_enabled)) 243 nft_trace_init(&info, pkt, ®s.verdict, basechain); 244 do_chain: 245 if (genbit) 246 blob = rcu_dereference(chain->blob_gen_1); 247 else 248 blob = rcu_dereference(chain->blob_gen_0); 249 250 rule = (struct nft_rule_dp *)blob->data; 251 last_rule = (void *)blob->data + blob->size; 252 next_rule: 253 regs.verdict.code = NFT_CONTINUE; 254 for (; rule < last_rule; rule = nft_rule_next(rule)) { 255 nft_rule_dp_for_each_expr(expr, last, rule) { 256 if (expr->ops == &nft_cmp_fast_ops) 257 nft_cmp_fast_eval(expr, ®s); 258 else if (expr->ops == &nft_cmp16_fast_ops) 259 nft_cmp16_fast_eval(expr, ®s); 260 else if (expr->ops == &nft_bitwise_fast_ops) 261 nft_bitwise_fast_eval(expr, ®s); 262 else if (expr->ops != &nft_payload_fast_ops || 263 !nft_payload_fast_eval(expr, ®s, pkt)) 264 expr_call_ops_eval(expr, ®s, pkt); 265 266 if (regs.verdict.code != NFT_CONTINUE) 267 break; 268 } 269 270 switch (regs.verdict.code) { 271 case NFT_BREAK: 272 regs.verdict.code = NFT_CONTINUE; 273 nft_trace_copy_nftrace(pkt, &info); 274 continue; 275 case NFT_CONTINUE: 276 nft_trace_packet(pkt, &info, chain, rule, 277 NFT_TRACETYPE_RULE); 278 continue; 279 } 280 break; 281 } 282 283 nft_trace_verdict(&info, chain, rule, ®s); 284 285 switch (regs.verdict.code & NF_VERDICT_MASK) { 286 case NF_ACCEPT: 287 case NF_DROP: 288 case NF_QUEUE: 289 case NF_STOLEN: 290 return regs.verdict.code; 291 } 292 293 switch (regs.verdict.code) { 294 case NFT_JUMP: 295 if (WARN_ON_ONCE(stackptr >= NFT_JUMP_STACK_SIZE)) 296 return NF_DROP; 297 jumpstack[stackptr].chain = chain; 298 jumpstack[stackptr].rule = nft_rule_next(rule); 299 jumpstack[stackptr].last_rule = last_rule; 300 stackptr++; 301 fallthrough; 302 case NFT_GOTO: 303 chain = regs.verdict.chain; 304 goto do_chain; 305 case NFT_CONTINUE: 306 case NFT_RETURN: 307 break; 308 default: 309 WARN_ON_ONCE(1); 310 } 311 312 if (stackptr > 0) { 313 stackptr--; 314 chain = jumpstack[stackptr].chain; 315 rule = jumpstack[stackptr].rule; 316 last_rule = jumpstack[stackptr].last_rule; 317 goto next_rule; 318 } 319 320 nft_trace_packet(pkt, &info, basechain, NULL, NFT_TRACETYPE_POLICY); 321 322 if (static_branch_unlikely(&nft_counters_enabled)) 323 nft_update_chain_stats(basechain, pkt); 324 325 return nft_base_chain(basechain)->policy; 326 } 327 EXPORT_SYMBOL_GPL(nft_do_chain); 328 329 static struct nft_expr_type *nft_basic_types[] = { 330 &nft_imm_type, 331 &nft_cmp_type, 332 &nft_lookup_type, 333 &nft_bitwise_type, 334 &nft_byteorder_type, 335 &nft_payload_type, 336 &nft_dynset_type, 337 &nft_range_type, 338 &nft_meta_type, 339 &nft_rt_type, 340 &nft_exthdr_type, 341 &nft_last_type, 342 &nft_counter_type, 343 }; 344 345 static struct nft_object_type *nft_basic_objects[] = { 346 #ifdef CONFIG_NETWORK_SECMARK 347 &nft_secmark_obj_type, 348 #endif 349 &nft_counter_obj_type, 350 }; 351 352 int __init nf_tables_core_module_init(void) 353 { 354 int err, i, j = 0; 355 356 nft_counter_init_seqcount(); 357 358 for (i = 0; i < ARRAY_SIZE(nft_basic_objects); i++) { 359 err = nft_register_obj(nft_basic_objects[i]); 360 if (err) 361 goto err; 362 } 363 364 for (j = 0; j < ARRAY_SIZE(nft_basic_types); j++) { 365 err = nft_register_expr(nft_basic_types[j]); 366 if (err) 367 goto err; 368 } 369 370 return 0; 371 372 err: 373 while (j-- > 0) 374 nft_unregister_expr(nft_basic_types[j]); 375 376 while (i-- > 0) 377 nft_unregister_obj(nft_basic_objects[i]); 378 379 return err; 380 } 381 382 void nf_tables_core_module_exit(void) 383 { 384 int i; 385 386 i = ARRAY_SIZE(nft_basic_types); 387 while (i-- > 0) 388 nft_unregister_expr(nft_basic_types[i]); 389 390 i = ARRAY_SIZE(nft_basic_objects); 391 while (i-- > 0) 392 nft_unregister_obj(nft_basic_objects[i]); 393 } 394