Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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