PageRenderTime 51ms CodeModel.GetById 18ms app.highlight 25ms RepoModel.GetById 1ms app.codeStats 0ms

/net/ipv4/netfilter/ipt_owner.c

https://bitbucket.org/abioy/linux
C | 204 lines | 173 code | 26 blank | 5 comment | 33 complexity | b41117c322034207a4f51ccc0678d1de MD5 | raw file
Possible License(s): CC-BY-SA-3.0, GPL-2.0, LGPL-2.0, AGPL-1.0
  1/* Kernel module to match various things tied to sockets associated with
  2   locally generated outgoing packets.
  3
  4   Copyright (C) 2000 Marc Boucher
  5 */
  6#include <linux/module.h>
  7#include <linux/skbuff.h>
  8#include <linux/file.h>
  9#include <net/sock.h>
 10
 11#include <linux/netfilter_ipv4/ipt_owner.h>
 12#include <linux/netfilter_ipv4/ip_tables.h>
 13
 14MODULE_LICENSE("GPL");
 15MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
 16MODULE_DESCRIPTION("iptables owner match");
 17
 18static int
 19match_comm(const struct sk_buff *skb, const char *comm)
 20{
 21	struct task_struct *g, *p;
 22	struct files_struct *files;
 23	int i;
 24
 25	read_lock(&tasklist_lock);
 26	do_each_thread(g, p) {
 27		if(strncmp(p->comm, comm, sizeof(p->comm)))
 28			continue;
 29
 30		task_lock(p);
 31		files = p->files;
 32		if(files) {
 33			spin_lock(&files->file_lock);
 34			for (i=0; i < files->max_fds; i++) {
 35				if (fcheck_files(files, i) ==
 36				    skb->sk->sk_socket->file) {
 37					spin_unlock(&files->file_lock);
 38					task_unlock(p);
 39					read_unlock(&tasklist_lock);
 40					return 1;
 41				}
 42			}
 43			spin_unlock(&files->file_lock);
 44		}
 45		task_unlock(p);
 46	} while_each_thread(g, p);
 47	read_unlock(&tasklist_lock);
 48	return 0;
 49}
 50
 51static int
 52match_pid(const struct sk_buff *skb, pid_t pid)
 53{
 54	struct task_struct *p;
 55	struct files_struct *files;
 56	int i;
 57
 58	read_lock(&tasklist_lock);
 59	p = find_task_by_pid(pid);
 60	if (!p)
 61		goto out;
 62	task_lock(p);
 63	files = p->files;
 64	if(files) {
 65		spin_lock(&files->file_lock);
 66		for (i=0; i < files->max_fds; i++) {
 67			if (fcheck_files(files, i) ==
 68			    skb->sk->sk_socket->file) {
 69				spin_unlock(&files->file_lock);
 70				task_unlock(p);
 71				read_unlock(&tasklist_lock);
 72				return 1;
 73			}
 74		}
 75		spin_unlock(&files->file_lock);
 76	}
 77	task_unlock(p);
 78out:
 79	read_unlock(&tasklist_lock);
 80	return 0;
 81}
 82
 83static int
 84match_sid(const struct sk_buff *skb, pid_t sid)
 85{
 86	struct task_struct *g, *p;
 87	struct file *file = skb->sk->sk_socket->file;
 88	int i, found=0;
 89
 90	read_lock(&tasklist_lock);
 91	do_each_thread(g, p) {
 92		struct files_struct *files;
 93		if (p->session != sid)
 94			continue;
 95
 96		task_lock(p);
 97		files = p->files;
 98		if (files) {
 99			spin_lock(&files->file_lock);
100			for (i=0; i < files->max_fds; i++) {
101				if (fcheck_files(files, i) == file) {
102					found = 1;
103					break;
104				}
105			}
106			spin_unlock(&files->file_lock);
107		}
108		task_unlock(p);
109		if (found)
110			goto out;
111	} while_each_thread(g, p);
112out:
113	read_unlock(&tasklist_lock);
114
115	return found;
116}
117
118static int
119match(const struct sk_buff *skb,
120      const struct net_device *in,
121      const struct net_device *out,
122      const void *matchinfo,
123      int offset,
124      int *hotdrop)
125{
126	const struct ipt_owner_info *info = matchinfo;
127
128	if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
129		return 0;
130
131	if(info->match & IPT_OWNER_UID) {
132		if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
133		    !!(info->invert & IPT_OWNER_UID))
134			return 0;
135	}
136
137	if(info->match & IPT_OWNER_GID) {
138		if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
139		    !!(info->invert & IPT_OWNER_GID))
140			return 0;
141	}
142
143	if(info->match & IPT_OWNER_PID) {
144		if (!match_pid(skb, info->pid) ^
145		    !!(info->invert & IPT_OWNER_PID))
146			return 0;
147	}
148
149	if(info->match & IPT_OWNER_SID) {
150		if (!match_sid(skb, info->sid) ^
151		    !!(info->invert & IPT_OWNER_SID))
152			return 0;
153	}
154
155	if(info->match & IPT_OWNER_COMM) {
156		if (!match_comm(skb, info->comm) ^
157		    !!(info->invert & IPT_OWNER_COMM))
158			return 0;
159	}
160
161	return 1;
162}
163
164static int
165checkentry(const char *tablename,
166           const struct ipt_ip *ip,
167           void *matchinfo,
168           unsigned int matchsize,
169           unsigned int hook_mask)
170{
171        if (hook_mask
172            & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
173                printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
174                return 0;
175        }
176
177	if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) {
178		printk("Matchsize %u != %Zu\n", matchsize,
179		       IPT_ALIGN(sizeof(struct ipt_owner_info)));
180		return 0;
181	}
182
183	return 1;
184}
185
186static struct ipt_match owner_match = {
187	.name		= "owner",
188	.match		= &match,
189	.checkentry	= &checkentry,
190	.me		= THIS_MODULE,
191};
192
193static int __init init(void)
194{
195	return ipt_register_match(&owner_match);
196}
197
198static void __exit fini(void)
199{
200	ipt_unregister_match(&owner_match);
201}
202
203module_init(init);
204module_exit(fini);