1 /* 2 * Xtables module to match the process control group. 3 * 4 * Might be used to implement individual "per-application" firewall 5 * policies in contrast to global policies based on control groups. 6 * Matching is based upon processes tagged to net_cls' classid marker. 7 * 8 * (C) 2013 Daniel Borkmann <dborkman@redhat.com> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 */ 14 15 #include <linux/skbuff.h> 16 #include <linux/module.h> 17 #include <linux/netfilter/x_tables.h> 18 #include <linux/netfilter/xt_cgroup.h> 19 #include <net/sock.h> 20 21 MODULE_LICENSE("GPL"); 22 MODULE_AUTHOR("Daniel Borkmann <dborkman@redhat.com>"); 23 MODULE_DESCRIPTION("Xtables: process control group matching"); 24 MODULE_ALIAS("ipt_cgroup"); 25 MODULE_ALIAS("ip6t_cgroup"); 26 27 static int cgroup_mt_check_v0(const struct xt_mtchk_param *par) 28 { 29 struct xt_cgroup_info_v0 *info = par->matchinfo; 30 31 if (info->invert & ~1) 32 return -EINVAL; 33 34 return 0; 35 } 36 37 static int cgroup_mt_check_v1(const struct xt_mtchk_param *par) 38 { 39 struct xt_cgroup_info_v1 *info = par->matchinfo; 40 struct cgroup *cgrp; 41 42 if ((info->invert_path & ~1) || (info->invert_classid & ~1)) 43 return -EINVAL; 44 45 if (!info->has_path && !info->has_classid) { 46 pr_info("xt_cgroup: no path or classid specified\n"); 47 return -EINVAL; 48 } 49 50 if (info->has_path && info->has_classid) { 51 pr_info("xt_cgroup: both path and classid specified\n"); 52 return -EINVAL; 53 } 54 55 if (info->has_path) { 56 cgrp = cgroup_get_from_path(info->path); 57 if (IS_ERR(cgrp)) { 58 pr_info("xt_cgroup: 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 bool 69 cgroup_mt_v0(const struct sk_buff *skb, struct xt_action_param *par) 70 { 71 const struct xt_cgroup_info_v0 *info = par->matchinfo; 72 73 if (skb->sk == NULL || !sk_fullsock(skb->sk)) 74 return false; 75 76 return (info->id == sock_cgroup_classid(&skb->sk->sk_cgrp_data)) ^ 77 info->invert; 78 } 79 80 static bool cgroup_mt_v1(const struct sk_buff *skb, struct xt_action_param *par) 81 { 82 const struct xt_cgroup_info_v1 *info = par->matchinfo; 83 struct sock_cgroup_data *skcd = &skb->sk->sk_cgrp_data; 84 struct cgroup *ancestor = info->priv; 85 86 if (!skb->sk || !sk_fullsock(skb->sk)) 87 return false; 88 89 if (ancestor) 90 return cgroup_is_descendant(sock_cgroup_ptr(skcd), ancestor) ^ 91 info->invert_path; 92 else 93 return (info->classid == sock_cgroup_classid(skcd)) ^ 94 info->invert_classid; 95 } 96 97 static void cgroup_mt_destroy_v1(const struct xt_mtdtor_param *par) 98 { 99 struct xt_cgroup_info_v1 *info = par->matchinfo; 100 101 if (info->priv) 102 cgroup_put(info->priv); 103 } 104 105 static struct xt_match cgroup_mt_reg[] __read_mostly = { 106 { 107 .name = "cgroup", 108 .revision = 0, 109 .family = NFPROTO_UNSPEC, 110 .checkentry = cgroup_mt_check_v0, 111 .match = cgroup_mt_v0, 112 .matchsize = sizeof(struct xt_cgroup_info_v0), 113 .me = THIS_MODULE, 114 .hooks = (1 << NF_INET_LOCAL_OUT) | 115 (1 << NF_INET_POST_ROUTING) | 116 (1 << NF_INET_LOCAL_IN), 117 }, 118 { 119 .name = "cgroup", 120 .revision = 1, 121 .family = NFPROTO_UNSPEC, 122 .checkentry = cgroup_mt_check_v1, 123 .match = cgroup_mt_v1, 124 .matchsize = sizeof(struct xt_cgroup_info_v1), 125 .usersize = offsetof(struct xt_cgroup_info_v1, priv), 126 .destroy = cgroup_mt_destroy_v1, 127 .me = THIS_MODULE, 128 .hooks = (1 << NF_INET_LOCAL_OUT) | 129 (1 << NF_INET_POST_ROUTING) | 130 (1 << NF_INET_LOCAL_IN), 131 }, 132 }; 133 134 static int __init cgroup_mt_init(void) 135 { 136 return xt_register_matches(cgroup_mt_reg, ARRAY_SIZE(cgroup_mt_reg)); 137 } 138 139 static void __exit cgroup_mt_exit(void) 140 { 141 xt_unregister_matches(cgroup_mt_reg, ARRAY_SIZE(cgroup_mt_reg)); 142 } 143 144 module_init(cgroup_mt_init); 145 module_exit(cgroup_mt_exit); 146
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.