~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/netfilter/xt_cgroup.c

Version: ~ [ linux-5.18 ] ~ [ linux-5.17.9 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.41 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.117 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.195 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.244 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.280 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.315 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.302 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * Xtables module to match the process control group.
  4  *
  5  * Might be used to implement individual "per-application" firewall
  6  * policies in contrast to global policies based on control groups.
  7  * Matching is based upon processes tagged to net_cls' classid marker.
  8  *
  9  * (C) 2013 Daniel Borkmann <dborkman@redhat.com>
 10  */
 11 
 12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 13 
 14 #include <linux/skbuff.h>
 15 #include <linux/module.h>
 16 #include <linux/netfilter/x_tables.h>
 17 #include <linux/netfilter/xt_cgroup.h>
 18 #include <net/sock.h>
 19 
 20 MODULE_LICENSE("GPL");
 21 MODULE_AUTHOR("Daniel Borkmann <dborkman@redhat.com>");
 22 MODULE_DESCRIPTION("Xtables: process control group matching");
 23 MODULE_ALIAS("ipt_cgroup");
 24 MODULE_ALIAS("ip6t_cgroup");
 25 
 26 static int cgroup_mt_check_v0(const struct xt_mtchk_param *par)
 27 {
 28         struct xt_cgroup_info_v0 *info = par->matchinfo;
 29 
 30         if (info->invert & ~1)
 31                 return -EINVAL;
 32 
 33         return 0;
 34 }
 35 
 36 static int cgroup_mt_check_v1(const struct xt_mtchk_param *par)
 37 {
 38         struct xt_cgroup_info_v1 *info = par->matchinfo;
 39         struct cgroup *cgrp;
 40 
 41         if ((info->invert_path & ~1) || (info->invert_classid & ~1))
 42                 return -EINVAL;
 43 
 44         if (!info->has_path && !info->has_classid) {
 45                 pr_info("xt_cgroup: no path or classid specified\n");
 46                 return -EINVAL;
 47         }
 48 
 49         if (info->has_path && info->has_classid) {
 50                 pr_info_ratelimited("path and classid specified\n");
 51                 return -EINVAL;
 52         }
 53 
 54         info->priv = NULL;
 55         if (info->has_path) {
 56                 cgrp = cgroup_get_from_path(info->path);
 57                 if (IS_ERR(cgrp)) {
 58                         pr_info_ratelimited("invalid path, errno=%ld\n",
 59                                             PTR_ERR(cgrp));
 60                         return -EINVAL;
 61                 }
 62                 info->priv = cgrp;
 63         }
 64 
 65         return 0;
 66 }
 67 
 68 static int cgroup_mt_check_v2(const struct xt_mtchk_param *par)
 69 {
 70         struct xt_cgroup_info_v2 *info = par->matchinfo;
 71         struct cgroup *cgrp;
 72 
 73         if ((info->invert_path & ~1) || (info->invert_classid & ~1))
 74                 return -EINVAL;
 75 
 76         if (!info->has_path && !info->has_classid) {
 77                 pr_info("xt_cgroup: no path or classid specified\n");
 78                 return -EINVAL;
 79         }
 80 
 81         if (info->has_path && info->has_classid) {
 82                 pr_info_ratelimited("path and classid specified\n");
 83                 return -EINVAL;
 84         }
 85 
 86         info->priv = NULL;
 87         if (info->has_path) {
 88                 cgrp = cgroup_get_from_path(info->path);
 89                 if (IS_ERR(cgrp)) {
 90                         pr_info_ratelimited("invalid path, errno=%ld\n",
 91                                             PTR_ERR(cgrp));
 92                         return -EINVAL;
 93                 }
 94                 info->priv = cgrp;
 95         }
 96 
 97         return 0;
 98 }
 99 
100 static bool
101 cgroup_mt_v0(const struct sk_buff *skb, struct xt_action_param *par)
102 {
103         const struct xt_cgroup_info_v0 *info = par->matchinfo;
104         struct sock *sk = skb->sk;
105 
106         if (!sk || !sk_fullsock(sk) || !net_eq(xt_net(par), sock_net(sk)))
107                 return false;
108 
109         return (info->id == sock_cgroup_classid(&skb->sk->sk_cgrp_data)) ^
110                 info->invert;
111 }
112 
113 static bool cgroup_mt_v1(const struct sk_buff *skb, struct xt_action_param *par)
114 {
115         const struct xt_cgroup_info_v1 *info = par->matchinfo;
116         struct sock_cgroup_data *skcd = &skb->sk->sk_cgrp_data;
117         struct cgroup *ancestor = info->priv;
118         struct sock *sk = skb->sk;
119 
120         if (!sk || !sk_fullsock(sk) || !net_eq(xt_net(par), sock_net(sk)))
121                 return false;
122 
123         if (ancestor)
124                 return cgroup_is_descendant(sock_cgroup_ptr(skcd), ancestor) ^
125                         info->invert_path;
126         else
127                 return (info->classid == sock_cgroup_classid(skcd)) ^
128                         info->invert_classid;
129 }
130 
131 static bool cgroup_mt_v2(const struct sk_buff *skb, struct xt_action_param *par)
132 {
133         const struct xt_cgroup_info_v2 *info = par->matchinfo;
134         struct sock_cgroup_data *skcd = &skb->sk->sk_cgrp_data;
135         struct cgroup *ancestor = info->priv;
136         struct sock *sk = skb->sk;
137 
138         if (!sk || !sk_fullsock(sk) || !net_eq(xt_net(par), sock_net(sk)))
139                 return false;
140 
141         if (ancestor)
142                 return cgroup_is_descendant(sock_cgroup_ptr(skcd), ancestor) ^
143                         info->invert_path;
144         else
145                 return (info->classid == sock_cgroup_classid(skcd)) ^
146                         info->invert_classid;
147 }
148 
149 static void cgroup_mt_destroy_v1(const struct xt_mtdtor_param *par)
150 {
151         struct xt_cgroup_info_v1 *info = par->matchinfo;
152 
153         if (info->priv)
154                 cgroup_put(info->priv);
155 }
156 
157 static void cgroup_mt_destroy_v2(const struct xt_mtdtor_param *par)
158 {
159         struct xt_cgroup_info_v2 *info = par->matchinfo;
160 
161         if (info->priv)
162                 cgroup_put(info->priv);
163 }
164 
165 static struct xt_match cgroup_mt_reg[] __read_mostly = {
166         {
167                 .name           = "cgroup",
168                 .revision       = 0,
169                 .family         = NFPROTO_UNSPEC,
170                 .checkentry     = cgroup_mt_check_v0,
171                 .match          = cgroup_mt_v0,
172                 .matchsize      = sizeof(struct xt_cgroup_info_v0),
173                 .me             = THIS_MODULE,
174                 .hooks          = (1 << NF_INET_LOCAL_OUT) |
175                                   (1 << NF_INET_POST_ROUTING) |
176                                   (1 << NF_INET_LOCAL_IN),
177         },
178         {
179                 .name           = "cgroup",
180                 .revision       = 1,
181                 .family         = NFPROTO_UNSPEC,
182                 .checkentry     = cgroup_mt_check_v1,
183                 .match          = cgroup_mt_v1,
184                 .matchsize      = sizeof(struct xt_cgroup_info_v1),
185                 .usersize       = offsetof(struct xt_cgroup_info_v1, priv),
186                 .destroy        = cgroup_mt_destroy_v1,
187                 .me             = THIS_MODULE,
188                 .hooks          = (1 << NF_INET_LOCAL_OUT) |
189                                   (1 << NF_INET_POST_ROUTING) |
190                                   (1 << NF_INET_LOCAL_IN),
191         },
192         {
193                 .name           = "cgroup",
194                 .revision       = 2,
195                 .family         = NFPROTO_UNSPEC,
196                 .checkentry     = cgroup_mt_check_v2,
197                 .match          = cgroup_mt_v2,
198                 .matchsize      = sizeof(struct xt_cgroup_info_v2),
199                 .usersize       = offsetof(struct xt_cgroup_info_v2, priv),
200                 .destroy        = cgroup_mt_destroy_v2,
201                 .me             = THIS_MODULE,
202                 .hooks          = (1 << NF_INET_LOCAL_OUT) |
203                                   (1 << NF_INET_POST_ROUTING) |
204                                   (1 << NF_INET_LOCAL_IN),
205         },
206 };
207 
208 static int __init cgroup_mt_init(void)
209 {
210         return xt_register_matches(cgroup_mt_reg, ARRAY_SIZE(cgroup_mt_reg));
211 }
212 
213 static void __exit cgroup_mt_exit(void)
214 {
215         xt_unregister_matches(cgroup_mt_reg, ARRAY_SIZE(cgroup_mt_reg));
216 }
217 
218 module_init(cgroup_mt_init);
219 module_exit(cgroup_mt_exit);
220 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp