public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2.6.15.4 1/1][RFC] ipt_owner: inode match supporting both incoming and outgoing packets
@ 2006-02-18 12:10 Török Edwin
  2006-02-18 12:25 ` Christoph Hellwig
  2006-02-20 16:26 ` James Morris
  0 siblings, 2 replies; 15+ messages in thread
From: Török Edwin @ 2006-02-18 12:10 UTC (permalink / raw)
  To: netfilter-devel, fireflier-devel; +Cc: linux-kernel, martinmaurer

[Please Cc: fireflier-devel@lists.sourceforge.net, Martin, and me on replys, 
thanks]
[Excuse me for cross-posting, but I think this rfc/patch concerns both the 
netfilter subsystem, and the kernel in general]

Hi,


This is a patch based on Luke Kenneth Casson Leighton's patch [1] 
One problem with that patch was that it couldn't be used for filtering 
incoming packets, due to the fact that more than one process can listen on 
the same socket ([2],[3]).
I am not familiar with kernel internals, so please correct me where I am 
wrong, and please point out any security holes,race conditions,coding style 
issues, etc.
Also please tell me if there are any (planned) internal kernel API changes 
that would need to change this patch to be changed for kernel 2.6.16.

First of all this is what I'd like to achieve:
- filter packets by the program who sent the packet
- filter packets by the program who is going to receive the packet
- when multiple programs share a socket (i.e. they listen on the same socket), 
allow the packet only if all programs are allowed to receive the packet

A program is identified by the mountpoint and the inode of the file.


Luke searched through all the files of all running threads to find out the 
process that sent the packet (which is pretty much the same what fireflier 
[4] does from userspace: searching /proc).
I tried using a different approach. The kernel has to know which processes 
listen on which sockets (and which processes send data on them), since it has 
to wake them up when a packet comes, right?

So I checked the wait_queue of a socket (sk_sleep, fasync_list) instead. This 
should contain all the programs that would be woken up by an incoming 
packets, so this should be a list of _all_ the programs that are able to read 
that packet. Is there a way for a program to read/send data on a socket 
without being on this list?

IMHO checking the wait_queue is the proper thing to do, because: 
- the performance doesn't depend on the number of threads running, it only 
depends on the number of processes sharing a socket
- it finds all programs that are going to read from the socket, even if it 
(the socket) is shared between multiple processes

Problems with the wait_queue:
- I based __authorize_programs on __wake_up, and __kill_fasync
      - it  duplicates code, and if something changes in those functions, that 
changes needs to be done here
      - in kernel 2.6.11 __wait_queue had a field named task, it has now been 
renamed to private. Does it mean that it shouldn't be accessed directly, but 
only through some functions? Which are those functions?
      - is there a better way to iterate through wait_queue_t? (without waking 
up the processes, I just need to know which those processes are)

Problems with the fasync_list:
- It only gives me the pid of the process (process group), so I need to lookup 
the task corresponding to the pid
- do I really need to check fasync_list too? If a process listens on a socket 
asynchronously, does it appear only in fasync_list, or does it appear in 
sk_sleep too?

Problems with proc_check_exe_fown:
- based on send_sigio
- I need to lock the task_list
	- task_list lock export might be gone some day?
	- is locking tasklist when inside a softirq allowed?
- I need to iterate through all the thread if I get a process group id, is 
there a better way?

Problems with proc_check_exe:
- kernel complains about proc_task_dentry_lookup might_sleep inside a softirq, 
how do I solve this?

Problems with proc_task_dentry_lookup:
- fs/proc/task_mmu.c,task_nommu.c, root.c had to be patched, so one has to 
recompile his kernel in order to make this inode-matching to work (I'd prefer 
if it could be loaded as a module, without recompiling the kernel)
- is there a function I missed that does what proc_task_dentry_lookup would 
do?
- where is the proper place to put this function?


I need this inode filtering done in-kernel, because:
- fireflier currently searches /proc for the first incoming/outgoing packet to 
find out which process sent it. Then it puts its pid in a cache
- when the next packet arrives it only checks if the process who's pid is in 
the cache still has the socket with the right inode, if yes the packet is 
allowed to pass
- if somebody floods with random destination ports, each packet triggers 
a /proc lookup -> slows down fireflier
- when multiple programs share a socket, fireflier only looks at the first
- if we were to find all the programs that share a socket from userspace, we 
would have to do so on every packet, since we can't know when a process 
decides to fork/share its socket

Please note that this patch is work in progress, it is not meant for immediate 
use. If you decide to experiment, you'll also need the iptables userspace 
patch [1]

[1] https://bugzilla.netfilter.org/bugzilla/show_bug.cgi?id=449
[2] http://www.uwsg.iu.edu/hypermail/linux/kernel/0409.1/0499.html
[3] http://www.ussg.iu.edu/hypermail/linux/kernel/0409.1/0068.html
[4] http://fireflier.sourceforge.net/

Thanks in advance,
Edwin
---
 fs/proc/root.c                           |    3
 fs/proc/task_mmu.c                       |    9 +
 fs/proc/task_nommu.c                     |    8 +
 include/linux/netfilter_ipv4/ipt_owner.h |    8 +
 net/ipv4/netfilter/ipt_owner.c           |  179 
++++++++++++++++++++++++++++++-
 5 files changed, 199 insertions(+), 8 deletions(-)
diff -uprN -X vanilla/linux-2.6.15.4/Documentation/dontdiff 
vanilla/linux-2.6.15.4/fs/proc/root.c linux-2.6.15.4/fs/proc/root.c
--- vanilla/linux-2.6.15.4/fs/proc/root.c	2006-02-10 09:22:48.000000000 +0200
+++ linux-2.6.15.4/fs/proc/root.c	2006-02-18 11:36:06.000000000 +0200
@@ -149,6 +149,8 @@ struct proc_dir_entry proc_root = {
 	.parent		= &proc_root,
 };
 
+extern int proc_task_dentry_lookup(struct task_struct *task, struct dentry 
**dentry, struct vfsmount **mnt);
+
 EXPORT_SYMBOL(proc_symlink);
 EXPORT_SYMBOL(proc_mkdir);
 EXPORT_SYMBOL(create_proc_entry);
@@ -159,3 +161,4 @@ EXPORT_SYMBOL(proc_net);
 EXPORT_SYMBOL(proc_net_stat);
 EXPORT_SYMBOL(proc_bus);
 EXPORT_SYMBOL(proc_root_driver);
+EXPORT_SYMBOL(proc_task_dentry_lookup);
diff -uprN -X vanilla/linux-2.6.15.4/Documentation/dontdiff 
vanilla/linux-2.6.15.4/fs/proc/task_mmu.c linux-2.6.15.4/fs/proc/task_mmu.c
--- vanilla/linux-2.6.15.4/fs/proc/task_mmu.c	2006-02-10 09:22:48.000000000 
+0200
+++ linux-2.6.15.4/fs/proc/task_mmu.c	2006-02-18 11:38:36.000000000 +0200
@@ -71,11 +71,11 @@ int task_statm(struct mm_struct *mm, int
 	return mm->total_vm;
 }
 
-int proc_exe_link(struct inode *inode, struct dentry **dentry, struct 
vfsmount **mnt)
+extern int proc_task_dentry_lookup(struct task_struct *task, struct dentry 
**dentry, struct vfsmount **mnt);
+int proc_task_dentry_lookup(struct task_struct *task, struct dentry **dentry, 
struct vfsmount **mnt)
 {
 	struct vm_area_struct * vma;
 	int result = -ENOENT;
-	struct task_struct *task = proc_task(inode);
 	struct mm_struct * mm = get_task_mm(task);
 
 	if (!mm)
@@ -101,6 +101,11 @@ out:
 	return result;
 }
 
+int proc_exe_link(struct inode *inode, struct dentry **dentry, struct 
vfsmount **mnt)
+{
+	return proc_task_dentry_lookup(proc_task(inode), dentry, mnt);
+}
+
 static void pad_len_spaces(struct seq_file *m, int len)
 {
 	len = 25 + sizeof(void*) * 6 - len;
diff -uprN -X vanilla/linux-2.6.15.4/Documentation/dontdiff 
vanilla/linux-2.6.15.4/fs/proc/task_nommu.c 
linux-2.6.15.4/fs/proc/task_nommu.c
--- vanilla/linux-2.6.15.4/fs/proc/task_nommu.c	2006-02-10 09:22:48.000000000 
+0200
+++ linux-2.6.15.4/fs/proc/task_nommu.c	2006-02-18 11:38:27.000000000 +0200
@@ -103,11 +103,11 @@ int task_statm(struct mm_struct *mm, int
 	return size;
 }
 
-int proc_exe_link(struct inode *inode, struct dentry **dentry, struct 
vfsmount **mnt)
+extern int proc_task_dentry_lookup(struct task_struct *task, struct dentry 
**dentry, struct vfsmount **mnt);
+int proc_task_dentry_lookup(struct task_struct *task, struct dentry **dentry, 
struct vfsmount **mnt)
 {
 	struct vm_list_struct *vml;
 	struct vm_area_struct *vma;
-	struct task_struct *task = proc_task(inode);
 	struct mm_struct *mm = get_task_mm(task);
 	int result = -ENOENT;
 
@@ -137,6 +137,10 @@ out:
 	return result;
 }
 
+int proc_exe_link(struct inode *inode, struct dentry **dentry, struct 
vfsmount **mnt)
+{
+	return proc_task_dentry_lookup(proc_task(inode), dentry, mnt);
+}
 /*
  * Albert D. Cahalan suggested to fake entries for the traditional
  * sections here.  This might be worth investigating.
diff -uprN -X vanilla/linux-2.6.15.4/Documentation/dontdiff 
vanilla/linux-2.6.15.4/include/linux/netfilter_ipv4/ipt_owner.h 
linux-2.6.15.4/include/linux/netfilter_ipv4/ipt_owner.h
--- vanilla/linux-2.6.15.4/include/linux/netfilter_ipv4/ipt_owner.h	2006-02-10 
09:22:48.000000000 +0200
+++ linux-2.6.15.4/include/linux/netfilter_ipv4/ipt_owner.h	2006-02-17 
21:39:41.000000000 +0200
@@ -7,6 +7,10 @@
 #define IPT_OWNER_PID	0x04
 #define IPT_OWNER_SID	0x08
 #define IPT_OWNER_COMM	0x10
+#define IPT_OWNER_INO   0x20
+#define IPT_OWNER_DEV   0x40
+
+#define IPT_DEVNAME_SZ  80
 
 struct ipt_owner_info {
     uid_t uid;
@@ -14,6 +18,10 @@ struct ipt_owner_info {
     pid_t pid;
     pid_t sid;
     char comm[16];
+    /* set these as a pair: specify the filesystem, specify the inode */
+    /* it's the only simple (and unambigous) way to reference a program */
+    char device[IPT_DEVNAME_SZ];
+    unsigned long ino;
     u_int8_t match, invert;	/* flags */
 };
 
diff -uprN -X vanilla/linux-2.6.15.4/Documentation/dontdiff 
vanilla/linux-2.6.15.4/net/ipv4/netfilter/ipt_owner.c 
linux-2.6.15.4/net/ipv4/netfilter/ipt_owner.c
--- vanilla/linux-2.6.15.4/net/ipv4/netfilter/ipt_owner.c	2006-02-10 
09:22:48.000000000 +0200
+++ linux-2.6.15.4/net/ipv4/netfilter/ipt_owner.c	2006-02-18 
11:48:44.000000000 +0200
@@ -1,7 +1,21 @@
 /* Kernel module to match various things tied to sockets associated with
-   locally generated outgoing packets. */
+ locally generated outgoing packets.
+ lkcl 2004sep9: match against filesystem on which program handling the
+                packet can be found (IPT_OWNER_DEV) and also the inode
+                on that filesystem of that same program.
+
+                why anyone would want to only check just the mountpoint
+				  i don't know (well, i do - e.g. /usr/local is a
+				  separate untrusted or even an nfs-mounted partition)
+				  but i had to include and check the mountpoint because
+				  otherwise the inode is meaningless.
+edwin 2006feb17: use the wait queue of the socket instead of walking through 
the tasklist
+                 this should allow ipt_owner to be used for incoming packets 
as well
+*/
 
 /* (C) 2000 Marc Boucher <marc@mbsi.ca>
+ * (C) 2004 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
+ * (C) 2006 Torok Edwin <edwin@gurde.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -17,10 +31,157 @@
 #include <linux/netfilter_ipv4/ipt_owner.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/dcache.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/rwsem.h>
+#include <linux/spinlock.h>
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
 MODULE_DESCRIPTION("iptables owner match");
 
+/* lkcl: this function is in fs/proc/base.c.  it's a generic function
+ * derived from proc_exe_link().  it's inappropriate to leave that
+ * function in fs/proc/base.c.  but i don't care: i don't have the
+ * knowledge to say where it should go.  therefore i'm leaving
+ * it in fs/proc/base.c.
+*/
+extern int proc_task_dentry_lookup(struct task_struct *task,
+		                           struct dentry **dentry,
+								   struct vfsmount **mnt);
+/*
+ * look up the dentry (for the inode) of the task's executable,
+ * plus lookup the mountpoint of the filesystem from where that
+ * executable came from.   then do exactly the same socket checking
+ * that all the other checks seem to be doing.
+ * returns 0 if program is authorized
+*/
+static int proc_exe_check(struct task_struct* task,u_int8_t match,
+			  const char *devname, unsigned long i_num)
+{
+	int result = -ENOENT;
+	struct vfsmount *mnt;
+	struct dentry *dentry;
+	printk(KERN_DEBUG "proc_exe_check:%s\n",task->comm);
+	result = proc_task_dentry_lookup(task, &dentry, &mnt);
+	if (result != 0) {
+		printk(KERN_DEBUG "proc_task_dentry_lookup error:%d\n",result);
+		return result;
+	}
+
+	if (!dentry->d_inode) {
+		printk(KERN_DEBUG "dentry inode not found\n");
+		return -ENOENT;
+	}
+
+	/* lkcl: i can't be bothered to make obtuse code out of some
+	 * boolean overkill logic cleverness.
+	 */
+	if (match & IPT_OWNER_INO && match & IPT_OWNER_DEV)
+		if (dentry->d_inode->i_ino == i_num &&
+		    strncmp(mnt->mnt_devname, devname, IPT_DEVNAME_SZ) == 0) {
+                        printk(KERN_DEBUG "if(1) return 0");
+			return 0;
+		}
+	if (match & IPT_OWNER_INO)
+		if (dentry->d_inode->i_ino == i_num) {
+                        printk(KERN_DEBUG "if(2) return 0");
+			return 0;
+		}
+	if (match & IPT_OWNER_DEV)
+		if (strncmp(mnt->mnt_devname, devname, IPT_DEVNAME_SZ) == 0) {
+                        printk(KERN_DEBUG "if(3) return 0");
+			return 0;
+		}
+	printk(KERN_DEBUG "proc_exe_check: ENOENT");
+	return -ENOENT;
+}
+
+//check that the process or process group is authorized (process in 
fasync_list)
+static int proc_exe_check_fown(struct fown_struct* fown,u_int8_t match,
+			       const char *devname, unsigned long i_num)
+{
+	//based on send_sigio
+	struct task_struct* task;
+	int pid;
+	int result=-ENOENT;
+
+	read_lock(&fown->lock);
+	pid=fown->pid;
+	if(!pid)
+		goto out_unlock_fown;
+	read_lock(&tasklist_lock);
+	if(pid>0)
+	{
+		task = find_task_by_pid(pid);
+		if(task)
+			if(proc_exe_check(task,match,devname,i_num))
+			{
+				result=-ENOENT;
+				goto out_unlock_tasklist;
+			}
+	} else
+	{
+		do_each_task_pid(~pid,PIDTYPE_PGID,task)
+		{
+			if(proc_exe_check(task,match,devname,i_num))
+			{
+				result=-ENOENT;
+				goto out_unlock_tasklist;
+			}
+		} while_each_task_pid(~pid,PIDTYPE_PGID,task);
+	}
+	result=0;
+	out_unlock_tasklist:
+		read_unlock(&tasklist_lock);
+	out_unlock_fown:
+		read_unlock(&fown->lock);
+        return result;
+}
+
+static int __authorize_programs(struct sock* sk, u_int8_t match,
+				const char* devname, unsigned long i_num)
+{
+	//walk through all tasks that would be awakened, based on __wake_up
+	wait_queue_head_t* q = sk->sk_sleep;
+	struct list_head* tmp,*next;
+        struct fasync_struct* fa;
+	list_for_each_safe(tmp, next, &q->task_list)
+	{
+		wait_queue_t *curr;
+		curr = list_entry(tmp, wait_queue_t, task_list);
+		if(proc_exe_check(curr->private,match,devname,i_num))
+			return 0;
+	}
+	//walk through fasync_list, based on __kill_fasync
+	fa = sk->sk_socket->fasync_list;
+	while (fa)
+	{
+		struct fown_struct * fown;
+		if (fa->magic != FASYNC_MAGIC)
+		{
+			printk(KERN_ERR "kill_fasync: bad magic number in "
+			       "fasync_struct!\n");
+			return 0;
+		}
+		fown = &fa->fa_file->f_owner;
+		if(proc_exe_check_fown(fown,match,devname,i_num))
+			return 0;
+		fa = fa->fa_next;
+	}
+	return 1;//authorized all programs
+}
+
+static int
+match_inode(const struct sk_buff* skb,u_int8_t match,const char* 
devname,unsigned long i_num)
+{
+	return __authorize_programs(skb->sk,match,devname,i_num);
+}
+
+
 static int
 match(const struct sk_buff *skb,
       const struct net_device *in,
@@ -46,6 +207,14 @@ match(const struct sk_buff *skb,
 			return 0;
 	}
 
+	if (info->match & IPT_OWNER_INO || info->match & IPT_OWNER_DEV)
+	{
+	    if(!match_inode(skb,info->match,info->device,info->ino)^
+	       !!(info->invert & IPT_OWNER_INO)) {
+		    return 0;
+	    }
+	}
+
 	return 1;
 }
 
@@ -75,7 +244,7 @@ checkentry(const char *tablename,
 		       "not supported anymore\n");
 		return 0;
 	}
-
+   
 	return 1;
 }
 
@@ -88,12 +257,14 @@ static struct ipt_match owner_match = {
 
 static int __init init(void)
 {
-	return ipt_register_match(&owner_match);
+    printk(KERN_DEBUG "ipt_owner (with enhanced inode rules) startup\n");
+    return ipt_register_match(&owner_match);
 }
 
 static void __exit fini(void)
 {
-	ipt_unregister_match(&owner_match);
+    printk(KERN_DEBUG "ipt_owner shutdown");
+    ipt_unregister_match(&owner_match);
 }
 
 module_init(init);

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 2.6.15.4 1/1][RFC] ipt_owner: inode match supporting both incoming and outgoing packets
@ 2006-02-18 12:20 Török Edwin
  2006-02-18 19:28 ` Patrick McHardy
  0 siblings, 1 reply; 15+ messages in thread
From: Török Edwin @ 2006-02-18 12:20 UTC (permalink / raw)
  To: netfilter-devel, fireflier-devel; +Cc: linux-kernel, martinmaurer

[Please Cc: fireflier-devel@lists.sourceforge.net, Martin, and me on replys, 
thanks]
[Excuse me for cross-posting, but I think this rfc/patch concerns both the 
netfilter subsystem, and the kernel in general]

Hi,


This is a patch based on Luke Kenneth Casson Leighton's patch [1] 
One problem with that patch was that it couldn't be used for filtering 
incoming packets, due to the fact that more than one process can listen on 
the same socket ([2],[3]).
I am not familiar with kernel internals, so please correct me where I am 
wrong, and please point out any security holes,race conditions,coding style 
issues, etc.
Also please tell me if there are any (planned) internal kernel API changes 
that would need to change this patch to be changed for kernel 2.6.16.

First of all this is what I'd like to achieve:
- filter packets by the program who sent the packet
- filter packets by the program who is going to receive the packet
- when multiple programs share a socket (i.e. they listen on the same socket), 
allow the packet only if all programs are allowed to receive the packet

A program is identified by the mountpoint and the inode of the file.


Luke searched through all the files of all running threads to find out the 
process that sent the packet (which is pretty much the same what fireflier 
[4] does from userspace: searching /proc).
I tried using a different approach. The kernel has to know which processes 
listen on which sockets (and which processes send data on them), since it has 
to wake them up when a packet comes, right?

So I checked the wait_queue of a socket (sk_sleep, fasync_list) instead. This 
should contain all the programs that would be woken up by an incoming 
packets, so this should be a list of _all_ the programs that are able to read 
that packet. Is there a way for a program to read/send data on a socket 
without being on this list?

IMHO checking the wait_queue is the proper thing to do, because: 
- the performance doesn't depend on the number of threads running, it only 
depends on the number of processes sharing a socket
- it finds all programs that are going to read from the socket, even if it 
(the socket) is shared between multiple processes

Problems with the wait_queue:
- I based __authorize_programs on __wake_up, and __kill_fasync
      - it  duplicates code, and if something changes in those functions, that 
changes needs to be done here
      - in kernel 2.6.11 __wait_queue had a field named task, it has now been 
renamed to private. Does it mean that it shouldn't be accessed directly, but 
only through some functions? Which are those functions?
      - is there a better way to iterate through wait_queue_t? (without waking 
up the processes, I just need to know which those processes are)

Problems with the fasync_list:
- It only gives me the pid of the process (process group), so I need to lookup 
the task corresponding to the pid
- do I really need to check fasync_list too? If a process listens on a socket 
asynchronously, does it appear only in fasync_list, or does it appear in 
sk_sleep too?

Problems with proc_check_exe_fown:
- based on send_sigio
- I need to lock the task_list
	- task_list lock export might be gone some day?
	- is locking tasklist when inside a softirq allowed?
- I need to iterate through all the thread if I get a process group id, is 
there a better way?

Problems with proc_check_exe:
- kernel complains about proc_task_dentry_lookup might_sleep inside a softirq, 
how do I solve this?

Problems with proc_task_dentry_lookup:
- fs/proc/task_mmu.c,task_nommu.c, root.c had to be patched, so one has to 
recompile his kernel in order to make this inode-matching to work (I'd prefer 
if it could be loaded as a module, without recompiling the kernel)
- is there a function I missed that does what proc_task_dentry_lookup would 
do?
- where is the proper place to put this function?


I need this inode filtering done in-kernel, because:
- fireflier currently searches /proc for the first incoming/outgoing packet to 
find out which process sent it. Then it puts its pid in a cache
- when the next packet arrives it only checks if the process who's pid is in 
the cache still has the socket with the right inode, if yes the packet is 
allowed to pass
- if somebody floods with random destination ports, each packet triggers 
a /proc lookup -> slows down fireflier
- when multiple programs share a socket, fireflier only looks at the first
- if we were to find all the programs that share a socket from userspace, we 
would have to do so on every packet, since we can't know when a process 
decides to fork/share its socket

Please note that this patch is work in progress, it is not meant for immediate 
use. If you decide to experiment, you'll also need the iptables userspace 
patch [1]

[1] https://bugzilla.netfilter.org/bugzilla/show_bug.cgi?id=449
[2] http://www.uwsg.iu.edu/hypermail/linux/kernel/0409.1/0499.html
[3] http://www.ussg.iu.edu/hypermail/linux/kernel/0409.1/0068.html
[4] http://fireflier.sourceforge.net/

Thanks in advance,
Edwin
---
 fs/proc/root.c                           |    3
 fs/proc/task_mmu.c                       |    9 +
 fs/proc/task_nommu.c                     |    8 +
 include/linux/netfilter_ipv4/ipt_owner.h |    8 +
 net/ipv4/netfilter/ipt_owner.c           |  179 
++++++++++++++++++++++++++++++-
 5 files changed, 199 insertions(+), 8 deletions(-)
diff -uprN -X vanilla/linux-2.6.15.4/Documentation/dontdiff 
vanilla/linux-2.6.15.4/fs/proc/root.c linux-2.6.15.4/fs/proc/root.c
--- vanilla/linux-2.6.15.4/fs/proc/root.c	2006-02-10 09:22:48.000000000 +0200
+++ linux-2.6.15.4/fs/proc/root.c	2006-02-18 11:36:06.000000000 +0200
@@ -149,6 +149,8 @@ struct proc_dir_entry proc_root = {
 	.parent		= &proc_root,
 };
 
+extern int proc_task_dentry_lookup(struct task_struct *task, struct dentry 
**dentry, struct vfsmount **mnt);
+
 EXPORT_SYMBOL(proc_symlink);
 EXPORT_SYMBOL(proc_mkdir);
 EXPORT_SYMBOL(create_proc_entry);
@@ -159,3 +161,4 @@ EXPORT_SYMBOL(proc_net);
 EXPORT_SYMBOL(proc_net_stat);
 EXPORT_SYMBOL(proc_bus);
 EXPORT_SYMBOL(proc_root_driver);
+EXPORT_SYMBOL(proc_task_dentry_lookup);
diff -uprN -X vanilla/linux-2.6.15.4/Documentation/dontdiff 
vanilla/linux-2.6.15.4/fs/proc/task_mmu.c linux-2.6.15.4/fs/proc/task_mmu.c
--- vanilla/linux-2.6.15.4/fs/proc/task_mmu.c	2006-02-10 09:22:48.000000000 
+0200
+++ linux-2.6.15.4/fs/proc/task_mmu.c	2006-02-18 11:38:36.000000000 +0200
@@ -71,11 +71,11 @@ int task_statm(struct mm_struct *mm, int
 	return mm->total_vm;
 }
 
-int proc_exe_link(struct inode *inode, struct dentry **dentry, struct 
vfsmount **mnt)
+extern int proc_task_dentry_lookup(struct task_struct *task, struct dentry 
**dentry, struct vfsmount **mnt);
+int proc_task_dentry_lookup(struct task_struct *task, struct dentry **dentry, 
struct vfsmount **mnt)
 {
 	struct vm_area_struct * vma;
 	int result = -ENOENT;
-	struct task_struct *task = proc_task(inode);
 	struct mm_struct * mm = get_task_mm(task);
 
 	if (!mm)
@@ -101,6 +101,11 @@ out:
 	return result;
 }
 
+int proc_exe_link(struct inode *inode, struct dentry **dentry, struct 
vfsmount **mnt)
+{
+	return proc_task_dentry_lookup(proc_task(inode), dentry, mnt);
+}
+
 static void pad_len_spaces(struct seq_file *m, int len)
 {
 	len = 25 + sizeof(void*) * 6 - len;
diff -uprN -X vanilla/linux-2.6.15.4/Documentation/dontdiff 
vanilla/linux-2.6.15.4/fs/proc/task_nommu.c 
linux-2.6.15.4/fs/proc/task_nommu.c
--- vanilla/linux-2.6.15.4/fs/proc/task_nommu.c	2006-02-10 09:22:48.000000000 
+0200
+++ linux-2.6.15.4/fs/proc/task_nommu.c	2006-02-18 11:38:27.000000000 +0200
@@ -103,11 +103,11 @@ int task_statm(struct mm_struct *mm, int
 	return size;
 }
 
-int proc_exe_link(struct inode *inode, struct dentry **dentry, struct 
vfsmount **mnt)
+extern int proc_task_dentry_lookup(struct task_struct *task, struct dentry 
**dentry, struct vfsmount **mnt);
+int proc_task_dentry_lookup(struct task_struct *task, struct dentry **dentry, 
struct vfsmount **mnt)
 {
 	struct vm_list_struct *vml;
 	struct vm_area_struct *vma;
-	struct task_struct *task = proc_task(inode);
 	struct mm_struct *mm = get_task_mm(task);
 	int result = -ENOENT;
 
@@ -137,6 +137,10 @@ out:
 	return result;
 }
 
+int proc_exe_link(struct inode *inode, struct dentry **dentry, struct 
vfsmount **mnt)
+{
+	return proc_task_dentry_lookup(proc_task(inode), dentry, mnt);
+}
 /*
  * Albert D. Cahalan suggested to fake entries for the traditional
  * sections here.  This might be worth investigating.
diff -uprN -X vanilla/linux-2.6.15.4/Documentation/dontdiff 
vanilla/linux-2.6.15.4/include/linux/netfilter_ipv4/ipt_owner.h 
linux-2.6.15.4/include/linux/netfilter_ipv4/ipt_owner.h
--- vanilla/linux-2.6.15.4/include/linux/netfilter_ipv4/ipt_owner.h	2006-02-10 
09:22:48.000000000 +0200
+++ linux-2.6.15.4/include/linux/netfilter_ipv4/ipt_owner.h	2006-02-17 
21:39:41.000000000 +0200
@@ -7,6 +7,10 @@
 #define IPT_OWNER_PID	0x04
 #define IPT_OWNER_SID	0x08
 #define IPT_OWNER_COMM	0x10
+#define IPT_OWNER_INO   0x20
+#define IPT_OWNER_DEV   0x40
+
+#define IPT_DEVNAME_SZ  80
 
 struct ipt_owner_info {
     uid_t uid;
@@ -14,6 +18,10 @@ struct ipt_owner_info {
     pid_t pid;
     pid_t sid;
     char comm[16];
+    /* set these as a pair: specify the filesystem, specify the inode */
+    /* it's the only simple (and unambigous) way to reference a program */
+    char device[IPT_DEVNAME_SZ];
+    unsigned long ino;
     u_int8_t match, invert;	/* flags */
 };
 
diff -uprN -X vanilla/linux-2.6.15.4/Documentation/dontdiff 
vanilla/linux-2.6.15.4/net/ipv4/netfilter/ipt_owner.c 
linux-2.6.15.4/net/ipv4/netfilter/ipt_owner.c
--- vanilla/linux-2.6.15.4/net/ipv4/netfilter/ipt_owner.c	2006-02-10 
09:22:48.000000000 +0200
+++ linux-2.6.15.4/net/ipv4/netfilter/ipt_owner.c	2006-02-18 
11:48:44.000000000 +0200
@@ -1,7 +1,21 @@
 /* Kernel module to match various things tied to sockets associated with
-   locally generated outgoing packets. */
+ locally generated outgoing packets.
+ lkcl 2004sep9: match against filesystem on which program handling the
+                packet can be found (IPT_OWNER_DEV) and also the inode
+                on that filesystem of that same program.
+
+                why anyone would want to only check just the mountpoint
+				  i don't know (well, i do - e.g. /usr/local is a
+				  separate untrusted or even an nfs-mounted partition)
+				  but i had to include and check the mountpoint because
+				  otherwise the inode is meaningless.
+edwin 2006feb17: use the wait queue of the socket instead of walking through 
the tasklist
+                 this should allow ipt_owner to be used for incoming packets 
as well
+*/
 
 /* (C) 2000 Marc Boucher <marc@mbsi.ca>
+ * (C) 2004 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
+ * (C) 2006 Torok Edwin <edwin@gurde.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -17,10 +31,157 @@
 #include <linux/netfilter_ipv4/ipt_owner.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/dcache.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/rwsem.h>
+#include <linux/spinlock.h>
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
 MODULE_DESCRIPTION("iptables owner match");
 
+/* lkcl: this function is in fs/proc/base.c.  it's a generic function
+ * derived from proc_exe_link().  it's inappropriate to leave that
+ * function in fs/proc/base.c.  but i don't care: i don't have the
+ * knowledge to say where it should go.  therefore i'm leaving
+ * it in fs/proc/base.c.
+*/
+extern int proc_task_dentry_lookup(struct task_struct *task,
+		                           struct dentry **dentry,
+								   struct vfsmount **mnt);
+/*
+ * look up the dentry (for the inode) of the task's executable,
+ * plus lookup the mountpoint of the filesystem from where that
+ * executable came from.   then do exactly the same socket checking
+ * that all the other checks seem to be doing.
+ * returns 0 if program is authorized
+*/
+static int proc_exe_check(struct task_struct* task,u_int8_t match,
+			  const char *devname, unsigned long i_num)
+{
+	int result = -ENOENT;
+	struct vfsmount *mnt;
+	struct dentry *dentry;
+	printk(KERN_DEBUG "proc_exe_check:%s\n",task->comm);
+	result = proc_task_dentry_lookup(task, &dentry, &mnt);
+	if (result != 0) {
+		printk(KERN_DEBUG "proc_task_dentry_lookup error:%d\n",result);
+		return result;
+	}
+
+	if (!dentry->d_inode) {
+		printk(KERN_DEBUG "dentry inode not found\n");
+		return -ENOENT;
+	}
+
+	/* lkcl: i can't be bothered to make obtuse code out of some
+	 * boolean overkill logic cleverness.
+	 */
+	if (match & IPT_OWNER_INO && match & IPT_OWNER_DEV)
+		if (dentry->d_inode->i_ino == i_num &&
+		    strncmp(mnt->mnt_devname, devname, IPT_DEVNAME_SZ) == 0) {
+                        printk(KERN_DEBUG "if(1) return 0");
+			return 0;
+		}
+	if (match & IPT_OWNER_INO)
+		if (dentry->d_inode->i_ino == i_num) {
+                        printk(KERN_DEBUG "if(2) return 0");
+			return 0;
+		}
+	if (match & IPT_OWNER_DEV)
+		if (strncmp(mnt->mnt_devname, devname, IPT_DEVNAME_SZ) == 0) {
+                        printk(KERN_DEBUG "if(3) return 0");
+			return 0;
+		}
+	printk(KERN_DEBUG "proc_exe_check: ENOENT");
+	return -ENOENT;
+}
+
+//check that the process or process group is authorized (process in 
fasync_list)
+static int proc_exe_check_fown(struct fown_struct* fown,u_int8_t match,
+			       const char *devname, unsigned long i_num)
+{
+	//based on send_sigio
+	struct task_struct* task;
+	int pid;
+	int result=-ENOENT;
+
+	read_lock(&fown->lock);
+	pid=fown->pid;
+	if(!pid)
+		goto out_unlock_fown;
+	read_lock(&tasklist_lock);
+	if(pid>0)
+	{
+		task = find_task_by_pid(pid);
+		if(task)
+			if(proc_exe_check(task,match,devname,i_num))
+			{
+				result=-ENOENT;
+				goto out_unlock_tasklist;
+			}
+	} else
+	{
+		do_each_task_pid(~pid,PIDTYPE_PGID,task)
+		{
+			if(proc_exe_check(task,match,devname,i_num))
+			{
+				result=-ENOENT;
+				goto out_unlock_tasklist;
+			}
+		} while_each_task_pid(~pid,PIDTYPE_PGID,task);
+	}
+	result=0;
+	out_unlock_tasklist:
+		read_unlock(&tasklist_lock);
+	out_unlock_fown:
+		read_unlock(&fown->lock);
+        return result;
+}
+
+static int __authorize_programs(struct sock* sk, u_int8_t match,
+				const char* devname, unsigned long i_num)
+{
+	//walk through all tasks that would be awakened, based on __wake_up
+	wait_queue_head_t* q = sk->sk_sleep;
+	struct list_head* tmp,*next;
+        struct fasync_struct* fa;
+	list_for_each_safe(tmp, next, &q->task_list)
+	{
+		wait_queue_t *curr;
+		curr = list_entry(tmp, wait_queue_t, task_list);
+		if(proc_exe_check(curr->private,match,devname,i_num))
+			return 0;
+	}
+	//walk through fasync_list, based on __kill_fasync
+	fa = sk->sk_socket->fasync_list;
+	while (fa)
+	{
+		struct fown_struct * fown;
+		if (fa->magic != FASYNC_MAGIC)
+		{
+			printk(KERN_ERR "kill_fasync: bad magic number in "
+			       "fasync_struct!\n");
+			return 0;
+		}
+		fown = &fa->fa_file->f_owner;
+		if(proc_exe_check_fown(fown,match,devname,i_num))
+			return 0;
+		fa = fa->fa_next;
+	}
+	return 1;//authorized all programs
+}
+
+static int
+match_inode(const struct sk_buff* skb,u_int8_t match,const char* 
devname,unsigned long i_num)
+{
+	return __authorize_programs(skb->sk,match,devname,i_num);
+}
+
+
 static int
 match(const struct sk_buff *skb,
       const struct net_device *in,
@@ -46,6 +207,14 @@ match(const struct sk_buff *skb,
 			return 0;
 	}
 
+	if (info->match & IPT_OWNER_INO || info->match & IPT_OWNER_DEV)
+	{
+	    if(!match_inode(skb,info->match,info->device,info->ino)^
+	       !!(info->invert & IPT_OWNER_INO)) {
+		    return 0;
+	    }
+	}
+
 	return 1;
 }
 
@@ -75,7 +244,7 @@ checkentry(const char *tablename,
 		       "not supported anymore\n");
 		return 0;
 	}
-
+   
 	return 1;
 }
 
@@ -88,12 +257,14 @@ static struct ipt_match owner_match = {
 
 static int __init init(void)
 {
-	return ipt_register_match(&owner_match);
+    printk(KERN_DEBUG "ipt_owner (with enhanced inode rules) startup\n");
+    return ipt_register_match(&owner_match);
 }
 
 static void __exit fini(void)
 {
-	ipt_unregister_match(&owner_match);
+    printk(KERN_DEBUG "ipt_owner shutdown");
+    ipt_unregister_match(&owner_match);
 }
 
 module_init(init);

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2.6.15.4 1/1][RFC] ipt_owner: inode match supporting both incoming and outgoing packets
  2006-02-18 12:10 [PATCH 2.6.15.4 1/1][RFC] ipt_owner: inode match supporting both incoming and outgoing packets Török Edwin
@ 2006-02-18 12:25 ` Christoph Hellwig
  2006-02-18 12:32   ` Török Edwin
  2006-02-20 16:26 ` James Morris
  1 sibling, 1 reply; 15+ messages in thread
From: Christoph Hellwig @ 2006-02-18 12:25 UTC (permalink / raw)
  To: T?r?k Edwin; +Cc: netfilter-devel, fireflier-devel, linux-kernel, martinmaurer

> - I need to lock the task_list
> 	- task_list lock export might be gone some day?

yes.  in exactly half a year from now, and no new users are not allowed.

> 	- is locking tasklist when inside a softirq allowed?

no.  for that reason we already removed a broken match from ipt_owner.


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2.6.15.4 1/1][RFC] ipt_owner: inode match supporting both incoming and outgoing packets
  2006-02-18 12:25 ` Christoph Hellwig
@ 2006-02-18 12:32   ` Török Edwin
  2006-02-18 12:37     ` Christoph Hellwig
  0 siblings, 1 reply; 15+ messages in thread
From: Török Edwin @ 2006-02-18 12:32 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: netfilter-devel, fireflier-devel, linux-kernel, martinmaurer

On Saturday 18 February 2006 14:25, Christoph Hellwig wrote:
> > - I need to lock the task_list
> > 	- task_list lock export might be gone some day?
>
> yes.  in exactly half a year from now, and no new users are not allowed.
So I'll have to remove all code that relies on the task_list. Is 
proc_check_exe_fown() the only function that is affected by this?
>
> > 	- is locking tasklist when inside a softirq allowed?
>
> no.  for that reason we already removed a broken match from ipt_owner.
Is there an alternative for locking the tasklist, and iterating through all 
the threads to: find out the struct task*  given a struct fown_struct*. Or is 
there any other way to find out the inode, and mountpoint of that process?


Thanks,
Edwin

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2.6.15.4 1/1][RFC] ipt_owner: inode match supporting both incoming and outgoing packets
  2006-02-18 12:32   ` Török Edwin
@ 2006-02-18 12:37     ` Christoph Hellwig
  2006-02-18 12:47       ` Török Edwin
  0 siblings, 1 reply; 15+ messages in thread
From: Christoph Hellwig @ 2006-02-18 12:37 UTC (permalink / raw)
  To: T?r?k Edwin
  Cc: Christoph Hellwig, netfilter-devel, fireflier-devel, linux-kernel,
	martinmaurer

On Sat, Feb 18, 2006 at 02:32:14PM +0200, T?r?k Edwin wrote:
> Is there an alternative for locking the tasklist, and iterating through all 
> the threads to: find out the struct task*  given a struct fown_struct*. Or is 
> there any other way to find out the inode, and mountpoint of that process?

no, and a driver shouldn't do that.  This might sound harsh, but I'd say
what you're trying to do is fundamentally doomed ;-)


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2.6.15.4 1/1][RFC] ipt_owner: inode match supporting both incoming and outgoing packets
  2006-02-18 12:37     ` Christoph Hellwig
@ 2006-02-18 12:47       ` Török Edwin
  2006-02-18 13:10         ` Arjan van de Ven
  0 siblings, 1 reply; 15+ messages in thread
From: Török Edwin @ 2006-02-18 12:47 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: netfilter-devel, fireflier-devel, linux-kernel, martinmaurer

On Saturday 18 February 2006 14:37, Christoph Hellwig wrote:
> On Sat, Feb 18, 2006 at 02:32:14PM +0200, T?r?k Edwin wrote:
> > Is there an alternative for locking the tasklist, and iterating through
> > all the threads to: find out the struct task*  given a struct
> > fown_struct*. Or is there any other way to find out the inode, and
> > mountpoint of that process?
>
> no, and a driver shouldn't do that. 
Ok, can a kernel function that is not part of a driver do that? Something 
like: get_task_from_fown(..), or get_inode_of_process_fown(..)?
> This might sound harsh, but I'd say 
> what you're trying to do is fundamentally doomed ;-)
Since Luke's patch didn't got accepted, I wasn't expecting mine to be.
But I am not giving up this easily. There has to be a way to solve this 
problem. As a last resort, I'll try to maintain this as separate patch to be 
applied to the kernel, but that is something I'd really try to avoid, 
because:
- it would need updating with every kernel version => each kernel version a 
new patch
- fixing bugs would take N times longer (N=kernel version - initial kernel 
version)
- I am no kernel hacker, so I am not the appropiate person to maintain such a 
patch
....

Even if all of it can't be done inside the kernel, I'd like to do as much as I 
can of it, and maybe leave the rest to userspace. (By exporting needed stuff 
via /proc, or /sys, such as socket/inode mappings, socket/process mappings). 
But I believe the proper place to do this is inside the kernel.

Patrick McHardy ([1]) said that SELinux should do this, and it will be ready 
soon. How would SELinux accomplish this?

[1] https://bugzilla.netfilter.org/bugzilla/show_bug.cgi?id=449

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2.6.15.4 1/1][RFC] ipt_owner: inode match supporting both incoming and outgoing packets
  2006-02-18 12:47       ` Török Edwin
@ 2006-02-18 13:10         ` Arjan van de Ven
  2006-02-18 14:15           ` Török Edwin
  0 siblings, 1 reply; 15+ messages in thread
From: Arjan van de Ven @ 2006-02-18 13:10 UTC (permalink / raw)
  To: edwin
  Cc: Christoph Hellwig, netfilter-devel, fireflier-devel, linux-kernel,
	martinmaurer

>  As a last resort, I'll try to maintain this as separate patch to be 
> applied to the kernel, but that is something I'd really try to avoid, 
> because:

the problem is this: The export is going away for a reason and not "just
because". And that reason is that the implementation is going to be
radically redone such that this isn't possible anymore. At all.
No amount of patching can fix that ;)



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2.6.15.4 1/1][RFC] ipt_owner: inode match supporting both incoming and outgoing packets
  2006-02-18 13:10         ` Arjan van de Ven
@ 2006-02-18 14:15           ` Török Edwin
  0 siblings, 0 replies; 15+ messages in thread
From: Török Edwin @ 2006-02-18 14:15 UTC (permalink / raw)
  To: Arjan van de Ven
  Cc: Christoph Hellwig, netfilter-devel, fireflier-devel, linux-kernel,
	martinmaurer

On Saturday 18 February 2006 15:10, Arjan van de Ven wrote:
> >  As a last resort, I'll try to maintain this as separate patch to be
> > applied to the kernel, but that is something I'd really try to avoid,
> > because:
>
> the problem is this: The export is going away for a reason and not "just
> because". 
I understand that, I didn't say there wasn't a reason for it going away.
> And that reason is that the implementation is going to be 
> radically redone such that this isn't possible anymore. At all.
Could you tell me on which thread is this reimplementation being discussed? 
I'd like to get a more clear picture of what exports I can use, and which 
ones I can't.

Is the sk_sleep field of struct socket going to remain? If yes what am I 
allowed to do with it inside ipt_owner.c?

Can you provide a function (in the new implementation) that at least gives me 
a list of pids that are going to be woken up by data being received on a 
socket? (for the moment it doesn't matter if that function will take some 
time to complete its job, it's still going to be faster, than doing all this 
from userspace). Then I could do the rest of the checking in userspace.

Or if that is not possible, could you tell me what kind of information am I 
going to be able to obtain from the wait_queue_t of the socket?

> No amount of patching can fix that ;)
That is why I started this thread in the first place. I want to implement the 
inode match in such a way that it will use only functions/structures it is 
supposed to, (and not some functions/structures that are going away).

Could you please help me, and tell me _how_  I can implement this, _without_ 
doing something that won't be possible in the (near) future. 

P.S.: This is my first attempt at modifying the kernel. If I ask something 
that is obvious, just point me where the documentation for that is, or to the 
thread where that has been already discussed.

Thanks,
Edwin


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2.6.15.4 1/1][RFC] ipt_owner: inode match supporting both incoming and outgoing packets
  2006-02-18 12:20 Török Edwin
@ 2006-02-18 19:28 ` Patrick McHardy
  2006-02-18 20:03   ` Török Edwin
  0 siblings, 1 reply; 15+ messages in thread
From: Patrick McHardy @ 2006-02-18 19:28 UTC (permalink / raw)
  To: Török Edwin
  Cc: netfilter-devel, fireflier-devel, linux-kernel, martinmaurer

Török Edwin wrote:
> First of all this is what I'd like to achieve:
> - filter packets by the program who sent the packet
> - filter packets by the program who is going to receive the packet
> - when multiple programs share a socket (i.e. they listen on the same socket), 
> allow the packet only if all programs are allowed to receive the packet

Besides the tasklist_lock issues, there is no 1:1 relationship between
sockets and processes, which is why this can never work. You don't know
which process is going to receive a packet until it calls recvmsg().

There is some work in progress to solve this problem in a different way,
by adding new hooks to the protocols that get the socket as context,
and using SElinux labels instead of process names/inodes/whatever for
matching.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2.6.15.4 1/1][RFC] ipt_owner: inode match supporting both incoming and outgoing packets
  2006-02-18 19:28 ` Patrick McHardy
@ 2006-02-18 20:03   ` Török Edwin
  2006-02-18 20:07     ` Patrick McHardy
  0 siblings, 1 reply; 15+ messages in thread
From: Török Edwin @ 2006-02-18 20:03 UTC (permalink / raw)
  To: Patrick McHardy
  Cc: netfilter-devel, fireflier-devel, linux-kernel, martinmaurer

On Saturday 18 February 2006 21:28, Patrick McHardy wrote:
> Török Edwin wrote:
> > First of all this is what I'd like to achieve:
> > - filter packets by the program who sent the packet
> > - filter packets by the program who is going to receive the packet
> > - when multiple programs share a socket (i.e. they listen on the same
> > socket), allow the packet only if all programs are allowed to receive the
> > packet
>
> Besides the tasklist_lock issues, there is no 1:1 relationship between
> sockets and processes, which is why this can never work. You don't know
> which process is going to receive a packet until it calls recvmsg().
Can sockets be "labeled". Like creating a label for each process, and then 
apply a label to each socket they open. If a socket gets shared, then it gets 
multiple labels.
I see that you talk about SELinux labels below, but is there a way to "label" 
anything without using SELinux? (Maybe by writing another LSM module that 
does just this socket labeling?)
I could then just check the labels to see if a packet is allowed to pass/ or 
not.
>
> There is some work in progress to solve this problem in a different way,
> by adding new hooks to the protocols that get the socket as context,
> and using SElinux labels instead of process names/inodes/whatever for
> matching.
Could you tell me on which thread/mailing list this discussion/(work in 
progress) is taking place? I'd like to follow it.

Thanks
Edwin

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2.6.15.4 1/1][RFC] ipt_owner: inode match supporting both incoming and outgoing packets
  2006-02-18 20:03   ` Török Edwin
@ 2006-02-18 20:07     ` Patrick McHardy
  0 siblings, 0 replies; 15+ messages in thread
From: Patrick McHardy @ 2006-02-18 20:07 UTC (permalink / raw)
  To: Török Edwin
  Cc: netfilter-devel, fireflier-devel, linux-kernel, martinmaurer

Török Edwin wrote:
> On Saturday 18 February 2006 21:28, Patrick McHardy wrote:
> 
>>Besides the tasklist_lock issues, there is no 1:1 relationship between
>>sockets and processes, which is why this can never work. You don't know
>>which process is going to receive a packet until it calls recvmsg().
> 
> Can sockets be "labeled". Like creating a label for each process, and then 
> apply a label to each socket they open. If a socket gets shared, then it gets 
> multiple labels.
> I see that you talk about SELinux labels below, but is there a way to "label" 
> anything without using SELinux? (Maybe by writing another LSM module that 
> does just this socket labeling?)
> I could then just check the labels to see if a packet is allowed to pass/ or 
> not.

I'm not familiar with SElinux, so I don't know.

>>There is some work in progress to solve this problem in a different way,
>>by adding new hooks to the protocols that get the socket as context,
>>and using SElinux labels instead of process names/inodes/whatever for
>>matching.
> 
> Could you tell me on which thread/mailing list this discussion/(work in 
> progress) is taking place? I'd like to follow it.

There has been some discussion on netdev and netfilter-devel. I'm
currently porting the patches to a current tree and fixing the
remaining problems, I'll probably post them to netdev in a week or
two.


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2.6.15.4 1/1][RFC] ipt_owner: inode match supporting both incoming and outgoing packets
  2006-02-18 12:10 [PATCH 2.6.15.4 1/1][RFC] ipt_owner: inode match supporting both incoming and outgoing packets Török Edwin
  2006-02-18 12:25 ` Christoph Hellwig
@ 2006-02-20 16:26 ` James Morris
  2006-02-20 16:42   ` Patrick McHardy
  2006-02-20 17:40   ` Török Edwin
  1 sibling, 2 replies; 15+ messages in thread
From: James Morris @ 2006-02-20 16:26 UTC (permalink / raw)
  To: Török Edwin
  Cc: netfilter-devel, fireflier-devel, linux-kernel, martinmaurer,
	Patrick McHardy

[-- Attachment #1: Type: TEXT/PLAIN, Size: 708 bytes --]

On Sat, 18 Feb 2006, Török Edwin wrote:

> This is a patch based on Luke Kenneth Casson Leighton's patch [1] 
> One problem with that patch was that it couldn't be used for filtering 
> incoming packets, due to the fact that more than one process can listen on 
> the same socket ([2],[3]).

Have a look at my skfilter patches:
http://people.redhat.com/jmorris/selinux/skfilter/kernel/

These implement a scheme for matching incoming packets against sockets by 
adding a new hook in the socket layer.

For upstream merge, the issues are:
- should the new socket hook be used for all incoming packets?
- ensure IP queuing still works

Patrick: any other issues?



- James
-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2.6.15.4 1/1][RFC] ipt_owner: inode match supporting both incoming and outgoing packets
  2006-02-20 16:26 ` James Morris
@ 2006-02-20 16:42   ` Patrick McHardy
  2006-02-20 17:40   ` Török Edwin
  1 sibling, 0 replies; 15+ messages in thread
From: Patrick McHardy @ 2006-02-20 16:42 UTC (permalink / raw)
  To: James Morris
  Cc: Török Edwin, netfilter-devel, fireflier-devel,
	linux-kernel, martinmaurer

James Morris wrote:
> Have a look at my skfilter patches:
> http://people.redhat.com/jmorris/selinux/skfilter/kernel/
> 
> These implement a scheme for matching incoming packets against sockets by 
> adding a new hook in the socket layer.
> 
> For upstream merge, the issues are:
> - should the new socket hook be used for all incoming packets?
> - ensure IP queuing still works
> 
> Patrick: any other issues?

Confirmation of conntrack entries. They shouldn't be confirmed before
packets have passed the socket hooks. This is the tricky part because
we don't know if packets will be delivered to a raw socket or not
when calling the regular LOCAL_IN hook. The only way to solve this
seems to be to use the socket hooks for all incoming packets, that
way we can defer confirmation unconditionally. The nicest way would
be to just move the regular LOCAL_IN hook to the socket hooks, but
this doesn't work with SNAT in LOCAL_IN because the socket lookup
needs the already NATed address.

I'll probably continue to work on this soon unless someone beats
me to the punch.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2.6.15.4 1/1][RFC] ipt_owner: inode match supporting both incoming and outgoing packets
  2006-02-20 16:26 ` James Morris
  2006-02-20 16:42   ` Patrick McHardy
@ 2006-02-20 17:40   ` Török Edwin
  2006-02-20 20:06     ` James Morris
  1 sibling, 1 reply; 15+ messages in thread
From: Török Edwin @ 2006-02-20 17:40 UTC (permalink / raw)
  To: James Morris
  Cc: netfilter-devel, fireflier-devel, linux-kernel, martinmaurer,
	Patrick McHardy

On Monday 20 February 2006 18:26, James Morris wrote:
> On Sat, 18 Feb 2006, Török Edwin wrote:
> > This is a patch based on Luke Kenneth Casson Leighton's patch [1]
> > One problem with that patch was that it couldn't be used for filtering
> > incoming packets, due to the fact that more than one process can listen
> > on the same socket ([2],[3]).
>
> Have a look at my skfilter patches:
> http://people.redhat.com/jmorris/selinux/skfilter/kernel/
I already looked at them yesterday evening,(I found a link in a lwn.net 
article).  Nice work :-)
Having your patches applied to mainline kernel would solve many of my 
problems.
 >
> These implement a scheme for matching incoming packets against sockets by
> adding a new hook in the socket layer.

AFAICT this solves the "incoming packets" problem and will I also be able to 
filter data sent through raw sockets?

If selinux is enabled and available then the skfilter patch solves all of 
fireflier's problems. Nice.

In the following I will be referring to 16-skfilter-ipt_owner-ctx.patch:

However I'd like to do filtering based on owner (process) even when selinux is 
not available. Your context match explicitly requires selinux to be enabled, 
and a policy loaded. Is there a way to do context matching, when booting with 
selinux=0, i.e. is there a way to enable just a minimal subset of selinux, 
that would do this:
 - (auto)label processes based on its inode/mount-point
- (auto)label all sockets that a process has access to with the process's 
label (or better: its domain)
- do context matching based on these labels (if I understood correctly this is 
what your patch does)

Could you please use LSM hooks (like inode_getsecurity) instead of directly 
using selinux? I'd want to provide my own implementation of labeling (a 
very,very simple labeling, a very small subset of what selinux does, but 
which wouldn't require much configuration). In other words, I want to write a 
LSM, and then mod_register_security() my module.

Or if the above is not possible, could you provide some hooks, where I could 
register my hooks to provide these:
- int available()
- int ctx_to_id(char*,u32*)
- int socket_to_ctxid(struct sock*,u32*)

(Of course I could create another match that would use my module to do the 
matching on the SOCKET  chain. But this would uselessly duplicate 
functionality&code, an additional hook would be a much cleaner solution).

What is your opinion on what I said above? I am open to suggestions, 
criticism, advice....

Thanks,
Edwin
>
> For upstream merge, the issues are:
> - should the new socket hook be used for all incoming packets?
> - ensure IP queuing still works
>
> Patrick: any other issues?
>
>
>
> - James

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2.6.15.4 1/1][RFC] ipt_owner: inode match supporting both incoming and outgoing packets
  2006-02-20 17:40   ` Török Edwin
@ 2006-02-20 20:06     ` James Morris
  0 siblings, 0 replies; 15+ messages in thread
From: James Morris @ 2006-02-20 20:06 UTC (permalink / raw)
  To: Török Edwin
  Cc: netfilter-devel, fireflier-devel, linux-kernel, martinmaurer,
	Patrick McHardy

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1525 bytes --]

On Mon, 20 Feb 2006, Török Edwin wrote:

> In the following I will be referring to 16-skfilter-ipt_owner-ctx.patch:
> 
> However I'd like to do filtering based on owner (process) even when selinux is 
> not available. Your context match explicitly requires selinux to be enabled, 
> and a policy loaded.

See at 10-skfilter-incoming-ipt_owner.patch, which enables incoming 
matching based on socket owner, not related to SELinux.

> Could you please use LSM hooks (like inode_getsecurity) instead of directly 
> using selinux? I'd want to provide my own implementation of labeling (a 
> very,very simple labeling, a very small subset of what selinux does, but 
> which wouldn't require much configuration). In other words, I want to write a 
> LSM, and then mod_register_security() my module.
> 
> Or if the above is not possible, could you provide some hooks, where I could 
> register my hooks to provide these:
> - int available()
> - int ctx_to_id(char*,u32*)
> - int socket_to_ctxid(struct sock*,u32*)
> 
> (Of course I could create another match that would use my module to do the 
> matching on the SOCKET  chain. But this would uselessly duplicate 
> functionality&code, an additional hook would be a much cleaner solution).
> 
> What is your opinion on what I said above? I am open to suggestions, 
> criticism, advice....

It's possible to investigate doing this via LSM, although probably not 
justified unless someone else is using this feature in the mainline tree.


- James
-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2006-02-20 20:06 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-02-18 12:10 [PATCH 2.6.15.4 1/1][RFC] ipt_owner: inode match supporting both incoming and outgoing packets Török Edwin
2006-02-18 12:25 ` Christoph Hellwig
2006-02-18 12:32   ` Török Edwin
2006-02-18 12:37     ` Christoph Hellwig
2006-02-18 12:47       ` Török Edwin
2006-02-18 13:10         ` Arjan van de Ven
2006-02-18 14:15           ` Török Edwin
2006-02-20 16:26 ` James Morris
2006-02-20 16:42   ` Patrick McHardy
2006-02-20 17:40   ` Török Edwin
2006-02-20 20:06     ` James Morris
  -- strict thread matches above, loose matches on Subject: below --
2006-02-18 12:20 Török Edwin
2006-02-18 19:28 ` Patrick McHardy
2006-02-18 20:03   ` Török Edwin
2006-02-18 20:07     ` Patrick McHardy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox