nft_meta.c (21120B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net> 4 * Copyright (c) 2014 Intel Corporation 5 * Author: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com> 6 * 7 * Development of this code funded by Astaro AG (http://www.astaro.com/) 8 */ 9 10#include <linux/kernel.h> 11#include <linux/netlink.h> 12#include <linux/netfilter.h> 13#include <linux/netfilter/nf_tables.h> 14#include <linux/in.h> 15#include <linux/ip.h> 16#include <linux/ipv6.h> 17#include <linux/random.h> 18#include <linux/smp.h> 19#include <linux/static_key.h> 20#include <net/dst.h> 21#include <net/ip.h> 22#include <net/sock.h> 23#include <net/tcp_states.h> /* for TCP_TIME_WAIT */ 24#include <net/netfilter/nf_tables.h> 25#include <net/netfilter/nf_tables_core.h> 26#include <net/netfilter/nft_meta.h> 27#include <net/netfilter/nf_tables_offload.h> 28 29#include <uapi/linux/netfilter_bridge.h> /* NF_BR_PRE_ROUTING */ 30 31#define NFT_META_SECS_PER_MINUTE 60 32#define NFT_META_SECS_PER_HOUR 3600 33#define NFT_META_SECS_PER_DAY 86400 34#define NFT_META_DAYS_PER_WEEK 7 35 36static u8 nft_meta_weekday(void) 37{ 38 time64_t secs = ktime_get_real_seconds(); 39 unsigned int dse; 40 u8 wday; 41 42 secs -= NFT_META_SECS_PER_MINUTE * sys_tz.tz_minuteswest; 43 dse = div_u64(secs, NFT_META_SECS_PER_DAY); 44 wday = (4 + dse) % NFT_META_DAYS_PER_WEEK; 45 46 return wday; 47} 48 49static u32 nft_meta_hour(time64_t secs) 50{ 51 struct tm tm; 52 53 time64_to_tm(secs, 0, &tm); 54 55 return tm.tm_hour * NFT_META_SECS_PER_HOUR 56 + tm.tm_min * NFT_META_SECS_PER_MINUTE 57 + tm.tm_sec; 58} 59 60static noinline_for_stack void 61nft_meta_get_eval_time(enum nft_meta_keys key, 62 u32 *dest) 63{ 64 switch (key) { 65 case NFT_META_TIME_NS: 66 nft_reg_store64(dest, ktime_get_real_ns()); 67 break; 68 case NFT_META_TIME_DAY: 69 nft_reg_store8(dest, nft_meta_weekday()); 70 break; 71 case NFT_META_TIME_HOUR: 72 *dest = nft_meta_hour(ktime_get_real_seconds()); 73 break; 74 default: 75 break; 76 } 77} 78 79static noinline bool 80nft_meta_get_eval_pkttype_lo(const struct nft_pktinfo *pkt, 81 u32 *dest) 82{ 83 const struct sk_buff *skb = pkt->skb; 84 85 switch (nft_pf(pkt)) { 86 case NFPROTO_IPV4: 87 if (ipv4_is_multicast(ip_hdr(skb)->daddr)) 88 nft_reg_store8(dest, PACKET_MULTICAST); 89 else 90 nft_reg_store8(dest, PACKET_BROADCAST); 91 break; 92 case NFPROTO_IPV6: 93 nft_reg_store8(dest, PACKET_MULTICAST); 94 break; 95 case NFPROTO_NETDEV: 96 switch (skb->protocol) { 97 case htons(ETH_P_IP): { 98 int noff = skb_network_offset(skb); 99 struct iphdr *iph, _iph; 100 101 iph = skb_header_pointer(skb, noff, 102 sizeof(_iph), &_iph); 103 if (!iph) 104 return false; 105 106 if (ipv4_is_multicast(iph->daddr)) 107 nft_reg_store8(dest, PACKET_MULTICAST); 108 else 109 nft_reg_store8(dest, PACKET_BROADCAST); 110 111 break; 112 } 113 case htons(ETH_P_IPV6): 114 nft_reg_store8(dest, PACKET_MULTICAST); 115 break; 116 default: 117 WARN_ON_ONCE(1); 118 return false; 119 } 120 break; 121 default: 122 WARN_ON_ONCE(1); 123 return false; 124 } 125 126 return true; 127} 128 129static noinline bool 130nft_meta_get_eval_skugid(enum nft_meta_keys key, 131 u32 *dest, 132 const struct nft_pktinfo *pkt) 133{ 134 struct sock *sk = skb_to_full_sk(pkt->skb); 135 struct socket *sock; 136 137 if (!sk || !sk_fullsock(sk) || !net_eq(nft_net(pkt), sock_net(sk))) 138 return false; 139 140 read_lock_bh(&sk->sk_callback_lock); 141 sock = sk->sk_socket; 142 if (!sock || !sock->file) { 143 read_unlock_bh(&sk->sk_callback_lock); 144 return false; 145 } 146 147 switch (key) { 148 case NFT_META_SKUID: 149 *dest = from_kuid_munged(sock_net(sk)->user_ns, 150 sock->file->f_cred->fsuid); 151 break; 152 case NFT_META_SKGID: 153 *dest = from_kgid_munged(sock_net(sk)->user_ns, 154 sock->file->f_cred->fsgid); 155 break; 156 default: 157 break; 158 } 159 160 read_unlock_bh(&sk->sk_callback_lock); 161 return true; 162} 163 164#ifdef CONFIG_CGROUP_NET_CLASSID 165static noinline bool 166nft_meta_get_eval_cgroup(u32 *dest, const struct nft_pktinfo *pkt) 167{ 168 struct sock *sk = skb_to_full_sk(pkt->skb); 169 170 if (!sk || !sk_fullsock(sk) || !net_eq(nft_net(pkt), sock_net(sk))) 171 return false; 172 173 *dest = sock_cgroup_classid(&sk->sk_cgrp_data); 174 return true; 175} 176#endif 177 178static noinline bool nft_meta_get_eval_kind(enum nft_meta_keys key, 179 u32 *dest, 180 const struct nft_pktinfo *pkt) 181{ 182 const struct net_device *in = nft_in(pkt), *out = nft_out(pkt); 183 184 switch (key) { 185 case NFT_META_IIFKIND: 186 if (!in || !in->rtnl_link_ops) 187 return false; 188 strncpy((char *)dest, in->rtnl_link_ops->kind, IFNAMSIZ); 189 break; 190 case NFT_META_OIFKIND: 191 if (!out || !out->rtnl_link_ops) 192 return false; 193 strncpy((char *)dest, out->rtnl_link_ops->kind, IFNAMSIZ); 194 break; 195 default: 196 return false; 197 } 198 199 return true; 200} 201 202static void nft_meta_store_ifindex(u32 *dest, const struct net_device *dev) 203{ 204 *dest = dev ? dev->ifindex : 0; 205} 206 207static void nft_meta_store_ifname(u32 *dest, const struct net_device *dev) 208{ 209 strncpy((char *)dest, dev ? dev->name : "", IFNAMSIZ); 210} 211 212static bool nft_meta_store_iftype(u32 *dest, const struct net_device *dev) 213{ 214 if (!dev) 215 return false; 216 217 nft_reg_store16(dest, dev->type); 218 return true; 219} 220 221static bool nft_meta_store_ifgroup(u32 *dest, const struct net_device *dev) 222{ 223 if (!dev) 224 return false; 225 226 *dest = dev->group; 227 return true; 228} 229 230static bool nft_meta_get_eval_ifname(enum nft_meta_keys key, u32 *dest, 231 const struct nft_pktinfo *pkt) 232{ 233 switch (key) { 234 case NFT_META_IIFNAME: 235 nft_meta_store_ifname(dest, nft_in(pkt)); 236 break; 237 case NFT_META_OIFNAME: 238 nft_meta_store_ifname(dest, nft_out(pkt)); 239 break; 240 case NFT_META_IIF: 241 nft_meta_store_ifindex(dest, nft_in(pkt)); 242 break; 243 case NFT_META_OIF: 244 nft_meta_store_ifindex(dest, nft_out(pkt)); 245 break; 246 case NFT_META_IFTYPE: 247 if (!nft_meta_store_iftype(dest, pkt->skb->dev)) 248 return false; 249 break; 250 case __NFT_META_IIFTYPE: 251 if (!nft_meta_store_iftype(dest, nft_in(pkt))) 252 return false; 253 break; 254 case NFT_META_OIFTYPE: 255 if (!nft_meta_store_iftype(dest, nft_out(pkt))) 256 return false; 257 break; 258 case NFT_META_IIFGROUP: 259 if (!nft_meta_store_ifgroup(dest, nft_in(pkt))) 260 return false; 261 break; 262 case NFT_META_OIFGROUP: 263 if (!nft_meta_store_ifgroup(dest, nft_out(pkt))) 264 return false; 265 break; 266 default: 267 return false; 268 } 269 270 return true; 271} 272 273#ifdef CONFIG_IP_ROUTE_CLASSID 274static noinline bool 275nft_meta_get_eval_rtclassid(const struct sk_buff *skb, u32 *dest) 276{ 277 const struct dst_entry *dst = skb_dst(skb); 278 279 if (!dst) 280 return false; 281 282 *dest = dst->tclassid; 283 return true; 284} 285#endif 286 287static noinline u32 nft_meta_get_eval_sdif(const struct nft_pktinfo *pkt) 288{ 289 switch (nft_pf(pkt)) { 290 case NFPROTO_IPV4: 291 return inet_sdif(pkt->skb); 292 case NFPROTO_IPV6: 293 return inet6_sdif(pkt->skb); 294 } 295 296 return 0; 297} 298 299static noinline void 300nft_meta_get_eval_sdifname(u32 *dest, const struct nft_pktinfo *pkt) 301{ 302 u32 sdif = nft_meta_get_eval_sdif(pkt); 303 const struct net_device *dev; 304 305 dev = sdif ? dev_get_by_index_rcu(nft_net(pkt), sdif) : NULL; 306 nft_meta_store_ifname(dest, dev); 307} 308 309void nft_meta_get_eval(const struct nft_expr *expr, 310 struct nft_regs *regs, 311 const struct nft_pktinfo *pkt) 312{ 313 const struct nft_meta *priv = nft_expr_priv(expr); 314 const struct sk_buff *skb = pkt->skb; 315 u32 *dest = ®s->data[priv->dreg]; 316 317 switch (priv->key) { 318 case NFT_META_LEN: 319 *dest = skb->len; 320 break; 321 case NFT_META_PROTOCOL: 322 nft_reg_store16(dest, (__force u16)skb->protocol); 323 break; 324 case NFT_META_NFPROTO: 325 nft_reg_store8(dest, nft_pf(pkt)); 326 break; 327 case NFT_META_L4PROTO: 328 if (!(pkt->flags & NFT_PKTINFO_L4PROTO)) 329 goto err; 330 nft_reg_store8(dest, pkt->tprot); 331 break; 332 case NFT_META_PRIORITY: 333 *dest = skb->priority; 334 break; 335 case NFT_META_MARK: 336 *dest = skb->mark; 337 break; 338 case NFT_META_IIF: 339 case NFT_META_OIF: 340 case NFT_META_IIFNAME: 341 case NFT_META_OIFNAME: 342 case NFT_META_IIFTYPE: 343 case NFT_META_OIFTYPE: 344 case NFT_META_IIFGROUP: 345 case NFT_META_OIFGROUP: 346 if (!nft_meta_get_eval_ifname(priv->key, dest, pkt)) 347 goto err; 348 break; 349 case NFT_META_SKUID: 350 case NFT_META_SKGID: 351 if (!nft_meta_get_eval_skugid(priv->key, dest, pkt)) 352 goto err; 353 break; 354#ifdef CONFIG_IP_ROUTE_CLASSID 355 case NFT_META_RTCLASSID: 356 if (!nft_meta_get_eval_rtclassid(skb, dest)) 357 goto err; 358 break; 359#endif 360#ifdef CONFIG_NETWORK_SECMARK 361 case NFT_META_SECMARK: 362 *dest = skb->secmark; 363 break; 364#endif 365 case NFT_META_PKTTYPE: 366 if (skb->pkt_type != PACKET_LOOPBACK) { 367 nft_reg_store8(dest, skb->pkt_type); 368 break; 369 } 370 371 if (!nft_meta_get_eval_pkttype_lo(pkt, dest)) 372 goto err; 373 break; 374 case NFT_META_CPU: 375 *dest = raw_smp_processor_id(); 376 break; 377#ifdef CONFIG_CGROUP_NET_CLASSID 378 case NFT_META_CGROUP: 379 if (!nft_meta_get_eval_cgroup(dest, pkt)) 380 goto err; 381 break; 382#endif 383 case NFT_META_PRANDOM: 384 *dest = get_random_u32(); 385 break; 386#ifdef CONFIG_XFRM 387 case NFT_META_SECPATH: 388 nft_reg_store8(dest, secpath_exists(skb)); 389 break; 390#endif 391 case NFT_META_IIFKIND: 392 case NFT_META_OIFKIND: 393 if (!nft_meta_get_eval_kind(priv->key, dest, pkt)) 394 goto err; 395 break; 396 case NFT_META_TIME_NS: 397 case NFT_META_TIME_DAY: 398 case NFT_META_TIME_HOUR: 399 nft_meta_get_eval_time(priv->key, dest); 400 break; 401 case NFT_META_SDIF: 402 *dest = nft_meta_get_eval_sdif(pkt); 403 break; 404 case NFT_META_SDIFNAME: 405 nft_meta_get_eval_sdifname(dest, pkt); 406 break; 407 default: 408 WARN_ON(1); 409 goto err; 410 } 411 return; 412 413err: 414 regs->verdict.code = NFT_BREAK; 415} 416EXPORT_SYMBOL_GPL(nft_meta_get_eval); 417 418void nft_meta_set_eval(const struct nft_expr *expr, 419 struct nft_regs *regs, 420 const struct nft_pktinfo *pkt) 421{ 422 const struct nft_meta *meta = nft_expr_priv(expr); 423 struct sk_buff *skb = pkt->skb; 424 u32 *sreg = ®s->data[meta->sreg]; 425 u32 value = *sreg; 426 u8 value8; 427 428 switch (meta->key) { 429 case NFT_META_MARK: 430 skb->mark = value; 431 break; 432 case NFT_META_PRIORITY: 433 skb->priority = value; 434 break; 435 case NFT_META_PKTTYPE: 436 value8 = nft_reg_load8(sreg); 437 438 if (skb->pkt_type != value8 && 439 skb_pkt_type_ok(value8) && 440 skb_pkt_type_ok(skb->pkt_type)) 441 skb->pkt_type = value8; 442 break; 443 case NFT_META_NFTRACE: 444 value8 = nft_reg_load8(sreg); 445 446 skb->nf_trace = !!value8; 447 break; 448#ifdef CONFIG_NETWORK_SECMARK 449 case NFT_META_SECMARK: 450 skb->secmark = value; 451 break; 452#endif 453 default: 454 WARN_ON(1); 455 } 456} 457EXPORT_SYMBOL_GPL(nft_meta_set_eval); 458 459const struct nla_policy nft_meta_policy[NFTA_META_MAX + 1] = { 460 [NFTA_META_DREG] = { .type = NLA_U32 }, 461 [NFTA_META_KEY] = { .type = NLA_U32 }, 462 [NFTA_META_SREG] = { .type = NLA_U32 }, 463}; 464EXPORT_SYMBOL_GPL(nft_meta_policy); 465 466int nft_meta_get_init(const struct nft_ctx *ctx, 467 const struct nft_expr *expr, 468 const struct nlattr * const tb[]) 469{ 470 struct nft_meta *priv = nft_expr_priv(expr); 471 unsigned int len; 472 473 priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY])); 474 switch (priv->key) { 475 case NFT_META_PROTOCOL: 476 case NFT_META_IIFTYPE: 477 case NFT_META_OIFTYPE: 478 len = sizeof(u16); 479 break; 480 case NFT_META_NFPROTO: 481 case NFT_META_L4PROTO: 482 case NFT_META_LEN: 483 case NFT_META_PRIORITY: 484 case NFT_META_MARK: 485 case NFT_META_IIF: 486 case NFT_META_OIF: 487 case NFT_META_SDIF: 488 case NFT_META_SKUID: 489 case NFT_META_SKGID: 490#ifdef CONFIG_IP_ROUTE_CLASSID 491 case NFT_META_RTCLASSID: 492#endif 493#ifdef CONFIG_NETWORK_SECMARK 494 case NFT_META_SECMARK: 495#endif 496 case NFT_META_PKTTYPE: 497 case NFT_META_CPU: 498 case NFT_META_IIFGROUP: 499 case NFT_META_OIFGROUP: 500#ifdef CONFIG_CGROUP_NET_CLASSID 501 case NFT_META_CGROUP: 502#endif 503 len = sizeof(u32); 504 break; 505 case NFT_META_IIFNAME: 506 case NFT_META_OIFNAME: 507 case NFT_META_IIFKIND: 508 case NFT_META_OIFKIND: 509 case NFT_META_SDIFNAME: 510 len = IFNAMSIZ; 511 break; 512 case NFT_META_PRANDOM: 513 len = sizeof(u32); 514 break; 515#ifdef CONFIG_XFRM 516 case NFT_META_SECPATH: 517 len = sizeof(u8); 518 break; 519#endif 520 case NFT_META_TIME_NS: 521 len = sizeof(u64); 522 break; 523 case NFT_META_TIME_DAY: 524 len = sizeof(u8); 525 break; 526 case NFT_META_TIME_HOUR: 527 len = sizeof(u32); 528 break; 529 default: 530 return -EOPNOTSUPP; 531 } 532 533 priv->len = len; 534 return nft_parse_register_store(ctx, tb[NFTA_META_DREG], &priv->dreg, 535 NULL, NFT_DATA_VALUE, len); 536} 537EXPORT_SYMBOL_GPL(nft_meta_get_init); 538 539static int nft_meta_get_validate_sdif(const struct nft_ctx *ctx) 540{ 541 unsigned int hooks; 542 543 switch (ctx->family) { 544 case NFPROTO_IPV4: 545 case NFPROTO_IPV6: 546 case NFPROTO_INET: 547 hooks = (1 << NF_INET_LOCAL_IN) | 548 (1 << NF_INET_FORWARD); 549 break; 550 default: 551 return -EOPNOTSUPP; 552 } 553 554 return nft_chain_validate_hooks(ctx->chain, hooks); 555} 556 557static int nft_meta_get_validate_xfrm(const struct nft_ctx *ctx) 558{ 559#ifdef CONFIG_XFRM 560 unsigned int hooks; 561 562 switch (ctx->family) { 563 case NFPROTO_NETDEV: 564 hooks = 1 << NF_NETDEV_INGRESS; 565 break; 566 case NFPROTO_IPV4: 567 case NFPROTO_IPV6: 568 case NFPROTO_INET: 569 hooks = (1 << NF_INET_PRE_ROUTING) | 570 (1 << NF_INET_LOCAL_IN) | 571 (1 << NF_INET_FORWARD); 572 break; 573 default: 574 return -EOPNOTSUPP; 575 } 576 577 return nft_chain_validate_hooks(ctx->chain, hooks); 578#else 579 return 0; 580#endif 581} 582 583static int nft_meta_get_validate(const struct nft_ctx *ctx, 584 const struct nft_expr *expr, 585 const struct nft_data **data) 586{ 587 const struct nft_meta *priv = nft_expr_priv(expr); 588 589 switch (priv->key) { 590 case NFT_META_SECPATH: 591 return nft_meta_get_validate_xfrm(ctx); 592 case NFT_META_SDIF: 593 case NFT_META_SDIFNAME: 594 return nft_meta_get_validate_sdif(ctx); 595 default: 596 break; 597 } 598 599 return 0; 600} 601 602int nft_meta_set_validate(const struct nft_ctx *ctx, 603 const struct nft_expr *expr, 604 const struct nft_data **data) 605{ 606 struct nft_meta *priv = nft_expr_priv(expr); 607 unsigned int hooks; 608 609 if (priv->key != NFT_META_PKTTYPE) 610 return 0; 611 612 switch (ctx->family) { 613 case NFPROTO_BRIDGE: 614 hooks = 1 << NF_BR_PRE_ROUTING; 615 break; 616 case NFPROTO_NETDEV: 617 hooks = 1 << NF_NETDEV_INGRESS; 618 break; 619 case NFPROTO_IPV4: 620 case NFPROTO_IPV6: 621 case NFPROTO_INET: 622 hooks = 1 << NF_INET_PRE_ROUTING; 623 break; 624 default: 625 return -EOPNOTSUPP; 626 } 627 628 return nft_chain_validate_hooks(ctx->chain, hooks); 629} 630EXPORT_SYMBOL_GPL(nft_meta_set_validate); 631 632int nft_meta_set_init(const struct nft_ctx *ctx, 633 const struct nft_expr *expr, 634 const struct nlattr * const tb[]) 635{ 636 struct nft_meta *priv = nft_expr_priv(expr); 637 unsigned int len; 638 int err; 639 640 priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY])); 641 switch (priv->key) { 642 case NFT_META_MARK: 643 case NFT_META_PRIORITY: 644#ifdef CONFIG_NETWORK_SECMARK 645 case NFT_META_SECMARK: 646#endif 647 len = sizeof(u32); 648 break; 649 case NFT_META_NFTRACE: 650 len = sizeof(u8); 651 break; 652 case NFT_META_PKTTYPE: 653 len = sizeof(u8); 654 break; 655 default: 656 return -EOPNOTSUPP; 657 } 658 659 priv->len = len; 660 err = nft_parse_register_load(tb[NFTA_META_SREG], &priv->sreg, len); 661 if (err < 0) 662 return err; 663 664 if (priv->key == NFT_META_NFTRACE) 665 static_branch_inc(&nft_trace_enabled); 666 667 return 0; 668} 669EXPORT_SYMBOL_GPL(nft_meta_set_init); 670 671int nft_meta_get_dump(struct sk_buff *skb, 672 const struct nft_expr *expr) 673{ 674 const struct nft_meta *priv = nft_expr_priv(expr); 675 676 if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key))) 677 goto nla_put_failure; 678 if (nft_dump_register(skb, NFTA_META_DREG, priv->dreg)) 679 goto nla_put_failure; 680 return 0; 681 682nla_put_failure: 683 return -1; 684} 685EXPORT_SYMBOL_GPL(nft_meta_get_dump); 686 687int nft_meta_set_dump(struct sk_buff *skb, const struct nft_expr *expr) 688{ 689 const struct nft_meta *priv = nft_expr_priv(expr); 690 691 if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key))) 692 goto nla_put_failure; 693 if (nft_dump_register(skb, NFTA_META_SREG, priv->sreg)) 694 goto nla_put_failure; 695 696 return 0; 697 698nla_put_failure: 699 return -1; 700} 701EXPORT_SYMBOL_GPL(nft_meta_set_dump); 702 703void nft_meta_set_destroy(const struct nft_ctx *ctx, 704 const struct nft_expr *expr) 705{ 706 const struct nft_meta *priv = nft_expr_priv(expr); 707 708 if (priv->key == NFT_META_NFTRACE) 709 static_branch_dec(&nft_trace_enabled); 710} 711EXPORT_SYMBOL_GPL(nft_meta_set_destroy); 712 713static int nft_meta_get_offload(struct nft_offload_ctx *ctx, 714 struct nft_flow_rule *flow, 715 const struct nft_expr *expr) 716{ 717 const struct nft_meta *priv = nft_expr_priv(expr); 718 struct nft_offload_reg *reg = &ctx->regs[priv->dreg]; 719 720 switch (priv->key) { 721 case NFT_META_PROTOCOL: 722 NFT_OFFLOAD_MATCH_EXACT(FLOW_DISSECTOR_KEY_BASIC, basic, n_proto, 723 sizeof(__u16), reg); 724 nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_NETWORK); 725 break; 726 case NFT_META_L4PROTO: 727 NFT_OFFLOAD_MATCH_EXACT(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto, 728 sizeof(__u8), reg); 729 nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT); 730 break; 731 case NFT_META_IIF: 732 NFT_OFFLOAD_MATCH_EXACT(FLOW_DISSECTOR_KEY_META, meta, 733 ingress_ifindex, sizeof(__u32), reg); 734 break; 735 case NFT_META_IIFTYPE: 736 NFT_OFFLOAD_MATCH_EXACT(FLOW_DISSECTOR_KEY_META, meta, 737 ingress_iftype, sizeof(__u16), reg); 738 break; 739 default: 740 return -EOPNOTSUPP; 741 } 742 743 return 0; 744} 745 746bool nft_meta_get_reduce(struct nft_regs_track *track, 747 const struct nft_expr *expr) 748{ 749 const struct nft_meta *priv = nft_expr_priv(expr); 750 const struct nft_meta *meta; 751 752 if (!nft_reg_track_cmp(track, expr, priv->dreg)) { 753 nft_reg_track_update(track, expr, priv->dreg, priv->len); 754 return false; 755 } 756 757 meta = nft_expr_priv(track->regs[priv->dreg].selector); 758 if (priv->key != meta->key || 759 priv->dreg != meta->dreg) { 760 nft_reg_track_update(track, expr, priv->dreg, priv->len); 761 return false; 762 } 763 764 if (!track->regs[priv->dreg].bitwise) 765 return true; 766 767 return nft_expr_reduce_bitwise(track, expr); 768} 769EXPORT_SYMBOL_GPL(nft_meta_get_reduce); 770 771static const struct nft_expr_ops nft_meta_get_ops = { 772 .type = &nft_meta_type, 773 .size = NFT_EXPR_SIZE(sizeof(struct nft_meta)), 774 .eval = nft_meta_get_eval, 775 .init = nft_meta_get_init, 776 .dump = nft_meta_get_dump, 777 .reduce = nft_meta_get_reduce, 778 .validate = nft_meta_get_validate, 779 .offload = nft_meta_get_offload, 780}; 781 782static bool nft_meta_set_reduce(struct nft_regs_track *track, 783 const struct nft_expr *expr) 784{ 785 int i; 786 787 for (i = 0; i < NFT_REG32_NUM; i++) { 788 if (!track->regs[i].selector) 789 continue; 790 791 if (track->regs[i].selector->ops != &nft_meta_get_ops) 792 continue; 793 794 __nft_reg_track_cancel(track, i); 795 } 796 797 return false; 798} 799 800static const struct nft_expr_ops nft_meta_set_ops = { 801 .type = &nft_meta_type, 802 .size = NFT_EXPR_SIZE(sizeof(struct nft_meta)), 803 .eval = nft_meta_set_eval, 804 .init = nft_meta_set_init, 805 .destroy = nft_meta_set_destroy, 806 .dump = nft_meta_set_dump, 807 .reduce = nft_meta_set_reduce, 808 .validate = nft_meta_set_validate, 809}; 810 811static const struct nft_expr_ops * 812nft_meta_select_ops(const struct nft_ctx *ctx, 813 const struct nlattr * const tb[]) 814{ 815 if (tb[NFTA_META_KEY] == NULL) 816 return ERR_PTR(-EINVAL); 817 818 if (tb[NFTA_META_DREG] && tb[NFTA_META_SREG]) 819 return ERR_PTR(-EINVAL); 820 821#if IS_ENABLED(CONFIG_NF_TABLES_BRIDGE) && IS_MODULE(CONFIG_NFT_BRIDGE_META) 822 if (ctx->family == NFPROTO_BRIDGE) 823 return ERR_PTR(-EAGAIN); 824#endif 825 if (tb[NFTA_META_DREG]) 826 return &nft_meta_get_ops; 827 828 if (tb[NFTA_META_SREG]) 829 return &nft_meta_set_ops; 830 831 return ERR_PTR(-EINVAL); 832} 833 834struct nft_expr_type nft_meta_type __read_mostly = { 835 .name = "meta", 836 .select_ops = nft_meta_select_ops, 837 .policy = nft_meta_policy, 838 .maxattr = NFTA_META_MAX, 839 .owner = THIS_MODULE, 840}; 841 842#ifdef CONFIG_NETWORK_SECMARK 843struct nft_secmark { 844 u32 secid; 845 char *ctx; 846}; 847 848static const struct nla_policy nft_secmark_policy[NFTA_SECMARK_MAX + 1] = { 849 [NFTA_SECMARK_CTX] = { .type = NLA_STRING, .len = NFT_SECMARK_CTX_MAXLEN }, 850}; 851 852static int nft_secmark_compute_secid(struct nft_secmark *priv) 853{ 854 u32 tmp_secid = 0; 855 int err; 856 857 err = security_secctx_to_secid(priv->ctx, strlen(priv->ctx), &tmp_secid); 858 if (err) 859 return err; 860 861 if (!tmp_secid) 862 return -ENOENT; 863 864 err = security_secmark_relabel_packet(tmp_secid); 865 if (err) 866 return err; 867 868 priv->secid = tmp_secid; 869 return 0; 870} 871 872static void nft_secmark_obj_eval(struct nft_object *obj, struct nft_regs *regs, 873 const struct nft_pktinfo *pkt) 874{ 875 const struct nft_secmark *priv = nft_obj_data(obj); 876 struct sk_buff *skb = pkt->skb; 877 878 skb->secmark = priv->secid; 879} 880 881static int nft_secmark_obj_init(const struct nft_ctx *ctx, 882 const struct nlattr * const tb[], 883 struct nft_object *obj) 884{ 885 struct nft_secmark *priv = nft_obj_data(obj); 886 int err; 887 888 if (tb[NFTA_SECMARK_CTX] == NULL) 889 return -EINVAL; 890 891 priv->ctx = nla_strdup(tb[NFTA_SECMARK_CTX], GFP_KERNEL); 892 if (!priv->ctx) 893 return -ENOMEM; 894 895 err = nft_secmark_compute_secid(priv); 896 if (err) { 897 kfree(priv->ctx); 898 return err; 899 } 900 901 security_secmark_refcount_inc(); 902 903 return 0; 904} 905 906static int nft_secmark_obj_dump(struct sk_buff *skb, struct nft_object *obj, 907 bool reset) 908{ 909 struct nft_secmark *priv = nft_obj_data(obj); 910 int err; 911 912 if (nla_put_string(skb, NFTA_SECMARK_CTX, priv->ctx)) 913 return -1; 914 915 if (reset) { 916 err = nft_secmark_compute_secid(priv); 917 if (err) 918 return err; 919 } 920 921 return 0; 922} 923 924static void nft_secmark_obj_destroy(const struct nft_ctx *ctx, struct nft_object *obj) 925{ 926 struct nft_secmark *priv = nft_obj_data(obj); 927 928 security_secmark_refcount_dec(); 929 930 kfree(priv->ctx); 931} 932 933static const struct nft_object_ops nft_secmark_obj_ops = { 934 .type = &nft_secmark_obj_type, 935 .size = sizeof(struct nft_secmark), 936 .init = nft_secmark_obj_init, 937 .eval = nft_secmark_obj_eval, 938 .dump = nft_secmark_obj_dump, 939 .destroy = nft_secmark_obj_destroy, 940}; 941struct nft_object_type nft_secmark_obj_type __read_mostly = { 942 .type = NFT_OBJECT_SECMARK, 943 .ops = &nft_secmark_obj_ops, 944 .maxattr = NFTA_SECMARK_MAX, 945 .policy = nft_secmark_policy, 946 .owner = THIS_MODULE, 947}; 948#endif /* CONFIG_NETWORK_SECMARK */