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