cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

nft_meta.c (21120B)


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