Index: fs/proc/base.c =================================================================== RCS file: /cvsroot/selinux/nsa/linux-2.6/fs/proc/base.c,v retrieving revision 1.1.1.9 diff -u -u -r1.1.1.9 base.c --- fs/proc/base.c 18 Jun 2004 19:30:20 -0000 1.1.1.9 +++ fs/proc/base.c 9 Sep 2004 15:32:32 -0000 @@ -206,11 +206,12 @@ return -ENOENT; } -static 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) @@ -233,6 +234,11 @@ return result; } +static int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) +{ + return proc_task_dentry_lookup(proc_task(inode), dentry, mnt); +} + static int proc_cwd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) { struct fs_struct *fs; Index: fs/proc/root.c =================================================================== RCS file: /cvsroot/selinux/nsa/linux-2.6/fs/proc/root.c,v retrieving revision 1.1.1.2 diff -u -u -r1.1.1.2 root.c --- fs/proc/root.c 8 Apr 2004 14:13:50 -0000 1.1.1.2 +++ fs/proc/root.c 9 Sep 2004 15:32:32 -0000 @@ -147,6 +147,8 @@ .parent = &proc_root, }; +extern int proc_task_dentry_lookup(struct task_struct *task, struct dentry **dentry, struct vfsmount **mnt); + #ifdef CONFIG_SYSCTL EXPORT_SYMBOL(proc_sys_root); #endif @@ -159,3 +161,4 @@ EXPORT_SYMBOL(proc_net); EXPORT_SYMBOL(proc_bus); EXPORT_SYMBOL(proc_root_driver); +EXPORT_SYMBOL(proc_task_dentry_lookup); Index: include/linux/netfilter_ipv4/ipt_owner.h =================================================================== RCS file: /cvsroot/selinux/nsa/linux-2.6/include/linux/netfilter_ipv4/ipt_owner.h,v retrieving revision 1.1.1.1 diff -u -u -r1.1.1.1 ipt_owner.h --- include/linux/netfilter_ipv4/ipt_owner.h 14 Aug 2003 12:09:16 -0000 1.1.1.1 +++ include/linux/netfilter_ipv4/ipt_owner.h 9 Sep 2004 15:32:40 -0000 @@ -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,12 @@ 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 */ }; Index: net/ipv4/netfilter/ipt_owner.c =================================================================== RCS file: /cvsroot/selinux/nsa/linux-2.6/net/ipv4/netfilter/ipt_owner.c,v retrieving revision 1.1.1.4 diff -u -u -r1.1.1.4 ipt_owner.c --- net/ipv4/netfilter/ipt_owner.c 13 May 2004 18:03:23 -0000 1.1.1.4 +++ net/ipv4/netfilter/ipt_owner.c 9 Sep 2004 15:32:44 -0000 @@ -1,16 +1,34 @@ /* 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. + */ /* (C) 2000 Marc Boucher + * (C) 2004 Luke Kenneth Casson Leighton * * 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 * published by the Free Software Foundation. + * */ #include #include #include +#include +#include +#include +#include +#include #include #include @@ -20,6 +38,86 @@ MODULE_AUTHOR("Marc Boucher "); 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. + */ +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; + result = proc_task_dentry_lookup(task, &dentry, &mnt); + if (result != 0) + return result; + + if (!dentry->d_inode) + 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) + return 0; + if (match & IPT_OWNER_INO) + if (dentry->d_inode->i_ino == i_num) + return 0; + if (match & IPT_OWNER_DEV) + if (strncmp(mnt->mnt_devname, devname, IPT_DEVNAME_SZ) == 0) + return 0; + return -ENOENT; +} + +static int +match_inode(const struct sk_buff *skb, u_int8_t match, + const char *devname, unsigned long i_num) +{ + struct task_struct *g, *p; + struct files_struct *files; + int i; + + read_lock(&tasklist_lock); + do_each_thread(g, p) { + + if (proc_exe_check(p, match, devname, i_num)) + continue; + + task_lock(p); + files = p->files; + if(files) { + spin_lock(&files->file_lock); + for (i=0; i < files->max_fds; i++) { + if (fcheck_files(files, i) == + skb->sk->sk_socket->file) { + spin_unlock(&files->file_lock); + task_unlock(p); + read_unlock(&tasklist_lock); + return 1; + } + } + spin_unlock(&files->file_lock); + } + task_unlock(p); + } while_each_thread(g, p); + read_unlock(&tasklist_lock); + return 0; +} + static int match_comm(const struct sk_buff *skb, const char *comm) { @@ -163,6 +261,12 @@ 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; }