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