Greetings, After much help from Chris, attached in Richard Offer's SECURE_FD patch and test program updated to use owlsm (minus memory leak, chrdev_open, and extra hook). Thanks for the excellent starting point Richard! Nick Bellinger Excerpt from Mr Offer's Post: Here is a test case to prove that the policy is working int main(int argc, char **argv) { int fd; fd=open("sfd.c.tmp",1); write(1,"hello\n",6); return 0; } % touch sfd.c.tmp Compile this and run it using strace, % strace ./sfd 1>&- you'll see the value of fd changes from 1 to 3 when the module is present. End Excerpt: --- owlsm.h.save Tue Nov 20 21:48:48 2001 +++ owlsm.h Tue Nov 20 02:12:52 2001 @@ -119,5 +126,246 @@ return 0; } #endif /* CONFIG_OWLSM_LINK */ + +#ifdef CONFIG_OWLSM_FD + +/* Helper struct and functions for OWLSM_FD */ + +struct secure_fds { + int fd_mask; + int priv_change; + struct file *fd_null; +}; + +static inline int tweak_fd_open_null(struct linux_binprm *bprm) +{ + struct inode *i; + struct dentry *d; + struct file *f; + struct secure_fds *sfds = (struct secure_fds *) bprm->security; + + if(!(i = get_empty_inode())) + return -ENOMEM; + if(!(d = dget(d_alloc_root(i)))) { + iput(i); + return -ENOMEM; + } + if(!(f = get_empty_filp())) { + dput(d); + iput(i); + return -ENFILE; + } + + i->i_mode = S_IFCHR | S_IRUGO | S_IWUGO; + i->i_uid = current->fsuid; + i->i_gid = current->fsgid; + i->i_rdev = MKDEV(MEM_MAJOR, 3); /* /dev/null */ + i->i_blksize = PAGE_SIZE; + i->i_blocks = 0; + i->i_atime = i->i_mtime = i->i_ctime = CURRENT_TIME; + i->i_op = &page_symlink_inode_operations; + i->i_state = I_DIRTY; /* so that mark_inode_dirty() won't touch us */ + + f->f_flags = O_RDWR; + f->f_mode = FMODE_READ | FMODE_WRITE; + f->f_dentry = d; + f->f_pos = 0; + f->f_reada = 0; + + init_special_inode(i, i->i_mode, i->i_rdev); + i->i_fop->open(i, f); + sfds->fd_null = f; + return 0; +} + +static int tweak_fd_0_1_2(struct linux_binprm *bprm) +{ + int fd, new, retval; + struct secure_fds *sfds = (struct secure_fds *) bprm->security; + struct file *f = (struct file *) sfds->fd_null; + + for(fd = 0 ; fd <= 2 ; fd++) { + if(current->files->fd[fd]) continue; + + if((new = get_unused_fd()) != fd) { + if(new >= 0) put_unused_fd(new); + return -EMFILE; + } + if(f) { + atomic_inc(&f->f_count); + } else { + if((retval = tweak_fd_open_null(bprm))) { + return retval; + } + } + + fd_install(fd, sfds->fd_null); + sfds->fd_mask |= 1 << fd; + } + return 0; +} + +/* End helper stuff */ + +static int do_owlsm_binprm_alloc_security(struct linux_binprm *bprm) +{ + struct secure_fds *s_fds; + + bprm->security = kmalloc(sizeof(struct secure_fds), GFP_KERNEL); + + s_fds = (struct secure_fds *) bprm->security; + s_fds->fd_mask = 0; + s_fds->fd_null = NULL; + s_fds->priv_change = 0; + + if (bprm->e_uid != current->euid) { + s_fds->priv_change = 1; + } else { + if (!in_group_p(bprm->e_gid)) { + s_fds->priv_change = 1; + } + } + + return tweak_fd_0_1_2(bprm); +} + +static void do_owlsm_binprm_free_security(struct linux_binprm *bprm) +{ + int i; + struct secure_fds *s_fds = ( struct secure_fds *) &bprm->security; + + if (s_fds->fd_mask) { + for (i = 0; i <= 2; i++) { + if ( s_fds->fd_mask & ( 1 << 1 )) + (void) sys_close(i); + } + } + + kfree(bprm->security); + +} +static void do_owlsm_binprm_compute_creds(struct linux_binprm *bprm) +{ + struct secure_fds *sfds = (struct secure_fds *) bprm->security; + + /* Take care of close-on-exec files */ + + if (sfds->priv_change) { + (void) tweak_fd_0_1_2(bprm); + } + +} + +#else + +static int do_owlsm_binprm_alloc_security(struct linux_binprm *bprm) +{ + return 0; +} + +static void do_owlsm_binprm_free_security(struct linux_binprm *bprm) +{ + return; +} + +static void do_owlsm_binprm_compute_creds(struct linux_binprm *bprm) +{ + return; +} + +#endif /* CONFIG_OWLSM_FD */ --- owlsm.c.save Tue Nov 20 21:48:53 2001 +++ owlsm.c Tue Nov 20 21:46:03 2001 @@ -20,6 +20,8 @@ #include <linux/stat.h> #include <linux/netfilter.h> #include <linux/netlink.h> +#include <linux/ctype.h> +#include <linux/file.h> #include "owlsm.h" @@ -160,17 +162,22 @@ static int owlsm_binprm_alloc_security(struct linux_binprm *bprm) { - return do_owlsm_exec_rlimit(bprm); + int exec_return, fd_return; + + exec_return = do_owlsm_exec_rlimit(bprm); + fd_return = do_owlsm_binprm_alloc_security(bprm); + + return (exec_return || fd_return) ? -EPERM : 0; } static void owlsm_binprm_free_security (struct linux_binprm *bprm) { - return; + return do_owlsm_binprm_free_security(bprm); } static void owlsm_binprm_compute_creds (struct linux_binprm *bprm) { - return; + return do_owlsm_binprm_compute_creds(bprm); } static int owlsm_binprm_set_security (struct linux_binprm *bprm) --- Config.in.save Tue Nov 20 21:49:02 2001 +++ Config.in Tue Nov 20 01:45:56 2001 @@ -9,6 +9,8 @@ if [ "$CONFIG_SECURITY_OWLSM" = "y" -o "$CONFIG_SECURITY_OWLSM" = "m" ]; then bool 'Add RLIMITS_NPROC check to execve' CONFIG_OWLSM_RLIMIT_NPROC bool 'Restricted links in /tmp' CONFIG_OWLSM_LINK + bool 'Special handling of fd 0, 1, and 2' CONFIG_OWLSM_FD fi dep_tristate 'Domain and Type Enforcement (EXPERIMENTAL)' CONFIG_SECURITY_DTE $CONFIG_EXPERIMENTAL endmenu _______________________________________________ linux-security-module mailing list linux-security-moduleat_private http://mail.wirex.com/mailman/listinfo/linux-security-module
This archive was generated by hypermail 2b30 : Tue Nov 20 2001 - 18:51:56 PST