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