root/net/netfilter/xt_cgroup.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cgroup_mt_check_v0
  2. cgroup_mt_check_v1
  3. cgroup_mt_check_v2
  4. cgroup_mt_v0
  5. cgroup_mt_v1
  6. cgroup_mt_v2
  7. cgroup_mt_destroy_v1
  8. cgroup_mt_destroy_v2
  9. cgroup_mt_init
  10. cgroup_mt_exit

   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);

/* [<][>][^][v][top][bottom][index][help] */