SECURE_FD OpenWall LSM Patch

From: Nick Bellinger (nickbat_private)
Date: Tue Nov 20 2001 - 17:48:15 PST

  • Next message: Chris Wright: "Re: SECURE_FD OpenWall LSM Patch"

    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