Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
0004  * Copyright (c) 2014 Intel Corporation
0005  * Author: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
0006  *
0007  * Development of this code funded by Astaro AG (http://www.astaro.com/)
0008  */
0009 
0010 #include <linux/kernel.h>
0011 #include <linux/netlink.h>
0012 #include <linux/netfilter.h>
0013 #include <linux/netfilter/nf_tables.h>
0014 #include <linux/in.h>
0015 #include <linux/ip.h>
0016 #include <linux/ipv6.h>
0017 #include <linux/random.h>
0018 #include <linux/smp.h>
0019 #include <linux/static_key.h>
0020 #include <net/dst.h>
0021 #include <net/ip.h>
0022 #include <net/sock.h>
0023 #include <net/tcp_states.h> /* for TCP_TIME_WAIT */
0024 #include <net/netfilter/nf_tables.h>
0025 #include <net/netfilter/nf_tables_core.h>
0026 #include <net/netfilter/nft_meta.h>
0027 #include <net/netfilter/nf_tables_offload.h>
0028 
0029 #include <uapi/linux/netfilter_bridge.h> /* NF_BR_PRE_ROUTING */
0030 
0031 #define NFT_META_SECS_PER_MINUTE    60
0032 #define NFT_META_SECS_PER_HOUR      3600
0033 #define NFT_META_SECS_PER_DAY       86400
0034 #define NFT_META_DAYS_PER_WEEK      7
0035 
0036 static u8 nft_meta_weekday(void)
0037 {
0038     time64_t secs = ktime_get_real_seconds();
0039     unsigned int dse;
0040     u8 wday;
0041 
0042     secs -= NFT_META_SECS_PER_MINUTE * sys_tz.tz_minuteswest;
0043     dse = div_u64(secs, NFT_META_SECS_PER_DAY);
0044     wday = (4 + dse) % NFT_META_DAYS_PER_WEEK;
0045 
0046     return wday;
0047 }
0048 
0049 static u32 nft_meta_hour(time64_t secs)
0050 {
0051     struct tm tm;
0052 
0053     time64_to_tm(secs, 0, &tm);
0054 
0055     return tm.tm_hour * NFT_META_SECS_PER_HOUR
0056         + tm.tm_min * NFT_META_SECS_PER_MINUTE
0057         + tm.tm_sec;
0058 }
0059 
0060 static noinline_for_stack void
0061 nft_meta_get_eval_time(enum nft_meta_keys key,
0062                u32 *dest)
0063 {
0064     switch (key) {
0065     case NFT_META_TIME_NS:
0066         nft_reg_store64(dest, ktime_get_real_ns());
0067         break;
0068     case NFT_META_TIME_DAY:
0069         nft_reg_store8(dest, nft_meta_weekday());
0070         break;
0071     case NFT_META_TIME_HOUR:
0072         *dest = nft_meta_hour(ktime_get_real_seconds());
0073         break;
0074     default:
0075         break;
0076     }
0077 }
0078 
0079 static noinline bool
0080 nft_meta_get_eval_pkttype_lo(const struct nft_pktinfo *pkt,
0081                  u32 *dest)
0082 {
0083     const struct sk_buff *skb = pkt->skb;
0084 
0085     switch (nft_pf(pkt)) {
0086     case NFPROTO_IPV4:
0087         if (ipv4_is_multicast(ip_hdr(skb)->daddr))
0088             nft_reg_store8(dest, PACKET_MULTICAST);
0089         else
0090             nft_reg_store8(dest, PACKET_BROADCAST);
0091         break;
0092     case NFPROTO_IPV6:
0093         nft_reg_store8(dest, PACKET_MULTICAST);
0094         break;
0095     case NFPROTO_NETDEV:
0096         switch (skb->protocol) {
0097         case htons(ETH_P_IP): {
0098             int noff = skb_network_offset(skb);
0099             struct iphdr *iph, _iph;
0100 
0101             iph = skb_header_pointer(skb, noff,
0102                          sizeof(_iph), &_iph);
0103             if (!iph)
0104                 return false;
0105 
0106             if (ipv4_is_multicast(iph->daddr))
0107                 nft_reg_store8(dest, PACKET_MULTICAST);
0108             else
0109                 nft_reg_store8(dest, PACKET_BROADCAST);
0110 
0111             break;
0112         }
0113         case htons(ETH_P_IPV6):
0114             nft_reg_store8(dest, PACKET_MULTICAST);
0115             break;
0116         default:
0117             WARN_ON_ONCE(1);
0118             return false;
0119         }
0120         break;
0121     default:
0122         WARN_ON_ONCE(1);
0123         return false;
0124     }
0125 
0126     return true;
0127 }
0128 
0129 static noinline bool
0130 nft_meta_get_eval_skugid(enum nft_meta_keys key,
0131              u32 *dest,
0132              const struct nft_pktinfo *pkt)
0133 {
0134     struct sock *sk = skb_to_full_sk(pkt->skb);
0135     struct socket *sock;
0136 
0137     if (!sk || !sk_fullsock(sk) || !net_eq(nft_net(pkt), sock_net(sk)))
0138         return false;
0139 
0140     read_lock_bh(&sk->sk_callback_lock);
0141     sock = sk->sk_socket;
0142     if (!sock || !sock->file) {
0143         read_unlock_bh(&sk->sk_callback_lock);
0144         return false;
0145     }
0146 
0147     switch (key) {
0148     case NFT_META_SKUID:
0149         *dest = from_kuid_munged(sock_net(sk)->user_ns,
0150                      sock->file->f_cred->fsuid);
0151         break;
0152     case NFT_META_SKGID:
0153         *dest = from_kgid_munged(sock_net(sk)->user_ns,
0154                      sock->file->f_cred->fsgid);
0155         break;
0156     default:
0157         break;
0158     }
0159 
0160     read_unlock_bh(&sk->sk_callback_lock);
0161     return true;
0162 }
0163 
0164 #ifdef CONFIG_CGROUP_NET_CLASSID
0165 static noinline bool
0166 nft_meta_get_eval_cgroup(u32 *dest, const struct nft_pktinfo *pkt)
0167 {
0168     struct sock *sk = skb_to_full_sk(pkt->skb);
0169 
0170     if (!sk || !sk_fullsock(sk) || !net_eq(nft_net(pkt), sock_net(sk)))
0171         return false;
0172 
0173     *dest = sock_cgroup_classid(&sk->sk_cgrp_data);
0174     return true;
0175 }
0176 #endif
0177 
0178 static noinline bool nft_meta_get_eval_kind(enum nft_meta_keys key,
0179                         u32 *dest,
0180                         const struct nft_pktinfo *pkt)
0181 {
0182     const struct net_device *in = nft_in(pkt), *out = nft_out(pkt);
0183 
0184     switch (key) {
0185     case NFT_META_IIFKIND:
0186         if (!in || !in->rtnl_link_ops)
0187             return false;
0188         strncpy((char *)dest, in->rtnl_link_ops->kind, IFNAMSIZ);
0189         break;
0190     case NFT_META_OIFKIND:
0191         if (!out || !out->rtnl_link_ops)
0192             return false;
0193         strncpy((char *)dest, out->rtnl_link_ops->kind, IFNAMSIZ);
0194         break;
0195     default:
0196         return false;
0197     }
0198 
0199     return true;
0200 }
0201 
0202 static void nft_meta_store_ifindex(u32 *dest, const struct net_device *dev)
0203 {
0204     *dest = dev ? dev->ifindex : 0;
0205 }
0206 
0207 static void nft_meta_store_ifname(u32 *dest, const struct net_device *dev)
0208 {
0209     strncpy((char *)dest, dev ? dev->name : "", IFNAMSIZ);
0210 }
0211 
0212 static bool nft_meta_store_iftype(u32 *dest, const struct net_device *dev)
0213 {
0214     if (!dev)
0215         return false;
0216 
0217     nft_reg_store16(dest, dev->type);
0218     return true;
0219 }
0220 
0221 static bool nft_meta_store_ifgroup(u32 *dest, const struct net_device *dev)
0222 {
0223     if (!dev)
0224         return false;
0225 
0226     *dest = dev->group;
0227     return true;
0228 }
0229 
0230 static bool nft_meta_get_eval_ifname(enum nft_meta_keys key, u32 *dest,
0231                      const struct nft_pktinfo *pkt)
0232 {
0233     switch (key) {
0234     case NFT_META_IIFNAME:
0235         nft_meta_store_ifname(dest, nft_in(pkt));
0236         break;
0237     case NFT_META_OIFNAME:
0238         nft_meta_store_ifname(dest, nft_out(pkt));
0239         break;
0240     case NFT_META_IIF:
0241         nft_meta_store_ifindex(dest, nft_in(pkt));
0242         break;
0243     case NFT_META_OIF:
0244         nft_meta_store_ifindex(dest, nft_out(pkt));
0245         break;
0246     case NFT_META_IFTYPE:
0247         if (!nft_meta_store_iftype(dest, pkt->skb->dev))
0248             return false;
0249         break;
0250     case __NFT_META_IIFTYPE:
0251         if (!nft_meta_store_iftype(dest, nft_in(pkt)))
0252             return false;
0253         break;
0254     case NFT_META_OIFTYPE:
0255         if (!nft_meta_store_iftype(dest, nft_out(pkt)))
0256             return false;
0257         break;
0258     case NFT_META_IIFGROUP:
0259         if (!nft_meta_store_ifgroup(dest, nft_in(pkt)))
0260             return false;
0261         break;
0262     case NFT_META_OIFGROUP:
0263         if (!nft_meta_store_ifgroup(dest, nft_out(pkt)))
0264             return false;
0265         break;
0266     default:
0267         return false;
0268     }
0269 
0270     return true;
0271 }
0272 
0273 #ifdef CONFIG_IP_ROUTE_CLASSID
0274 static noinline bool
0275 nft_meta_get_eval_rtclassid(const struct sk_buff *skb, u32 *dest)
0276 {
0277     const struct dst_entry *dst = skb_dst(skb);
0278 
0279     if (!dst)
0280         return false;
0281 
0282     *dest = dst->tclassid;
0283     return true;
0284 }
0285 #endif
0286 
0287 static noinline u32 nft_meta_get_eval_sdif(const struct nft_pktinfo *pkt)
0288 {
0289     switch (nft_pf(pkt)) {
0290     case NFPROTO_IPV4:
0291         return inet_sdif(pkt->skb);
0292     case NFPROTO_IPV6:
0293         return inet6_sdif(pkt->skb);
0294     }
0295 
0296     return 0;
0297 }
0298 
0299 static noinline void
0300 nft_meta_get_eval_sdifname(u32 *dest, const struct nft_pktinfo *pkt)
0301 {
0302     u32 sdif = nft_meta_get_eval_sdif(pkt);
0303     const struct net_device *dev;
0304 
0305     dev = sdif ? dev_get_by_index_rcu(nft_net(pkt), sdif) : NULL;
0306     nft_meta_store_ifname(dest, dev);
0307 }
0308 
0309 void nft_meta_get_eval(const struct nft_expr *expr,
0310                struct nft_regs *regs,
0311                const struct nft_pktinfo *pkt)
0312 {
0313     const struct nft_meta *priv = nft_expr_priv(expr);
0314     const struct sk_buff *skb = pkt->skb;
0315     u32 *dest = &regs->data[priv->dreg];
0316 
0317     switch (priv->key) {
0318     case NFT_META_LEN:
0319         *dest = skb->len;
0320         break;
0321     case NFT_META_PROTOCOL:
0322         nft_reg_store16(dest, (__force u16)skb->protocol);
0323         break;
0324     case NFT_META_NFPROTO:
0325         nft_reg_store8(dest, nft_pf(pkt));
0326         break;
0327     case NFT_META_L4PROTO:
0328         if (!(pkt->flags & NFT_PKTINFO_L4PROTO))
0329             goto err;
0330         nft_reg_store8(dest, pkt->tprot);
0331         break;
0332     case NFT_META_PRIORITY:
0333         *dest = skb->priority;
0334         break;
0335     case NFT_META_MARK:
0336         *dest = skb->mark;
0337         break;
0338     case NFT_META_IIF:
0339     case NFT_META_OIF:
0340     case NFT_META_IIFNAME:
0341     case NFT_META_OIFNAME:
0342     case NFT_META_IIFTYPE:
0343     case NFT_META_OIFTYPE:
0344     case NFT_META_IIFGROUP:
0345     case NFT_META_OIFGROUP:
0346         if (!nft_meta_get_eval_ifname(priv->key, dest, pkt))
0347             goto err;
0348         break;
0349     case NFT_META_SKUID:
0350     case NFT_META_SKGID:
0351         if (!nft_meta_get_eval_skugid(priv->key, dest, pkt))
0352             goto err;
0353         break;
0354 #ifdef CONFIG_IP_ROUTE_CLASSID
0355     case NFT_META_RTCLASSID:
0356         if (!nft_meta_get_eval_rtclassid(skb, dest))
0357             goto err;
0358         break;
0359 #endif
0360 #ifdef CONFIG_NETWORK_SECMARK
0361     case NFT_META_SECMARK:
0362         *dest = skb->secmark;
0363         break;
0364 #endif
0365     case NFT_META_PKTTYPE:
0366         if (skb->pkt_type != PACKET_LOOPBACK) {
0367             nft_reg_store8(dest, skb->pkt_type);
0368             break;
0369         }
0370 
0371         if (!nft_meta_get_eval_pkttype_lo(pkt, dest))
0372             goto err;
0373         break;
0374     case NFT_META_CPU:
0375         *dest = raw_smp_processor_id();
0376         break;
0377 #ifdef CONFIG_CGROUP_NET_CLASSID
0378     case NFT_META_CGROUP:
0379         if (!nft_meta_get_eval_cgroup(dest, pkt))
0380             goto err;
0381         break;
0382 #endif
0383     case NFT_META_PRANDOM:
0384         *dest = get_random_u32();
0385         break;
0386 #ifdef CONFIG_XFRM
0387     case NFT_META_SECPATH:
0388         nft_reg_store8(dest, secpath_exists(skb));
0389         break;
0390 #endif
0391     case NFT_META_IIFKIND:
0392     case NFT_META_OIFKIND:
0393         if (!nft_meta_get_eval_kind(priv->key, dest, pkt))
0394             goto err;
0395         break;
0396     case NFT_META_TIME_NS:
0397     case NFT_META_TIME_DAY:
0398     case NFT_META_TIME_HOUR:
0399         nft_meta_get_eval_time(priv->key, dest);
0400         break;
0401     case NFT_META_SDIF:
0402         *dest = nft_meta_get_eval_sdif(pkt);
0403         break;
0404     case NFT_META_SDIFNAME:
0405         nft_meta_get_eval_sdifname(dest, pkt);
0406         break;
0407     default:
0408         WARN_ON(1);
0409         goto err;
0410     }
0411     return;
0412 
0413 err:
0414     regs->verdict.code = NFT_BREAK;
0415 }
0416 EXPORT_SYMBOL_GPL(nft_meta_get_eval);
0417 
0418 void nft_meta_set_eval(const struct nft_expr *expr,
0419                struct nft_regs *regs,
0420                const struct nft_pktinfo *pkt)
0421 {
0422     const struct nft_meta *meta = nft_expr_priv(expr);
0423     struct sk_buff *skb = pkt->skb;
0424     u32 *sreg = &regs->data[meta->sreg];
0425     u32 value = *sreg;
0426     u8 value8;
0427 
0428     switch (meta->key) {
0429     case NFT_META_MARK:
0430         skb->mark = value;
0431         break;
0432     case NFT_META_PRIORITY:
0433         skb->priority = value;
0434         break;
0435     case NFT_META_PKTTYPE:
0436         value8 = nft_reg_load8(sreg);
0437 
0438         if (skb->pkt_type != value8 &&
0439             skb_pkt_type_ok(value8) &&
0440             skb_pkt_type_ok(skb->pkt_type))
0441             skb->pkt_type = value8;
0442         break;
0443     case NFT_META_NFTRACE:
0444         value8 = nft_reg_load8(sreg);
0445 
0446         skb->nf_trace = !!value8;
0447         break;
0448 #ifdef CONFIG_NETWORK_SECMARK
0449     case NFT_META_SECMARK:
0450         skb->secmark = value;
0451         break;
0452 #endif
0453     default:
0454         WARN_ON(1);
0455     }
0456 }
0457 EXPORT_SYMBOL_GPL(nft_meta_set_eval);
0458 
0459 const struct nla_policy nft_meta_policy[NFTA_META_MAX + 1] = {
0460     [NFTA_META_DREG]    = { .type = NLA_U32 },
0461     [NFTA_META_KEY]     = { .type = NLA_U32 },
0462     [NFTA_META_SREG]    = { .type = NLA_U32 },
0463 };
0464 EXPORT_SYMBOL_GPL(nft_meta_policy);
0465 
0466 int nft_meta_get_init(const struct nft_ctx *ctx,
0467               const struct nft_expr *expr,
0468               const struct nlattr * const tb[])
0469 {
0470     struct nft_meta *priv = nft_expr_priv(expr);
0471     unsigned int len;
0472 
0473     priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
0474     switch (priv->key) {
0475     case NFT_META_PROTOCOL:
0476     case NFT_META_IIFTYPE:
0477     case NFT_META_OIFTYPE:
0478         len = sizeof(u16);
0479         break;
0480     case NFT_META_NFPROTO:
0481     case NFT_META_L4PROTO:
0482     case NFT_META_LEN:
0483     case NFT_META_PRIORITY:
0484     case NFT_META_MARK:
0485     case NFT_META_IIF:
0486     case NFT_META_OIF:
0487     case NFT_META_SDIF:
0488     case NFT_META_SKUID:
0489     case NFT_META_SKGID:
0490 #ifdef CONFIG_IP_ROUTE_CLASSID
0491     case NFT_META_RTCLASSID:
0492 #endif
0493 #ifdef CONFIG_NETWORK_SECMARK
0494     case NFT_META_SECMARK:
0495 #endif
0496     case NFT_META_PKTTYPE:
0497     case NFT_META_CPU:
0498     case NFT_META_IIFGROUP:
0499     case NFT_META_OIFGROUP:
0500 #ifdef CONFIG_CGROUP_NET_CLASSID
0501     case NFT_META_CGROUP:
0502 #endif
0503         len = sizeof(u32);
0504         break;
0505     case NFT_META_IIFNAME:
0506     case NFT_META_OIFNAME:
0507     case NFT_META_IIFKIND:
0508     case NFT_META_OIFKIND:
0509     case NFT_META_SDIFNAME:
0510         len = IFNAMSIZ;
0511         break;
0512     case NFT_META_PRANDOM:
0513         len = sizeof(u32);
0514         break;
0515 #ifdef CONFIG_XFRM
0516     case NFT_META_SECPATH:
0517         len = sizeof(u8);
0518         break;
0519 #endif
0520     case NFT_META_TIME_NS:
0521         len = sizeof(u64);
0522         break;
0523     case NFT_META_TIME_DAY:
0524         len = sizeof(u8);
0525         break;
0526     case NFT_META_TIME_HOUR:
0527         len = sizeof(u32);
0528         break;
0529     default:
0530         return -EOPNOTSUPP;
0531     }
0532 
0533     priv->len = len;
0534     return nft_parse_register_store(ctx, tb[NFTA_META_DREG], &priv->dreg,
0535                     NULL, NFT_DATA_VALUE, len);
0536 }
0537 EXPORT_SYMBOL_GPL(nft_meta_get_init);
0538 
0539 static int nft_meta_get_validate_sdif(const struct nft_ctx *ctx)
0540 {
0541     unsigned int hooks;
0542 
0543     switch (ctx->family) {
0544     case NFPROTO_IPV4:
0545     case NFPROTO_IPV6:
0546     case NFPROTO_INET:
0547         hooks = (1 << NF_INET_LOCAL_IN) |
0548             (1 << NF_INET_FORWARD);
0549         break;
0550     default:
0551         return -EOPNOTSUPP;
0552     }
0553 
0554     return nft_chain_validate_hooks(ctx->chain, hooks);
0555 }
0556 
0557 static int nft_meta_get_validate_xfrm(const struct nft_ctx *ctx)
0558 {
0559 #ifdef CONFIG_XFRM
0560     unsigned int hooks;
0561 
0562     switch (ctx->family) {
0563     case NFPROTO_NETDEV:
0564         hooks = 1 << NF_NETDEV_INGRESS;
0565         break;
0566     case NFPROTO_IPV4:
0567     case NFPROTO_IPV6:
0568     case NFPROTO_INET:
0569         hooks = (1 << NF_INET_PRE_ROUTING) |
0570             (1 << NF_INET_LOCAL_IN) |
0571             (1 << NF_INET_FORWARD);
0572         break;
0573     default:
0574         return -EOPNOTSUPP;
0575     }
0576 
0577     return nft_chain_validate_hooks(ctx->chain, hooks);
0578 #else
0579     return 0;
0580 #endif
0581 }
0582 
0583 static int nft_meta_get_validate(const struct nft_ctx *ctx,
0584                  const struct nft_expr *expr,
0585                  const struct nft_data **data)
0586 {
0587     const struct nft_meta *priv = nft_expr_priv(expr);
0588 
0589     switch (priv->key) {
0590     case NFT_META_SECPATH:
0591         return nft_meta_get_validate_xfrm(ctx);
0592     case NFT_META_SDIF:
0593     case NFT_META_SDIFNAME:
0594         return nft_meta_get_validate_sdif(ctx);
0595     default:
0596         break;
0597     }
0598 
0599     return 0;
0600 }
0601 
0602 int nft_meta_set_validate(const struct nft_ctx *ctx,
0603               const struct nft_expr *expr,
0604               const struct nft_data **data)
0605 {
0606     struct nft_meta *priv = nft_expr_priv(expr);
0607     unsigned int hooks;
0608 
0609     if (priv->key != NFT_META_PKTTYPE)
0610         return 0;
0611 
0612     switch (ctx->family) {
0613     case NFPROTO_BRIDGE:
0614         hooks = 1 << NF_BR_PRE_ROUTING;
0615         break;
0616     case NFPROTO_NETDEV:
0617         hooks = 1 << NF_NETDEV_INGRESS;
0618         break;
0619     case NFPROTO_IPV4:
0620     case NFPROTO_IPV6:
0621     case NFPROTO_INET:
0622         hooks = 1 << NF_INET_PRE_ROUTING;
0623         break;
0624     default:
0625         return -EOPNOTSUPP;
0626     }
0627 
0628     return nft_chain_validate_hooks(ctx->chain, hooks);
0629 }
0630 EXPORT_SYMBOL_GPL(nft_meta_set_validate);
0631 
0632 int nft_meta_set_init(const struct nft_ctx *ctx,
0633               const struct nft_expr *expr,
0634               const struct nlattr * const tb[])
0635 {
0636     struct nft_meta *priv = nft_expr_priv(expr);
0637     unsigned int len;
0638     int err;
0639 
0640     priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
0641     switch (priv->key) {
0642     case NFT_META_MARK:
0643     case NFT_META_PRIORITY:
0644 #ifdef CONFIG_NETWORK_SECMARK
0645     case NFT_META_SECMARK:
0646 #endif
0647         len = sizeof(u32);
0648         break;
0649     case NFT_META_NFTRACE:
0650         len = sizeof(u8);
0651         break;
0652     case NFT_META_PKTTYPE:
0653         len = sizeof(u8);
0654         break;
0655     default:
0656         return -EOPNOTSUPP;
0657     }
0658 
0659     priv->len = len;
0660     err = nft_parse_register_load(tb[NFTA_META_SREG], &priv->sreg, len);
0661     if (err < 0)
0662         return err;
0663 
0664     if (priv->key == NFT_META_NFTRACE)
0665         static_branch_inc(&nft_trace_enabled);
0666 
0667     return 0;
0668 }
0669 EXPORT_SYMBOL_GPL(nft_meta_set_init);
0670 
0671 int nft_meta_get_dump(struct sk_buff *skb,
0672               const struct nft_expr *expr)
0673 {
0674     const struct nft_meta *priv = nft_expr_priv(expr);
0675 
0676     if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key)))
0677         goto nla_put_failure;
0678     if (nft_dump_register(skb, NFTA_META_DREG, priv->dreg))
0679         goto nla_put_failure;
0680     return 0;
0681 
0682 nla_put_failure:
0683     return -1;
0684 }
0685 EXPORT_SYMBOL_GPL(nft_meta_get_dump);
0686 
0687 int nft_meta_set_dump(struct sk_buff *skb, const struct nft_expr *expr)
0688 {
0689     const struct nft_meta *priv = nft_expr_priv(expr);
0690 
0691     if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key)))
0692         goto nla_put_failure;
0693     if (nft_dump_register(skb, NFTA_META_SREG, priv->sreg))
0694         goto nla_put_failure;
0695 
0696     return 0;
0697 
0698 nla_put_failure:
0699     return -1;
0700 }
0701 EXPORT_SYMBOL_GPL(nft_meta_set_dump);
0702 
0703 void nft_meta_set_destroy(const struct nft_ctx *ctx,
0704               const struct nft_expr *expr)
0705 {
0706     const struct nft_meta *priv = nft_expr_priv(expr);
0707 
0708     if (priv->key == NFT_META_NFTRACE)
0709         static_branch_dec(&nft_trace_enabled);
0710 }
0711 EXPORT_SYMBOL_GPL(nft_meta_set_destroy);
0712 
0713 static int nft_meta_get_offload(struct nft_offload_ctx *ctx,
0714                 struct nft_flow_rule *flow,
0715                 const struct nft_expr *expr)
0716 {
0717     const struct nft_meta *priv = nft_expr_priv(expr);
0718     struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
0719 
0720     switch (priv->key) {
0721     case NFT_META_PROTOCOL:
0722         NFT_OFFLOAD_MATCH_EXACT(FLOW_DISSECTOR_KEY_BASIC, basic, n_proto,
0723                     sizeof(__u16), reg);
0724         nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_NETWORK);
0725         break;
0726     case NFT_META_L4PROTO:
0727         NFT_OFFLOAD_MATCH_EXACT(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
0728                     sizeof(__u8), reg);
0729         nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
0730         break;
0731     case NFT_META_IIF:
0732         NFT_OFFLOAD_MATCH_EXACT(FLOW_DISSECTOR_KEY_META, meta,
0733                     ingress_ifindex, sizeof(__u32), reg);
0734         break;
0735     case NFT_META_IIFTYPE:
0736         NFT_OFFLOAD_MATCH_EXACT(FLOW_DISSECTOR_KEY_META, meta,
0737                     ingress_iftype, sizeof(__u16), reg);
0738         break;
0739     default:
0740         return -EOPNOTSUPP;
0741     }
0742 
0743     return 0;
0744 }
0745 
0746 bool nft_meta_get_reduce(struct nft_regs_track *track,
0747              const struct nft_expr *expr)
0748 {
0749     const struct nft_meta *priv = nft_expr_priv(expr);
0750     const struct nft_meta *meta;
0751 
0752     if (!nft_reg_track_cmp(track, expr, priv->dreg)) {
0753         nft_reg_track_update(track, expr, priv->dreg, priv->len);
0754         return false;
0755     }
0756 
0757     meta = nft_expr_priv(track->regs[priv->dreg].selector);
0758     if (priv->key != meta->key ||
0759         priv->dreg != meta->dreg) {
0760         nft_reg_track_update(track, expr, priv->dreg, priv->len);
0761         return false;
0762     }
0763 
0764     if (!track->regs[priv->dreg].bitwise)
0765         return true;
0766 
0767     return nft_expr_reduce_bitwise(track, expr);
0768 }
0769 EXPORT_SYMBOL_GPL(nft_meta_get_reduce);
0770 
0771 static const struct nft_expr_ops nft_meta_get_ops = {
0772     .type       = &nft_meta_type,
0773     .size       = NFT_EXPR_SIZE(sizeof(struct nft_meta)),
0774     .eval       = nft_meta_get_eval,
0775     .init       = nft_meta_get_init,
0776     .dump       = nft_meta_get_dump,
0777     .reduce     = nft_meta_get_reduce,
0778     .validate   = nft_meta_get_validate,
0779     .offload    = nft_meta_get_offload,
0780 };
0781 
0782 static bool nft_meta_set_reduce(struct nft_regs_track *track,
0783                 const struct nft_expr *expr)
0784 {
0785     int i;
0786 
0787     for (i = 0; i < NFT_REG32_NUM; i++) {
0788         if (!track->regs[i].selector)
0789             continue;
0790 
0791         if (track->regs[i].selector->ops != &nft_meta_get_ops)
0792             continue;
0793 
0794         __nft_reg_track_cancel(track, i);
0795     }
0796 
0797     return false;
0798 }
0799 
0800 static const struct nft_expr_ops nft_meta_set_ops = {
0801     .type       = &nft_meta_type,
0802     .size       = NFT_EXPR_SIZE(sizeof(struct nft_meta)),
0803     .eval       = nft_meta_set_eval,
0804     .init       = nft_meta_set_init,
0805     .destroy    = nft_meta_set_destroy,
0806     .dump       = nft_meta_set_dump,
0807     .reduce     = nft_meta_set_reduce,
0808     .validate   = nft_meta_set_validate,
0809 };
0810 
0811 static const struct nft_expr_ops *
0812 nft_meta_select_ops(const struct nft_ctx *ctx,
0813             const struct nlattr * const tb[])
0814 {
0815     if (tb[NFTA_META_KEY] == NULL)
0816         return ERR_PTR(-EINVAL);
0817 
0818     if (tb[NFTA_META_DREG] && tb[NFTA_META_SREG])
0819         return ERR_PTR(-EINVAL);
0820 
0821 #if IS_ENABLED(CONFIG_NF_TABLES_BRIDGE) && IS_MODULE(CONFIG_NFT_BRIDGE_META)
0822     if (ctx->family == NFPROTO_BRIDGE)
0823         return ERR_PTR(-EAGAIN);
0824 #endif
0825     if (tb[NFTA_META_DREG])
0826         return &nft_meta_get_ops;
0827 
0828     if (tb[NFTA_META_SREG])
0829         return &nft_meta_set_ops;
0830 
0831     return ERR_PTR(-EINVAL);
0832 }
0833 
0834 struct nft_expr_type nft_meta_type __read_mostly = {
0835     .name       = "meta",
0836     .select_ops = nft_meta_select_ops,
0837     .policy     = nft_meta_policy,
0838     .maxattr    = NFTA_META_MAX,
0839     .owner      = THIS_MODULE,
0840 };
0841 
0842 #ifdef CONFIG_NETWORK_SECMARK
0843 struct nft_secmark {
0844     u32 secid;
0845     char *ctx;
0846 };
0847 
0848 static const struct nla_policy nft_secmark_policy[NFTA_SECMARK_MAX + 1] = {
0849     [NFTA_SECMARK_CTX]     = { .type = NLA_STRING, .len = NFT_SECMARK_CTX_MAXLEN },
0850 };
0851 
0852 static int nft_secmark_compute_secid(struct nft_secmark *priv)
0853 {
0854     u32 tmp_secid = 0;
0855     int err;
0856 
0857     err = security_secctx_to_secid(priv->ctx, strlen(priv->ctx), &tmp_secid);
0858     if (err)
0859         return err;
0860 
0861     if (!tmp_secid)
0862         return -ENOENT;
0863 
0864     err = security_secmark_relabel_packet(tmp_secid);
0865     if (err)
0866         return err;
0867 
0868     priv->secid = tmp_secid;
0869     return 0;
0870 }
0871 
0872 static void nft_secmark_obj_eval(struct nft_object *obj, struct nft_regs *regs,
0873                  const struct nft_pktinfo *pkt)
0874 {
0875     const struct nft_secmark *priv = nft_obj_data(obj);
0876     struct sk_buff *skb = pkt->skb;
0877 
0878     skb->secmark = priv->secid;
0879 }
0880 
0881 static int nft_secmark_obj_init(const struct nft_ctx *ctx,
0882                 const struct nlattr * const tb[],
0883                 struct nft_object *obj)
0884 {
0885     struct nft_secmark *priv = nft_obj_data(obj);
0886     int err;
0887 
0888     if (tb[NFTA_SECMARK_CTX] == NULL)
0889         return -EINVAL;
0890 
0891     priv->ctx = nla_strdup(tb[NFTA_SECMARK_CTX], GFP_KERNEL);
0892     if (!priv->ctx)
0893         return -ENOMEM;
0894 
0895     err = nft_secmark_compute_secid(priv);
0896     if (err) {
0897         kfree(priv->ctx);
0898         return err;
0899     }
0900 
0901     security_secmark_refcount_inc();
0902 
0903     return 0;
0904 }
0905 
0906 static int nft_secmark_obj_dump(struct sk_buff *skb, struct nft_object *obj,
0907                 bool reset)
0908 {
0909     struct nft_secmark *priv = nft_obj_data(obj);
0910     int err;
0911 
0912     if (nla_put_string(skb, NFTA_SECMARK_CTX, priv->ctx))
0913         return -1;
0914 
0915     if (reset) {
0916         err = nft_secmark_compute_secid(priv);
0917         if (err)
0918             return err;
0919     }
0920 
0921     return 0;
0922 }
0923 
0924 static void nft_secmark_obj_destroy(const struct nft_ctx *ctx, struct nft_object *obj)
0925 {
0926     struct nft_secmark *priv = nft_obj_data(obj);
0927 
0928     security_secmark_refcount_dec();
0929 
0930     kfree(priv->ctx);
0931 }
0932 
0933 static const struct nft_object_ops nft_secmark_obj_ops = {
0934     .type       = &nft_secmark_obj_type,
0935     .size       = sizeof(struct nft_secmark),
0936     .init       = nft_secmark_obj_init,
0937     .eval       = nft_secmark_obj_eval,
0938     .dump       = nft_secmark_obj_dump,
0939     .destroy    = nft_secmark_obj_destroy,
0940 };
0941 struct nft_object_type nft_secmark_obj_type __read_mostly = {
0942     .type       = NFT_OBJECT_SECMARK,
0943     .ops        = &nft_secmark_obj_ops,
0944     .maxattr    = NFTA_SECMARK_MAX,
0945     .policy     = nft_secmark_policy,
0946     .owner      = THIS_MODULE,
0947 };
0948 #endif /* CONFIG_NETWORK_SECMARK */