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        return nft_parse_register_store(ctx, tb[NFTA_META_DREG], &priv->dreg,
 539                                        NULL, NFT_DATA_VALUE, len);
 540}
 541EXPORT_SYMBOL_GPL(nft_meta_get_init);
 542
 543static int nft_meta_get_validate_sdif(const struct nft_ctx *ctx)
 544{
 545        unsigned int hooks;
 546
 547        switch (ctx->family) {
 548        case NFPROTO_IPV4:
 549        case NFPROTO_IPV6:
 550        case NFPROTO_INET:
 551                hooks = (1 << NF_INET_LOCAL_IN) |
 552                        (1 << NF_INET_FORWARD);
 553                break;
 554        default:
 555                return -EOPNOTSUPP;
 556        }
 557
 558        return nft_chain_validate_hooks(ctx->chain, hooks);
 559}
 560
 561static int nft_meta_get_validate_xfrm(const struct nft_ctx *ctx)
 562{
 563#ifdef CONFIG_XFRM
 564        unsigned int hooks;
 565
 566        switch (ctx->family) {
 567        case NFPROTO_NETDEV:
 568                hooks = 1 << NF_NETDEV_INGRESS;
 569                break;
 570        case NFPROTO_IPV4:
 571        case NFPROTO_IPV6:
 572        case NFPROTO_INET:
 573                hooks = (1 << NF_INET_PRE_ROUTING) |
 574                        (1 << NF_INET_LOCAL_IN) |
 575                        (1 << NF_INET_FORWARD);
 576                break;
 577        default:
 578                return -EOPNOTSUPP;
 579        }
 580
 581        return nft_chain_validate_hooks(ctx->chain, hooks);
 582#else
 583        return 0;
 584#endif
 585}
 586
 587static int nft_meta_get_validate(const struct nft_ctx *ctx,
 588                                 const struct nft_expr *expr,
 589                                 const struct nft_data **data)
 590{
 591        const struct nft_meta *priv = nft_expr_priv(expr);
 592
 593        switch (priv->key) {
 594        case NFT_META_SECPATH:
 595                return nft_meta_get_validate_xfrm(ctx);
 596        case NFT_META_SDIF:
 597        case NFT_META_SDIFNAME:
 598                return nft_meta_get_validate_sdif(ctx);
 599        default:
 600                break;
 601        }
 602
 603        return 0;
 604}
 605
 606int nft_meta_set_validate(const struct nft_ctx *ctx,
 607                          const struct nft_expr *expr,
 608                          const struct nft_data **data)
 609{
 610        struct nft_meta *priv = nft_expr_priv(expr);
 611        unsigned int hooks;
 612
 613        if (priv->key != NFT_META_PKTTYPE)
 614                return 0;
 615
 616        switch (ctx->family) {
 617        case NFPROTO_BRIDGE:
 618                hooks = 1 << NF_BR_PRE_ROUTING;
 619                break;
 620        case NFPROTO_NETDEV:
 621                hooks = 1 << NF_NETDEV_INGRESS;
 622                break;
 623        case NFPROTO_IPV4:
 624        case NFPROTO_IPV6:
 625        case NFPROTO_INET:
 626                hooks = 1 << NF_INET_PRE_ROUTING;
 627                break;
 628        default:
 629                return -EOPNOTSUPP;
 630        }
 631
 632        return nft_chain_validate_hooks(ctx->chain, hooks);
 633}
 634EXPORT_SYMBOL_GPL(nft_meta_set_validate);
 635
 636int nft_meta_set_init(const struct nft_ctx *ctx,
 637                      const struct nft_expr *expr,
 638                      const struct nlattr * const tb[])
 639{
 640        struct nft_meta *priv = nft_expr_priv(expr);
 641        unsigned int len;
 642        int err;
 643
 644        priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
 645        switch (priv->key) {
 646        case NFT_META_MARK:
 647        case NFT_META_PRIORITY:
 648#ifdef CONFIG_NETWORK_SECMARK
 649        case NFT_META_SECMARK:
 650#endif
 651                len = sizeof(u32);
 652                break;
 653        case NFT_META_NFTRACE:
 654                len = sizeof(u8);
 655                break;
 656        case NFT_META_PKTTYPE:
 657                len = sizeof(u8);
 658                break;
 659        default:
 660                return -EOPNOTSUPP;
 661        }
 662
 663        err = nft_parse_register_load(tb[NFTA_META_SREG], &priv->sreg, len);
 664        if (err < 0)
 665                return err;
 666
 667        if (priv->key == NFT_META_NFTRACE)
 668                static_branch_inc(&nft_trace_enabled);
 669
 670        return 0;
 671}
 672EXPORT_SYMBOL_GPL(nft_meta_set_init);
 673
 674int nft_meta_get_dump(struct sk_buff *skb,
 675                      const struct nft_expr *expr)
 676{
 677        const struct nft_meta *priv = nft_expr_priv(expr);
 678
 679        if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key)))
 680                goto nla_put_failure;
 681        if (nft_dump_register(skb, NFTA_META_DREG, priv->dreg))
 682                goto nla_put_failure;
 683        return 0;
 684
 685nla_put_failure:
 686        return -1;
 687}
 688EXPORT_SYMBOL_GPL(nft_meta_get_dump);
 689
 690int nft_meta_set_dump(struct sk_buff *skb, const struct nft_expr *expr)
 691{
 692        const struct nft_meta *priv = nft_expr_priv(expr);
 693
 694        if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key)))
 695                goto nla_put_failure;
 696        if (nft_dump_register(skb, NFTA_META_SREG, priv->sreg))
 697                goto nla_put_failure;
 698
 699        return 0;
 700
 701nla_put_failure:
 702        return -1;
 703}
 704EXPORT_SYMBOL_GPL(nft_meta_set_dump);
 705
 706void nft_meta_set_destroy(const struct nft_ctx *ctx,
 707                          const struct nft_expr *expr)
 708{
 709        const struct nft_meta *priv = nft_expr_priv(expr);
 710
 711        if (priv->key == NFT_META_NFTRACE)
 712                static_branch_dec(&nft_trace_enabled);
 713}
 714EXPORT_SYMBOL_GPL(nft_meta_set_destroy);
 715
 716static int nft_meta_get_offload(struct nft_offload_ctx *ctx,
 717                                struct nft_flow_rule *flow,
 718                                const struct nft_expr *expr)
 719{
 720        const struct nft_meta *priv = nft_expr_priv(expr);
 721        struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
 722
 723        switch (priv->key) {
 724        case NFT_META_PROTOCOL:
 725                NFT_OFFLOAD_MATCH_EXACT(FLOW_DISSECTOR_KEY_BASIC, basic, n_proto,
 726                                        sizeof(__u16), reg);
 727                nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_NETWORK);
 728                break;
 729        case NFT_META_L4PROTO:
 730                NFT_OFFLOAD_MATCH_EXACT(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
 731                                        sizeof(__u8), reg);
 732                nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
 733                break;
 734        case NFT_META_IIF:
 735                NFT_OFFLOAD_MATCH_EXACT(FLOW_DISSECTOR_KEY_META, meta,
 736                                        ingress_ifindex, sizeof(__u32), reg);
 737                break;
 738        case NFT_META_IIFTYPE:
 739                NFT_OFFLOAD_MATCH_EXACT(FLOW_DISSECTOR_KEY_META, meta,
 740                                        ingress_iftype, sizeof(__u16), reg);
 741                break;
 742        default:
 743                return -EOPNOTSUPP;
 744        }
 745
 746        return 0;
 747}
 748
 749static const struct nft_expr_ops nft_meta_get_ops = {
 750        .type           = &nft_meta_type,
 751        .size           = NFT_EXPR_SIZE(sizeof(struct nft_meta)),
 752        .eval           = nft_meta_get_eval,
 753        .init           = nft_meta_get_init,
 754        .dump           = nft_meta_get_dump,
 755        .validate       = nft_meta_get_validate,
 756        .offload        = nft_meta_get_offload,
 757};
 758
 759static const struct nft_expr_ops nft_meta_set_ops = {
 760        .type           = &nft_meta_type,
 761        .size           = NFT_EXPR_SIZE(sizeof(struct nft_meta)),
 762        .eval           = nft_meta_set_eval,
 763        .init           = nft_meta_set_init,
 764        .destroy        = nft_meta_set_destroy,
 765        .dump           = nft_meta_set_dump,
 766        .validate       = nft_meta_set_validate,
 767};
 768
 769static const struct nft_expr_ops *
 770nft_meta_select_ops(const struct nft_ctx *ctx,
 771                    const struct nlattr * const tb[])
 772{
 773        if (tb[NFTA_META_KEY] == NULL)
 774                return ERR_PTR(-EINVAL);
 775
 776        if (tb[NFTA_META_DREG] && tb[NFTA_META_SREG])
 777                return ERR_PTR(-EINVAL);
 778
 779#if IS_ENABLED(CONFIG_NF_TABLES_BRIDGE) && IS_MODULE(CONFIG_NFT_BRIDGE_META)
 780        if (ctx->family == NFPROTO_BRIDGE)
 781                return ERR_PTR(-EAGAIN);
 782#endif
 783        if (tb[NFTA_META_DREG])
 784                return &nft_meta_get_ops;
 785
 786        if (tb[NFTA_META_SREG])
 787                return &nft_meta_set_ops;
 788
 789        return ERR_PTR(-EINVAL);
 790}
 791
 792struct nft_expr_type nft_meta_type __read_mostly = {
 793        .name           = "meta",
 794        .select_ops     = nft_meta_select_ops,
 795        .policy         = nft_meta_policy,
 796        .maxattr        = NFTA_META_MAX,
 797        .owner          = THIS_MODULE,
 798};
 799
 800#ifdef CONFIG_NETWORK_SECMARK
 801struct nft_secmark {
 802        u32 secid;
 803        char *ctx;
 804};
 805
 806static const struct nla_policy nft_secmark_policy[NFTA_SECMARK_MAX + 1] = {
 807        [NFTA_SECMARK_CTX]     = { .type = NLA_STRING, .len = NFT_SECMARK_CTX_MAXLEN },
 808};
 809
 810static int nft_secmark_compute_secid(struct nft_secmark *priv)
 811{
 812        u32 tmp_secid = 0;
 813        int err;
 814
 815        err = security_secctx_to_secid(priv->ctx, strlen(priv->ctx), &tmp_secid);
 816        if (err)
 817                return err;
 818
 819        if (!tmp_secid)
 820                return -ENOENT;
 821
 822        err = security_secmark_relabel_packet(tmp_secid);
 823        if (err)
 824                return err;
 825
 826        priv->secid = tmp_secid;
 827        return 0;
 828}
 829
 830static void nft_secmark_obj_eval(struct nft_object *obj, struct nft_regs *regs,
 831                                 const struct nft_pktinfo *pkt)
 832{
 833        const struct nft_secmark *priv = nft_obj_data(obj);
 834        struct sk_buff *skb = pkt->skb;
 835
 836        skb->secmark = priv->secid;
 837}
 838
 839static int nft_secmark_obj_init(const struct nft_ctx *ctx,
 840                                const struct nlattr * const tb[],
 841                                struct nft_object *obj)
 842{
 843        struct nft_secmark *priv = nft_obj_data(obj);
 844        int err;
 845
 846        if (tb[NFTA_SECMARK_CTX] == NULL)
 847                return -EINVAL;
 848
 849        priv->ctx = nla_strdup(tb[NFTA_SECMARK_CTX], GFP_KERNEL);
 850        if (!priv->ctx)
 851                return -ENOMEM;
 852
 853        err = nft_secmark_compute_secid(priv);
 854        if (err) {
 855                kfree(priv->ctx);
 856                return err;
 857        }
 858
 859        security_secmark_refcount_inc();
 860
 861        return 0;
 862}
 863
 864static int nft_secmark_obj_dump(struct sk_buff *skb, struct nft_object *obj,
 865                                bool reset)
 866{
 867        struct nft_secmark *priv = nft_obj_data(obj);
 868        int err;
 869
 870        if (nla_put_string(skb, NFTA_SECMARK_CTX, priv->ctx))
 871                return -1;
 872
 873        if (reset) {
 874                err = nft_secmark_compute_secid(priv);
 875                if (err)
 876                        return err;
 877        }
 878
 879        return 0;
 880}
 881
 882static void nft_secmark_obj_destroy(const struct nft_ctx *ctx, struct nft_object *obj)
 883{
 884        struct nft_secmark *priv = nft_obj_data(obj);
 885
 886        security_secmark_refcount_dec();
 887
 888        kfree(priv->ctx);
 889}
 890
 891static const struct nft_object_ops nft_secmark_obj_ops = {
 892        .type           = &nft_secmark_obj_type,
 893        .size           = sizeof(struct nft_secmark),
 894        .init           = nft_secmark_obj_init,
 895        .eval           = nft_secmark_obj_eval,
 896        .dump           = nft_secmark_obj_dump,
 897        .destroy        = nft_secmark_obj_destroy,
 898};
 899struct nft_object_type nft_secmark_obj_type __read_mostly = {
 900        .type           = NFT_OBJECT_SECMARK,
 901        .ops            = &nft_secmark_obj_ops,
 902        .maxattr        = NFTA_SECMARK_MAX,
 903        .policy         = nft_secmark_policy,
 904        .owner          = THIS_MODULE,
 905};
 906#endif /* CONFIG_NETWORK_SECMARK */
 907