projects/linux·blob master · refs

1025 lines · 22.7 KiB

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