Commit | Line | Data |
---|---|---|
d2912cb1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
100468e9 JM |
2 | /* |
3 | * This module is used to copy security markings from packets | |
4 | * to connections, and restore security markings from connections | |
5 | * back to packets. This would normally be performed in conjunction | |
6 | * with the SECMARK target and state match. | |
7 | * | |
8 | * Based somewhat on CONNMARK: | |
9 | * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com> | |
10 | * by Henrik Nordstrom <hno@marasystems.com> | |
11 | * | |
560ee653 | 12 | * (C) 2006,2008 Red Hat, Inc., James Morris <jmorris@redhat.com> |
100468e9 | 13 | */ |
8bee4bad | 14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
100468e9 JM |
15 | #include <linux/module.h> |
16 | #include <linux/skbuff.h> | |
17 | #include <linux/netfilter/x_tables.h> | |
18 | #include <linux/netfilter/xt_CONNSECMARK.h> | |
587aa641 | 19 | #include <net/netfilter/nf_conntrack.h> |
37fccd85 | 20 | #include <net/netfilter/nf_conntrack_ecache.h> |
100468e9 | 21 | |
100468e9 JM |
22 | MODULE_LICENSE("GPL"); |
23 | MODULE_AUTHOR("James Morris <jmorris@redhat.com>"); | |
2ae15b64 | 24 | MODULE_DESCRIPTION("Xtables: target for copying between connection and security mark"); |
100468e9 JM |
25 | MODULE_ALIAS("ipt_CONNSECMARK"); |
26 | MODULE_ALIAS("ip6t_CONNSECMARK"); | |
27 | ||
28 | /* | |
29 | * If the packet has a security mark and the connection does not, copy | |
30 | * the security mark from the packet to the connection. | |
31 | */ | |
a47362a2 | 32 | static void secmark_save(const struct sk_buff *skb) |
100468e9 JM |
33 | { |
34 | if (skb->secmark) { | |
587aa641 | 35 | struct nf_conn *ct; |
100468e9 JM |
36 | enum ip_conntrack_info ctinfo; |
37 | ||
587aa641 | 38 | ct = nf_ct_get(skb, &ctinfo); |
37fccd85 | 39 | if (ct && !ct->secmark) { |
587aa641 | 40 | ct->secmark = skb->secmark; |
a71996fc | 41 | nf_conntrack_event_cache(IPCT_SECMARK, ct); |
37fccd85 | 42 | } |
100468e9 JM |
43 | } |
44 | } | |
45 | ||
46 | /* | |
47 | * If packet has no security mark, and the connection does, restore the | |
48 | * security mark from the connection to the packet. | |
49 | */ | |
50 | static void secmark_restore(struct sk_buff *skb) | |
51 | { | |
52 | if (!skb->secmark) { | |
3cf93c96 | 53 | const struct nf_conn *ct; |
100468e9 JM |
54 | enum ip_conntrack_info ctinfo; |
55 | ||
587aa641 PM |
56 | ct = nf_ct_get(skb, &ctinfo); |
57 | if (ct && ct->secmark) | |
58 | skb->secmark = ct->secmark; | |
100468e9 JM |
59 | } |
60 | } | |
61 | ||
d3c5ee6d | 62 | static unsigned int |
4b560b44 | 63 | connsecmark_tg(struct sk_buff *skb, const struct xt_action_param *par) |
100468e9 | 64 | { |
7eb35586 | 65 | const struct xt_connsecmark_target_info *info = par->targinfo; |
100468e9 JM |
66 | |
67 | switch (info->mode) { | |
68 | case CONNSECMARK_SAVE: | |
69 | secmark_save(skb); | |
70 | break; | |
71 | ||
72 | case CONNSECMARK_RESTORE: | |
73 | secmark_restore(skb); | |
74 | break; | |
75 | ||
76 | default: | |
77 | BUG(); | |
78 | } | |
79 | ||
80 | return XT_CONTINUE; | |
81 | } | |
82 | ||
135367b8 | 83 | static int connsecmark_tg_check(const struct xt_tgchk_param *par) |
100468e9 | 84 | { |
af5d6dc2 | 85 | const struct xt_connsecmark_target_info *info = par->targinfo; |
4a5a5c73 | 86 | int ret; |
100468e9 | 87 | |
af5d6dc2 JE |
88 | if (strcmp(par->table, "mangle") != 0 && |
89 | strcmp(par->table, "security") != 0) { | |
cc48baef FW |
90 | pr_info_ratelimited("only valid in \'mangle\' or \'security\' table, not \'%s\'\n", |
91 | par->table); | |
d6b00a53 | 92 | return -EINVAL; |
560ee653 JM |
93 | } |
94 | ||
100468e9 JM |
95 | switch (info->mode) { |
96 | case CONNSECMARK_SAVE: | |
97 | case CONNSECMARK_RESTORE: | |
98 | break; | |
99 | ||
100 | default: | |
b2606644 | 101 | pr_info_ratelimited("invalid mode: %hu\n", info->mode); |
4a5a5c73 | 102 | return -EINVAL; |
100468e9 JM |
103 | } |
104 | ||
ecb2421b | 105 | ret = nf_ct_netns_get(par->net, par->family); |
f95c74e3 | 106 | if (ret < 0) |
b2606644 FW |
107 | pr_info_ratelimited("cannot load conntrack support for proto=%u\n", |
108 | par->family); | |
f95c74e3 | 109 | return ret; |
100468e9 JM |
110 | } |
111 | ||
a2df1648 | 112 | static void connsecmark_tg_destroy(const struct xt_tgdtor_param *par) |
11078c37 | 113 | { |
ecb2421b | 114 | nf_ct_netns_put(par->net, par->family); |
11078c37 YK |
115 | } |
116 | ||
92f3b2b1 JE |
117 | static struct xt_target connsecmark_tg_reg __read_mostly = { |
118 | .name = "CONNSECMARK", | |
119 | .revision = 0, | |
120 | .family = NFPROTO_UNSPEC, | |
121 | .checkentry = connsecmark_tg_check, | |
122 | .destroy = connsecmark_tg_destroy, | |
123 | .target = connsecmark_tg, | |
124 | .targetsize = sizeof(struct xt_connsecmark_target_info), | |
125 | .me = THIS_MODULE, | |
100468e9 JM |
126 | }; |
127 | ||
d3c5ee6d | 128 | static int __init connsecmark_tg_init(void) |
100468e9 | 129 | { |
92f3b2b1 | 130 | return xt_register_target(&connsecmark_tg_reg); |
100468e9 JM |
131 | } |
132 | ||
d3c5ee6d | 133 | static void __exit connsecmark_tg_exit(void) |
100468e9 | 134 | { |
92f3b2b1 | 135 | xt_unregister_target(&connsecmark_tg_reg); |
100468e9 JM |
136 | } |
137 | ||
d3c5ee6d JE |
138 | module_init(connsecmark_tg_init); |
139 | module_exit(connsecmark_tg_exit); |