Linux Audio

Check our new training course

Linux kernel drivers training

Mar 31-Apr 9, 2025, special US time zones
Register
Loading...
Note: File does not exist in v3.1.
  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
 21MODULE_LICENSE("GPL");
 22MODULE_AUTHOR("Daniel Borkmann <dborkman@redhat.com>");
 23MODULE_DESCRIPTION("Xtables: process control group matching");
 24MODULE_ALIAS("ipt_cgroup");
 25MODULE_ALIAS("ip6t_cgroup");
 26
 27static 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
 37static 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
 68static bool
 69cgroup_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
 80static 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
 97static 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
105static 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		.destroy	= cgroup_mt_destroy_v1,
126		.me		= THIS_MODULE,
127		.hooks		= (1 << NF_INET_LOCAL_OUT) |
128				  (1 << NF_INET_POST_ROUTING) |
129				  (1 << NF_INET_LOCAL_IN),
130	},
131};
132
133static int __init cgroup_mt_init(void)
134{
135	return xt_register_matches(cgroup_mt_reg, ARRAY_SIZE(cgroup_mt_reg));
136}
137
138static void __exit cgroup_mt_exit(void)
139{
140	xt_unregister_matches(cgroup_mt_reg, ARRAY_SIZE(cgroup_mt_reg));
141}
142
143module_init(cgroup_mt_init);
144module_exit(cgroup_mt_exit);