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