LSM Patch Additions for CAPP (C2) Audit Trails

From: Casey Schaufler (caseyat_private)
Date: Tue Jun 26 2001 - 13:10:54 PDT

  • Next message: Stephen Smalley: "Re: LSM Patch Additions for CAPP (C2) Audit Trails"

    This is SGI's initial LSM patch for C2 (now Controlled
    Access Protection Profile (CAPP)) auditing. It is not
    complete. There will be more coming. The work left to
    do is outlined in the notes below.
    
    A Security Audit Trail provides for the accountability
    requirements of a CAPP system. All access control decisions
    and changes to the security state of the system are logged,
    along with sufficient context information to be meaningful.
    This particular implementation is based on two primary
    sources; the withdrawn POSIX P1003.1eD17 DRAFT standard
    and the Irix audit trail implementation.
    
    General notes regarding the patch:
    
    Any system call which includes a hook that is used
    for auditing will also require a hook at each return.
    This is a result of the fact that an audit hook may
    set aside information to be included in an audit record,
    and that the record may not be complete until the
    return status of the system call is known.
    
    The return hook count is based on the number of returns
    present in a stock kernel and may be lower if existing
    hooks make some of them unnecessary.
    
    In some cases capability checks have been moved into
    the security module. This allows audit to be isolated
    to the secuirty module.
    
    Only the i386 architecture has been addressed.
    
    The mechanisms and data structures required to
    actually implement an audit facility are not included.
    In particular, the information collected and the
    way it's initialized, stored, and manipulated are
    not defined.
    
    This proposal assumes kernel-memory-space arguments
    except in a few, rare cases.
    
    This patch fixes earlier work in kernel/capability_plug.c and
    include/linux/security.h in regard to the msg_queue_security_ops and
    msg_msg_security_ops structures. It now compiles, but Stephen should
    probably look it over to check its doing what he wanted.
    
    It is not clear in all cases which is a better datum to
    pass to LSM hooks, a "struct files *" or a file descriptor.
    Each is useful in some cases, with the fd being better for
    logging but an "struct files *" better for actually making
    decisions. In at least one case passing both is proposed.
    "/tmp/foo" [New file] 324 lines, 10841 characters 
    You have new mail
    anchovy% cat /tmp/foo
    
    General notes regarding the patch:
    
    Any system call which includes a hook that is used
    for auditing will also require a hook at each return.
    This is a result of the fact that an audit hook may
    set aside information to be included in an audit record,
    and that the record may not be complete until the
    return status of the system call is known.
    
    The return hook count is based on the number of returns 
    present in a stock kernel and may be lower if existing
    hooks make some of them unnecessary.
    
    In some cases capability checks have been moved into
    the security module. This allows audit to be isolated
    to the secuirty module.
    
    Only the i386 architecture has been addressed.
    
    The mechanisms and data structures required to
    actually implement an audit facility are not included.
    In particular, the information collected and the
    way it's initialized, stored, and manipulated are
    not defined.
    
    This proposal assumes kernel-memory-space arguments
    except in a few, rare cases. 
    
    This patch fixes earlier work in kernel/capability_plug.c and
    include/linux/security.h in regard to the msg_queue_security_ops and
    msg_msg_security_ops structures. It now compiles, but Stephen should
    probably look it over to check its doing what he wanted.
    
    It is not clear in all cases which is a better datum to
    pass to LSM hooks, a "struct files *" or a file descriptor.
    Each is useful in some cases, with the fd being better for
    logging but an "struct files *" better for actually making
    decisions. In at least one case passing both is proposed.
    
    
    
    
    System Calls needed:
    
    get / set capability mask
    get/set login user id (luid)
    get arbitrary process audit mask
    set audit mask of <process, proc. group, all or uid>
    
    
    CAPS NEEDED:
    
    CAP_AUDIT_WRITE, CAP_AUDIT_CONTROL
    
    
    Currently done:
    
    ================ ./kernel/acct.c
    sys_acct        stdsec hook added (name), return_status hook
    
    
    ================ ./kernel/capability.c
    sys_capset      stdsec(const int pid, const struct task_struct * target,
            const __u32 version, const kernel_cap_t *inheritable,
            const kernel_cap_t * permitted, const kernel_cap_t *
    effective)
            1 return status hook
    
    
    ================ ./arch/i386/kernel/ioport.c:
    sys_ioperm      1 stdsec hook(from, num, turn_on)
    sys_iopl        1 stdsec hook(old,level)
    
    
    ======================= ./fs/buffer.c
    sys_bdflush     stdsec hook added, 2 return_status hooks
    
    
    ================ ./fs/attr.c:
    inode_change_ok stdsec hook added
    
    
    ================ ./kernel/module.c
    sys_create_module
            stdsec hook added(name,size), status_return hook
    sys_init_module stdsec hook(name, mod), status_return hook
    sys_delete_module
            2 stdsec hooks (name/NULL), return_status hook
    
    
    ========= ./arch/i386/kernel/process.c
    sys_execve      use existing hook for for
    security_ops->execve(filename),
            add 1 return_status hook
    
    
    ================ ./arch/i386/kernel/sys_i386.c
    sys_pipe        return pipe status
    sys_old_mmap    stdsec hook (fd, prot, flags), return_status
    sys_mmap2       stdsec hook (fd, prot, flags), return_status
    
    
    ================ ./fs/dquot.c
    sys_quotactl    stdsec hook added, return_status
    
    
    ================ ./fs/filesystems.c
    sys_nfsservctl  stdsec hook added, return_status
    
    
    ================ ./fs/ioctl.c
    sys_ioctl       stdsec hook added, return_status
    
    
    ================ ./fs/namei.c
    vfs_permission  stdhook
    permission      adapted to new vfs_permission hook
    vfs_create      hook moved to catch all post-creates, error passed in
    open_namei      return_status added
    vfs_mknod       hook moved to catch all post-creates, error passed in
    vfs_mkdir       hook moved to catch all post-creates, error passed in
    vfs_rmdir       return_status added
    vfs_rmdir       return_status added
    vfs_unlink      return_status added
    vfs_symlink     hook moved to catch all post-creates, error passed in
    vfs_link        hook moved to catch all post-creates, error passed in
    vfs_rename_dir  hooks moved to catch all post-creates, error passed in,
            return_status added
    
    ================ ./fs/open.c
    sys_statfs      1 return hook,  1 [m] entry hook (path)
    sys_fstatfs     1 return hook, 1 [m] entry hook (fd) 
    do_sys_truncate 1 return hook, 1 [m] entry hook (path, length)
    do_sys_ftruncate 1 return hook, 1 [m] entry hook (fd, length)
    sys_utime       1 return hook (newattrs, time_isset, filename), [o]
    entry
    hook
    sys_utimes      1 return hook (newattrs, time_isset, filename), [o]
    entry
    hook
    sys_access      2 return hooks, 1 [m] entry hook (filename, mode)
    sys_chdir       1 return hook, 1 [m] entry hook (filename)
    sys_fchdir      1 return hook, 1 [m] entry hook (fd)
    sys_chroot      1 return hook, 1 [m] entry hook (filename) 
    sys_fchmod      1 return hook, 1 [m] entry hook (fd, mode) 
    
    
    ================ ./kernel/sys.c
    sys_setpriority stdsec, return_status
    sys_reboot      stdsec, return_status (8 calls)
    sys_setregid    stdsec, return_status
    sys_setgid      stdsec, return_status
    sys_setreuid    stdsec, return_status
    sys_setuid      stdsec, return_status
    sys_setresuid   stdsec, 2 return_status
    sys_setresgid   stdsec, 2 return_status
    sys_setfsuid    stdsec, 3 return_status
    sys_setfsgid    stdsec, 3 return_status
    sys_setpgid     partially done, return status
    sys_setsid      stdsec, 2 return_status
    sys_setgroups   added 2 return_status
    sys_sethostname added 2 return_status
    sys_setdomainname
            3 return hooks, entry hook(name, len)
    sys_setrlimit   6 return hooks (resource, 0 or &new_rlim if resource
    valid)
    sys_prctl       std_sec, 2 return_status
    
    -----------------------------------------------------------------------
    Partials/outstanding issues:
    
    ================ ./mm/mmap.c
            The mm/mmap.c call to security_ops->file_ops->mmap() 
            has been commented out. The function (do_mmap_pgoff()) is 
            called from arch/i368/kernel/sys_i386:do_mmap2() and this is
            alreday hooked. After changing the prototype of the
            file_ops hooks to take fd's rather than struct file *, 
            this was the only place that couldn't be fixed.
    
    ================ ./fs/proc/base.c
            The prototype to security_ops->ptrace() has changed to 
            allow for passing in the pid and request type, passing
            PTRACE_PEEKUSR as the request type here, and a pid of 0.
    
    =============== ./drivers/char/tty_io.c
            Calls file_ops->set_fowner() with a dummy fd.
    
    ================ .arch/i386/kernel/ptrace.c
    sys_ptrace      stdsec hook added, but still need to move
                    uid and cap checks
    
    
    ================ ./fs/fcntl.c
    sys_dup2        incomplete, as the do_fcntl call needs to be
                    audited with the F_DUPD cmd.
    
    
    -----------------------------------------------------------------------
    ToDo's
    
    ================ ./fs/open.c
    sys_access      need stdsec
    sys_chmod       1 return hook, 1 [m] entry hook (filename, mode) 
    sys_chown       1 return hook, 1 [m] entry hook (filename, user, group) 
    sys_lchown      1 return hook, 1 [m] entry hook (filename, user, group) 
    sys_fchown      1 return hook, 1 [m] entry hook (fd, user, group) 
    sys_open        1 return hook (filename, flags, fd), 1 [m] entry hook
    sys_close       2 return hooks, 1 entry hook (fd)
    sys_vhangup     2 return hooks, 1 entry hook
    
    
    
    ================ ./fs/read_write.c
    sys_read        1 return hook, 1 entry hook (fd)
    sys_write       1 return hook, 1 entry hook (fd)
    sys_readv       1 return hook, 1 entry hook (fd)
    sys_writev      1 return hook, 1 entry hook (fd)
    sys_pread       1 return hook, 1 entry hook (fd)
    sys_pwrite      1 return hook, 1 entry hook (fd)
    
    
    ================ ./fs/smbfs/file.c
    smb_file_permission 1 status hook on EACCES failure
    
    
    ================ ./fs/stat.c
    sys_stat        1 return hook, 1 entry hook(filename)
    sys_newstat     1 return hook, 1 entry hook(filename)
    
    
    ================ ./fs/super.c
    sys_umount      1 return hook, 1 entry hook(name)
    sys_mount       1 return hook, 1 entry hook (dev_name, dir_name, flags)
    sys_pivot_root  2 return hooks, 1 entry hook (new_root, put_old)
    
    
    ================ ./init/main.c
    init            init_hook
    
    
    ================ ./ipc/msg.c
    sys_msgget      1 return hook, 1 entry hook (key, msgflg)
    sys_msgctl      9 return hooks, entry hook (msqid, cmd)
    sys_msgsnd      2 return hooks, entry hook(msqid)
    sys_msgrcv      2 return hooks, entry hook(msqid)
    
    
    ================ ./ipc/sem.c
    sys_semget      2 return hooks, entry hook (key, nsems, semflg)
    sys_semctl      5 return hooks, entry hook (semid, cmd)
    
    
    ================ ./ipc/shm.c
    sys_shmget      1 return hook (key, size, shmflg), [opt] entry hook
    sys_shmctl      16 return hooks, entry hook (shmid, cmd, shmid_ds)
    sys_shmat       4 return hooks, entry hook (shmid, shmflg)
    sys_shmdt       1 return hook, [opt] entry hook
    
    
    ================ ./kernel/exit.c
    do_exit         hook to cleanup audit (existing hook in release_task
    would
    work)
    sys_exit        1 hook (error_code)
    
    
    
    ================ ./kernel/printk.c
    sys_syslog      2 return hooks, 1 [opt] entry hook
    
    
    ================ ./kernel/sched.c
    sys_nice        2 return hooks, 1 entry hook (increment)
    setscheduler    1 return hook, entry hook (pid,policy), hook after param
            copied to lp (lp.sched_priority)
    sys_sched_setscheduler
            1 entry hook
    sys_sched_setparam
            1 entry hook
    
    
    ================ ./kernel/signal.c
    sig_info        1 return hook needs(ret val of "bad_signal" or -1, t)
            note that we need to know if capable was used(1), 
            failure(0), and success(2) -- i.e. pass/fail isn't 
            sufficient
    
    sys_kill        1 return hook, entry hook(pid, sig)
    sys_rt_sigqueueinfo
            3 return hooks, 1 entry hook(pid,sig)
    
    
    
    ================ ./kernel/sysctl.c
    sys_sysctl      2 return hooks (0 or tmp.name), [mand] entry hook
    test_perm       status hook on -EACCES (type of failure, DAC/MAC)
    sys_stime       3 return hooks, [opt] entry hook
    sys_settimeofday
            3 return hooks, entry hook, 2nd hook after arg copy
             (tv->tv_sec, tv->tv_usec)
    sys_adjtimex    3 return hooks, [opt] entry hook
    
    
    ================ ./mm/mlock.c
    sys_mlock       1 return hook, [opt] entry hook (start, len)
    sys_mlockall    1 return hook, [opt] entry hook (flags)
    
    
    ================ ./mm/swapfile.c
    sys_swapoff     2 return hooks, [mand] entry hook (specialfile)
    sys_swapon      2 return hooks, [mand] entry hook (specialfile,
    swap_flags)
    
    
    =============== ./net/socket.c
    sys_socket      2 return hooks, [mand] entry hook (family, type,
    protocol)
    
    
    ================ ./kernel/fork.c        2 return hooks (-1 or newpid),
    entry
    hook, new process init hook
            (could use existing)
    
    =============== ./include/linux/sched.h
    suser           hook to save status of priv used or not
    fsuser          hook to save status of priv used or not
    capable         hook to save status of priv used or not
    struct task_struct
            security structure to hold luid and audit bitmask
    INIT_TASK       audit defaults for initial process
    
    
    ---------------------------------------------------------
    
    The SGI Trusted Linux Team Includes:
    
    	ktillat_private			- Kevin Till
    	lachlan.mcilroyat_private	- Lachlan McIlroy
    	lawat_private			- Linda Walsh
    	offerat_private			- Richard Offer
    
    Special thanks to former members James Buster and Emil Ong.
    
    -- 
    
    Casey Schaufler				Manager, Trust Technology, SGI
    caseyat_private				voice: 650.933.1634
    casey_pat_private			Pager: 888.220.0607
    
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/arch/i386/kernel/ioport.c ./arch/i386/kernel/ioport.c
    --- /work/bitkeeper/lsm/arch/i386/kernel/ioport.c	Fri Jun 22 13:56:58 2001
    +++ ./arch/i386/kernel/ioport.c	Mon Jun 25 10:14:38 2001
    @@ -61,9 +61,8 @@
     
     	if ((from + num <= from) || (from + num > IO_BITMAP_SIZE*32))
     		return -EINVAL;
    -	if (turn_on && !capable(CAP_SYS_RAWIO))
    -		return -EPERM;
     
    +	/* check that we have permission to do this */
     	retval = security_ops->ioperm(from, num, turn_on);
     	if (retval) {
     		return retval;
    @@ -115,11 +114,8 @@
     
     	if (level > 3)
     		return -EINVAL;
    -	/* Trying to gain more privileges? */
    -	if (level > old) {
    -		if (!capable(CAP_SYS_RAWIO))
    -			return -EPERM;
    -	}
    +
    +	/* check that we have permission to do this */
     	retval = security_ops->iopl(old, level);
     	if (retval) {
     		return retval;
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/arch/i386/kernel/process.c ./arch/i386/kernel/process.c
    --- /work/bitkeeper/lsm/arch/i386/kernel/process.c	Fri Jun 22 13:56:59 2001
    +++ ./arch/i386/kernel/process.c	Mon Jun 25 10:14:40 2001
    @@ -728,14 +728,21 @@
     	char * filename;
     
     	filename = getname((char *) regs.ebx);
    +
     	error = PTR_ERR(filename);
     	if (IS_ERR(filename))
     		goto out;
    +
    +	error = security_ops->execve(filename);
    +	if ( error )
    +		goto free_out;
     	error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, &regs);
     	if (error == 0)
     		current->ptrace &= ~PT_DTRACE;
    +free_out:
     	putname(filename);
     out:
    +	security_ops->return_status(error);
     	return error;
     }
     
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/arch/i386/kernel/ptrace.c ./arch/i386/kernel/ptrace.c
    --- /work/bitkeeper/lsm/arch/i386/kernel/ptrace.c	Fri Jun 22 13:56:59 2001
    +++ ./arch/i386/kernel/ptrace.c	Mon Jun 25 18:16:27 2001
    @@ -147,7 +147,7 @@
     		/* are we already being traced? */
     		if (current->ptrace & PT_PTRACED)
     			goto out;
    -		ret = security_ops->ptrace(current->p_pptr, current);
    +		ret = security_ops->ptrace(pid,request,current->p_pptr, current);
     		if (ret)
     			goto out;
     		/* set the ptrace bit in the process flags. */
    @@ -164,16 +164,17 @@
     	if (!child)
     		goto out;
     
    +	ret = security_ops->ptrace(pid,request,current,child);
    +	if (ret)
    +		goto out;
     	ret = -EPERM;
    -	if (pid == 1)		/* you may not mess with init */
    -		goto out_tsk;
     
     	if (request == PTRACE_ATTACH) {
     		if (child == current)
     			goto out_tsk;
    -		ret = security_ops->ptrace(current, child);
    -		if (ret)
    -			goto out_tsk;
    +		/* LSM-ToDo. 
    +		 * This uid checking needs to be moved to the std_sec.c file. 
    +		 */
     		ret = -EPERM;
     		if(((current->uid != child->euid) ||
     		    (current->uid != child->suid) ||
    @@ -476,6 +477,7 @@
     out_tsk:
     	free_task_struct(child);
     out:
    +	security_ops->return_status(ret);
     	unlock_kernel();
     	return ret;
     }
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/arch/i386/kernel/sys_i386.c ./arch/i386/kernel/sys_i386.c
    --- /work/bitkeeper/lsm/arch/i386/kernel/sys_i386.c	Fri Jun 22 13:56:59 2001
    +++ ./arch/i386/kernel/sys_i386.c	Mon Jun 25 17:00:57 2001
    @@ -18,6 +18,7 @@
     #include <linux/mman.h>
     #include <linux/file.h>
     #include <linux/utsname.h>
    +#include <linux/security.h>
     
     #include <asm/uaccess.h>
     #include <asm/ipc.h>
    @@ -36,6 +37,7 @@
     		if (copy_to_user(fildes, fd, 2*sizeof(int)))
     			error = -EFAULT;
     	}
    +	security_ops->return_pipe_status(error,fd);
     	return error;
     }
     
    @@ -69,7 +71,15 @@
     	unsigned long prot, unsigned long flags,
     	unsigned long fd, unsigned long pgoff)
     {
    -	return do_mmap2(addr, len, prot, flags, fd, pgoff);
    +	int retval = -EPERM;
    +
    +	if (  security_ops->file_ops->mmap(fd, prot, flags) )
    +		goto out;
    +
    +	retval = do_mmap2(addr, len, prot, flags, fd, pgoff);
    +out:
    +	security_ops->return_status(retval);
    +	return retval;
     }
     
     /*
    @@ -93,14 +103,22 @@
     	struct mmap_arg_struct a;
     	int err = -EFAULT;
     
    -	if (copy_from_user(&a, arg, sizeof(a)))
    +	if (copy_from_user(&a, arg, sizeof(a))) {
    +		err = -EFAULT;
     		goto out;
    +	}
    +
    +	err=security_ops->file_ops->mmap(a.fd, a.prot, a.flags);
    +	if ( err )
    +		goto err_out;
     
     	err = -EINVAL;
     	if (a.offset & ~PAGE_MASK)
    -		goto out;
    +		goto err_out;
     
     	err = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
    +err_out:
    +	security_ops->return_status(err);
     out:
     	return err;
     }
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/drivers/char/tty_io.c ./drivers/char/tty_io.c
    --- /work/bitkeeper/lsm/drivers/char/tty_io.c	Fri Jun 22 13:56:35 2001
    +++ ./drivers/char/tty_io.c	Tue Jun 26 07:34:38 2001
    @@ -1462,7 +1462,7 @@
     		if (!waitqueue_active(&tty->read_wait))
     			tty->minimum_to_wake = 1;
     		if (filp->f_owner.pid == 0) {
    -			retval = security_ops->file_ops->set_fowner(filp);
    +			retval = security_ops->file_ops->set_fowner(fd);
     			if (retval)
     				return retval;
     
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/fs/attr.c ./fs/attr.c
    --- /work/bitkeeper/lsm/fs/attr.c	Fri Jun 22 13:56:05 2001
    +++ ./fs/attr.c	Mon Jun 25 10:14:42 2001
    @@ -18,44 +18,12 @@
     /* POSIX UID/GID verification for setting inode attributes. */
     int inode_change_ok(struct inode *inode, struct iattr *attr)
     {
    -	int retval = -EPERM;
    -	unsigned int ia_valid = attr->ia_valid;
    -
    -	/* If force is set do it anyway. */
    -	if (ia_valid & ATTR_FORCE)
    -		goto fine;
    -
    -	/* Make sure a caller can chown. */
    -	if ((ia_valid & ATTR_UID) &&
    -	    (current->fsuid != inode->i_uid ||
    -	     attr->ia_uid != inode->i_uid) && !capable(CAP_CHOWN))
    -		goto error;
    -
    -	/* Make sure caller can chgrp. */
    -	if ((ia_valid & ATTR_GID) &&
    -	    (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid) &&
    -	    !capable(CAP_CHOWN))
    -		goto error;
    -
    -	/* Make sure a caller can chmod. */
    -	if (ia_valid & ATTR_MODE) {
    -		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
    -			goto error;
    -		/* Also check the setgid bit! */
    -		if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
    -				inode->i_gid) && !capable(CAP_FSETID))
    -			attr->ia_mode &= ~S_ISGID;
    -	}
    -
    -	/* Check for setting the inode time. */
    -	if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) {
    -		if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER))
    -			goto error;
    -	}
    -fine:
    -	retval = 0;
    -error:
    -	return retval;
    +	/* keep this function in as its exported by the kernel (kernel/ksym.c).
    +	 * Until the kernel API is changed, keep the call, but simply
    +	 * call the hook. Worst case scenario, an extra function call, worth it
    +	 * for improved compatability --- offer.
    +	 */
    +	return security_ops->inode_ops->changeattr(inode, attr);
     }
     
     void inode_setattr(struct inode * inode, struct iattr * attr)
    @@ -127,9 +95,7 @@
     	if (inode->i_op && inode->i_op->setattr) 
     		error = inode->i_op->setattr(dentry, attr);
     	else {
    -		error = inode_change_ok(inode, attr);
    -		if (!error)
    -			inode_setattr(inode, attr);
    +		inode_setattr(inode, attr);
     	}
     unlock_and_out:
     	unlock_kernel();
    @@ -138,5 +104,6 @@
     		if (dn_mask)
     			inode_dir_notify(dentry->d_parent->d_inode, dn_mask);
     	}
    +	security_ops->return_status(error);
     	return error;
     }
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/fs/buffer.c ./fs/buffer.c
    --- /work/bitkeeper/lsm/fs/buffer.c	Fri Jun 22 13:56:05 2001
    +++ ./fs/buffer.c	Mon Jun 25 10:14:43 2001
    @@ -2618,11 +2618,15 @@
     
     asmlinkage long sys_bdflush(int func, long data)
     {
    -	if (!capable(CAP_SYS_ADMIN))
    -		return -EPERM;
    +	int error;
    +
    +	error = security_ops->bdflush(func);
    +	if ( error )
    +		goto out;
     
     	if (func == 1) {
     		/* do_exit directly and let kupdate to do its work alone. */
    +		security_ops->return_status(0);
     		do_exit(0);
     #if 0 /* left here as it's the only example of lazy-mm-stuff used from
     	 a syscall that doesn't care about the current mm context. */
    @@ -2646,22 +2650,28 @@
     	if (func >= 2) {
     		int i = (func-2) >> 1;
     		if (i >= 0 && i < N_PARAM) {
    -			if ((func & 1) == 0)
    -				return put_user(bdf_prm.data[i], (int*)data);
    +			if ((func & 1) == 0) {
    +				error = put_user(bdf_prm.data[i], (int*)data);
    +				goto out;
    +			}
     
     			if (data >= bdflush_min[i] && data <= bdflush_max[i]) {
     				bdf_prm.data[i] = data;
    -				return 0;
    +				error=0;
    +				goto out;
     			}
     		}
    -		return -EINVAL;
    +		error = -EINVAL;
    +		goto out;
     	}
     
     	/* Having func 0 used to launch the actual bdflush and then never
     	 * return (unless explicitly killed). We return zero here to 
     	 * remain semi-compatible with present update(8) programs.
     	 */
    -	return 0;
    +out:
    +	security_ops->return_status(error);
    +	return error;
     }
     
     /*
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/fs/dnotify.c ./fs/dnotify.c
    --- /work/bitkeeper/lsm/fs/dnotify.c	Fri Jun 22 13:56:05 2001
    +++ ./fs/dnotify.c	Mon Jun 25 17:04:28 2001
    @@ -77,7 +77,7 @@
     	if (turning_off)
     		goto out;
     
    -	error = security_ops->file_ops->set_fowner(filp);
    +	error = security_ops->file_ops->set_fowner(fd);
     	if (error) {
     		write_unlock(&dn_lock);
     		return error;
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/fs/dquot.c ./fs/dquot.c
    --- /work/bitkeeper/lsm/fs/dquot.c	Fri Jun 22 13:56:06 2001
    +++ ./fs/dquot.c	Mon Jun 25 10:14:44 2001
    @@ -52,6 +52,7 @@
     #include <linux/smp.h>
     #include <linux/smp_lock.h>
     #include <linux/init.h>
    +#include <linux/security.h>
     
     #include <asm/uaccess.h>
     
    @@ -1522,21 +1523,9 @@
     	if (id & ~0xFFFF)
     		goto out;
     
    -	ret = -EPERM;
    -	switch (cmds) {
    -		case Q_SYNC:
    -		case Q_GETSTATS:
    -			break;
    -		case Q_GETQUOTA:
    -			if (((type == USRQUOTA && current->euid != id) ||
    -			     (type == GRPQUOTA && !in_egroup_p(id))) &&
    -			    !capable(CAP_SYS_RESOURCE))
    -				goto out;
    -			break;
    -		default:
    -			if (!capable(CAP_SYS_RESOURCE))
    -				goto out;
    -	}
    +	ret = security_ops->quotactl(cmds, type, special, id);
    +	if ( ret )
    +		goto out;
     
     	ret = -EINVAL;
     	dev = NODEV;
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/fs/fcntl.c ./fs/fcntl.c
    --- /work/bitkeeper/lsm/fs/fcntl.c	Fri Jun 22 13:56:06 2001
    +++ ./fs/fcntl.c	Tue Jun 26 07:49:23 2001
    @@ -174,6 +174,7 @@
     		filp_close(tofree, files);
     	err = newfd;
     out:
    +	security_ops->return_dup_status(err,oldfd,newfd);
     	return err;
     out_unlock:
     	write_unlock(&files->file_lock);
    @@ -192,6 +193,7 @@
     
     	if (file)
     		ret = dupfd(file, 0);
    +	security_ops->return_dup_status(ret < 0 ? ret :0,fildes,ret < 0 ? -1 : ret);
     	return ret;
     }
     
    @@ -238,6 +240,9 @@
     				get_file(filp);
     				err = dupfd(filp, arg);
     			}
    +			/* LSM-ToDo 
    +			 * somehow we need to record this event --- offer 
    +			 */
     			break;
     		case F_GETFD:
     			err = get_close_on_exec(fd);
    @@ -274,7 +279,7 @@
     		case F_SETOWN:
     			lock_kernel();
     
    -			err = security_ops->file_ops->set_fowner(filp);
    +			err = security_ops->file_ops->set_fowner(fd);
     			if (err) {
     				unlock_kernel();
     				break;
    @@ -328,7 +333,7 @@
     	if (!filp)
     		goto out;
     
    -	err = security_ops->file_ops->fcntl(filp, cmd, arg);
    +	err = security_ops->file_ops->fcntl(fd, cmd, arg);
     	if (err) {
     		fput(filp);
     		return err;
    @@ -352,7 +357,7 @@
     	if (!filp)
     		goto out;
     
    -	err = security_ops->file_ops->fcntl64(filp, cmd, arg);
    +	err = security_ops->file_ops->fcntl64(fd, cmd, arg);
     	if (err) {
     		fput(filp);
     		return err;
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/fs/filesystems.c ./fs/filesystems.c
    --- /work/bitkeeper/lsm/fs/filesystems.c	Fri Jun 22 13:56:05 2001
    +++ ./fs/filesystems.c	Mon Jun 25 10:14:45 2001
    @@ -12,6 +12,7 @@
     #include <linux/smp_lock.h>
     #include <linux/kmod.h>
     #include <linux/nfsd/interface.h>
    +#include <linux/security.h>
     
     #if defined(CONFIG_NFSD_MODULE)
     struct nfsd_linkage *nfsd_linkage = NULL;
    @@ -23,10 +24,18 @@
     	
     	lock_kernel();
     
    +	ret=security_ops->nfsserv(cmd);
    +	if ( ret ) 
    +		goto out;
    +	
    +	ret = -ENOSYS;
    +
     	if (nfsd_linkage ||
     	    (request_module ("nfsd") == 0 && nfsd_linkage))
     		ret = nfsd_linkage->do_nfsservctl(cmd, argp, resp);
     
    +out:
    +	security_ops->return_status(ret);
     	unlock_kernel();
     	return ret;
     }
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/fs/ioctl.c ./fs/ioctl.c
    --- /work/bitkeeper/lsm/fs/ioctl.c	Fri Jun 22 13:56:06 2001
    +++ ./fs/ioctl.c	Tue Jun 26 09:07:33 2001
    @@ -26,7 +26,7 @@
     			/* do we support this mess? */
     			if (!mapping->a_ops->bmap)
     				return -EINVAL;
    -			if (!capable(CAP_SYS_RAWIO))
    +			if (!security_ops->capable(current,CAP_SYS_RAWIO))
     				return -EPERM;
     			if ((error = get_user(block, (int *) arg)) != 0)
     				return error;
    @@ -59,11 +59,10 @@
     	error = 0;
     
     	/* Call the Linux Security Module to perform its checks. */
    -	error = security_ops->file_ops->ioctl(filp, cmd, arg);
    -        if (error) {
    -                fput(filp);
    -                goto out;
    -        }
    +	error = security_ops->file_ops->ioctl(fd, cmd, arg);
    +	if (error) {
    +		goto free_out;
    +	}
     
     	lock_kernel();
     	switch (cmd) {
    @@ -118,8 +117,10 @@
     				error = filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
     	}
     	unlock_kernel();
    +free_out:
     	fput(filp);
     
     out:
    +	security_ops->return_status(error);
     	return error;
     }
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/fs/locks.c ./fs/locks.c
    --- /work/bitkeeper/lsm/fs/locks.c	Fri Jun 22 13:56:06 2001
    +++ ./fs/locks.c	Mon Jun 25 17:07:14 2001
    @@ -1270,7 +1270,7 @@
     	*before = fl;
     	list_add(&fl->fl_link, &file_lock_list);
     
    -	error = security_ops->file_ops->set_fowner(filp);
    +	error = security_ops->file_ops->set_fowner(fd);
     	if (error)
     		goto out_unlock;
     
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/fs/namei.c ./fs/namei.c
    --- /work/bitkeeper/lsm/fs/namei.c	Fri Jun 22 13:56:06 2001
    +++ ./fs/namei.c	Mon Jun 25 11:47:02 2001
    @@ -147,32 +147,13 @@
      * for filesystem access without changing the "normal" uids which
      * are used for other things..
      */
    +
    +/* We need to keep this function pending changling the kernel/module API.
    + * vfs_permission() is an exported symbol.
    + */
     int vfs_permission(struct inode * inode,int mask)
     {
    -	int mode = inode->i_mode;
    -
    -	if ((mask & S_IWOTH) && IS_RDONLY(inode) &&
    -		 (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
    -		return -EROFS; /* Nobody gets write access to a read-only fs */
    -
    -	if ((mask & S_IWOTH) && IS_IMMUTABLE(inode))
    -		return -EACCES; /* Nobody gets write access to an immutable file */
    -
    -	if (current->fsuid == inode->i_uid)
    -		mode >>= 6;
    -	else if (in_group_p(inode->i_gid))
    -		mode >>= 3;
    -
    -	if (((mode & mask & S_IRWXO) == mask) || capable(CAP_DAC_OVERRIDE))
    -		return 0;
    -
    -	/* read and search access */
    -	if ((mask == S_IROTH) ||
    -	    (S_ISDIR(inode->i_mode)  && !(mask & ~(S_IROTH | S_IXOTH))))
    -		if (capable(CAP_DAC_READ_SEARCH))
    -			return 0;
    -
    -	return -EACCES;
    +	return security_ops->inode_ops->vfs_permission(inode,mask);
     }
     
     int permission(struct inode * inode,int mask)
    @@ -192,6 +173,11 @@
     		unlock_kernel();
     		return retval;
     	}
    +	/* we should probably get rid of this function all together
    +	 * and simply call the LSM hook directly, but vfs_permission is
    +	 * called directly by other parts (and I bet it forms part of the
    +	 * kernel/module API --- offer
    +	 */
     	return vfs_permission(inode, mask);
     }
     
    @@ -928,8 +914,8 @@
     	up(&dir->i_zombie);
     	if (!error) {
     		inode_dir_notify(dir, DN_CREATE);
    -		security_ops->inode_ops->post_create(dir, dentry, mode);
     	}
    +	security_ops->inode_ops->post_create(dir, dentry, mode,error);
     	return error;
     }
     
    @@ -1127,6 +1113,7 @@
     	dput(dentry);
     exit:
     	path_release(nd);
    +	security_ops->return_status(error);
     	return error;
     
     do_link:
    @@ -1226,8 +1213,8 @@
     	up(&dir->i_zombie);
     	if (!error) {
     		inode_dir_notify(dir, DN_CREATE);
    -		security_ops->inode_ops->post_mknod(dir, dentry, mode, dev);
     	}
    +	security_ops->inode_ops->post_mknod(dir, dentry, mode, dev, error);
     	return error;
     }
     
    @@ -1302,8 +1289,8 @@
     	up(&dir->i_zombie);
     	if (!error) {
     		inode_dir_notify(dir, DN_CREATE);
    -		security_ops->inode_ops->post_mkdir(dir,dentry, mode);
     	}
    +	security_ops->inode_ops->post_mkdir(dir,dentry, mode, error);
     	return error;
     }
     
    @@ -1394,6 +1381,7 @@
     			if (!error)
     				dentry->d_inode->i_flags |= S_DEAD;
     		}
    +		security_ops->return_status(error);
     	}
     	double_up(&dir->i_zombie, &dentry->d_inode->i_zombie);
     	if (!error) {
    @@ -1468,6 +1456,7 @@
     					if (!error)
     						d_delete(dentry);
     				}
    +				security_ops->return_status(error);
     			}
     		}
     	}
    @@ -1546,8 +1535,8 @@
     	up(&dir->i_zombie);
     	if (!error) {
     		inode_dir_notify(dir, DN_CREATE);
    -		security_ops->inode_ops->post_symlink(dir, dentry, oldname);
     	}
    +	security_ops->inode_ops->post_symlink(dir, dentry, oldname,error);
     	return error;
     }
     
    @@ -1626,8 +1615,8 @@
     	up(&dir->i_zombie);
     	if (!error) {
     		inode_dir_notify(dir, DN_CREATE);
    -		security_ops->inode_ops->post_link(old_dentry, dir, new_dentry);
     	}
    +	security_ops->inode_ops->post_link(old_dentry, dir, new_dentry,error);
     	return error;
     }
     
    @@ -1749,8 +1738,10 @@
     		return error;
     
     	error = security_ops->inode_ops->rename(old_dir, old_dentry, new_dir, new_dentry);
    -	if (error)
    +	if (error) {
    +		security_ops->return_status(error);
     		return error;
    +	}
     
     	DQUOT_INIT(old_dir);
     	DQUOT_INIT(new_dir);
    @@ -1788,9 +1779,8 @@
     		
     	if (!error) {
     		d_move(old_dentry,new_dentry);
    -		security_ops->inode_ops->post_rename(old_dir, old_dentry,
    -							new_dir, new_dentry);
     	}
    +	security_ops->inode_ops->post_rename(old_dir, old_dentry, new_dir, new_dentry, error);
     out_unlock:
     	up(&old_dir->i_sb->s_vfs_rename_sem);
     	return error;
    @@ -1822,8 +1812,10 @@
     		return -EPERM;
     
     	error = security_ops->inode_ops->rename(old_dir, old_dentry, new_dir, new_dentry);
    -	if (error)
    +	if (error) {
    +		security_ops->return_status(error);
     		return error;
    +	}
     
     	DQUOT_INIT(old_dir);
     	DQUOT_INIT(new_dir);
    @@ -1839,7 +1831,7 @@
     	if (!(old_dir->i_sb->s_type->fs_flags & FS_ODD_RENAME)) {
     		d_move(old_dentry, new_dentry);
     	}
    -	security_ops->inode_ops->post_rename(old_dir, old_dentry, new_dir, new_dentry);
    +	security_ops->inode_ops->post_rename(old_dir, old_dentry, new_dir, new_dentry,error);
     	return 0;
     }
     
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/fs/open.c ./fs/open.c
    --- /work/bitkeeper/lsm/fs/open.c	Fri Jun 22 13:56:06 2001
    +++ ./fs/open.c	Tue Jun 26 07:08:41 2001
    @@ -29,8 +29,10 @@
     		if (sb->s_op && sb->s_op->statfs) {
     			memset(buf, 0, sizeof(struct statfs));
     			retval = security_ops->sb_ops->statfs(sb);
    -			if (retval)
    +			if (retval) {
    +				security_ops->return_status(retval);
     				return retval;
    +			}
     			lock_kernel();
     			retval = sb->s_op->statfs(sb, buf);
     			unlock_kernel();
    @@ -111,6 +113,9 @@
     	if (!S_ISREG(inode->i_mode))
     		goto dput_and_out;
     
    +	error=security_ops->inode_ops->truncate((const char *) nd.dentry->d_name.name,NULL,length);
    +	if ( error )
    +		goto sec_out;
     	error = permission(inode,MAY_WRITE);
     	if (error)
     		goto dput_and_out;
    @@ -141,6 +146,8 @@
     	}
     	put_write_access(inode);
     
    +sec_out:
    +	security_ops->return_status(error);
     dput_and_out:
     	path_release(&nd);
     out:
    @@ -168,6 +175,11 @@
     		goto out;
     	dentry = file->f_dentry;
     	inode = dentry->d_inode;
    +
    +	error=security_ops->inode_ops->ftruncate(fd,length);
    +	if ( error )
    +		goto out_putf;
    +	
     	error = -EACCES;
     	if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
     		goto out_putf;
    @@ -179,6 +191,7 @@
     	if (!error)
     		error = do_truncate(dentry, length);
     out_putf:
    +	security_ops->return_status(error);
     	fput(file);
     out:
     	return error;
    @@ -248,6 +261,7 @@
     	}
     	error = notify_change(nd.dentry, &newattrs);
     dput_and_out:
    +	security_ops->inode_ops->post_utime(nd.dentry,&newattrs,error);
     	path_release(&nd);
     out:
     	return error;
    @@ -292,6 +306,7 @@
     	}
     	error = notify_change(nd.dentry, &newattrs);
     dput_and_out:
    +	security_ops->inode_ops->post_utime(nd.dentry,&newattrs,error);
     	path_release(&nd);
     out:
     	return error;
    @@ -312,6 +327,11 @@
     	if (mode & ~S_IRWXO)	/* where's F_OK, X_OK, W_OK, R_OK? */
     		return -EINVAL;
     
    +	/* LSM-ToDo: 
    +	 * We need a hook here for audit to record filename and mode.
    +	 * All the uid/cap mangling should be moved into a hook.
    +	 * --- offer 
    +	 */ 
     	old_fsuid = current->fsuid;
     	old_fsgid = current->fsgid;
     	old_cap = current->cap_effective;
    @@ -353,12 +373,16 @@
     	if (IS_ERR(name))
     		goto out;
     
    +	error = security_ops->inode_ops->chdir(name);
    +	if (error)
    +		goto sec_out;
    +
     	error = 0;
     	if (path_init(name,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd))
     		error = path_walk(name, &nd);
     	putname(name);
     	if (error)
    -		goto out;
    +		goto sec_out;
     
     	error = permission(nd.dentry->d_inode,MAY_EXEC);
     	if (error)
    @@ -368,6 +392,8 @@
     
     dput_and_out:
     	path_release(&nd);
    +sec_out:
    +	security_ops->return_status(error);
     out:
     	return error;
     }
    @@ -389,6 +415,10 @@
     	mnt = file->f_vfsmnt;
     	inode = dentry->d_inode;
     
    +	error=security_ops->inode_ops->fchdir(fd);
    +	if (error)
    +		goto out_putf;
    +
     	error = -ENOTDIR;
     	if (!S_ISDIR(inode->i_mode))
     		goto out_putf;
    @@ -397,6 +427,7 @@
     	if (!error)
     		set_fs_pwd(current->fs, mnt, dentry);
     out_putf:
    +	security_ops->return_status(error);
     	fput(file);
     out:
     	return error;
    @@ -413,26 +444,28 @@
     	if (IS_ERR(name))
     		goto out;
     
    +	error=security_ops->chroot(name);
    +	if ( error )
    +		goto sec_out;
    +
     	path_init(name, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
     		      LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
     	error = path_walk(name, &nd);	
     	putname(name);
     	if (error)
    -		goto out;
    +		goto sec_out;
     
     	error = permission(nd.dentry->d_inode,MAY_EXEC);
     	if (error)
     		goto dput_and_out;
     
    -	error = -EPERM;
    -	if (!capable(CAP_SYS_CHROOT))
    -		goto dput_and_out;
    -
     	set_fs_root(current->fs, nd.mnt, nd.dentry);
     	set_fs_altroot();
     	error = 0;
     dput_and_out:
     	path_release(&nd);
    +sec_out:
    +	security_ops->return_status(error);
     out:
     	return error;
     }
    @@ -452,6 +485,10 @@
     	dentry = file->f_dentry;
     	inode = dentry->d_inode;
     
    +	err=security_ops->inode_ops->fchmod(fd,mode);
    +	if ( err )
    +		goto out_putf;
    +
     	err = -EROFS;
     	if (IS_RDONLY(inode))
     		goto out_putf;
    @@ -465,6 +502,7 @@
     	err = notify_change(dentry, &newattrs);
     
     out_putf:
    +	security_ops->return_status(err);
     	fput(file);
     out:
     	return err;
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/fs/proc/base.c ./fs/proc/base.c
    --- /work/bitkeeper/lsm/fs/proc/base.c	Fri Jun 22 13:56:06 2001
    +++ ./fs/proc/base.c	Mon Jun 25 19:09:11 2001
    @@ -310,7 +310,7 @@
     };
     
     #define MAY_PTRACE(p) \
    -(p==current||(p->p_pptr==current&&(p->ptrace & PT_PTRACED)&&p->state==TASK_STOPPED&&security_ops->ptrace(current,p)==0))
    +(p==current||(p->p_pptr==current&&(p->ptrace & PT_PTRACED)&&p->state==TASK_STOPPED&&security_ops->ptrace(0,PTRACE_PEEKUSR,current,p)==0))
     
     static ssize_t mem_read(struct file * file, char * buf,
     			size_t count, loff_t *ppos)
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/fs/read_write.c ./fs/read_write.c
    --- /work/bitkeeper/lsm/fs/read_write.c	Fri Jun 22 13:56:06 2001
    +++ ./fs/read_write.c	Mon Jun 25 17:08:02 2001
    @@ -131,7 +131,7 @@
     				ssize_t (*read)(struct file *, char *, size_t, loff_t *);
     				ret = -EINVAL;
     				if (file->f_op && (read = file->f_op->read) != NULL) {
    -					ret = security_ops->file_ops->permission (file, MAY_READ);
    +					ret = security_ops->file_ops->permission (fd, MAY_READ);
     					if (!ret)
     						ret = read(file, buf, count, &file->f_pos);
     				}
    @@ -161,7 +161,7 @@
     				ssize_t (*write)(struct file *, const char *, size_t, loff_t *);
     				ret = -EINVAL;
     				if (file->f_op && (write = file->f_op->write) != NULL) {
    -					ret = security_ops->file_ops->permission (file, MAY_WRITE);
    +					ret = security_ops->file_ops->permission (fd, MAY_WRITE);
     					if (!ret)
     						ret = write(file, buf, count, &file->f_pos);
     				}
    @@ -291,7 +291,7 @@
     		goto bad_file;
     	if (file->f_op && (file->f_mode & FMODE_READ) &&
     	    (file->f_op->readv || file->f_op->read)) {
    -		ret = security_ops->file_ops->permission (file, MAY_READ);
    +		ret = security_ops->file_ops->permission (fd, MAY_READ);
     		if (!ret)
     			ret = do_readv_writev(VERIFY_WRITE, file, vector, count);
     	}
    @@ -314,7 +314,7 @@
     		goto bad_file;
     	if (file->f_op && (file->f_mode & FMODE_WRITE) &&
     	    (file->f_op->writev || file->f_op->write)) {
    -		ret = security_ops->file_ops->permission (file, MAY_WRITE);
    +		ret = security_ops->file_ops->permission (fd, MAY_WRITE);
     		if (!ret)
     			ret = do_readv_writev(VERIFY_READ, file, vector, count);
     	}
    @@ -351,7 +351,7 @@
     	if (pos < 0)
     		goto out;
     
    -	ret = security_ops->file_ops->permission (file, MAY_READ);
    +	ret = security_ops->file_ops->permission (fd, MAY_READ);
     	if (ret)
     		goto out;
     
    @@ -387,7 +387,7 @@
     	if (pos < 0)
     		goto out;
     
    -	ret = security_ops->file_ops->permission (file, MAY_WRITE);
    +	ret = security_ops->file_ops->permission (fd, MAY_WRITE);
     	if (ret)
     		goto out;
     
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/fs/super.c ./fs/super.c
    --- /work/bitkeeper/lsm/fs/super.c	Fri Jun 22 13:56:06 2001
    +++ ./fs/super.c	Tue Jun 26 08:55:10 2001
    @@ -1291,8 +1291,8 @@
     		return retval;
     
     	retval = do_remount_sb(nd->mnt->mnt_sb, flags, data);
    -	if (!retval)
    -		security_ops->post_remount(nd->mnt, flags, data);
    +		
    +	security_ops->post_remount(nd->mnt, flags, data,retval);
     
     	return retval;
     }
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/include/linux/security.h ./include/linux/security.h
    --- /work/bitkeeper/lsm/include/linux/security.h	Fri Jun 22 13:56:10 2001
    +++ ./include/linux/security.h	Tue Jun 26 08:40:44 2001
    @@ -25,6 +25,8 @@
     #ifdef __KERNEL__
     
     #include <linux/fs.h>
    +#include <linux/sched.h>
    +#include <linux/capability.h>
     #include <linux/binfmts.h>
     #include <linux/signal.h>
     #include <linux/resource.h>
    @@ -32,9 +34,10 @@
     #include <linux/sem.h>
     #include <linux/shm.h>
     #include <linux/msg.h>
    +#include <linux/sysctl.h>
     
     /* Security plug operations */
    -#define SECURITY_INTERFACE_VERSION	0x00000101	/* change this every time the security_operations structure changes */
    +#define SECURITY_INTERFACE_VERSION	0x00000102	/* change this every time the security_operations structure changes */
     
     struct binprm_security_ops {
     	int (* alloc_security)		(struct linux_binprm *bprm);	// create per binprm security
    @@ -54,48 +57,56 @@
     	void (* free_security)		(struct inode *inode);	// free it
     	
     	int (* create)		(struct inode *dir, struct dentry *dentry, int mode);
    -	void (* post_create)	(struct inode *dir, struct dentry *dentry, int mode);
    +	void (* post_create)	(struct inode *dir, struct dentry *dentry, int mode, int error);
     	int (* link)		(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry);
    -	void (* post_link)	(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry);
    +	void (* post_link)	(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry, int error);
     	int (* unlink)		(struct inode *dir, struct dentry *dentry);
     	int (* symlink)		(struct inode *dir, struct dentry *dentry, const char *old_name);
    -	void (* post_symlink)	(struct inode *dir, struct dentry *dentry, const char *old_name);
    +	void (* post_symlink)	(struct inode *dir, struct dentry *dentry, const char *old_name, int error);
     	int (* mkdir)		(struct inode *dir, struct dentry *dentry, int mode);
    -	void (* post_mkdir)	(struct inode *dir, struct dentry *dentry, int mode);
    +	void (* post_mkdir)	(struct inode *dir, struct dentry *dentry, int mode, int error);
     	int (* rmdir)		(struct inode *dir, struct dentry *dentry);
     	int (* mknod)		(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
    -	void (* post_mknod)	(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
    +	void (* post_mknod)	(struct inode *dir, struct dentry *dentry, int mode, dev_t dev, int error);
     	int (* rename)		(struct inode *old_dir, struct dentry *old_dentry,
     				 struct inode *new_dir, struct dentry *new_dentry);
     	void (* post_rename)	(struct inode *old_dir, struct dentry *old_dentry,
    -				 struct inode *new_dir, struct dentry *new_dentry);
    +				 struct inode *new_dir, struct dentry *new_dentry, int error);
     	int (* readlink)	(struct dentry *dentry, char *buf, int bufsiz);
     	int (* follow_link)	(struct dentry *dentry, struct nameidata *nd);
    -	int (* truncate)	(struct inode *inode);
    +	int (* truncate)	(const char *path, struct inode *inode, loff_t length); /* allow for both real paths (inode=NULL) and vm (path=NULL) */
    +	int (* ftruncate)	(int fd, loff_t length);
     	int (* permission)	(struct inode *inode, int mask);
    +	int (* vfs_permission)	(struct inode *inode, int mask);
     	int (* revalidate)	(struct dentry *dentry);
     	int (* setattr)		(struct dentry *dentry, struct iattr *attr);
    +	int (* changeattr)		(struct inode *inode, struct iattr *attr);
     	void (* attach_pathlabel)(struct dentry *dentry, struct vfsmount *mnt);	// DTE project needs this
     	int (* stat)		        (struct inode *inode);
    +	void (* post_utime)(struct dentry *dentry, struct iattr *attr, int error);
    +	int (* chdir)(const char *path);
    +	int (* fchdir) (int fd);
    +	int (* chmod)(const char *path, mode_t mode);
    +	int (* fchmod) (int fd,mode_t mode);
     };
     
     struct file_security_ops {
    -	int (* permission)		(struct file *, int);
    +	int (* permission)		(int fd, int);
     	int (* alloc_security)		(struct file *);
     	void (* free_security)		(struct file *);
     	/* cmw: essentially copied from struct file_operations */
    -	int (* llseek)			(struct file *);
    -	int (* read)			(struct file *);
    -	int (* write)			(struct file *);
    -	int (* ioctl)			(struct file *, unsigned int cmd, unsigned long arg);
    -	int (* mmap)			(struct file *, unsigned long, unsigned long);
    +	int (* llseek)			(int fd);
    +	int (* read)			(int fd);
    +	int (* write)			(int fd);
    +	int (* ioctl)			(int fd, unsigned int cmd, unsigned long arg);
    +	int (* mmap)			(int fd, unsigned long, unsigned long);
     	int (* mprotect)		(struct vm_area_struct *, unsigned long);
    -	int (* lock)			(struct file *);
    -	int (* readv)			(struct file *);
    -	int (* writev)			(struct file *);
    -	int (* fcntl)			(struct file *, unsigned int, unsigned long);
    -	int (* fcntl64)			(struct file *, unsigned int, unsigned long);
    -	int (* set_fowner)		(struct file *file);
    +	int (* lock)			(int fd);
    +	int (* readv)			(int fd);
    +	int (* writev)			(int fd);
    +	int (* fcntl)			(int fd, unsigned int, unsigned long);
    +	int (* fcntl64)			(int fd, unsigned int, unsigned long);
    +	int (* set_fowner)		(int fd);
     	int (* send_sigiotask)		(struct task_struct *tsk, struct fown_struct *fown, int fd, int reason);
     };
     
    @@ -110,9 +121,15 @@
     	int (* setuid)			(uid_t id0, uid_t id1, uid_t id2, int flags);
     	int (* post_setuid)		(uid_t old_ruid /* or fsuid */, uid_t old_euid, uid_t old_suid, int flags);
     	int (* setgid)			(gid_t id0, gid_t id1, gid_t id2, int flags);
    +	int (* setpgid)		(struct task_struct *p, pid_t pid, pid_t pgid);
    +	int (* getpgid)		(struct task_struct *p, pid_t pid);
     	int (* setgroups)               (int gidsetsize, gid_t *grouplist);
    -	int (* setnice)			(struct task_struct *p, int nice);
    -	int (* setrlimit)		(unsigned int resource, struct rlimit *new_rlim);
    +	int (* setnice)			(struct task_struct *p, int nice, int which, int who);
    +	int (*setsid)			(pid_t pid);
    +	int (*getsid)			(struct task_struct *p, pid_t pid);
    +	int (* setrlimit)		(unsigned int resource, struct rlimit *new_rlim, struct rlimit *old_rlim);
    +	int (* prctl)			(int option, unsigned long arg2, unsigned long arg3,
    +			unsigned long arg4, unsigned long arg5);
     	int (* setscheduler)		(struct task_struct *p, int policy);
     	int (* kill)			(struct task_struct *p, struct siginfo *info, int sig);
     	int (* wait)			(struct task_struct *p);
    @@ -121,6 +138,9 @@
     	int (* set_label)		(char *filename);
     	void (* reset_label)		(void);
     
    +	void (* exit)           (int error_code);
    +	int (* fork)            (int error);
    +
     	void (* kmod_set_label)	        (void);
     };
     
    @@ -133,17 +153,27 @@
      	int  (* delete_module)		(const char *name_user);				
     };
     
    +/* this struct seemed to be missing---
    + * 	I suspect Stephen will redo it soon--offer 
    + */
    +struct msg_msg_security_ops {
    +	int (* alloc_security) (struct msg_msg *msg);
    +	void (* free_security) (struct msg_msg *msg);
    +	int (* test_message) (struct msg_msg *msg, long type, int mode);
    +};
    +
     struct ipc_security_ops {
     	int (* permission)	(struct kern_ipc_perm *ipcp, short flag);
     	int (* getinfo)		(int id, int cmd);
     };
     
     struct msg_queue_security_ops {
    -	int (* create)			(key_t key);	// can i create
    -	int (* permission)		(void);		
    -	int (* setmaxqbytes)		(void);		
    -	int (* setattr)			(void);		// can i set attributes
    -	int (* delete)			(void);		// can i delete
    +	int (* alloc_security)	(struct msg_queue *msq);
    +	void (*free_security)	(struct msg_queue *msq);
    +	int (* associate)		(struct msg_queue *msq, int msqid, int msqflg);
    +	int (*msgctl)			(struct msg_queue *msq, int msqid, int cmd);
    +	int (*msgsnd)			(struct msg_queue *msq);
    +	int (*msgrcv)			(struct msg_queue *msq,  struct msg_msg *msg, int msqid, int msgflg);
     };
     
     struct shm_security_ops {
    @@ -177,14 +207,27 @@
     	void (* umount_close)		(struct vfsmount *mnt);    
     	void (* umount_busy)		(struct vfsmount *mnt);    
     	int  (* remount)		(struct vfsmount *mnt, unsigned long flags, void *data);    
    -	void (* post_remount)		(struct vfsmount *mnt, unsigned long flags, void *data);    
    +	void (* post_remount)		(struct vfsmount *mnt, unsigned long flags, void *data, int error);    
     	int  (* ioperm)			(unsigned long from, unsigned long num, int turn_on);
     	int  (* iopl)			(unsigned int old, unsigned int level);		
    -	int  (* ptrace)			(struct task_struct *parent, struct task_struct *child);		
    -	int  (* setcapability)		(void);		
    -	int  (* acct)			(struct file *file);
    +	int  (* ptrace)			(long pid, long request, struct task_struct *parent, struct task_struct *child);		
    +	int  (* setcapability)          (int pid, struct task_struct * target,
    +			__u32 version,
    +			kernel_cap_t *inheritable,
    +			kernel_cap_t * permitted,
    +			kernel_cap_t * effective); // CAP_SETPCAP
    +	int  (* acct)			(const char *path);
     	int  (* capable)	        (struct task_struct *tsk, int cap); 
     
    +	int (* sysctl)		(ctl_table *table, int op);
    +	int (* execve)			(const char * path);
    +	int (* return_pipe_status)	(int error, int fd[2]); 
    +	int (* return_dup_status)	(int error, int fd1, int fd2); 
    +	int (* bdflush)			(int func);
    +	int (* quotactl)		(int cmd, int subcmd, const char *path, int fd);
    +	int (* nfsserv)			(int cmd);
    +	int (* chroot)(const char *path);
    +
     	struct binprm_security_ops	* bprm_ops;
     	struct super_block_security_ops	* sb_ops;
     	struct inode_security_ops	* inode_ops;
    @@ -192,6 +235,7 @@
     	struct task_security_ops	* task_ops;
     	struct socket_security_ops	* socket_ops;
     	struct module_security_ops 	* module_ops;
    +	struct msg_msg_security_ops	* msg_msg_ops;
     	struct ipc_security_ops		* ipc_ops;
     	struct msg_queue_security_ops	* msg_queue_ops;
     	struct shm_security_ops		* shm_ops;
    @@ -200,6 +244,7 @@
     	/* allow module stacking */
     	int (* register_security)	(const char *name, struct security_operations *ops);
     	int (* unregister_security)	(const char *name, struct security_operations *ops);
    +	void (*return_status) 		(long);
     };
     
     
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/ipc/msg.c ./ipc/msg.c
    --- /work/bitkeeper/lsm/ipc/msg.c	Fri Jun 22 13:56:26 2001
    +++ ./ipc/msg.c	Mon Jun 25 10:14:50 2001
    @@ -22,6 +22,7 @@
     #include <linux/init.h>
     #include <linux/proc_fs.h>
     #include <linux/list.h>
    +#include <linux/security.h>
     #include <asm/uaccess.h>
     #include "util.h"
     
    @@ -317,6 +318,7 @@
     		msg_unlock(id);
     	}
     	up(&msg_ids.sem);
    +	security_ops->return_status(ret);
     	return ret;
     }
     
    @@ -418,8 +420,10 @@
     	struct msq_setbuf setbuf;
     	struct kern_ipc_perm *ipcp;
     	
    -	if (msqid < 0 || cmd < 0)
    +	if (msqid < 0 || cmd < 0) {
    +		security_ops->return_status(-EINVAL);
     		return -EINVAL;
    +	}
     
     	version = ipc_parse_version(&cmd);
     
    @@ -429,8 +433,10 @@
     	{ 
     		struct msginfo msginfo;
     		int max_id;
    -		if (!buf)
    +		if (!buf) {
    +			security_ops->return_status(-EFAULT);
     			return -EFAULT;
    +		}
     		/* We must not return kernel stack data.
     		 * due to padding, it's not enough
     		 * to set all member fields.
    @@ -458,26 +464,35 @@
     		}
     		max_id = msg_ids.max_id;
     		up(&msg_ids.sem);
    -		if (copy_to_user (buf, &msginfo, sizeof(struct msginfo)))
    +		if (copy_to_user (buf, &msginfo, sizeof(struct msginfo))) {
    +			security_ops->return_status(-EFAULT);
     			return -EFAULT;
    -		return (max_id < 0) ? 0: max_id;
    +		}
    +		if (max_id < 0)
    +			max_id = 0;
    +		security_ops->return_status(max_id);
    +		return max_id;
     	}
     	case MSG_STAT:
     	case IPC_STAT:
     	{
     		struct msqid64_ds tbuf;
     		int success_return;
    -		if (!buf)
    +		if (!buf) {
    +			security_ops->return_status(-EFAULT);
     			return -EFAULT;
    -		if(cmd == MSG_STAT && msqid >= msg_ids.size)
    +		}
    +		if(cmd == MSG_STAT && msqid >= msg_ids.size) {
    +			security_ops->return_status(-EINVAL);
     			return -EINVAL;
    -
    +		}
     		memset(&tbuf,0,sizeof(tbuf));
     
     		msq = msg_lock(msqid);
    -		if (msq == NULL)
    +		if (msq == NULL) {
    +			security_ops->return_status(-EINVAL);
     			return -EINVAL;
    -
    +		}
     		if(cmd == MSG_STAT) {
     			success_return = msg_buildid(msqid, msq->q_perm.seq);
     		} else {
    @@ -504,19 +519,27 @@
     		tbuf.msg_lspid  = msq->q_lspid;
     		tbuf.msg_lrpid  = msq->q_lrpid;
     		msg_unlock(msqid);
    -		if (copy_msqid_to_user(buf, &tbuf, version))
    +		if (copy_msqid_to_user(buf, &tbuf, version)) {
    +			security_ops->return_status(-EFAULT);
     			return -EFAULT;
    +		}
    +		security_ops->return_status(success_return);
     		return success_return;
     	}
     	case IPC_SET:
    -		if (!buf)
    +		if (!buf) {
    +			security_ops->return_status(-EFAULT);
     			return -EFAULT;
    -		if (copy_msqid_from_user (&setbuf, buf, version))
    +		}
    +		if (copy_msqid_from_user (&setbuf, buf, version)) {
    +			security_ops->return_status(-EFAULT);
     			return -EFAULT;
    +		}
     		break;
     	case IPC_RMID:
     		break;
     	default:
    +		security_ops->return_status(-EINVAL);
     		return  -EINVAL;
     	}
     
    @@ -575,12 +598,14 @@
     	err = 0;
     out_up:
     	up(&msg_ids.sem);
    +	security_ops->return_status(err);
     	return err;
     out_unlock_up:
     	msg_unlock(msqid);
     	goto out_up;
     out_unlock:
     	msg_unlock(msqid);
    +	security_ops->return_status(err);
     	return err;
     }
     
    @@ -642,17 +667,24 @@
     	long mtype;
     	int err;
     	
    -	if (msgsz > msg_ctlmax || (long) msgsz < 0 || msqid < 0)
    +	if (msgsz > msg_ctlmax || (long) msgsz < 0 || msqid < 0) {
    +		security_ops->return_status(-EINVAL);
     		return -EINVAL;
    -	if (get_user(mtype, &msgp->mtype))
    +	}
    +	if (get_user(mtype, &msgp->mtype)) {
    +		security_ops->return_status(-EFAULT);
     		return -EFAULT; 
    -	if (mtype < 1)
    +	}
    +	if (mtype < 1) {
    +		security_ops->return_status(-EINVAL);
     		return -EINVAL;
    -
    +	}
     	msg = load_msg(msgp->mtext, msgsz);
    -	if(IS_ERR(msg))
    -		return PTR_ERR(msg);
    -
    +	if(IS_ERR(msg)) {
    +		err = PTR_ERR(msg);
    +		security_ops->return_status(err);
    +		return err;
    +	}
     	msg->m_type = mtype;
     	msg->m_ts = msgsz;
     
    @@ -669,7 +701,7 @@
     	if (ipcperms(&msq->q_perm, S_IWUGO)) 
     		goto out_unlock_free;
     
    -	err = security_ops->msg_queue_ops->msgsnd(msq, msg, msqid, msgflg);
    +	err = security_ops->msg_queue_ops->msgsnd(msq);
     	if (err)
     		goto out_unlock_free;
     
    @@ -718,6 +750,7 @@
     out_free:
     	if(msg!=NULL)
     		free_msg(msg);
    +	security_ops->return_status(err);
     	return err;
     }
     
    @@ -750,13 +783,17 @@
     	int err;
     	int mode;
     
    -	if (msqid < 0 || (long) msgsz < 0)
    +	if (msqid < 0 || (long) msgsz < 0) {
    +		security_ops->return_status(-EINVAL);
     		return -EINVAL;
    +	}
     	mode = convert_mode(&msgtyp,msgflg);
     
     	msq = msg_lock(msqid);
    -	if(msq==NULL)
    +	if(msq==NULL) {
    +		security_ops->return_status(-EINVAL);
     		return -EINVAL;
    +	}
     retry:
     	err=-EACCES;
     	if (ipcperms (&msq->q_perm, S_IRUGO))
    @@ -805,6 +842,7 @@
     			    msgsz = -EFAULT;
     		}
     		free_msg(msg);
    +		security_ops->return_status(msgsz);
     		return msgsz;
     	} else
     	{
    @@ -861,6 +899,7 @@
     out_unlock:
     	if(msqid!=-1)
     		msg_unlock(msqid);
    +	security_ops->return_status(err);
     	return err;
     }
     
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/ipc/sem.c ./ipc/sem.c
    --- /work/bitkeeper/lsm/ipc/sem.c	Fri Jun 22 13:56:26 2001
    +++ ./ipc/sem.c	Mon Jun 25 10:14:54 2001
    @@ -181,7 +181,7 @@
     		if (nsems > sma->sem_nsems)
     			err = -EINVAL;
     		else if (ipcperms(&sma->sem_perm, semflg) ||
    -			 security_ops->sem_ops->associate(sma, sem_buildid(id, sma->sem_perm.seq), semflg))
    +			 (err=security_ops->sem_ops->associate(sma, sem_buildid(id, sma->sem_perm.seq), semflg)))
     			err = -EACCES;
     		else
     			err = sem_buildid(id, sma->sem_perm.seq);
    @@ -189,6 +189,7 @@
     	}
     
     	up(&sem_ids.sem);
    +	security_ops->return_status(err);
     	return err;
     }
     
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/ipc/shm.c ./ipc/shm.c
    --- /work/bitkeeper/lsm/ipc/shm.c	Fri Jun 22 13:56:26 2001
    +++ ./ipc/shm.c	Mon Jun 25 10:14:54 2001
    @@ -240,13 +240,14 @@
     		if (shp->shm_segsz < size)
     			err = -EINVAL;
     		else if (ipcperms(&shp->shm_perm, shmflg) ||
    -			 security_ops->shm_ops->associate(shp, shm_buildid(id, shp->shm_perm.seq), shmflg))
    +			 (err=security_ops->shm_ops->associate(shp, shm_buildid(id, shp->shm_perm.seq), shmflg)))
     			err = -EACCES;
     		else
     			err = shm_buildid(id, shp->shm_perm.seq);
     		shm_unlock(id);
     	}
     	up(&shm_ids.sem);
    +	security_ops->return_status(err);
     	return err;
     }
     
    @@ -380,8 +381,10 @@
     		struct shminfo64 shminfo;
     
     		err = security_ops->ipc_ops->getinfo(shmid, cmd);
    -		if (err)
    +		if (err) {
    +			security_ops->return_status(err);
     			return err;
    +		}
     
     		memset(&shminfo,0,sizeof(shminfo));
     		shminfo.shmmni = shminfo.shmseg = shm_ctlmni;
    @@ -389,12 +392,15 @@
     		shminfo.shmall = shm_ctlall;
     
     		shminfo.shmmin = SHMMIN;
    -		if(copy_shminfo_to_user (buf, &shminfo, version))
    +		if(copy_shminfo_to_user (buf, &shminfo, version)) {
    +			security_ops->return_status(-EFAULT);
     			return -EFAULT;
    +		}
     		/* reading a integer is always atomic */
     		err= shm_ids.max_id;
     		if(err<0)
     			err = 0;
    +		security_ops->return_status(err);
     		return err;
     	}
     	case SHM_INFO:
    @@ -402,8 +408,10 @@
     		struct shm_info shm_info;
     
     		err = security_ops->ipc_ops->getinfo(shmid, cmd);
    -		if (err)
    +		if (err) {
    +			security_ops->return_status(err);
     			return err;
    +		}
     
     		memset(&shm_info,0,sizeof(shm_info));
     		down(&shm_ids.sem);
    @@ -416,9 +424,12 @@
     		err = shm_ids.max_id;
     		shm_unlockall();
     		up(&shm_ids.sem);
    -		if(copy_to_user (buf, &shm_info, sizeof(shm_info)))
    +		if(copy_to_user (buf, &shm_info, sizeof(shm_info))) {
    +			security_ops->return_status(-EFAULT);
     			return -EFAULT;
    +		}
     
    +		security_ops->return_status(err < 0 ? 0 : err);
     		return err < 0 ? 0 : err;
     	}
     	case SHM_STAT:
    @@ -458,8 +469,11 @@
     		tbuf.shm_lpid	= shp->shm_lprid;
     		tbuf.shm_nattch	= shp->shm_nattch;
     		shm_unlock(shmid);
    -		if(copy_shmid_to_user (buf, &tbuf, version))
    +		if(copy_shmid_to_user (buf, &tbuf, version)) {
    +			security_ops->return_status(-EFAULT);
     			return -EFAULT;
    +		}
    +		security_ops->return_status(result);
     		return result;
     	}
     	case SHM_LOCK:
    @@ -538,8 +552,10 @@
     
     	case IPC_SET:
     	{
    -		if(copy_shmid_from_user (&setbuf, buf, version))
    +		if(copy_shmid_from_user (&setbuf, buf, version)) {
    +			security_ops->return_status(-EFAULT);
     			return -EFAULT;
    +		}
     		down(&shm_ids.sem);
     		shp = shm_lock(shmid);
     		err=-EINVAL;
    @@ -579,6 +595,7 @@
     	up(&shm_ids.sem);
     	return err;
     out_unlock:
    +	security_ops->return_status(err);
     	shm_unlock(shmid);
     	return err;
     }
    @@ -637,6 +654,7 @@
     	err = security_ops->shm_ops->shmat(shp, shmid, shmaddr, shmflg);
     	if (err) {
     		shm_unlock(shmid);
    +		security_ops->return_status(err);
     		return err;
     	}
     		
    @@ -662,6 +680,7 @@
     	err = 0;
     	if (IS_ERR(user_addr))
     		err = PTR_ERR(user_addr);
    +	security_ops->return_status(err);
     	return err;
     
     }
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/kernel/Makefile ./kernel/Makefile
    --- /work/bitkeeper/lsm/kernel/Makefile	Fri Jun 22 13:56:10 2001
    +++ ./kernel/Makefile	Mon Jun 25 10:14:55 2001
    @@ -15,7 +15,7 @@
     	    module.o exit.o itimer.o info.o time.o softirq.o resource.o \
     	    sysctl.o acct.o capability.o ptrace.o timer.o user.o \
     	    signal.o sys.o kmod.o context.o \
    -	    security.o
    +	    security.o std_sec.o
     
     obj-$(CONFIG_UID16) += uid16.o
     obj-$(CONFIG_MODULES) += ksyms.o
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/kernel/acct.c ./kernel/acct.c
    --- /work/bitkeeper/lsm/kernel/acct.c	Fri Jun 22 13:56:10 2001
    +++ ./kernel/acct.c	Tue Jun 26 08:16:28 2001
    @@ -156,16 +156,20 @@
     {
     	struct file *file = NULL, *old_acct = NULL;
     	char *tmp;
    -	int error;
    -
    -	if (!capable(CAP_SYS_PACCT))
    -		return -EPERM;
    +	long int error=0;
     
     	if (name) {
     		tmp = getname(name);
     		error = PTR_ERR(tmp);
    +
     		if (IS_ERR(tmp))
    +			return error;
    +
    +		if ((error=security_ops->acct(tmp))) {
    +			putname(tmp);
     			goto out;
    +		}
    +
     		/* Difference from BSD - they don't do O_APPEND */
     		file = filp_open(tmp, O_WRONLY|O_APPEND, 0);
     		putname(tmp);
    @@ -180,11 +184,11 @@
     		error = -EIO;
     		if (!file->f_op->write) 
     			goto out_err;
    +	} else {
    +		if ((error = security_ops->acct(NULL)))
    +			goto out_err;
     	}
     
    -	error = security_ops->acct(file);
    -	if (error)
    -		goto out_err;
     
     	error = 0;
     	lock_kernel();
    @@ -211,6 +215,7 @@
     		filp_close(old_acct, NULL);
     	}
     out:
    +	security_ops->return_status(error);
     	return error;
     out_err:
     	filp_close(file, NULL);
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/kernel/capability.c ./kernel/capability.c
    --- /work/bitkeeper/lsm/kernel/capability.c	Fri Jun 22 13:56:10 2001
    +++ ./kernel/capability.c	Tue Jun 26 08:29:30 2001
    @@ -128,33 +128,34 @@
     
     asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
     {
    -     kernel_cap_t inheritable, permitted, effective;
    -     __u32 version;
    +     kernel_cap_t inheritable=0 , permitted=0, effective=0;
    +     __u32 version=0;
          struct task_struct *target;
    -     int error, pid;
    +     int error=0, pid=-EINVAL;
    +
    +     error=0;
     
          if (get_user(version, &header->version))
    -	     return -EFAULT; 
    +	     return -EFAULT;
     
          if (version != _LINUX_CAPABILITY_VERSION) {
                  version = _LINUX_CAPABILITY_VERSION;
     	     if (put_user(version, &header->version))
    -		     return -EFAULT; 
    -             return -EINVAL;
    +		     return -EFAULT;
    +		return -EINVAL;
          }
     
          if (get_user(pid, &header->pid))
    -	     return -EFAULT; 
    -
    -     if (pid && !capable(CAP_SETPCAP))
    -             return -EPERM;
    +	     return -EINVAL;
     
          if (copy_from_user(&effective, &data->effective, sizeof(effective)) ||
     	 copy_from_user(&inheritable, &data->inheritable, sizeof(inheritable)) ||
     	 copy_from_user(&permitted, &data->permitted, sizeof(permitted)))
    -	     return -EFAULT; 
    +	     return -EINVAL;
    +
    +	error=0;
    +	
     
    -     error = -EPERM;
          spin_lock(&task_capability_lock);
     
          if (pid > 0 && pid != current->pid) {
    @@ -170,23 +171,12 @@
     
     
          /* verify restrictions on target's new Inheritable set */
    -     if (!cap_issubset(inheritable,
    -                       cap_combine(target->cap_inheritable,
    -                                   current->cap_permitted))) {
    -             goto out;
    -     }
     
    -     /* verify restrictions on target's new Permitted set */
    -     if (!cap_issubset(permitted,
    -                       cap_combine(target->cap_permitted,
    -                                   current->cap_permitted))) {
    -             goto out;
    -     }
    +      error = -EPERM;
     
    -     /* verify the _new_Effective_ is a subset of the _new_Permitted_ */
    -     if (!cap_issubset(effective, permitted)) {
    -             goto out;
    -     }
    +	if (security_ops->setcapability(pid, target, version, &inheritable,
    +					&permitted, &effective))
    +		 goto out;
     
          /* having verified that the proposed changes are legal,
                we now put them into effect. */
    @@ -212,5 +202,7 @@
          }
     spin_out:
          spin_unlock(&task_capability_lock);
    +     security_ops->return_status(error);
          return error;
     }
    +
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/kernel/capability_plug.c ./kernel/capability_plug.c
    --- /work/bitkeeper/lsm/kernel/capability_plug.c	Fri Jun 22 13:56:10 2001
    +++ ./kernel/capability_plug.c	Tue Jun 26 08:41:19 2001
    @@ -45,8 +45,11 @@
     		return -EPERM;
     }
     
    -static int cap_ptrace(struct task_struct *parent, struct task_struct *child) 
    +static int cap_ptrace(long pid, long request, struct task_struct *parent, struct task_struct *child) 
     { 
    +	if ( pid == 1 )
    +		return -EPERM;
    +
     	/* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */
     	if (!cap_issubset(child->cap_permitted, current->cap_permitted) &&
     	    !cap_capable(current, CAP_SYS_PTRACE))
    @@ -55,8 +58,8 @@
     		return 0;
     }
     
    -static int cap_setcapablity	(void)	{return 0;}
    -static int cap_acct		(struct file *file) { return 0; }
    +static int cap_setcapablity	(int pid, struct task_struct * target, __u32 version, kernel_cap_t *inheritable, kernel_cap_t * permitted, kernel_cap_t * effective)	{return 0;}
    +static int cap_acct		(const char *path) { return 0; }
     
     static int cap_binprm_alloc_security(struct linux_binprm *bprm)
     {
    @@ -145,44 +148,44 @@
     static int cap_inode_alloc_security	(struct inode *inode)	{return 0;}
     static void cap_inode_free_security	(struct inode *inode)	{return;}
     static int cap_inode_create		(struct inode *inode, struct dentry *dentry, int mask) {return 0;}
    -static void cap_inode_post_create	(struct inode *inode, struct dentry *dentry, int mask) {return;}
    +static void cap_inode_post_create	(struct inode *inode, struct dentry *dentry, int mask, int error) {return;}
     static int cap_inode_link		(struct dentry *old_dentry, struct inode *inode, struct dentry *new_dentry) {return 0;}
    -static void cap_inode_post_link	(struct dentry *old_dentry, struct inode *inode, struct dentry *new_dentry) {return;}
    +static void cap_inode_post_link	(struct dentry *old_dentry, struct inode *inode, struct dentry *new_dentry, int error) {return;}
     static int cap_inode_unlink		(struct inode *inode, struct dentry *dentry) {return 0;}
     static int cap_inode_symlink		(struct inode *inode, struct dentry *dentry, const char *name) {return 0;}
    -static void cap_inode_post_symlink	(struct inode *inode, struct dentry *dentry, const char *name) {return;}
    +static void cap_inode_post_symlink	(struct inode *inode, struct dentry *dentry, const char *name, int error) {return;}
     static int cap_inode_mkdir		(struct inode *inode, struct dentry *dentry, int mask) {return 0;}
    -static void cap_inode_post_mkdir	(struct inode *inode, struct dentry *dentry, int mask) {return;}
    +static void cap_inode_post_mkdir	(struct inode *inode, struct dentry *dentry, int mask, int error) {return;}
     static int cap_inode_rmdir		(struct inode *inode, struct dentry *dentry) {return 0;}
     static int cap_inode_mknod		(struct inode *inode, struct dentry *dentry, int major, dev_t minor) {return 0;}
    -static void cap_inode_post_mknod	(struct inode *inode, struct dentry *dentry, int major, dev_t minor) {return;}
    +static void cap_inode_post_mknod	(struct inode *inode, struct dentry *dentry, int major, dev_t minor, int error) {return;}
     static int cap_inode_rename		(struct inode *old_inode, struct dentry *old_dentry, struct inode *new_inode, struct dentry *new_dentry) {return 0;}
    -static void cap_inode_post_rename	(struct inode *old_inode, struct dentry *old_dentry, struct inode *new_inode, struct dentry *new_dentry) {return;}
    +static void cap_inode_post_rename	(struct inode *old_inode, struct dentry *old_dentry, struct inode *new_inode, struct dentry *new_dentry, int error) {return;}
     static int cap_inode_readlink		(struct dentry *dentry, char *name, int mask) {return 0;}
     static int cap_inode_follow_link	(struct dentry *dentry, struct nameidata *nameidata) {return 0;}
    -static int cap_inode_truncate		(struct inode *inode) {return 0;}
    +static int cap_inode_truncate		(struct dentry *dentry, loff_t len) {return 0;}
     static int cap_inode_permission(struct inode *inode, int mask) { return 0; }
     static int cap_inode_revalidate	(struct dentry *inode) {return 0;}
     static int cap_inode_setattr(struct dentry *dentry, struct iattr *iattr) { return 0; }
     static void cap_inode_attach_pathlabel(struct dentry *dentry, struct vfsmount *mnt) {return;}
     static int cap_inode_stat(struct inode *inode) {return 0;}
     
    -static int cap_file_permission	(struct file *file, int mask)	{return 0;}
    +static int cap_file_permission	(int fd, int mask)	{return 0;}
     static int cap_file_alloc_security	(struct file *file)	{return 0;}
     static void cap_file_free_security	(struct file *file)	{return;}
    -static int cap_file_llseek		(struct file *file)	{return 0;}
    -static int cap_file_read		(struct file *file)	{return 0;}
    -static int cap_file_write		(struct file *file)	{return 0;}
    -static int cap_file_ioctl		(struct file *file, unsigned int command
    +static int cap_file_llseek		(int fd)	{return 0;}
    +static int cap_file_read		(int fd)	{return 0;}
    +static int cap_file_write		(int fd)	{return 0;}
    +static int cap_file_ioctl		(int fd, unsigned int command
     , unsigned long arg)	{return 0;}
    -static int cap_file_mmap		(struct file *file, unsigned long prot, unsigned long flags)	{return 0;}
    +static int cap_file_mmap		(int fd, unsigned long prot, unsigned long flags)	{return 0;}
     static int cap_file_mprotect		(struct vm_area_struct *vma, unsigned long prot)	{return 0;}
    -static int cap_file_lock		(struct file *file)	{return 0;}
    -static int cap_file_readv		(struct file *file)	{return 0;}
    -static int cap_file_writev		(struct file *file)	{return 0;}
    -static int cap_file_fcntl		(struct file *file, unsigned int cmd, unsigned long arg)	{return 0;}
    -static int cap_file_fcntl64		(struct file *file, unsigned int cmd, unsigned long arg)	{return 0;}
    -static int cap_file_set_fowner	(struct file *file)	{return 0;}
    +static int cap_file_lock		(int fd)	{return 0;}
    +static int cap_file_readv		(int fd)	{return 0;}
    +static int cap_file_writev		(int fd)	{return 0;}
    +static int cap_file_fcntl		(int fd, unsigned int cmd, unsigned long arg)	{return 0;}
    +static int cap_file_fcntl64		(int fd, unsigned int cmd, unsigned long arg)	{return 0;}
    +static int cap_file_set_fowner	(int fd)	{return 0;}
     static int cap_file_send_sigiotask	(struct task_struct *tsk, struct fown_struct *fown, int fd, int reason) { return 0; }
     
     static int cap_task_create		(void)	{return 0;}
    @@ -279,8 +282,8 @@
     
     static int cap_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags) { return 0; }
     static int cap_task_setgroups(int gidsetsize, gid_t *grouplist) { return 0; }
    -static int cap_task_setnice(struct task_struct *p, int nice) { return 0; }
    -static int cap_task_setrlimit(unsigned int resource, struct rlimit *new_rlim) { return 0; }
    +static int cap_task_setnice(struct task_struct *p, int nice, int which, int who) { return 0; }
    +static int cap_task_setrlimit(unsigned int resource, struct rlimit *new_rlim, struct rlimit *old_rlim) { return 0; }
     static int cap_task_setscheduler(struct task_struct *p, int policy) { return 0; }
     static int cap_task_wait		(struct task_struct *p) {return 0;}
     
    @@ -302,11 +305,12 @@
     static int cap_ipc_permission(struct kern_ipc_perm *ipcp, short flag) { return 0; }
     static int cap_ipc_getinfo(int id, int cmd) {return 0;}
     
    -static int cap_msg_queue_create	(key_t key)	{return 0;}
    -static int cap_msg_queue_permission	(void)	{return 0;}
    -static int cap_msg_queue_setmaxqbytes	(void)	{return 0;}
    -static int cap_msg_queue_setattr	(void)	{return 0;}
    -static int cap_msg_queue_delete	(void)	{return 0;}
    +static int cap_msg_queue_alloc_security(struct msg_queue *msq) {return 0;}
    +static void cap_msg_queue_free_security(struct msg_queue *msq) {return;}
    +static int cap_msg_queue_associate(struct msg_queue *msq, int msqid, int msqflg) {return 0;}
    +static int cap_msg_queue_msgctl(struct msg_queue *msq, int msqid, int cmd) {return 0;}
    +static int cap_msg_queue_msgsnd(struct msg_queue *msq) {return 0;}
    +static int cap_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, int msqid, int msgflg) {return 0;}
     
     static int cap_shm_alloc_security(struct shmid_kernel *shp) {return 0;}
     static void cap_shm_free_security(struct shmid_kernel *shp) {return;}
    @@ -414,11 +418,12 @@
     };
     
     static struct msg_queue_security_ops cap_msg_queue_ops = {
    -	create:		cap_msg_queue_create,
    -	permission:	cap_msg_queue_permission,
    -	setmaxqbytes:	cap_msg_queue_setmaxqbytes,
    -	setattr:	cap_msg_queue_setattr,
    -	delete:		cap_msg_queue_delete,
    +	alloc_security:	cap_msg_queue_alloc_security,
    +	free_security:	cap_msg_queue_free_security,
    +	associate:	cap_msg_queue_associate,
    +	msgctl:		cap_msg_queue_msgctl,
    +	msgsnd:		cap_msg_queue_msgsnd,
    +	msgrcv:		cap_msg_queue_msgrcv,
     };
     
     static struct shm_security_ops cap_shm_ops = {
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/kernel/exit.c ./kernel/exit.c
    --- /work/bitkeeper/lsm/kernel/exit.c	Fri Jun 22 13:56:10 2001
    +++ ./kernel/exit.c	Mon Jun 25 10:14:57 2001
    @@ -44,7 +44,6 @@
     		task_unlock(p);
     #endif
     		atomic_dec(&p->user->processes);
    -		security_ops->task_ops->free_security(p);
     		free_uid(p->user);
     		unhash_process(p);
     
    @@ -439,6 +438,7 @@
     #ifdef CONFIG_BSD_PROCESS_ACCT
     	acct_process(code);
     #endif
    +	security_ops->task_ops->free_security(tsk);
     	__exit_mm(tsk);
     
     	lock_kernel();
    @@ -485,6 +485,7 @@
     
     asmlinkage long sys_exit(int error_code)
     {
    +	security_ops->task_ops->exit(error_code);
     	do_exit((error_code&0xff)<<8);
     }
     
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/kernel/fork.c ./kernel/fork.c
    --- /work/bitkeeper/lsm/kernel/fork.c	Fri Jun 22 13:56:10 2001
    +++ ./kernel/fork.c	Mon Jun 25 10:14:58 2001
    @@ -564,8 +564,10 @@
     
     	if (clone_flags & CLONE_PID) {
     		/* This is only allowed from the boot up thread */
    -		if (current->pid)
    +		if (current->pid) {
    +			security_ops->task_ops->fork(-EPERM);
     			return -EPERM;
    +		}
     	}
     	
     	current->vfork_sem = &sem;
    @@ -577,8 +579,10 @@
     	*p = *current;
     
     	retval = -EAGAIN;
    -	if (atomic_read(&p->user->processes) >= p->rlim[RLIMIT_NPROC].rlim_cur)
    +
    +	if (security_ops->task_ops->fork(0))
     		goto bad_fork_free;
    +	
     	atomic_inc(&p->user->__count);
     	atomic_inc(&p->user->processes);
     
    @@ -707,6 +711,7 @@
     fork_out:
     	if ((clone_flags & CLONE_VFORK) && (retval > 0)) 
     		down(&sem);
    +	security_ops->return_status(retval);
     	return retval;
     
     bad_fork_cleanup_mm:
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/kernel/module.c ./kernel/module.c
    --- /work/bitkeeper/lsm/kernel/module.c	Fri Jun 22 13:56:10 2001
    +++ ./kernel/module.c	Tue Jun 26 08:14:29 2001
    @@ -298,8 +298,6 @@
     	struct module *mod;
     	unsigned long flags;
     
    -	if (!capable(CAP_SYS_MODULE))
    -		return -EPERM;
     	lock_kernel();
     	if ((namelen = get_mod_name(name_user, &name)) < 0) {
     		error = namelen;
    @@ -343,6 +341,7 @@
     	put_mod_name(name);
     err0:
     	unlock_kernel();
    +	security_ops->return_status(error);
     	return error;
     }
     
    @@ -359,8 +358,6 @@
     	unsigned long mod_user_size;
     	struct module_ref *dep;
     
    -	if (!capable(CAP_SYS_MODULE))
    -		return -EPERM;
     	lock_kernel();
     	if ((namelen = get_mod_name(name_user, &name)) < 0) {
     		error = namelen;
    @@ -593,6 +590,7 @@
     err0:
     	unlock_kernel();
     	kfree(name_tmp);
    +	security_ops->return_status(error);
     	return error;
     }
     
    @@ -656,6 +654,9 @@
     		goto out;
     	}
     
    +	if ((error=security_ops->module_ops->delete_module(NULL)))
    +		goto out;
    +
     	/* Do automatic reaping */
     restart:
     	something_changed = 0;
    @@ -693,6 +694,7 @@
     	error = 0;
     out:
     	unlock_kernel();
    +	security_ops->return_status(error);
     	return error;
     }
     
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/kernel/sched.c ./kernel/sched.c
    --- /work/bitkeeper/lsm/kernel/sched.c	Fri Jun 22 13:56:10 2001
    +++ ./kernel/sched.c	Mon Jun 25 10:14:59 2001
    @@ -849,12 +849,8 @@
     	 *	We don't have to worry. Conceptually one call occurs first
     	 *	and we have a single winner.
     	 */
    -	if (increment < 0) {
    -		if (!capable(CAP_SYS_NICE))
    -			return -EPERM;
    -		if (increment < -40)
    -			increment = -40;
    -	}
    +	if (increment < -40)
    +		increment = -40;
     	if (increment > 40)
     		increment = 40;
     
    @@ -864,11 +860,14 @@
     	if (newprio > 19)
     		newprio = 19;
     
    -	retval = security_ops->task_ops->setnice(current, newprio);
    -	if (retval)
    +	retval = security_ops->task_ops->setnice(current, newprio,PRIO_PROCESS,0);
    +	if (retval) { 
    +		security_ops->return_status(retval);
     		return retval;
    +	}
     	
     	current->nice = newprio;
    +	security_ops->return_status(0);
     	return 0;
     }
     
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/kernel/security.c ./kernel/security.c
    --- /work/bitkeeper/lsm/kernel/security.c	Fri Jun 22 13:56:10 2001
    +++ ./kernel/security.c	Tue Jun 26 08:41:05 2001
    @@ -45,12 +45,15 @@
     static void dummy_umount_close	(struct vfsmount *mnt)									{return;}
     static void dummy_umount_busy	(struct vfsmount *mnt)									{return;}
     static int dummy_remount	(struct vfsmount *mnt, unsigned long flags, void *data)					{return 0;}
    -static void dummy_post_remount	(struct vfsmount *mnt, unsigned long flags, void *data)					{return;}
    +static void dummy_post_remount	(struct vfsmount *mnt, unsigned long flags, void *data, int error)					{return;}
     static int dummy_ioperm	(unsigned long from, unsigned long num, int turn_on)	{return 0;}
     static int dummy_iopl	(unsigned int old, unsigned int level)	{return 0;}
    -static int dummy_ptrace		(struct task_struct *parent, struct task_struct *child)	{return 0;}
    -static int dummy_setcapablity	(void)	{return 0;}
    -static int dummy_acct		(struct file *file)	{return 0;}
    +static int dummy_ptrace		(long pid, long request,struct task_struct *parent, struct task_struct *child)	{return 0;}
    +static int dummy_setcapability        (int pid, struct task_struct * target, __u32 version, kernel_cap_t *inheritable, kernel_cap_t * permitted, kernel_cap_t * effective)     {return 0;}
    +static void dummy_exit        (int error_code) {return;}
    +static int dummy_fork     (int error_code) {return 0;}
    +
    +static int dummy_acct		(int fd)	{return 0;}
     
     static int dummy_capable(struct task_struct *tsk, int cap)
     {
    @@ -63,6 +66,13 @@
     }
     
     static int dummy_sysctl         (ctl_table * table, int op)     {return 0;}
    +static int dummy_bdflush(int func) { return 0; }
    +static int dummy_quotactl(int cmd, int subcmd, const char * path, int id) {return 0;};
    +static void dummy_return_status		(long status) {return;}
    +static int dummy_return_pipe_status (int error, int fd[2]) { return 0 ; }
    +static int dummy_return_dup_status (int error, int fd1, int fd2) { return 0 ; }
    +static int dummy_execve (const char * path) { return 0 ; }
    +static int dummy_chroot(const char *path) {return 0;}
     
     static int dummy_binprm_alloc_security(struct linux_binprm *bprm)	{return 0;}
     static void dummy_binprm_free_security	(struct linux_binprm *bprm)		{return;}
    @@ -75,43 +85,51 @@
     static int dummy_inode_alloc_security	(struct inode *inode)	{return 0;}
     static void dummy_inode_free_security	(struct inode *inode)	{return;}
     static int dummy_inode_create		(struct inode *inode, struct dentry *dentry, int mask) {return 0;}
    -static void dummy_inode_post_create	(struct inode *inode, struct dentry *dentry, int mask) {return;}
    +static void dummy_inode_post_create	(struct inode *inode, struct dentry *dentry, int mask, int error) {return;}
     static int dummy_inode_link		(struct dentry *old_dentry, struct inode *inode, struct dentry *new_dentry) {return 0;}
    -static void dummy_inode_post_link	(struct dentry *old_dentry, struct inode *inode, struct dentry *new_dentry) {return;}
    +static void dummy_inode_post_link	(struct dentry *old_dentry, struct inode *inode, struct dentry *new_dentry, int error) {return;}
     static int dummy_inode_unlink		(struct inode *inode, struct dentry *dentry) {return 0;}
     static int dummy_inode_symlink		(struct inode *inode, struct dentry *dentry, const char *name) {return 0;}
    -static void dummy_inode_post_symlink	(struct inode *inode, struct dentry *dentry, const char *name) {return;}
    +static void dummy_inode_post_symlink	(struct inode *inode, struct dentry *dentry, const char *name, int error) {return;}
     static int dummy_inode_mkdir		(struct inode *inode, struct dentry *dentry, int mask) {return 0;}
    -static void dummy_inode_post_mkdir	(struct inode *inode, struct dentry *dentry, int mask) {return;}
    +static void dummy_inode_post_mkdir	(struct inode *inode, struct dentry *dentry, int mask, int retval, int error) {return;}
     static int dummy_inode_rmdir		(struct inode *inode, struct dentry *dentry) {return 0;}
     static int dummy_inode_mknod		(struct inode *inode, struct dentry *dentry, int major, dev_t minor) {return 0;}
    -static void dummy_inode_post_mknod	(struct inode *inode, struct dentry *dentry, int major, dev_t minor) {return;}
    +static void dummy_inode_post_mknod	(struct inode *inode, struct dentry *dentry, int major, dev_t minor, int error) {return;}
     static int dummy_inode_rename		(struct inode *old_inode, struct dentry *old_dentry, struct inode *new_inode, struct dentry *new_dentry) {return 0;}
    -static void dummy_inode_post_rename	(struct inode *old_inode, struct dentry *old_dentry, struct inode *new_inode, struct dentry *new_dentry) {return;}
    +static void dummy_inode_post_rename	(struct inode *old_inode, struct dentry *old_dentry, struct inode *new_inode, struct dentry *new_dentry, int error) {return;}
     static int dummy_inode_readlink		(struct dentry *dentry, char *name, int mask) {return 0;}
     static int dummy_inode_follow_link	(struct dentry *dentry, struct nameidata *nameidata) {return 0;}
    -static int dummy_inode_truncate		(struct inode *inode) {return 0;}
    +static int dummy_inode_truncate		(const char *path,struct inode *inode, loff_t length) {return 0;}
    +static int dummy_inode_ftruncate(int fd, loff_t length) {return 0;}
     static int dummy_inode_permission(struct inode *inode, int mask) { return 0; }
    +static int dummy_inode_vfs_permission(struct inode *inode, int mask) { return 0; }
     static int dummy_inode_revalidate	(struct dentry *inode) {return 0;}
     static int dummy_inode_setattr(struct dentry *dentry, struct iattr *iattr) { return 0; }
    +static int dummy_inode_changeattr(struct inode *inode, struct iattr *iattr) { return 0; }
     static void dummy_inode_attach_pathlabel(struct dentry *dentry, struct vfsmount *mnt) {return;}
     static int dummy_inode_stat(struct inode *inode) {return 0;}
    +static void dummy_inode_post_utime(struct dentry *dentry, struct iattr *attr, int error) {return;}
    +static int dummy_inode_chdir(const char *dir) {return 0;}
    +static int dummy_inode_fchdir(int fd) {return 0;}
    +static int dummy_inode_chmod(const char *dir, mode_t mode) {return 0;}
    +static int dummy_inode_fchmod(int fd, mode_t mode) {return 0;}
     
    -static int dummy_file_permission	(struct file *file, int mask)	{return 0;}
    +static int dummy_file_permission	(int fd, int mask)	{return 0;}
     static int dummy_file_alloc_security	(struct file *file)	{return 0;}
     static void dummy_file_free_security	(struct file *file)	{return;}
    -static int dummy_file_llseek		(struct file *file)	{return 0;}
    -static int dummy_file_read		(struct file *file)	{return 0;}
    -static int dummy_file_write		(struct file *file)	{return 0;}
    -static int dummy_file_ioctl		(struct file *file, unsigned int command, unsigned long arg)	{return 0;}
    -static int dummy_file_mmap		(struct file *file, unsigned long prot, unsigned long flags)	{return 0;}
    +static int dummy_file_llseek		(int fd)	{return 0;}
    +static int dummy_file_read		(int fd)	{return 0;}
    +static int dummy_file_write		(int fd)	{return 0;}
    +static int dummy_file_ioctl		(int fd, unsigned int command, unsigned long arg)	{return 0;}
    +static int dummy_file_mmap		(int fd, unsigned long prot, unsigned long flags)	{return 0;}
     static int dummy_file_mprotect		(struct vm_area_struct *vma, unsigned long prot)	{return 0;}
    -static int dummy_file_lock		(struct file *file)	{return 0;}
    -static int dummy_file_readv		(struct file *file)	{return 0;}
    -static int dummy_file_writev		(struct file *file)	{return 0;}
    -static int dummy_file_fcntl		(struct file *file, unsigned int cmd, unsigned long arg)	{return 0;}
    -static int dummy_file_fcntl64		(struct file *file, unsigned int cmd, unsigned long arg)	{return 0;}
    -static int dummy_file_set_fowner	(struct file *file)	{return 0;}
    +static int dummy_file_lock		(int fd)	{return 0;}
    +static int dummy_file_readv		(int fd)	{return 0;}
    +static int dummy_file_writev		(int fd)	{return 0;}
    +static int dummy_file_fcntl		(int fd, unsigned int cmd, unsigned long arg)	{return 0;}
    +static int dummy_file_fcntl64		(int fd, unsigned int cmd, unsigned long arg)	{return 0;}
    +static int dummy_file_set_fowner	(int fd)	{return 0;}
     static int dummy_file_send_sigiotask	(struct task_struct *tsk, struct fown_struct *fown, int fd, int reason)		{return 0;}
     
     static int dummy_task_create		(void)	{return 0;}
    @@ -121,8 +139,11 @@
     static int dummy_task_post_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) { return 0; }
     static int dummy_task_setgid	(gid_t id0, gid_t id1, gid_t id2, int flags)	{return 0;}
     static int dummy_task_setgroups	(int gidsetsize, gid_t *grouplist) {return 0;}
    -static int dummy_task_setnice	(struct task_struct *p, int nice) {return 0;}
    -static int dummy_task_setrlimit	(unsigned int resource, struct rlimit *new_rlim)	{return 0;}
    +static int dummy_task_setnice	(struct task_struct *p, int nice, int which, int who) {return 0;}
    +static int dummy_task_setrlimit	(unsigned int resource, struct rlimit *new_rlim, struct rlimit *old_rlim)	{return 0;}
    +static int dummy_task_prctl		(int option, unsigned long arg2, unsigned long arg3, 
    +		unsigned long arg4, unsigned long arg5)		{return 0;}
    +
     static int dummy_task_setscheduler	(struct task_struct *p, int policy)	{return 0;}
     static int dummy_task_wait		(struct task_struct *p) {return 0;}
     static int dummy_task_kill		(struct task_struct *p, struct siginfo *info, int sig)	{return 0;}
    @@ -195,11 +216,19 @@
     	readlink:	dummy_inode_readlink,
     	follow_link:	dummy_inode_follow_link,
     	truncate:	dummy_inode_truncate,
    +	ftruncate:	dummy_inode_ftruncate,
     	permission:	dummy_inode_permission,
    +	vfs_permission:	dummy_inode_vfs_permission,
     	revalidate:	dummy_inode_revalidate,
     	setattr:	dummy_inode_setattr,
    +	changeattr:	dummy_inode_changeattr,
     	attach_pathlabel:dummy_inode_attach_pathlabel,
     	stat:           dummy_inode_stat,
    +	post_utime:     dummy_inode_post_utime,
    +	chdir:     dummy_inode_chdir,
    +	fchdir:     dummy_inode_fchdir,
    +	chmod:     dummy_inode_chmod,
    +	fchmod:     dummy_inode_fchmod,
     };
     
     static struct file_security_ops	dummy_file_ops = {
    @@ -231,9 +260,12 @@
     	setgroups:	dummy_task_setgroups,
     	setnice:	dummy_task_setnice,
     	setrlimit:	dummy_task_setrlimit,
    +	prctl: 		dummy_task_prctl,
     	setscheduler:	dummy_task_setscheduler,
     	wait:		dummy_task_wait,
     	kill:		dummy_task_kill,
    +	exit:			dummy_exit,
    +	fork:			dummy_fork,
     	set_label:	dummy_task_set_label,
     	reset_label:	dummy_task_reset_label,
     	kmod_set_label:  dummy_task_kmod_set_label
    @@ -300,10 +332,16 @@
     	ioperm:			dummy_ioperm,
     	iopl:			dummy_iopl,
     	ptrace:			dummy_ptrace,
    -	setcapability:		dummy_setcapablity,
    +	setcapability:		dummy_setcapability,
     	acct:			dummy_acct,
     	capable:		dummy_capable,
     	sysctl:			dummy_sysctl,
    +	execve:			dummy_execve,
    +	return_pipe_status:	dummy_return_pipe_status,
    +	return_dup_status:	dummy_return_dup_status,
    +	quotactl:		dummy_quotactl,
    +	bdflush:		dummy_bdflush,
    +	chroot:		dummy_chroot,
     
     	bprm_ops:		&dummy_binprm_ops,
     	sb_ops:			&dummy_sb_ops,
    @@ -320,6 +358,7 @@
     	
     	register_security:	dummy_register,
     	unregister_security:	dummy_unregister,
    +	return_status:		dummy_return_status,
     };
     
     
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/kernel/std_sec.c ./kernel/std_sec.c
    --- /work/bitkeeper/lsm/kernel/std_sec.c	Wed Dec 31 16:00:00 1969
    +++ ./kernel/std_sec.c	Tue Jun 26 08:50:23 2001
    @@ -0,0 +1,398 @@
    +/*
    + * linux/kernel/std_sec.c
    + *
    + */
    + 
    +#include <linux/mm.h>
    +#include <asm/uaccess.h>
    +#include <linux/capability.h>
    +
    +
    +static inline int std_capable(int cap)
    +{
    +	/* verbatim copy from sched.h definition of capable */
    +#if 1 /* ok now */
    +	if (cap_raised(current->cap_effective, cap))
    +#else
    +	if (cap_is_fs_cap(cap) ? current->fsuid == 0 : current->euid == 0)
    +#endif
    +        {
    +                current->flags |= PF_SUPERPRIV;
    +                return 1;
    +        }
    +        return 0;
    +}
    +
    +int std_acct(const char * name)
    +{
    +	if (!std_capable(CAP_SYS_PACCT)) return -EPERM;
    +	return 0;
    +}
    +
    +int std_setcapability(const int pid, const struct task_struct * target, 
    +		const __u32 version, const kernel_cap_t *inheritable, 
    +		const kernel_cap_t * permitted, const kernel_cap_t * effective)
    +{
    +	int error=-EINVAL;
    +
    +	if (!inheritable || !target || !permitted || !effective)
    +		goto out;
    +
    +     error = -EPERM;
    +
    +     if (target->pid && !std_capable(CAP_SETPCAP))
    +             goto out;
    +
    +     /* verify restrictions on target's new Inheritable set */
    +     if (!cap_issubset(*inheritable,
    +                       cap_combine(target->cap_inheritable,
    +                                   current->cap_permitted))) {
    +             goto out;
    +     }
    +
    +     /* verify restrictions on target's new Permitted set */
    +     if (!cap_issubset(*permitted,
    +                       cap_combine(target->cap_permitted,
    +                                   current->cap_permitted))) {
    +             goto out;
    +     }
    +
    +     /* verify the _new_Effective_ is a subset of the _new_Permitted_ */
    +     if (!cap_issubset(*effective, *permitted)) {
    +             goto out;
    +     }
    +	error=0;
    +
    +out:
    +	return error;
    +}
    +
    +
    +int std_fork(int error)
    +{
    +	if (!error)
    +		return (atomic_read(&current->user->processes) >= current->rlim[RLIMIT_NPROC].rlim_cur);
    +	return error;
    +}
    +
    +int std_ioperm(unsigned long from, unsigned long num, int turn_on, int retval)
    +{
    +	if ( turn_on && ! std_capable(CAP_SYS_RAWIO))
    +			return retval;
    +	return 0;
    +}
    +
    +int std_iopl(unsigned int old, unsigned int level, int retval)
    +{
    +	if ( ! std_capable(CAP_SYS_RAWIO))
    +		return retval;
    +	return 0;
    +}
    +
    +int std_vfs_permission(struct inode * inode,int mask)
    +{
    +	int mode = inode->i_mode;
    +
    +	if ((mask & S_IWOTH) && IS_RDONLY(inode) &&
    +		 (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
    +		return -EROFS; /* Nobody gets write access to a read-only fs */
    +
    +	if ((mask & S_IWOTH) && IS_IMMUTABLE(inode))
    +		return -EACCES; /* Nobody gets write access to an immutable file */
    +
    +	if (current->fsuid == inode->i_uid)
    +		mode >>= 6;
    +	else if (in_group_p(inode->i_gid))
    +		mode >>= 3;
    +
    +	if (((mode & mask & S_IRWXO) == mask) || std_capable(CAP_DAC_OVERRIDE))
    +		return 0;
    +
    +	/* read and search access */
    +	if ((mask == S_IROTH) ||
    +	    (S_ISDIR(inode->i_mode)  && !(mask & ~(S_IROTH | S_IXOTH))))
    +		if (std_capable(CAP_DAC_READ_SEARCH))
    +			return 0;
    +
    +	return -EACCES;	
    +}
    +
    +int std_ptrace(long pid, long request, struct task_struct *parent, struct task_struct *child )
    +{
    +	if ( pid == 1 ) /* do not mess with in init */
    +		return -EPERM;
    +	return 0;
    +}
    +
    +int std_bdflush(int func)
    +{
    +	return ( std_capable(CAP_SYS_ADMIN) ? 0 : -EPERM );
    +	
    +}
    +
    +int std_quotactl(int cmd, int subcmd, const char * path, int id)
    +{
    +	int ret=0;
    +	
    +	switch ( cmd ) {
    +		case Q_SYNC:
    +		case Q_GETSTATS:
    +			break;
    +		case Q_GETQUOTA:
    +			if (((subcmd == USRQUOTA && current->euid != id) || 
    +						(subcmd == GRPQUOTA && !in_egroup_p(id))) && 
    +					!std_capable(CAP_SYS_RESOURCE))
    +				ret=-EPERM;
    +			break;
    +		default:
    +			if ( !std_capable(CAP_SYS_RESOURCE))
    +				ret=-EPERM;
    +			break;
    +	}
    +	return ret;	
    +}
    +
    +
    +int std_inode_changeattr(struct inode *inode, struct iattr *attr)
    +{
    +/* POSIX UID/GID verification for setting inode attributes. */	
    +	int retval=-EPERM;
    +	unsigned int ia_valid = attr->ia_valid;
    +
    +	/* If force is set do it anyway. */
    +	if (ia_valid & ATTR_FORCE)
    +		goto fine;
    +
    +	/* Make sure a caller can chown. */
    +	if ((ia_valid & ATTR_UID) &&
    +	    (current->fsuid != inode->i_uid ||
    +	     attr->ia_uid != inode->i_uid) && !std_capable(CAP_CHOWN))
    +		goto error;
    +
    +	/* Make sure caller can chgrp. */
    +	if ((ia_valid & ATTR_GID) &&
    +	    (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid) &&
    +	    !std_capable(CAP_CHOWN))
    +		goto error;
    +
    +	/* Make sure a caller can chmod. */
    +	if (ia_valid & ATTR_MODE) {
    +		if ((current->fsuid != inode->i_uid) && !std_capable(CAP_FOWNER))
    +			goto error;
    +		/* Also check the setgid bit! */
    +		if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
    +				inode->i_gid) && !std_capable(CAP_FSETID))
    +			attr->ia_mode &= ~S_ISGID;
    +	}
    +
    +	/* Check for setting the inode time. */
    +	if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) {
    +		if (current->fsuid != inode->i_uid && !std_capable(CAP_FOWNER))
    +			goto error;
    +	}
    +fine:
    +	retval = 0;
    +error:
    +	return retval;	
    +}
    +
    +int std_inode_setattr(struct dentry *dentry, struct iattr *attr)
    +{
    +	return std_inode_changeattr(dentry->d_inode,attr);
    +}
    +
    +int std_chroot(const char *path)
    +{
    +	if ( ! std_capable(CAP_SYS_CHROOT) )
    +		return -EPERM;
    +
    +	return 0;
    +}
    +
    +int std_reboot (unsigned int cmd, void * arg)
    +{
    +	if (!std_capable(CAP_SYS_BOOT))
    +		return -EPERM;
    +
    +	return 0;
    +}
    +
    +int std_sethostname (char *name, int len)
    +{
    +	if (!std_capable(CAP_SYS_ADMIN))
    +		return -EPERM;
    +
    +	return 0;
    +}
    +
    +int std_setdomainname (char *name, int len)
    +{
    +	if (!std_capable(CAP_SYS_ADMIN))
    +		return -EPERM;
    +
    +	return 0;
    +}
    +
    +int std_task_setuid (uid_t id0, uid_t id1, uid_t id2, int flags)
    +{
    +	if (capable(CAP_SETUID))
    +		return 0;
    +
    +	switch (flags)
    +	{
    +		case LSM_SETID_RE:
    +			if (id0 != (uid_t) -1)
    +				if (current->uid != id0 && current->euid != id0)
    +					return -EPERM;
    +			if (id1 != (uid_t) -1)
    +				if (current->uid != id1 && current->euid != id1 &&
    +					current->suid != id1)
    +					return -EPERM;
    +			break;
    +		case LSM_SETID_ID:
    +			if (id0 != current->uid && id0 != current->suid)
    +				return -EPERM;
    +			break;
    +		case LSM_SETID_RES:
    +			if ((id0 != (uid_t) -1) && (id0 != current->uid) &&
    +				(id0 != current->euid) && (id0 != current->suid))
    +				return -EPERM;
    +			if ((id1 != (uid_t) -1) && (id1 != current->uid) &&
    +				(id1 != current->euid) && (id1 != current->suid))
    +				return -EPERM;
    +			if ((id2 != (uid_t) -1) && (id2 != current->uid) &&
    +				(id2 != current->euid) && (id2 != current->suid))
    +				return -EPERM;
    +			break;
    +		case LSM_SETID_FS:
    +			if (id0 != current->uid && id0 != current->euid &&
    +				id0 != current->suid && id0 != current->fsuid)
    +				return -EPERM;
    +			break;
    +	}
    +
    +	return 0;
    +}
    +
    +int std_task_setgid (gid_t id0, gid_t id1, gid_t id2, int flags)
    +{
    +	if (capable(CAP_SETGID))
    +		return 0;
    +
    +	switch (flags)
    +	{
    +		case LSM_SETID_RE:
    +			if (id0 != (gid_t) -1)
    +				if (current->gid != id0 && current->egid != id0)
    +					return -EPERM;
    +			if (id1 != (gid_t) -1)
    +				if (current->gid != id1 && current->egid != id1 &&
    +					current->sgid != id1)
    +					return -EPERM;
    +			break;
    +		case LSM_SETID_ID:
    +			if (id0 != current->gid && id0 != current->sgid)
    +				return -EPERM;
    +			break;
    +		case LSM_SETID_RES:
    +			if ((id0 != (gid_t) -1) && (id0 != current->gid) &&
    +				(id0 != current->egid) && (id0 != current->sgid))
    +				return -EPERM;
    +			if ((id1 != (gid_t) -1) && (id1 != current->gid) &&
    +				(id1 != current->egid) && (id1 != current->sgid))
    +				return -EPERM;
    +			if ((id2 != (gid_t) -1) && (id2 != current->gid) &&
    +				(id2 != current->egid) && (id2 != current->sgid))
    +				return -EPERM;
    +			break;
    +		case LSM_SETID_FS:
    +			if (id0 != current->gid && id0 != current->egid &&
    +				id0 != current->sgid && id0 != current->fsgid)
    +				return -EPERM;
    +			break;
    +	}
    +
    +	return 0;
    +}
    +
    +int std_task_setpgid (struct task_struct *p, pid_t pid, pid_t pgid)
    +{
    +	return 0;
    +}
    +
    +int std_task_getpgid (struct task_struct *p, pid_t pid)
    +{
    +	return 0;
    +}
    +
    +int std_task_setsid (pid_t pid)
    +{
    +	return 0;
    +}
    +
    +int std_task_getsid (struct task_struct *p, pid_t pid)
    +{
    +	return 0;
    +}
    +
    +int std_task_setgroups (int gidsetsize, gid_t *grouplist)
    +{
    +	if (!capable(CAP_SETGID))
    +		return -EPERM;
    +
    +	return 0;
    +}
    +
    +int std_task_setnice (struct task_struct *p, int niceval, int which, int who)
    +{
    +	if (p->uid != current->euid &&
    +		p->uid != current->uid && !capable(CAP_SYS_NICE))
    +		return -EPERM;
    +
    +	if (niceval < p->nice && !capable(CAP_SYS_NICE))
    +		return -EACCES;
    +
    +	return 0;
    +}
    +
    +int std_task_setrlimit (unsigned int resource, struct rlimit *new_rlim, struct rlimit *old_rlim)
    +{
    +	if (((new_rlim->rlim_cur > old_rlim->rlim_max) ||
    +		(new_rlim->rlim_max > old_rlim->rlim_max)) &&
    +		!capable (CAP_SYS_RESOURCE))
    +		return -EPERM;
    +
    +	if (resource == RLIMIT_NOFILE)
    +		if (new_rlim->rlim_cur > NR_OPEN || new_rlim->rlim_max > NR_OPEN)
    +			return -EPERM;
    +
    +	return 0;
    +}
    +
    +int std_task_prctl (int option, unsigned long arg2, unsigned long arg3,
    +				unsigned long arg4, unsigned long arg5)
    +{
    +	return 0;
    +}
    +
    +int std_create_module(const char * name, size_t size)
    +{
    +	if (!capable(CAP_SYS_MODULE)) 
    +		return -EPERM;
    +	return 0;
    +}
    +
    +
    +int std_init_module(const char *name, struct module * mod)
    +{
    +	if (!capable(CAP_SYS_MODULE))
    +		return -EPERM;
    +	return 0;
    +}
    +
    +int std_delete_module(const char *name)
    +{
    +	if (!capable(CAP_SYS_MODULE)) 
    +		return -EPERM;
    +	return 0;
    +}
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/kernel/sys.c ./kernel/sys.c
    --- /work/bitkeeper/lsm/kernel/sys.c	Fri Jun 22 13:56:10 2001
    +++ ./kernel/sys.c	Tue Jun 26 08:55:42 2001
    @@ -209,30 +209,25 @@
     	if (niceval > 19)
     		niceval = 19;
     
    +	error = security_ops->task_ops->setnice(NULL, niceval, which, who);
    +	if (error) {
    +		security_ops->return_status(error);
    +		return error;
    +	}
    +	error=-EINVAL;
    +
     	read_lock(&tasklist_lock);
     	for_each_task(p) {
    -		int no_nice;
     		if (!proc_sel(p, which, who))
     			continue;
    -		no_nice = security_ops->task_ops->setnice(p, niceval);
    -		if (no_nice) {
    -			error = no_nice;
    -			continue;
    -		}
    -		if (p->uid != current->euid &&
    -			p->uid != current->uid && !capable(CAP_SYS_NICE)) {
    -			error = -EPERM;
    +		error = security_ops->task_ops->setnice(p, niceval, which, who);
    +		if (error)
     			continue;
    -		}
    -		if (error == -ESRCH)
    -			error = 0;
    -		if (niceval < p->nice && !capable(CAP_SYS_NICE))
    -			error = -EACCES;
    -		else
    -			p->nice = niceval;
    +		p->nice = niceval;
     	}
     	read_unlock(&tasklist_lock);
     
    +	security_ops->return_status(error);
     	return error;
     }
     
    @@ -278,26 +273,25 @@
     	char buffer[256];
     	int retval;
     
    -	/* We only trust the superuser with rebooting the system. */
    -	if (!capable(CAP_SYS_BOOT))
    -		return -EPERM;
    +	/* For safety, we require "magic" arguments. */
    +	if (magic1 != LINUX_REBOOT_MAGIC1 ||
    +	    (magic2 != LINUX_REBOOT_MAGIC2 && magic2 != LINUX_REBOOT_MAGIC2A &&
    +			magic2 != LINUX_REBOOT_MAGIC2B)) {
    +		return -EINVAL;
    +	}
     
     	retval = security_ops->reboot(cmd, arg);
     	if (retval) {
    +		security_ops->return_status(retval);
     		return retval;
     	}
     
    -	/* For safety, we require "magic" arguments. */
    -	if (magic1 != LINUX_REBOOT_MAGIC1 ||
    -	    (magic2 != LINUX_REBOOT_MAGIC2 && magic2 != LINUX_REBOOT_MAGIC2A &&
    -			magic2 != LINUX_REBOOT_MAGIC2B))
    -		return -EINVAL;
    -
     	lock_kernel();
     	switch (cmd) {
     	case LINUX_REBOOT_CMD_RESTART:
     		notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
     		printk(KERN_EMERG "Restarting system.\n");
    +		security_ops->return_status(0);
     		machine_restart(NULL);
     		break;
     
    @@ -312,6 +306,7 @@
     	case LINUX_REBOOT_CMD_HALT:
     		notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL);
     		printk(KERN_EMERG "System halted.\n");
    +		security_ops->return_status(0);
     		machine_halt();
     		do_exit(0);
     		break;
    @@ -319,6 +314,7 @@
     	case LINUX_REBOOT_CMD_POWER_OFF:
     		notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL);
     		printk(KERN_EMERG "Power down.\n");
    +		security_ops->return_status(0);
     		machine_power_off();
     		do_exit(0);
     		break;
    @@ -326,20 +322,24 @@
     	case LINUX_REBOOT_CMD_RESTART2:
     		if (strncpy_from_user(&buffer[0], (char *)arg, sizeof(buffer) - 1) < 0) {
     			unlock_kernel();
    +			security_ops->return_status(-EFAULT);
     			return -EFAULT;
     		}
     		buffer[sizeof(buffer) - 1] = '\0';
     
     		notifier_call_chain(&reboot_notifier_list, SYS_RESTART, buffer);
     		printk(KERN_EMERG "Restarting system with command '%s'.\n", buffer);
    +		security_ops->return_status(0);
     		machine_restart(buffer);
     		break;
     
     	default:
     		unlock_kernel();
    +		security_ops->return_status(-EINVAL);
     		return -EINVAL;
     	}
     	unlock_kernel();
    +	security_ops->return_status(0);
     	return 0;
     }
     
    @@ -397,24 +397,10 @@
     	if (retval)
     		return retval;
     
    -	if (rgid != (gid_t) -1) {
    -		if ((old_rgid == rgid) ||
    -		    (current->egid==rgid) ||
    -		    capable(CAP_SETGID))
    -			new_rgid = rgid;
    -		else
    -			return -EPERM;
    -	}
    -	if (egid != (gid_t) -1) {
    -		if ((old_rgid == egid) ||
    -		    (current->egid == egid) ||
    -		    (current->sgid == egid) ||
    -		    capable(CAP_SETGID))
    -			new_egid = egid;
    -		else {
    -			return -EPERM;
    -		}
    -	}
    +	if (rgid != (gid_t) -1)
    +		new_rgid = rgid;
    +	if (egid != (gid_t) -1)
    +		new_egid = egid;
     	if (new_egid != old_egid)
     	{
     		current->dumpable = 0;
    @@ -426,6 +412,7 @@
     	current->fsgid = new_egid;
     	current->egid = new_egid;
     	current->gid = new_rgid;
    +	security_ops->return_status(0);
     	return 0;
     }
     
    @@ -440,10 +427,8 @@
     	int retval;
     
     	retval = security_ops->task_ops->setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_ID);
    -	if (retval)
    -		return retval;
     
    -	if (capable(CAP_SETGID))
    +	if (!retval)
     	{
     		if(old_egid != gid)
     		{
    @@ -452,18 +437,9 @@
     		}
     		current->gid = current->egid = current->sgid = current->fsgid = gid;
     	}
    -	else if ((gid == current->gid) || (gid == current->sgid))
    -	{
    -		if(old_egid != gid)
    -		{
    -			current->dumpable=0;
    -			wmb();
    -		}
    -		current->egid = current->fsgid = gid;
    -	}
    -	else
    -		return -EPERM;
    -	return 0;
    +
    +	security_ops->return_status(retval);
    +	return retval;
     }
       
     static int set_user(uid_t new_ruid, int dumpclear)
    @@ -514,32 +490,24 @@
     	int retval;
     
     	retval = security_ops->task_ops->setuid(ruid, euid, (uid_t)-1, LSM_SETID_RE);
    -	if (retval)
    +	if (retval) {
    +		security_ops->return_status(retval);
     		return retval;
    +	}
     
     	new_ruid = old_ruid = current->uid;
     	new_euid = old_euid = current->euid;
     	old_suid = current->suid;
     
    -	if (ruid != (uid_t) -1) {
    +	if (ruid != (uid_t) -1)
     		new_ruid = ruid;
    -		if ((old_ruid != ruid) &&
    -		    (current->euid != ruid) &&
    -		    !capable(CAP_SETUID))
    -			return -EPERM;
    -	}
    -
    -	if (euid != (uid_t) -1) {
    +	if (euid != (uid_t) -1)
     		new_euid = euid;
    -		if ((old_ruid != euid) &&
    -		    (current->euid != euid) &&
    -		    (current->suid != euid) &&
    -		    !capable(CAP_SETUID))
    -			return -EPERM;
    -	}
     
    -	if (new_ruid != old_ruid && set_user(new_ruid, new_euid != old_euid) < 0)
    +	if (new_ruid != old_ruid && set_user(new_ruid, new_euid != old_euid) < 0) {
    +		security_ops->return_status(-EAGAIN);
     		return -EAGAIN;
    +	}
     
     	if (new_euid != old_euid)
     	{
    @@ -575,19 +543,20 @@
     	int retval;
     
     	retval = security_ops->task_ops->setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_ID);
    -	if (retval)
    +	if (retval) {
    +		security_ops->return_status(retval);
     		return retval;
    +	}
     
     	old_ruid = new_ruid = current->uid;
     	old_suid = current->suid;
     	new_suid = old_suid;
     	
    -	if (capable(CAP_SETUID)) {
    -		if (uid != old_ruid && set_user(uid, old_euid != uid) < 0)
    -			return -EAGAIN;
    -		new_suid = uid;
    -	} else if ((uid != current->uid) && (uid != new_suid))
    -		return -EPERM;
    +	if (uid != old_ruid && set_user(uid, old_euid != uid) < 0) {
    +		security_ops->return_status(-EAGAIN);
    +		return -EAGAIN;
    +	}
    +	new_suid = uid;
     
     	if (old_euid != uid)
     	{
    @@ -613,23 +582,16 @@
     	int retval;
     
     	retval = security_ops->task_ops->setuid(ruid, euid, suid, LSM_SETID_RES);
    -	if (retval)
    +	if (retval) {
    +		security_ops->return_status(retval);
     		return retval;
    -
    -	if (!capable(CAP_SETUID)) {
    -		if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
    -		    (ruid != current->euid) && (ruid != current->suid))
    -			return -EPERM;
    -		if ((euid != (uid_t) -1) && (euid != current->uid) &&
    -		    (euid != current->euid) && (euid != current->suid))
    -			return -EPERM;
    -		if ((suid != (uid_t) -1) && (suid != current->uid) &&
    -		    (suid != current->euid) && (suid != current->suid))
    -			return -EPERM;
     	}
    +
     	if (ruid != (uid_t) -1) {
    -		if (ruid != current->uid && set_user(ruid, euid != current->euid) < 0)
    +		if (ruid != current->uid && set_user(ruid, euid != current->euid) < 0) {
    +			security_ops->return_status(-EAGAIN);
     			return -EAGAIN;
    +		}
     	}
     	if (euid != (uid_t) -1) {
     		if (euid != current->euid)
    @@ -665,20 +627,11 @@
     	int retval;
     
     	retval = security_ops->task_ops->setgid(rgid, egid, sgid, LSM_SETID_RES);
    -	if (retval)
    +	if (retval) {
    +		security_ops->return_status(retval);
     		return retval;
    -
    -	if (!capable(CAP_SETGID)) {
    -		if ((rgid != (gid_t) -1) && (rgid != current->gid) &&
    -		    (rgid != current->egid) && (rgid != current->sgid))
    -			return -EPERM;
    -		if ((egid != (gid_t) -1) && (egid != current->gid) &&
    -		    (egid != current->egid) && (egid != current->sgid))
    -			return -EPERM;
    -		if ((sgid != (gid_t) -1) && (sgid != current->gid) &&
    -		    (sgid != current->egid) && (sgid != current->sgid))
    -			return -EPERM;
     	}
    +
     	if (egid != (gid_t) -1) {
     		if (egid != current->egid)
     		{
    @@ -692,6 +645,7 @@
     		current->gid = rgid;
     	if (sgid != (gid_t) -1)
     		current->sgid = sgid;
    +	security_ops->return_status(0);
     	return 0;
     }
     
    @@ -719,26 +673,26 @@
     	int retval;
     
     	retval = security_ops->task_ops->setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);
    -	if (retval)
    +	if (retval) {
    +		security_ops->return_status(retval);
     		return retval;
    +	}
     
     	old_fsuid = current->fsuid;
    -	if (uid == current->uid || uid == current->euid ||
    -	    uid == current->suid || uid == current->fsuid || 
    -	    capable(CAP_SETUID))
    +	if (uid != old_fsuid)
     	{
    -		if (uid != old_fsuid)
    -		{
    -			current->dumpable = 0;
    -			wmb();
    -		}
    -		current->fsuid = uid;
    +		current->dumpable = 0;
    +		wmb();
     	}
    +	current->fsuid = uid;
     
     	retval = security_ops->task_ops->post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);
    -	if (retval)
    +	if (retval) {
    +		security_ops->return_status(retval);
     		return retval;
    +	}
     
    +	security_ops->return_status(old_fsuid);
     	return old_fsuid;
     }
     
    @@ -751,21 +705,20 @@
     	int retval;
     
     	retval = security_ops->task_ops->setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS);
    -	if (retval)
    +	if (retval) {
    +		security_ops->return_status(retval);
     		return retval;
    +	}
     
     	old_fsgid = current->fsgid;
    -	if (gid == current->gid || gid == current->egid ||
    -	    gid == current->sgid || gid == current->fsgid || 
    -	    capable(CAP_SETGID))
    +	if (gid != old_fsgid)
     	{
    -		if (gid != old_fsgid)
    -		{
    -			current->dumpable = 0;
    -			wmb();
    -		}
    -		current->fsgid = gid;
    +		current->dumpable = 0;
    +		wmb();
     	}
    +	current->fsgid = gid;
    +
    +	security_ops->return_status(old_fsgid);
     	return old_fsgid;
     }
     
    @@ -818,6 +771,10 @@
     	if (!p)
     		goto out;
     
    +	err = security_ops->task_ops->setpgid(p, pid, pgid);
    +	if (err)
    +		goto out;
    +
     	if (p->p_pptr == current || p->p_opptr == current) {
     		err = -EPERM;
     		if (p->session != current->session)
    @@ -846,24 +803,35 @@
     out:
     	/* All paths lead to here, thus we are safe. -DaveM */
     	read_unlock(&tasklist_lock);
    +	security_ops->return_status(err);
     	return err;
     }
     
     asmlinkage long sys_getpgid(pid_t pid)
     {
    +	int retval;
    +
     	if (!pid) {
    -		return current->pgrp;
    +		retval = security_ops->task_ops->getpgid(current, pid);
    +		if (!retval)
    +			retval = current->pgrp;
    +		security_ops->return_status(retval);
    +		return retval;
     	} else {
    -		int retval;
     		struct task_struct *p;
     
     		read_lock(&tasklist_lock);
     		p = find_task_by_pid(pid);
     
     		retval = -ESRCH;
    -		if (p)
    -			retval = p->pgrp;
    +		if (p) {
    +			retval = security_ops->task_ops->getpgid(p, pid);
    +
    +			if (!retval)
    +				retval = p->pgrp;
    +		}
     		read_unlock(&tasklist_lock);
    +		security_ops->return_status(retval);
     		return retval;
     	}
     }
    @@ -876,19 +844,29 @@
     
     asmlinkage long sys_getsid(pid_t pid)
     {
    +	int retval;
    +
     	if (!pid) {
    -		return current->session;
    +		retval = security_ops->task_ops->getsid(current, pid);
    +		if (!retval)
    +			retval = current->session;
    +		security_ops->return_status(retval);
    +		return retval;
     	} else {
    -		int retval;
     		struct task_struct *p;
     
     		read_lock(&tasklist_lock);
     		p = find_task_by_pid(pid);
     
     		retval = -ESRCH;
    -		if(p)
    -			retval = p->session;
    +		if(p) {
    +			retval = security_ops->task_ops->getsid(p, pid);
    +
    +			if (!retval)
    +				retval = p->session;
    +		}
     		read_unlock(&tasklist_lock);
    +		security_ops->return_status(retval);
     		return retval;
     	}
     }
    @@ -896,8 +874,15 @@
     asmlinkage long sys_setsid(void)
     {
     	struct task_struct * p;
    -	int err = -EPERM;
    +	int err;
     
    +	err = security_ops->task_ops->setsid(current->pid);
    +	if (err) {
    +		security_ops->return_status(err);
    +		return err;
    +	}
    +
    +	err = -EPERM;
     	read_lock(&tasklist_lock);
     	for_each_task(p) {
     		if (p->pgrp == current->pid)
    @@ -911,6 +896,7 @@
     	err = current->pgrp;
     out:
     	read_unlock(&tasklist_lock);
    +	security_ops->return_status(err);
     	return err;
     }
     
    @@ -948,17 +934,18 @@
     	gid_t groups[NGROUPS];
     	int retval;
     
    -	if (!capable(CAP_SETGID))
    -		return -EPERM;
     	if ((unsigned) gidsetsize > NGROUPS)
     		return -EINVAL;
     	if(copy_from_user(groups, grouplist, gidsetsize * sizeof(gid_t)))
     		return -EFAULT;
     	retval = security_ops->task_ops->setgroups(gidsetsize, groups);
    -	if (retval)
    +	if (retval) {
    +		security_ops->return_status(retval);
     		return retval;
    +	}
     	memcpy(current->groups, groups, gidsetsize * sizeof(gid_t));
     	current->ngroups = gidsetsize;
    +	security_ops->return_status(0);
     	return 0;
     }
     
    @@ -1015,8 +1002,6 @@
     	char nodename[__NEW_UTS_LEN+1];
     	int errno;
     
    -	if (!capable(CAP_SYS_ADMIN))
    -		return -EPERM;
     	if (len < 0 || len > __NEW_UTS_LEN)
     		return -EINVAL;
     	if (copy_from_user(nodename, name, len)) 
    @@ -1024,12 +1009,15 @@
     	nodename[len] = 0;
     
     	errno = security_ops->sethostname(nodename);
    -	if (errno)
    +	if (errno) {
    +		security_ops->return_status(errno);
     		return errno;
    +	}
     
     	down_write(&uts_sem);
     	memcpy(system_utsname.nodename, nodename, len+1);
     	up_write(&uts_sem);
    +	security_ops->return_status(0);
     	return 0;
     }
     
    @@ -1059,8 +1047,6 @@
     	char domainname[__NEW_UTS_LEN+1];
     	int errno;
     
    -	if (!capable(CAP_SYS_ADMIN))
    -		return -EPERM;
     	if (len < 0 || len > __NEW_UTS_LEN)
     		return -EINVAL;
     	if (copy_from_user(domainname, name, len)) 
    @@ -1068,13 +1054,16 @@
     	domainname[len] = 0;
     
     	errno = security_ops->setdomainname(domainname);
    -	if (errno)
    +	if (errno) {
    +		security_ops->return_status(errno);
     		return errno;
    +	}
     
     	down_write(&uts_sem);
     	memcpy(system_utsname.domainname, domainname, len+1);
     	up_write(&uts_sem);
    -	return errno;
    +	security_ops->return_status(0);
    +	return 0;
     }
     
     asmlinkage long sys_getrlimit(unsigned int resource, struct rlimit *rlim)
    @@ -1120,20 +1109,14 @@
     	if (new_rlim.rlim_cur < 0 || new_rlim.rlim_max < 0)
     		return -EINVAL;
     	old_rlim = current->rlim + resource;
    -	if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
    -	     (new_rlim.rlim_max > old_rlim->rlim_max)) &&
    -	    !capable(CAP_SYS_RESOURCE))
    -		return -EPERM;
    -	if (resource == RLIMIT_NOFILE) {
    -		if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN)
    -			return -EPERM;
    -	}
    -
    -	retval = security_ops->task_ops->setrlimit(resource, &new_rlim);
    -	if (retval)
    +	retval = security_ops->task_ops->setrlimit(resource, &new_rlim, old_rlim);
    +	if (retval) {
    +		security_ops->return_status(retval);
     		return retval;
    +	}
     
     	*old_rlim = new_rlim;
    +	security_ops->return_status(0);
     	return 0;
     }
     
    @@ -1210,6 +1193,12 @@
     	int error = 0;
     	int sig;
     
    +	error = security_ops->task_ops->prctl(option, arg2, arg3, arg4, arg5);
    +	if (error) {
    +		security_ops->return_status(error);
    +		return error;
    +	}
    +
     	switch (option) {
     		case PR_SET_PDEATHSIG:
     			sig = arg2;
    @@ -1264,6 +1253,7 @@
     			error = -EINVAL;
     			break;
     	}
    +	security_ops->return_status(error);
     	return error;
     }
     
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/mm/filemap.c ./mm/filemap.c
    --- /work/bitkeeper/lsm/mm/filemap.c	Fri Jun 22 13:56:10 2001
    +++ ./mm/filemap.c	Mon Jun 25 19:04:00 2001
    @@ -1377,7 +1377,7 @@
     	if (retval)
     		goto fput_in;
     
    -	retval = security_ops->file_ops->permission (in_file, MAY_READ);
    +	retval = security_ops->file_ops->permission (in_fd, MAY_READ);
     	if (retval)
     		goto fput_in;
     
    @@ -1398,7 +1398,7 @@
     	if (retval)
     		goto fput_out;
     
    -	retval = security_ops->file_ops->permission (out_file, MAY_WRITE);
    +	retval = security_ops->file_ops->permission (out_fd, MAY_WRITE);
     	if (retval)
     		goto fput_out;
     
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/mm/memory.c ./mm/memory.c
    --- /work/bitkeeper/lsm/mm/memory.c	Fri Jun 22 13:56:10 2001
    +++ ./mm/memory.c	Mon Jun 25 18:53:45 2001
    @@ -1044,11 +1044,13 @@
     
     out_truncate:
     	if (inode->i_op && inode->i_op->truncate) {
    -		if (!security_ops->inode_ops->truncate(inode)) {
    +		int error=security_ops->inode_ops->truncate(NULL,inode,offset);
    +		if (! error) {
     			lock_kernel();
     			inode->i_op->truncate(inode);
     			unlock_kernel();
     		}
    +		security_ops->return_status(error);
     	}
     out:
     	return;
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/mm/mmap.c ./mm/mmap.c
    --- /work/bitkeeper/lsm/mm/mmap.c	Fri Jun 22 13:56:10 2001
    +++ ./mm/mmap.c	Tue Jun 26 07:32:28 2001
    @@ -291,11 +291,18 @@
     			break;
     		}
     	}
    -
    +/* LSM-ToDo 
    + * The only place that this code is called from is the do_mmap2 code in arch.
    + * That already has a mmap hook. Do we really need another here ? This is
    + * important because we wanted to change the file_ops hooks to take fd's
    + * rather than struct file *. This is the only place where we don't have
    + * and can't get a fd. Comments ? --- offer.  
    + 		
     	error = security_ops->file_ops->mmap(file, flags, prot);
     	if (error)
     		return error;
    -		
    +	
    + */
     	/* Clear old maps */
     	error = -ENOMEM;
     	if (do_munmap(mm, addr, len))
    diff -Nur --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet /work/bitkeeper/lsm/net/socket.c ./net/socket.c
    --- /work/bitkeeper/lsm/net/socket.c	Fri Jun 22 13:56:22 2001
    +++ ./net/socket.c	Mon Jun 25 10:15:00 2001
    @@ -72,6 +72,7 @@
     #include <linux/cache.h>
     #include <linux/module.h>
     #include <linux/highmem.h>
    +#include <linux/security.h>
     
     #if defined(CONFIG_KMOD) && defined(CONFIG_NET)
     #include <linux/kmod.h>
    @@ -923,10 +924,12 @@
     
     out:
     	/* It may be already another descriptor 8) Not kernel problem. */
    +	security_ops->return_status(retval);
     	return retval;
     
     out_release:
     	sock_release(sock);
    +	security_ops->return_status(retval);
     	return retval;
     }
     
    @@ -975,16 +978,20 @@
     	err = put_user(fd1, &usockvec[0]); 
     	if (!err)
     		err = put_user(fd2, &usockvec[1]);
    -	if (!err)
    +	if (!err) {
    +		security_ops->return_status(0);
     		return 0;
    +	}
     
     	sys_close(fd2);
     	sys_close(fd1);
    +	security_ops->return_status(err);
     	return err;
     
     out_close_1:
             sock_release(sock2);
     	sys_close(fd1);
    +	security_ops->return_status(err);
     	return err;
     
     out_release_both:
    @@ -992,6 +999,7 @@
     out_release_1:
             sock_release(sock1);
     out:
    +	security_ops->return_status(err);
     	return err;
     }
     
    @@ -1016,6 +1024,7 @@
     			err = sock->ops->bind(sock, (struct sockaddr *)address, addrlen);
     		sockfd_put(sock);
     	}			
    +	security_ops->return_status(err);
     	return err;
     }
     
    @@ -1037,6 +1046,7 @@
     		err=sock->ops->listen(sock, backlog);
     		sockfd_put(sock);
     	}
    +	security_ops->return_status(err);
     	return err;
     }
     
    @@ -1092,6 +1102,7 @@
     out_put:
     	sockfd_put(sock);
     out:
    +	security_ops->return_status(err);
     	return err;
     
     out_release:
    @@ -1129,6 +1140,7 @@
     out_put:
     	sockfd_put(sock);
     out:
    +	security_ops->return_status(err);
     	return err;
     }
     
    @@ -1219,6 +1231,7 @@
     out_put:		
     	sockfd_put(sock);
     out:
    +	security_ops->return_status(err);
     	return err;
     }
     
    @@ -1270,6 +1283,7 @@
     	}
     	sockfd_put(sock);			
     out:
    +	security_ops->return_status(err);
     	return err;
     }
     
    @@ -1342,6 +1356,7 @@
     		err=sock->ops->shutdown(sock, how);
     		sockfd_put(sock);
     	}
    +	security_ops->return_status(err);
     	return err;
     }
     
    @@ -1420,6 +1435,7 @@
     out_put:
     	sockfd_put(sock);
     out:       
    +	security_ops->return_status(err);
     	return err;
     }
     
    @@ -1506,6 +1522,7 @@
     out_put:
     	sockfd_put(sock);
     out:
    +	security_ops->return_status(err);
     	return err;
     }
     
    
    
    
    _______________________________________________
    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 Jun 26 2001 - 13:21:51 PDT