[LWN Logo]
[LWN.net]
From:	 Greg KH <greg@kroah.com>
To:	 Stephen Smalley <sds@tislabs.com>
Subject: Re: New LSM patch for consideration
Date:	 Tue, 12 Jun 2001 09:45:41 -0700
Cc:	 linux-security-module@wirex.com

On Tue, Jun 12, 2001 at 12:10:39PM -0400, Stephen Smalley wrote:
> 
> I've developed and attached a new LSM patch against the original 2.4.5 
> sources that diverges in several ways, detailed below, from the current 
> LSM patch.  I'm attaching this patch for consideration by the LSM 
> "community" as a new starting point for discussions.  I started over with
> the original 2.4.5 sources and selectively merged portions of the old LSM
> patch, since it seems that a number of the changes in the old LSM patch
> (e.g. removing the capability bits from the linux_binprm structure,
> replacing calls to capable with permissive hook calls, replacing all calls
> to compute_creds, some extraneous changes inherited from Immunix) may not
> be desirable.

Thanks for the patch.  As a comparison, I've included the diff between
your patch, and the current (for me) lsm patch (which includes the
current lsm.immunix.org bitkeeper tree + my ia64 patch).  It makes it
easier to compare by looking at this diff.

I haven't had much time to compare but here are a few comments:

> 2) Parameters were added to a number of the hooks, including ioperm, iopl,
> setuid, setgid, setrlimit, sethostname, setdomainname, reboot, and acct
> so that they are more generally useful.  In a few cases, like
> sethostname and setdomainname, this required changing the kernel
> code to copy the parameter from user space to an intermediate location
> first for the hook and then copying from the intermediate location to
> the final destination after authorization by the hook.  In other
> cases, like acct, it required relocating the hook to after useful
> information like the file was available.

I like these.

> 3) Recent changes made here by Chris Vance are integrated,
> including the patch he submitted recently to the mailing list
> and recent changes to support append vs. write distinctions.

I think Chris Wright is just now applying those patches.

> 4) Capabilities in the base kernel were left unmodified, since I
> wasn't clear what direction we are heading in for capabilities.
> If we do decide to retain a capabilities module, I would still
> favor leaving the existing capable() calls unchanged and being
> very conservative in only moving the real capabilities logic
> out of the base kernel, leaving the basic DAC/superuser/set[ug]id
> logic intact so that the base kernel remains useable.  I
> left the base kernel compute_creds function intact (and
> all calls to it) and merely added a call to our hook at
> the end of the function.

One of the explicit requirements to get LSM into the kernel was to have
the ability to make capabilities be a module.  This allows the embedded
people to completely remove capabilities, as they really want this.  I
don't think we can ignore this, no matter how much of a pain in the butt
it is :)

> 5) A few changes in the old LSM patch that seemed to be
> inherited from Immunix or irrelevant to LSM were omitted.  
> I did leave the changes to the Makefiles for people with
> StackGuard compilers for the convenience of WireX folks, but I 
> don't really expect that change to be in the final version
> for inclusion in the mainstream kernel.

The new Kbuild system that will be in 2.5 has support for the StackGuard
compiler.  In the meantime it doesn't hurt anything to have this patch
in the lsm tree for those developers who use this compiler.  And you are
correct, the lsm patch, whenever it will be submitted, will not have
this patch in it.

What other changes (besides the elf header change) did you see that was
left over from Immunix changes, or were irrelevant?  I thought I got all
of those out :)

thanks,

greg k-h

diff -Naur -X ../dontdiff lsm/arch/i386/kernel/ioport.c linux-2.4.5-lsm-nai/arch/i386/kernel/ioport.c
--- lsm/arch/i386/kernel/ioport.c	Fri Jun  8 10:19:38 2001
+++ linux-2.4.5-lsm-nai/arch/i386/kernel/ioport.c	Tue Jun 12 09:25:42 2001
@@ -61,11 +61,11 @@
 
 	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();
+	retval = 0;
+	if (turn_on && !capable(CAP_SYS_RAWIO))
+		retval = -EPERM;
+	retval = security_ops->ioperm(from, num, turn_on, retval);
 	if (retval) {
 		return retval;
 	}
@@ -117,13 +117,12 @@
 	if (level > 3)
 		return -EINVAL;
 	/* Trying to gain more privileges? */
+	retval = 0;
 	if (level > old) {
 		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
+			retval = -EPERM;
 	}
-
-	/* check that we have permission to do this */
-	retval = security_ops->ioperm();
+	retval = security_ops->iopl(old, level, retval);
 	if (retval) {
 		return retval;
 	}
diff -Naur -X ../dontdiff lsm/arch/i386/kernel/ptrace.c linux-2.4.5-lsm-nai/arch/i386/kernel/ptrace.c
--- lsm/arch/i386/kernel/ptrace.c	Fri Jun  8 10:19:39 2001
+++ linux-2.4.5-lsm-nai/arch/i386/kernel/ptrace.c	Tue Jun 12 09:25:42 2001
@@ -147,7 +147,8 @@
 		/* are we already being traced? */
 		if (current->ptrace & PT_PTRACED)
 			goto out;
-		if (security_ops->ptrace(current->p_pptr, current))
+		ret = security_ops->ptrace(current->p_pptr, current, 0);
+		if (ret)
 			goto out;
 		/* set the ptrace bit in the process flags. */
 		current->ptrace |= PT_PTRACED;
@@ -167,12 +168,10 @@
 	if (pid == 1)		/* you may not mess with init */
 		goto out_tsk;
 
-	if (security_ops->ptrace(current, child))
-		goto out_tsk;
-
 	if (request == PTRACE_ATTACH) {
 		if (child == current)
 			goto out_tsk;
+		ret = 0;
 		if(((current->uid != child->euid) ||
 		    (current->uid != child->suid) ||
 		    (current->uid != child->uid) ||
@@ -180,11 +179,15 @@
 	 	    (current->gid != child->sgid) ||
 	 	    (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
 	 	    (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
+			ret = -EPERM;
+		if (!ret && !child->dumpable && !capable(CAP_SYS_PTRACE))
+			ret = -EPERM;
+		ret = security_ops->ptrace(current, child, ret);
+		if (ret)
 			goto out_tsk;
 		rmb();
-		if (!child->dumpable && !capable(CAP_SYS_PTRACE))
-			goto out_tsk;
 		/* the same process cannot be attached many times */
+		ret = -EPERM;
 		if (child->ptrace & PT_PTRACED)
 			goto out_tsk;
 		child->ptrace |= PT_PTRACED;
diff -Naur -X ../dontdiff lsm/arch/ia64/config.in linux-2.4.5-lsm-nai/arch/ia64/config.in
--- lsm/arch/ia64/config.in	Fri Jun  8 10:42:20 2001
+++ linux-2.4.5-lsm-nai/arch/ia64/config.in	Tue Apr 17 17:19:24 2001
@@ -281,6 +281,3 @@
 bool 'Disable VHPT' CONFIG_DISABLE_VHPT
 
 endmenu
-
-source security/Config.in
-
diff -Naur -X ../dontdiff lsm/arch/ia64/ia32/sys_ia32.c linux-2.4.5-lsm-nai/arch/ia64/ia32/sys_ia32.c
--- lsm/arch/ia64/ia32/sys_ia32.c	Fri Jun  8 10:42:20 2001
+++ linux-2.4.5-lsm-nai/arch/ia64/ia32/sys_ia32.c	Thu Apr  5 12:51:47 2001
@@ -49,7 +49,6 @@
 #include <linux/personality.h>
 #include <linux/stat.h>
 #include <linux/ipc.h>
-#include <linux/security.h>
 
 #include <asm/types.h>
 #include <asm/uaccess.h>
@@ -2567,7 +2566,6 @@
 	unsigned int old;
 	unsigned long addr;
 	mm_segment_t old_fs = get_fs ();
-	int retval;
 
 	if (level != 3)
 		return(-EINVAL);
@@ -2577,13 +2575,6 @@
 		if (!capable(CAP_SYS_RAWIO))
 			return -EPERM;
 	}
-
-	/* check that we have permission to do this */
-	retval = security_ops->ioperm();
-	if (retval) {
-		return retval;
-	}
-
 	set_fs(KERNEL_DS);
 	fd = sys_open("/dev/mem", O_SYNC | O_RDWR, 0);
 	set_fs(old_fs);
diff -Naur -X ../dontdiff lsm/arch/ia64/kernel/ptrace.c linux-2.4.5-lsm-nai/arch/ia64/kernel/ptrace.c
--- lsm/arch/ia64/kernel/ptrace.c	Fri Jun  8 10:42:20 2001
+++ linux-2.4.5-lsm-nai/arch/ia64/kernel/ptrace.c	Thu Apr  5 12:51:47 2001
@@ -15,7 +15,6 @@
 #include <linux/ptrace.h>
 #include <linux/smp_lock.h>
 #include <linux/user.h>
-#include <linux/security.h>
 
 #include <asm/pgtable.h>
 #include <asm/processor.h>
@@ -749,8 +748,6 @@
 		/* are we already being traced? */
 		if (current->ptrace & PT_PTRACED)
 			goto out;
-		if (security_ops->ptrace(current->p_pptr, current))
-			goto out;
 		current->ptrace |= PT_PTRACED;
 		ret = 0;
 		goto out;
@@ -768,9 +765,6 @@
 		goto out;
 	ret = -EPERM;
 	if (pid == 1)		/* no messing around with init! */
-		goto out_tsk;
-
-	if (security_ops->ptrace(current, child))
 		goto out_tsk;
 
 	if (request == PTRACE_ATTACH) {
diff -Naur -X ../dontdiff lsm/arch/mips/kernel/irixelf.c linux-2.4.5-lsm-nai/arch/mips/kernel/irixelf.c
--- lsm/arch/mips/kernel/irixelf.c	Fri Jun  8 10:19:40 2001
+++ linux-2.4.5-lsm-nai/arch/mips/kernel/irixelf.c	Mon Mar 19 12:35:09 2001
@@ -29,7 +29,6 @@
 #include <linux/personality.h>
 #include <linux/elfcore.h>
 #include <linux/smp_lock.h>
-#include <linux/security.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
@@ -723,7 +722,7 @@
 	kfree(elf_phdata);
 	set_personality(PER_IRIX32);
 	set_binfmt(&irix_format);
-	security_ops->bprm_ops->compute_creds(bprm);
+	compute_creds(bprm);
 	current->flags &= ~PF_FORKNOEXEC;
 	bprm->p = (unsigned long) 
 	  create_irix_tables((char *)bprm->p, bprm->argc, bprm->envc,
diff -Naur -X ../dontdiff lsm/arch/sparc64/kernel/binfmt_aout32.c linux-2.4.5-lsm-nai/arch/sparc64/kernel/binfmt_aout32.c
--- lsm/arch/sparc64/kernel/binfmt_aout32.c	Fri Jun  8 10:19:46 2001
+++ linux-2.4.5-lsm-nai/arch/sparc64/kernel/binfmt_aout32.c	Sun Mar 25 18:14:21 2001
@@ -27,7 +27,6 @@
 #include <linux/binfmts.h>
 #include <linux/personality.h>
 #include <linux/init.h>
-#include <linux/security.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -241,7 +240,7 @@
 
 	current->mm->rss = 0;
 	current->mm->mmap = NULL;
-	security_ops->bprm_ops->compute_creds(bprm);
+	compute_creds(bprm);
  	current->flags &= ~PF_FORKNOEXEC;
 	if (N_MAGIC(ex) == NMAGIC) {
 		loff_t pos = fd_offset;
diff -Naur -X ../dontdiff lsm/fs/attr.c linux-2.4.5-lsm-nai/fs/attr.c
--- lsm/fs/attr.c	Fri Jun  8 10:19:04 2001
+++ linux-2.4.5-lsm-nai/fs/attr.c	Tue Jun 12 09:25:42 2001
@@ -121,17 +121,16 @@
 		attr->ia_mtime = now;
 
 	lock_kernel();
-	error = security_ops->inode_ops->setattr(dentry, attr);
-	if (error)
-		goto unlock_and_out;
 	if (inode->i_op && inode->i_op->setattr) {
-		error = inode->i_op->setattr(dentry, attr);
+		error = security_ops->inode_ops->setattr(dentry, attr, 0);
+		if (!error)
+			error = inode->i_op->setattr(dentry, attr);
 	} else {
 		error = inode_change_ok(inode, attr);
+		error = security_ops->inode_ops->setattr(dentry, attr, error);
 		if (!error)
 			inode_setattr(inode, attr);
 	}
-unlock_and_out:
 	unlock_kernel();
 	if (!error) {
 		unsigned long dn_mask = setattr_mask(ia_valid);
diff -Naur -X ../dontdiff lsm/fs/binfmt_aout.c linux-2.4.5-lsm-nai/fs/binfmt_aout.c
--- lsm/fs/binfmt_aout.c	Fri Jun  8 10:19:04 2001
+++ linux-2.4.5-lsm-nai/fs/binfmt_aout.c	Mon Mar 19 12:34:56 2001
@@ -24,7 +24,6 @@
 #include <linux/binfmts.h>
 #include <linux/personality.h>
 #include <linux/init.h>
-#include <linux/security.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -304,7 +303,7 @@
 
 	current->mm->rss = 0;
 	current->mm->mmap = NULL;
-	security_ops->bprm_ops->compute_creds(bprm);
+	compute_creds(bprm);
  	current->flags &= ~PF_FORKNOEXEC;
 #ifdef __sparc__
 	if (N_MAGIC(ex) == NMAGIC) {
diff -Naur -X ../dontdiff lsm/fs/binfmt_elf.c linux-2.4.5-lsm-nai/fs/binfmt_elf.c
--- lsm/fs/binfmt_elf.c	Fri Jun  8 10:19:04 2001
+++ linux-2.4.5-lsm-nai/fs/binfmt_elf.c	Tue Jun 12 09:24:36 2001
@@ -39,7 +39,6 @@
 #define DLINFO_ITEMS 13
 
 #include <linux/elf.h>
-#include <linux/security.h>
 
 static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs);
 static int load_elf_library(struct file*);
@@ -656,17 +655,6 @@
 	}
 	set_fs(old_fs);
 
-	/* Shell scripts get checked in binfmt_script.c */
-	if (!bprm->sh_bang) {
-		retval = security_ops->file_ops->permission (bprm->file, MAY_EXEC);
-		if (retval) {
-			kfree(elf_interpreter);
-			kfree(elf_phdata);
-			send_sig(SIGKILL, current, 0);
-			return retval;
-		}
-	}
-
 	elf_entry += load_bias;
 	elf_bss += load_bias;
 	elf_brk += load_bias;
@@ -703,7 +691,7 @@
 
 	set_binfmt(&elf_format);
 
-	security_ops->bprm_ops->compute_creds(bprm);
+	compute_creds(bprm);
 	current->flags &= ~PF_FORKNOEXEC;
 	bprm->p = (unsigned long)
 	  create_elf_tables((char *)bprm->p,
diff -Naur -X ../dontdiff lsm/fs/exec.c linux-2.4.5-lsm-nai/fs/exec.c
--- lsm/fs/exec.c	Fri Jun  8 10:19:04 2001
+++ linux-2.4.5-lsm-nai/fs/exec.c	Tue Jun 12 09:25:42 2001
@@ -36,7 +36,6 @@
 #include <linux/spinlock.h>
 #define __NO_VERSION__
 #include <linux/module.h>
-#include <linux/security.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
@@ -631,6 +630,28 @@
 			bprm->e_gid = inode->i_gid;
 	}
 
+	/* We don't have VFS support for capabilities yet */
+	cap_clear(bprm->cap_inheritable);
+	cap_clear(bprm->cap_permitted);
+	cap_clear(bprm->cap_effective);
+
+	/*  To support inheritance of root-permissions and suid-root
+         *  executables under compatibility mode, we raise all three
+         *  capability sets for the file.
+         *
+         *  If only the real uid is 0, we only raise the inheritable
+         *  and permitted sets of the executable file.
+         */
+
+	if (!issecure(SECURE_NOROOT)) {
+		if (bprm->e_uid == 0 || current->uid == 0) {
+			cap_set_full(bprm->cap_inheritable);
+			cap_set_full(bprm->cap_permitted);
+		}
+		if (bprm->e_uid == 0) 
+			cap_set_full(bprm->cap_effective);
+	}
+
 	/* fill in binprm security blob */
 	if (security_ops->bprm_ops->alloc_security(bprm))
 		return -EACCES;		/* hmm, is EACCES really right? */
@@ -656,7 +677,6 @@
 
 void compute_creds(struct linux_binprm *bprm) 
 {
-#if 0	/* pushed into security module */
 	kernel_cap_t new_permitted, working;
 	int do_unlock = 0;
 
@@ -704,7 +724,8 @@
 	if(do_unlock)
 		unlock_kernel();
 	current->keep_capabilities = 0;
-#endif
+
+	security_ops->bprm_ops->compute_creds(bprm);
 }
 
 
@@ -899,7 +920,6 @@
 			__free_page(page);
 	}
 
-	security_ops->bprm_ops->free_security(&bprm);
 	return retval;
 }
 
diff -Naur -X ../dontdiff lsm/fs/fcntl.c linux-2.4.5-lsm-nai/fs/fcntl.c
--- lsm/fs/fcntl.c	Fri Jun  8 10:19:04 2001
+++ linux-2.4.5-lsm-nai/fs/fcntl.c	Tue Jun 12 09:25:42 2001
@@ -10,6 +10,7 @@
 #include <linux/dnotify.h>
 #include <linux/smp_lock.h>
 #include <linux/slab.h>
+#include <linux/security.h>
 
 #include <asm/poll.h>
 #include <asm/siginfo.h>
@@ -278,6 +279,9 @@
 			err = 0;
 			if (S_ISSOCK (filp->f_dentry->d_inode->i_mode))
 				err = sock_fcntl (filp, F_SETOWN, arg);
+
+			if (!err)
+				err = security_ops->fown_ops->alloc_security(&filp->f_owner);
 			unlock_kernel();
 			break;
 		case F_GETSIG:
@@ -320,6 +324,12 @@
 	if (!filp)
 		goto out;
 
+	err = security_ops->file_ops->fcntl(filp, cmd, arg);
+	if (err) {
+		fput(filp);
+		return err;
+	}
+
 	err = do_fcntl(fd, cmd, arg, filp);
 
  	fput(filp);
@@ -338,6 +348,13 @@
 	if (!filp)
 		goto out;
 
+	err = security_ops->file_ops->fcntl64(filp, cmd, arg);
+	if (err) {
+		fput(filp);
+		return err;
+	}
+	err = -EBADF;
+	
 	switch (cmd) {
 		case F_GETLK64:
 			err = fcntl_getlk64(fd, (struct flock64 *) arg);
@@ -374,10 +391,17 @@
 			       int fd,
 			       int reason)
 {
+	int retval;
+
+	retval = 0;
 	if ((fown->euid != 0) &&
 	    (fown->euid ^ p->suid) && (fown->euid ^ p->uid) &&
 	    (fown->uid ^ p->suid) && (fown->uid ^ p->uid))
+		retval = -EPERM;
+
+	if (security_ops->fown_ops->send_sigiotask(p, fown, fd, reason, retval))
 		return;
+
 	switch (fown->signum) {
 		siginfo_t si;
 		default:
diff -Naur -X ../dontdiff lsm/fs/namei.c linux-2.4.5-lsm-nai/fs/namei.c
--- lsm/fs/namei.c	Fri Jun  8 10:19:04 2001
+++ linux-2.4.5-lsm-nai/fs/namei.c	Tue Jun 12 09:25:42 2001
@@ -183,19 +183,20 @@
 
 int permission(struct inode * inode,int mask)
 {
+	int submask;
 	int retval;
 
-	retval = security_ops->inode_ops->permission(inode, mask);
-	if (retval)
-		return retval;
+	/* Ordinary permission routines do not understand MAY_APPEND. */
+	submask = mask & ~MAY_APPEND;
 
 	if (inode->i_op && inode->i_op->permission) {
 		lock_kernel();
-		retval = inode->i_op->permission(inode, mask);
+		retval = inode->i_op->permission(inode, submask);
 		unlock_kernel();
-		return retval;
+	} else {
+		retval = vfs_permission(inode, submask);
 	}
-	return vfs_permission(inode, mask);
+	return security_ops->inode_ops->permission(inode, mask, retval);
 }
 
 /*
@@ -964,6 +965,11 @@
 	int count = 0;
 
 	acc_mode = ACC_MODE(flag);
+
+	/* Allow the LSM permission hook to distinguish append 
+	   access from general write access. */
+	if (flag & O_APPEND)
+		acc_mode |= MAY_APPEND;
 
 	/*
 	 * The simplest case - just a plain lookup.
diff -Naur -X ../dontdiff lsm/fs/proc/base.c linux-2.4.5-lsm-nai/fs/proc/base.c
--- lsm/fs/proc/base.c	Fri Jun  8 10:19:05 2001
+++ linux-2.4.5-lsm-nai/fs/proc/base.c	Tue Jun 12 09:25:42 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(current,p,0)==0))
 
 static ssize_t mem_read(struct file * file, char * buf,
 			size_t count, loff_t *ppos)
diff -Naur -X ../dontdiff lsm/include/linux/binfmts.h linux-2.4.5-lsm-nai/include/linux/binfmts.h
--- lsm/include/linux/binfmts.h	Fri Jun  8 10:19:08 2001
+++ linux-2.4.5-lsm-nai/include/linux/binfmts.h	Tue Jun 12 09:25:42 2001
@@ -4,7 +4,6 @@
 #include <linux/ptrace.h>
 #include <linux/capability.h>
 
-
 /*
  * MAX_ARG_PAGES defines the number of pages allocated for arguments
  * and envelope for the new program. 32 should suffice, this gives
@@ -27,7 +26,8 @@
 	int sh_bang;
 	struct file * file;
 	int e_uid, e_gid;
-	void *security;	/* was cap_inheritable, cap_permitted, cap_effective */
+	kernel_cap_t cap_inheritable, cap_permitted, cap_effective;
+	void *security;
 	int argc, envc;
 	char * filename;	/* Name of binary */
 	unsigned long loader, exec;
diff -Naur -X ../dontdiff lsm/include/linux/elf.h linux-2.4.5-lsm-nai/include/linux/elf.h
--- lsm/include/linux/elf.h	Fri Jun  8 10:19:08 2001
+++ linux-2.4.5-lsm-nai/include/linux/elf.h	Fri Apr 27 15:49:43 2001
@@ -512,7 +512,7 @@
 #define SHN_HIRESERVE	0xffff
 #define SHN_MIPS_ACCOMON	0xff00
  
-typedef struct elf32_shdr {
+typedef struct {
   Elf32_Word	sh_name;
   Elf32_Word	sh_type;
   Elf32_Word	sh_flags;
@@ -599,7 +599,6 @@
 #define elfhdr		elf32_hdr
 #define elf_phdr	elf32_phdr
 #define elf_note	elf32_note
-#define elf_shdr	elf32_shdr
 
 #else
 
@@ -607,7 +606,6 @@
 #define elfhdr		elf64_hdr
 #define elf_phdr	elf64_phdr
 #define elf_note	elf64_note
-#define elf_shdr	elf64_shdr
 
 #endif
 
diff -Naur -X ../dontdiff lsm/include/linux/fs.h linux-2.4.5-lsm-nai/include/linux/fs.h
--- lsm/include/linux/fs.h	Fri Jun  8 10:19:08 2001
+++ linux-2.4.5-lsm-nai/include/linux/fs.h	Tue Jun 12 09:25:42 2001
@@ -71,6 +71,7 @@
 #define MAY_EXEC 1
 #define MAY_WRITE 2
 #define MAY_READ 4
+#define MAY_APPEND 8
 
 #define FMODE_READ 1
 #define FMODE_WRITE 2
@@ -486,6 +487,7 @@
 	int pid;		/* pid or -pgrp where SIGIO should be sent */
 	uid_t uid, euid;	/* uid/euid of process setting the owner */
 	int signum;		/* posix.1b rt signal to be delivered on IO */
+	void *security;
 };
 
 struct file {
diff -Naur -X ../dontdiff lsm/include/linux/sched.h linux-2.4.5-lsm-nai/include/linux/sched.h
--- lsm/include/linux/sched.h	Fri Jun  8 10:19:08 2001
+++ linux-2.4.5-lsm-nai/include/linux/sched.h	Tue Jun 12 09:25:42 2001
@@ -694,6 +694,7 @@
  * New privilege checks should use this interface, rather than suser() or
  * fsuser(). See include/linux/capability.h for defined capabilities.
  */
+/* capable prototype and code moved to security.[hc] */
 #include <linux/security.h>
 #if 0
 static inline int capable(int cap)
diff -Naur -X ../dontdiff lsm/include/linux/security.h linux-2.4.5-lsm-nai/include/linux/security.h
--- lsm/include/linux/security.h	Fri Jun  8 10:19:08 2001
+++ linux-2.4.5-lsm-nai/include/linux/security.h	Tue Jun 12 09:25:42 2001
@@ -6,6 +6,10 @@
  *      the Free Software Foundation; either version 2 of the License, or
  *      (at your option) any later version.
  *
+ * 2001_Jun_12 Stephen Smalley <sds@tislabs.com>, NAI Labs, SELinux project
+ *      Changed all non-capable hooks to be authoritative or restrictive.
+ *      Added parameters to several of the hook functions.
+ *
  * 2001_Apr_12 greg k-h
  *	created based on original immunix.h code
  *
@@ -64,9 +68,9 @@
 	int (* readlink)	(struct dentry *dentry, char *buf, int bufsiz);
 	int (* follow_link)	(struct dentry *dentry, struct nameidata *nd);
 	int (* truncate)	(struct inode *inode);
-	int (* permission)	(struct inode *inode, int mask);
+	int (* permission)	(struct inode *inode, int mask, int kern_retval);
 	int (* revalidate)	(struct dentry *dentry);
-	int (* setattr)		(struct dentry *dentry, struct iattr *attr); // CAP_CHOWN
+	int (* setattr)		(struct dentry *dentry, struct iattr *attr, int kern_retval);
 	void (* attach_pathlabel)(struct dentry *dentry, struct vfsmount *mnt);	// DTE project needs this
 	int (* stat)		        (struct inode *inode);
 };
@@ -80,23 +84,37 @@
 	int (* read)			(struct file *);
 	int (* write)			(struct file *);
 	int (* ioctl)			(struct file *);	// need more than file*
-	int (* mmap)			(struct file *);
+	int (* mmap)			(struct file *, 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);
+};
+
+struct fown_security_ops {
+	int (* alloc_security)		(struct fown_struct *);
+	void (* free_security)		(struct fown_struct *);
+	int (* send_sigiotask)		(struct task_struct *tsk, struct fown_struct *fown, int fd, int reason, int kern_retval);
 };
 
 struct task_security_ops {
 	int (* create)			(void);
 	int (* alloc_security)		(struct task_struct *p);	// create per process security stuff
 	void (* free_security)		(struct task_struct *p);	// free it
-	int (* setuid)			(void);		// CAP_SETUID
-	int (* setgid)			(void);		// CAP_SETGID
-	int (* setgroups)               (void);         // CAP_SETGID
-	int (* setnice)			(struct task_struct *p, int nice); // CAP_SYS_NICE
-	int (* setrlimit)		(unsigned int resource);	// CAP_SYS_RESOURCE
-	int (* setscheduler)		(struct task_struct *p, int policy); // CAP_SYS_NICE
-	int (* kill)			(struct task_struct *p, struct siginfo *info, int sig);	// CAP_KILL
+#define LSM_SETID_ID  1 /* setuid or setgid, id0 == uid or gid */
+#define LSM_SETID_RE  2 /* setreuid or setregid, id0 == real, id1 == eff */
+#define LSM_SETID_RES 4 /* setresuid or setresgid, id0 == real, id1 == eff, uid2 == saved */
+#define LSM_SETID_FS  8 /* setfsuid or setfsgid, id0 == fsuid or fsgid */
+	int (* setuid)			(uid_t id0, uid_t id1, uid_t id2, int flags);
+	int (* setgid)			(gid_t id0, gid_t id1, gid_t id2, int flags);
+	int (* setgroups)               (int gidsetsize, gid_t *grouplist);
+	int (* setnice)			(struct task_struct *p, int nice, int kern_retval);
+	int (* setrlimit)		(unsigned int resource, struct rlimit *new_rlim, int kern_retval);
+	int (* setscheduler)		(struct task_struct *p, int policy, int kern_retval); 
+	int (* kill)			(struct task_struct *p, struct siginfo *info, int sig, int kern_retval);	
+	int (* wait)			(struct task_struct *p);
 	
 	/* set and (in case of exec failure) unset security label */
 	int (* set_label)		(char *filename);
@@ -133,30 +151,31 @@
 	int	version;
 	
 	/* syscalls that are checked for permissions */
-	int  (* sethostname)		(void);		// CAP_SYS_ADMIN
-	int  (* setdomainname)		(void);		// CAP_SYS_ADMIN
-	int  (* reboot)			(unsigned int cmd);	// CAP_SYS_BOOT
+	int  (* sethostname)		(char *hostname);		
+	int  (* setdomainname)		(char *domainname);
+	int  (* reboot)			(unsigned int cmd, void *arg, int kern_retval);	
 	int  (* mount)			(char * dev_name, struct nameidata *nd,
 					 char * type, unsigned long flags, 
 					 void * data);			// part of CAP_SYS_ADMIN
 	int  (* add_vfsmnt)	        (struct nameidata *nd, struct super_block *sb, char *dev_name);
-	int  (* umount)			(struct vfsmount *mnt, int flags);	// part of CAP_SYS_ADMIN
+	int  (* umount)			(struct vfsmount *mnt, int flags);	
 	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);    
-	int  (* ioperm)			(void);		// part of CAP_RAWIO
-	int  (* iopl)			(void);		// part of CAP_RAWIO
-	int  (* ptrace)			(struct task_struct *parent, struct task_struct *child);		// CAP_PTRACE
+	int  (* ioperm)			(unsigned long from, unsigned long num, int turn_on, int kern_retval);
+	int  (* iopl)			(unsigned int old, unsigned int level, int kern_retval);		
+	int  (* ptrace)			(struct task_struct *parent, struct task_struct *child, int kern_retval);		
 	int  (* setcapability)		(void);		// CAP_SETPCAP
-	int  (* acct)			(void);		// CAP_SYS_PACCT
+	int  (* acct)			(struct file *file);
 	/* old capable call, catch all for capabilities. */
-	int (* capable)			(int cap); 
+	int (* capable)			(int cap, int kern_retval); 
 
 	struct binprm_security_ops	* bprm_ops;
 	struct super_block_security_ops	* sb_ops;
 	struct inode_security_ops	* inode_ops;
 	struct file_security_ops	* file_ops;
+	struct fown_security_ops	* fown_ops;
 	struct task_security_ops	* task_ops;
 	struct socket_security_ops	* socket_ops;
 	struct module_security_ops 	* module_ops;
@@ -164,8 +183,8 @@
 	struct shm_security_ops		* shm_ops;
 
 	/* allow module stacking */
-	int (* register_security)	(const char *name, struct security_operations *ops);
-	int (* unregister_security)	(const char *name, struct security_operations *ops);
+	int (* register_security)	(struct security_operations *ops);
+	int (* unregister_security)	(struct security_operations *ops);
 };
 
 
@@ -173,8 +192,8 @@
 extern int security_scaffolding_startup	(void);
 extern int register_security	(struct security_operations *ops);
 extern int unregister_security	(struct security_operations *ops);
-extern int mod_reg_security	(const char *name, struct security_operations *ops);
-extern int mod_unreg_security	(const char *name, struct security_operations *ops);
+extern int mod_reg_security	(struct security_operations *ops);
+extern int mod_unreg_security	(struct security_operations *ops);
 extern int capable		(int cap);
 
 /* global variables */
diff -Naur -X ../dontdiff lsm/include/linux/sysctl.h linux-2.4.5-lsm-nai/include/linux/sysctl.h
--- lsm/include/linux/sysctl.h	Fri Jun  8 10:19:09 2001
+++ linux-2.4.5-lsm-nai/include/linux/sysctl.h	Tue Jun 12 09:24:39 2001
@@ -647,8 +647,6 @@
 extern ctl_handler sysctl_intvec;
 extern ctl_handler sysctl_jiffies;
 
-extern ctl_handler sysctl_codomain;
-
 
 /*
  * Register a set of sysctl names by calling register_sysctl_table
diff -Naur -X ../dontdiff lsm/kernel/Makefile linux-2.4.5-lsm-nai/kernel/Makefile
--- lsm/kernel/Makefile	Fri Jun  8 10:19:08 2001
+++ linux-2.4.5-lsm-nai/kernel/Makefile	Tue Jun 12 09:25:42 2001
@@ -20,7 +20,6 @@
 obj-$(CONFIG_UID16) += uid16.o
 obj-$(CONFIG_MODULES) += ksyms.o
 obj-$(CONFIG_PM) += pm.o
-obj-$(CONFIG_CAPABILITIES) += capability_plug.o
 
 ifneq ($(CONFIG_IA64),y)
 # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
diff -Naur -X ../dontdiff lsm/kernel/acct.c linux-2.4.5-lsm-nai/kernel/acct.c
--- lsm/kernel/acct.c	Fri Jun  8 10:19:08 2001
+++ linux-2.4.5-lsm-nai/kernel/acct.c	Tue Jun 12 09:25:42 2001
@@ -158,8 +158,7 @@
 	char *tmp;
 	int error;
 
-	/* XXX may want to defer this until we have file -cmw */
-	if (security_ops->acct());
+	if (!capable(CAP_SYS_PACCT))
 		return -EPERM;
 
 	if (name) {
@@ -182,6 +181,10 @@
 		if (!file->f_op->write) 
 			goto out_err;
 	}
+
+	error = security_ops->acct(file);
+	if (error)
+		goto out_err;
 
 	error = 0;
 	lock_kernel();
diff -Naur -X ../dontdiff lsm/kernel/capability_plug.c linux-2.4.5-lsm-nai/kernel/capability_plug.c
--- lsm/kernel/capability_plug.c	Fri Jun  8 10:19:08 2001
+++ linux-2.4.5-lsm-nai/kernel/capability_plug.c	Wed Dec 31 16:00:00 1969
@@ -1,700 +0,0 @@
-/*
- *  Capabilities Security plug
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- */ 
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/security.h>
-#include <linux/capability.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <asm/uaccess.h>
-
-/* #define DEBUG */
-
-#ifdef DEBUG
-static char *capabilities[] = { "CAP_CHOWN",
-				"CAP_DAC_OVERRIDE",
-				"CAP_DAC_READ_SEARCH",
-				"CAP_FOWNER",
-				"CAP_FSETID",
-				"CAP_KILL",
-				"CAP_SETGID",
-				"CAP_SETUID",
-				"CAP_SETPCAP",
-				"CAP_LINUX_IMMUTABLE",
-				"CAP_NET_BIND_SERVICE",
-				"CAP_NET_BROADCAST",
-				"CAP_NET_ADMIN",
-				"CAP_NET_RAW",
-				"CAP_IPC_LOCK",
-				"CAP_IPC_OWNER",
-				"CAP_SYS_MODULE",
-				"CAP_SYS_RAWIO",
-				"CAP_SYS_CHROOT",
-				"CAP_SYS_PTRACE",
-				"CAP_SYS_PACCT",
-				"CAP_SYS_ADMIN",
-				"CAP_SYS_BOOT",
-				"CAP_SYS_NICE",
-				"CAP_SYS_RESOURCE",
-				"CAP_SYS_TIME",
-				"CAP_SYS_TTY_CONFIG",
-				"CAP_MKNOD",
-				"CAP_LEASE" };
-#endif /* DEBUG */
-
-/* flag to keep track of how we were registered */
-static int secondary;
-
-struct cap_list {
-	kernel_cap_t	cap_inheritable, cap_permitted, cap_effective;
-};
-
-static inline int is_capable(int cap)
-{
-	if (current->security &&
-	cap_raised(((struct cap_list*)(current->security))->cap_effective, cap)) {
-		current->flags |= PF_SUPERPRIV;
-#ifdef DEBUG
-		printk(KERN_DEBUG " %s(%d) has %s\n", current->comm,
-			current->pid, capabilities[cap]);
-#endif
-		return 1;
-	}
-#ifdef DEBUG
-	printk(KERN_DEBUG " %s(%d) does not have %s\n", current->comm,
-		current->pid, capabilities[cap]);
-#endif
-	return 0;
-}
-
-/* assorted security operations  (mostly syscall interposition) */
-static int cap_sethostname(void)
-{
-	return is_capable(CAP_SYS_ADMIN) ? 0 : -EPERM;
-}
-static int cap_setdomainname(void)
-{
-	return is_capable(CAP_SYS_ADMIN) ? 0 : -EPERM;
-}
-static int cap_reboot(unsigned int cmd)
-{
-	return is_capable(CAP_SYS_BOOT) ? 0 : -EPERM;
-}
-
-static int cap_mount		(char * dev_name, struct nameidata *nd, char * type, unsigned long flags, void * data)	{return 0;}
-static int cap_add_vfsmnt	(struct nameidata *nd, struct super_block *sb, char * dev_name)				{return 0;}
-static int cap_umount		(struct vfsmount *mnt, int flags)							{return 0;}
-static void cap_umount_close	(struct vfsmount *mnt)									{return;}
-static void cap_umount_busy	(struct vfsmount *mnt)									{return;}
-static int cap_remount		(struct vfsmount *mnt, unsigned long flags, void *data)					{return 0;}
-static void cap_post_remount	(struct vfsmount *mnt, unsigned long flags, void *data)					{return;}
-
-static int cap_ioperm(void)
-{
-	return 0;
-}
-static int cap_iopl(void)
-{
-	return 0;
-}
-static int cap_ptrace(struct task_struct *parent, struct task_struct *child)
-{
-	if (current == child)	/* TRACEME */
-		return 0;
-	return is_capable(CAP_SYS_PTRACE) ? 0 : -EPERM;
-}
-static int cap_setcapablity(void)
-{
-	return 0;
-}
-static int cap_acct(void)
-{
-	return is_capable(CAP_SYS_PACCT) ? 0 : -EPERM;
-}
-static int cap_capable(int cap)
-{
-	return is_capable(cap) ? 0 : -EPERM;
-}
-
-/* binprm security operations */
-static int cap_bprm_alloc_security(struct linux_binprm *bprm)
-{
-	int rc = -1;
-	struct cap_list *caps;
-	caps = (struct cap_list*)kmalloc(sizeof(struct cap_list), GFP_KERNEL);
-	if (!caps)
-		goto out;
-
-	rc = 0;
-	/* from prepare_binprm() */
-	/* We don't have VFS support for capabilities yet */
-	cap_clear(caps->cap_inheritable);
-	cap_clear(caps->cap_permitted);
-	cap_clear(caps->cap_effective);
-
-	/*  To support inheritance of root-permissions and suid-root
-         *  executables under compatibility mode, we raise all three
-         *  capability sets for the file.
-         *
-         *  If only the real uid is 0, we only raise the inheritable
-         *  and permitted sets of the executable file.
-         */
-
-	if (!issecure(SECURE_NOROOT)) {
-		if (bprm->e_uid == 0 || current->uid == 0) {
-			cap_set_full(caps->cap_inheritable);
-			cap_set_full(caps->cap_permitted);
-		}
-		if (bprm->e_uid == 0) 
-			cap_set_full(caps->cap_effective);
-	}
-out:
-	bprm->security = (void *)caps;
-	return rc;
-}
-static void cap_bprm_free_security(struct linux_binprm *bprm)
-{
-	if (bprm->security)
-		kfree(bprm->security);
-}
-
-/* stolen from fs/exec.c needed for compute_creds below */
-static inline int must_not_trace_exec(struct task_struct * p)
-{
-	/* needs to be converted to use opaque security blob */
-	return (p->ptrace & PT_PTRACED) && !cap_raised(p->p_pptr->cap_effective, CAP_SYS_PTRACE);
-}
-static void cap_bprm_compute_creds(struct linux_binprm *bprm)
-{	/* from compute_creds() 
-	 * keep_capabilities is still in current
-	 */
-	kernel_cap_t new_permitted, working;
-	int do_unlock = 0;
-	struct cap_list *bprm_cap = (struct cap_list*)(bprm->security);
-	struct cap_list *cur_cap = (struct cap_list*)(current->security);
-
-	if (!bprm_cap || !cur_cap)
-		return;
-
-	new_permitted = cap_intersect(bprm_cap->cap_permitted, cap_bset);
-	working = cap_intersect(bprm_cap->cap_inheritable,
-				cur_cap->cap_inheritable);
-	new_permitted = cap_combine(new_permitted, working);
-
-	if (bprm->e_uid != current->uid || bprm->e_gid != current->gid ||
-	    !cap_issubset(new_permitted, cur_cap->cap_permitted)) {
-                current->dumpable = 0;
-		
-		lock_kernel();
-		if (must_not_trace_exec(current)
-		    || atomic_read(&current->fs->count) > 1
-		    || atomic_read(&current->files->count) > 1
-		    || atomic_read(&current->sig->count) > 1) {
-			if(!is_capable(CAP_SETUID)) {
-				bprm->e_uid = current->uid;
-				bprm->e_gid = current->gid;
-			}
-			if(!is_capable(CAP_SETPCAP)) {
-				new_permitted = cap_intersect(new_permitted,
-							cur_cap->cap_permitted);
-			}
-		}
-		do_unlock = 1;
-	}
-
-
-	/* For init, we want to retain the capabilities set
-         * in the init_task struct. Thus we skip the usual
-         * capability rules */
-	if (current->pid != 1) {
-		cur_cap->cap_permitted = new_permitted;
-		cur_cap->cap_effective =
-			cap_intersect(new_permitted, bprm_cap->cap_effective);
-	}
-	
-        /* AUD: Audit candidate if current->cap_effective is set */
-
-        current->suid = current->euid = current->fsuid = bprm->e_uid;
-        current->sgid = current->egid = current->fsgid = bprm->e_gid;
-
-	if(do_unlock)
-		unlock_kernel();
-	current->keep_capabilities = 0;
-}
-
-/* super_block security operations */
-static int cap_sb_alloc_security(struct super_block *sb)
-{
-	return 0;
-}
-static void cap_sb_free_security(struct super_block *sb)
-{
-	return;
-}
-static int cap_sb_statfs(struct super_block *sb)
-{
-	return 0;
-}
-
-/* inode security operations */
-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 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 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 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 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 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 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_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;
-}
-
-
-/* file security operations */
-static int cap_file_permission(struct file *file, 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)
-{
-	return 0;
-}
-static int cap_file_mmap(struct file *file)
-{
-	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;
-}
-
-/* task security operations */
-static int cap_task_create(void)
-{
-	return 0;
-}
-static int cap_task_alloc_security(struct task_struct *p)
-{
-	int rc = -1;
-	struct cap_list *caps;
-	caps = (struct cap_list *)kmalloc(sizeof(struct cap_list), GFP_KERNEL);
-	if (!caps)
-		goto out;
-	rc = 0;
-	if (current->security)
-		/* inherit from parent, this will break when parent
-		 * has a different security blob
-		 */
-		memcpy (caps, current->security, sizeof(struct cap_list));
-out:
-	p->security = (void *)caps;
-	return rc;
-}
-static void cap_task_free_security(struct task_struct *p)
-{
-	if (p->security)
-		kfree(p->security);
-}
-static int cap_task_setuid(void)
-{
-	return is_capable(CAP_SETUID) ? 0 : -EPERM;
-}
-static int cap_task_setgid(void)
-{
-	return is_capable(CAP_SETGID) ? 0 : -EPERM;
-}
-static int cap_task_setgroups(void)
-{
-	return is_capable(CAP_SETGID) ? 0 : -EPERM;
-}
-static int cap_task_setnice(struct task_struct *p, int nice)
-{
-	return is_capable(CAP_SYS_NICE) ? 0 : -EPERM;
-}
-static int cap_task_setrlimit(unsigned int resource)
-{
-	return is_capable(CAP_SYS_RESOURCE) ? 0 : -EPERM;
-}
-static int cap_task_setscheduler(struct task_struct *p, int policy)
-{
-	return is_capable(CAP_SYS_NICE) ? 0 : -EPERM;
-}
-static int cap_task_kill(struct task_struct *p, struct siginfo *info, int sig)
-{
-	return is_capable(CAP_KILL) ? 0 : -EPERM;
-}
-static int cap_task_set_label(char *filename)
-{
-	return 0;
-}
-static void cap_task_reset_label(void)
-{
-	return;
-}
-
-/* module security operations */
-static int cap_module_create_module(const char *name_user, size_t size)
-{
-	return is_capable(CAP_SYS_MODULE) ? 0 : -EPERM;
-}
-static int cap_module_init_module(const char *name_user, struct module *mod_user)
-{
-	return is_capable(CAP_SYS_MODULE) ? 0 : -EPERM;
-}
-static int cap_module_delete_module(const char *name_user)
-{
-	return is_capable(CAP_SYS_MODULE) ? 0 : -EPERM;
-}
-
-/* message queue security operations */
-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;
-}
-
-/* shared memory security operations */
-static int cap_shm_create(key_t key)
-{
-	return 0;
-}
-static int cap_shm_permission(void)
-{
-	return 0;
-}
-static int cap_shm_setattr(void)
-{
-	return 0;
-}
-static int cap_shm_delete(void)
-{
-	return 0;
-}
-
-/* for module stacking */
-int cap_register_security (const char *name, struct security_operations *ops)
-{
-	return -EPERM;
-}
-int cap_unregister_security (const char *name, struct security_operations *ops)
-{
-	return -EPERM;
-}
-
-
-static struct binprm_security_ops cap_bprm_ops = {
-	alloc_security:	cap_bprm_alloc_security,
-	free_security:	cap_bprm_free_security,
-	compute_creds:	cap_bprm_compute_creds,
-};
-static struct super_block_security_ops cap_sb_ops = {
-	alloc_security:	cap_sb_alloc_security,
-	free_security:	cap_sb_free_security,
-	statfs:	        cap_sb_statfs,
-};
-static struct inode_security_ops cap_inode_ops = {
-	alloc_security:	cap_inode_alloc_security,
-	free_security:	cap_inode_free_security,
-	create:		cap_inode_create,
-	post_create:	cap_inode_post_create,
-	link:		cap_inode_link,
-	post_link:	cap_inode_post_link,
-	unlink:		cap_inode_unlink,
-	symlink:	cap_inode_symlink,
-	post_symlink:	cap_inode_post_symlink,
-	mkdir:		cap_inode_mkdir,
-	post_mkdir:	cap_inode_post_mkdir,
-	rmdir:		cap_inode_rmdir,
-	mknod:		cap_inode_mknod,
-	post_mknod:	cap_inode_post_mknod,
-	rename:		cap_inode_rename,
-	post_rename:	cap_inode_post_rename,
-	readlink:	cap_inode_readlink,
-	follow_link:	cap_inode_follow_link,
-	truncate:	cap_inode_truncate,
-	permission:	cap_inode_permission,
-	revalidate:	cap_inode_revalidate,
-	setattr:	cap_inode_setattr,
-	attach_pathlabel:cap_inode_attach_pathlabel,
-	stat:           cap_inode_stat,
-};
-
-static struct file_security_ops	cap_file_ops = {
-	permission:	cap_file_permission,
-	alloc_security:	cap_file_alloc_security,
-	free_security:	cap_file_free_security,
-	llseek:		cap_file_llseek,
-	read:		cap_file_read,
-	write:		cap_file_write,
-	ioctl:		cap_file_ioctl,
-	mmap:		cap_file_mmap,
-	lock:		cap_file_lock,
-	readv:		cap_file_readv,
-	writev:		cap_file_writev,
-};
-
-static struct task_security_ops	cap_task_ops = {
-	create:		cap_task_create,
-	alloc_security:	cap_task_alloc_security,
-	free_security:	cap_task_free_security,
-	setuid:		cap_task_setuid,
-	setgid:		cap_task_setgid,
-	setgroups:	cap_task_setgroups,
-	setnice:	cap_task_setnice,
-	setrlimit:	cap_task_setrlimit,
-	setscheduler:	cap_task_setscheduler,
-	kill:		cap_task_kill,
-	set_label:	cap_task_set_label,
-	reset_label:	cap_task_reset_label,
-};
-
-static struct socket_security_ops cap_socket_ops = {};
-
-static struct module_security_ops cap_module_ops = {
-	create_module:	cap_module_create_module,
-	init_module:	cap_module_init_module,
-	delete_module:	cap_module_delete_module,
-
-};
-
-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,
-};
-
-static struct shm_security_ops cap_shm_ops = {
-	create:		cap_shm_create,
-	permission:	cap_shm_permission,
-	setattr:	cap_shm_setattr,
-	delete:		cap_shm_delete,
-};
-
-struct security_operations capability_ops = {
-        version:                SECURITY_INTERFACE_VERSION,
-
-	sethostname:		cap_sethostname,
-	setdomainname:		cap_setdomainname,
-	reboot:			cap_reboot,
-	mount:			cap_mount,
-	add_vfsmnt:             cap_add_vfsmnt,
-	umount:			cap_umount,
-	umount_close:		cap_umount_close,
-	umount_busy:		cap_umount_busy,
-	remount:		cap_remount,
-	post_remount:		cap_post_remount,
-	ioperm:			cap_ioperm,
-	iopl:			cap_iopl,
-	ptrace:			cap_ptrace,
-	setcapability:		cap_setcapablity,
-	acct:			cap_acct,
-	capable:		cap_capable,
-
-	bprm_ops:		&cap_bprm_ops,
-	sb_ops:			&cap_sb_ops,
-	inode_ops:		&cap_inode_ops,
-	file_ops:		&cap_file_ops,
-	task_ops:		&cap_task_ops,
-	socket_ops:		&cap_socket_ops,
-	module_ops:		&cap_module_ops,
-	msg_queue_ops:		&cap_msg_queue_ops,
-	shm_ops:		&cap_shm_ops,
-
-	register_security:	&cap_register_security,
-	unregister_security:	&cap_unregister_security,
-};
-
-#define MY_NAME THIS_MODULE->name
-static int __init capability_plug_init (void)
-{
-	/* register ourselves with the security framework */
-	if (register_security (&capability_ops)) {
-		printk (KERN_INFO "Failure registering capabilities with the kernel\n");
-		/* try registering with primary module */
-		if (mod_reg_security(MY_NAME, &capability_ops)) {
-			printk (KERN_INFO "Failure registering capbilities "
-				"with primary security module.\n");
-			return -EINVAL;
-		}
-		secondary = 1;
-	}
-#if defined(CONFIG_CAPABILITIES)  && !defined(CONFIG_CAPABILITIES_MODULE)
-	/* hack to make this work when compiled in to kernel */
-	if (current->pid == 1) {
-		struct cap_list *cap;
-		if (cap_task_alloc_security(current))
-			panic("Couldn't allocate initial task security blob\n");
-		cap = (struct cap_list *)current->security;
-		cap->cap_effective = CAP_INIT_EFF_SET;
-		cap->cap_inheritable = CAP_INIT_INH_SET;
-		cap->cap_permitted = CAP_FULL_SET;
-	}
-#endif /* CONFIG_CAPABILITIES && !CONFIG_CAPABILITIES_MODULE */
-	printk(KERN_INFO "Capability Plug initialized\n");
-	return 0;
-}
-
-
-static void __exit capability_plug_exit (void)
-{
-	/* remove ourselves from the security framework */
-	if (secondary) {
-		if (mod_unreg_security (MY_NAME, &capability_ops))
-			printk (KERN_INFO "Failure unregistering capabilities "
-				"with primary module.\n");
-		return;
-	}
-
-	if (unregister_security (&capability_ops)) {
-		printk (KERN_INFO "Failure unregistering capabilities with the kernel\n");
-	}
-}
-
-
-module_init (capability_plug_init);
-module_exit (capability_plug_exit);
-
-EXPORT_SYMBOL(capability_ops);
-
diff -Naur -X ../dontdiff lsm/kernel/exit.c linux-2.4.5-lsm-nai/kernel/exit.c
--- lsm/kernel/exit.c	Fri Jun  8 10:19:08 2001
+++ linux-2.4.5-lsm-nai/kernel/exit.c	Tue Jun 12 09:25:42 2001
@@ -524,6 +524,10 @@
 			if (((p->exit_signal != SIGCHLD) ^ ((options & __WCLONE) != 0))
 			    && !(options & __WALL))
 				continue;
+
+			if (security_ops->task_ops->wait(p))
+				continue;
+
 			flag = 1;
 			switch (p->state) {
 			case TASK_STOPPED:
diff -Naur -X ../dontdiff lsm/kernel/module.c linux-2.4.5-lsm-nai/kernel/module.c
--- lsm/kernel/module.c	Fri Jun  8 10:19:08 2001
+++ linux-2.4.5-lsm-nai/kernel/module.c	Tue Jun 12 09:25:42 2001
@@ -298,6 +298,8 @@
 	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;
@@ -357,6 +359,8 @@
 	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;
@@ -614,6 +618,9 @@
 	char *name;
 	long error;
 	int something_changed;
+
+	if (!capable(CAP_SYS_MODULE))
+		return -EPERM;
 
 	lock_kernel();
 	if (name_user) {
diff -Naur -X ../dontdiff lsm/kernel/sched.c linux-2.4.5-lsm-nai/kernel/sched.c
--- lsm/kernel/sched.c	Fri Jun  8 10:19:08 2001
+++ linux-2.4.5-lsm-nai/kernel/sched.c	Tue Jun 12 09:25:42 2001
@@ -842,14 +842,19 @@
 asmlinkage long sys_nice(int increment)
 {
 	long newprio;
+	int retval = 0;
 
 	/*
 	 *	Setpriority might change our priority at the same moment.
 	 *	We don't have to worry. Conceptually one call occurs first
 	 *	and we have a single winner.
 	 */
-	if (increment < -40)
-		increment = -40;
+	if (increment < 0) {
+		if (!capable(CAP_SYS_NICE))
+			retval = -EPERM;
+		if (increment < -40)
+			increment = -40;
+	}
 	if (increment > 40)
 		increment = 40;
 
@@ -858,10 +863,11 @@
 		newprio = -20;
 	if (newprio > 19)
 		newprio = 19;
-	if (increment < 0) {
-		if (security_ops->task_ops->setnice(current, newprio))
-			return -EPERM;
-	}
+
+	retval = security_ops->task_ops->setnice(current, newprio, retval);
+	if (retval)
+		return retval;
+	
 	current->nice = newprio;
 	return 0;
 }
@@ -883,7 +889,6 @@
 	struct sched_param lp;
 	struct task_struct *p;
 	int retval;
-	int no_sched;
 
 	retval = -EINVAL;
 	if (!param || pid < 0)
@@ -924,13 +929,16 @@
 	if ((policy == SCHED_OTHER) != (lp.sched_priority == 0))
 		goto out_unlock;
 
-	retval = -EPERM;
-	no_sched = security_ops->task_ops->setscheduler(p, policy);
+	retval = 0;
 	if ((policy == SCHED_FIFO || policy == SCHED_RR) && 
-	    no_sched)
-		goto out_unlock;
-	if ((current->euid != p->euid) && (current->euid != p->uid) &&
-	    no_sched)
+	    !capable(CAP_SYS_NICE))
+		retval = -EPERM;
+	if (!retval && 
+	    (current->euid != p->euid) && (current->euid != p->uid) &&
+	    !capable(CAP_SYS_NICE))
+		retval = -EPERM;
+	retval = security_ops->task_ops->setscheduler(p, policy, retval);
+	if (retval)
 		goto out_unlock;
 
 	retval = 0;
diff -Naur -X ../dontdiff lsm/kernel/security.c linux-2.4.5-lsm-nai/kernel/security.c
--- lsm/kernel/security.c	Fri Jun  8 10:19:08 2001
+++ linux-2.4.5-lsm-nai/kernel/security.c	Tue Jun 12 09:25:42 2001
@@ -6,6 +6,10 @@
  *      the Free Software Foundation; either version 2 of the License, or
  *      (at your option) any later version.
  *
+ * 2001_Jun_12 Stephen Smalley <sds@tislabs.com>, NAI Labs, SELinux project
+ *      Changed all non-capable hooks to be authoritative or restrictive.
+ *      Added parameters to several of the hook functions.
+ *
  * 2001_Apr_18 greg k-h
  *	fleshed out with current security.h stubs
  *
@@ -32,9 +36,18 @@
 
 
 /* Stub functions for the default security function pointers in case no security model is loaded */
-static int dummy_sethostname	(void)	{return 0;}
-static int dummy_setdomainname	(void)	{return 0;}
-static int dummy_reboot		(unsigned int cmd)	{return 0;}
+static int dummy_sethostname(char *hostname)	{return 0;}
+
+static int dummy_setdomainname(char *domainname)	
+{
+	return 0;
+}
+
+static int dummy_reboot		(unsigned int cmd, void *arg, int kern_retval)
+{
+	return kern_retval;
+}
+
 static int dummy_mount		(char * dev_name, struct nameidata *nd, char * type, unsigned long flags, void * data)	{return 0;}
 static int dummy_add_vfsmnt	(struct nameidata *nd, struct super_block *sb, char * dev_name)				{return 0;}
 static int dummy_umount		(struct vfsmount *mnt, int flags)					{return 0;}
@@ -42,20 +55,29 @@
 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 int dummy_ioperm		(void)	{return 0;}
-static int dummy_iopl		(void)	{return 0;}
-static int dummy_ptrace		(struct task_struct *parent, struct task_struct *child)	{return 0;}
+
+static int dummy_ioperm(unsigned long from, unsigned long num, int turn_on, int kern_retval)
+{
+	return kern_retval;
+}
+
+static int dummy_iopl(unsigned int old, unsigned int level, int kern_retval)
+{
+	return kern_retval;
+}
+
+
+static int dummy_ptrace		(struct task_struct *parent, struct task_struct *child, int kern_retval)	
+{
+	return kern_retval;
+}
+
 static int dummy_setcapablity	(void)	{return 0;}
-static int dummy_acct		(void)	{return 0;}
-static int dummy_capable	(int cap)
+static int dummy_acct		(struct file *file)
 {
-	/* stolen from original capable call */
-        if (cap_is_fs_cap(cap) ? current->fsuid == 0 : current->euid == 0) {
-                current->flags |= PF_SUPERPRIV;
-                return 0;
-        }
-        return -EPERM;
+	return 0;
 }
+static int dummy_capable	(int cap, int kern_retval)	{return kern_retval;}
 
 static int dummy_binprm_alloc_security(struct linux_binprm *bprm)	{return 0;}
 static void dummy_binprm_free_security	(struct linux_binprm *bprm)		{return;}
@@ -83,9 +105,20 @@
 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_permission	(struct inode *inode, int mask) {return 0;}
+
+static int dummy_inode_permission(struct inode *inode, int mask, 
+				  int kern_retval) 
+{
+	return kern_retval;
+}
+
 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_setattr(struct dentry *dentry, struct iattr *iattr, int kern_retval) 
+{
+	return kern_retval;
+}
+
 static void dummy_inode_attach_pathlabel(struct dentry *dentry, struct vfsmount *mnt) {return;}
 static int dummy_inode_stat(struct inode *inode) {return 0;}
 
@@ -96,21 +129,62 @@
 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)	{return 0;}
-static int dummy_file_mmap		(struct file *file)	{return 0;}
+static int dummy_file_mmap		(struct file *file, 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_fown_alloc_security	(struct fown_struct *fown)	{return 0;}
+static void dummy_fown_free_security	(struct fown_struct *fown)	{return;}
+
+static int dummy_fown_send_sigiotask	(struct task_struct *tsk, struct fown_struct *fown, int fd, int reason, int kern_retval)
+{
+	return kern_retval;
+}
 
 static int dummy_task_create		(void)	{return 0;}
 static int dummy_task_alloc_security	(struct task_struct *p)	{return 0;}
 static void dummy_task_free_security	(struct task_struct *p)	{return;}
-static int dummy_task_setuid		(void)	{return 0;}
-static int dummy_task_setgid		(void)	{return 0;}
-static int dummy_task_setgroups		(void)	{return 0;}
-static int dummy_task_setnice		(struct task_struct *p, int nice)			{return 0;}
-static int dummy_task_setrlimit		(unsigned int resource)	{return 0;}
-static int dummy_task_setscheduler	(struct task_struct *p, int policy)			{return 0;}
-static int dummy_task_kill		(struct task_struct *p, struct siginfo *info, int sig)	{return 0;}
+static int dummy_task_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, int kern_retval)
+{
+	return kern_retval;
+}
+
+static int dummy_task_setrlimit(unsigned int resource, 
+				struct rlimit *new_rlim,
+				int kern_retval)
+{
+	return kern_retval;
+}
+
+static int dummy_task_setscheduler(struct task_struct *p, int policy, int kern_retval)
+{
+	return kern_retval;
+}
+
+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, int kern_retval)	
+{
+	return kern_retval;
+}
+
 static int dummy_task_set_label		(char *filename)	{return 0;}
 static void dummy_task_reset_label	(void)			{return;}
 
@@ -129,9 +203,9 @@
 static int dummy_shm_setattr		(void)	{return 0;}
 static int dummy_shm_delete		(void)	{return 0;}
 
-static int dummy_register		(const char *name, struct security_operations *ops)
+static int dummy_register		(struct security_operations *ops)
 {return -EINVAL;}
-static int dummy_unregister		(const char *name, struct security_operations *ops)
+static int dummy_unregister		(struct security_operations *ops)
 {return -EINVAL;}
 
 static struct binprm_security_ops dummy_binprm_ops = {
@@ -180,9 +254,18 @@
 	write:		dummy_file_write,
 	ioctl:		dummy_file_ioctl,
 	mmap:		dummy_file_mmap,
+	mprotect:	dummy_file_mprotect,
 	lock:		dummy_file_lock,
 	readv:		dummy_file_readv,
 	writev:		dummy_file_writev,
+	fcntl:		dummy_file_fcntl,
+	fcntl64:	dummy_file_fcntl64,
+};
+
+static struct fown_security_ops dummy_fown_ops = {
+	alloc_security:	dummy_fown_alloc_security,
+	free_security:	dummy_fown_free_security,
+	send_sigiotask:	dummy_fown_send_sigiotask,
 };
 
 static struct task_security_ops	dummy_task_ops = {
@@ -195,6 +278,7 @@
 	setnice:	dummy_task_setnice,
 	setrlimit:	dummy_task_setrlimit,
 	setscheduler:	dummy_task_setscheduler,
+	wait:		dummy_task_wait,
 	kill:		dummy_task_kill,
 	set_label:	dummy_task_set_label,
 	reset_label:	dummy_task_reset_label,
@@ -248,6 +332,7 @@
 	sb_ops:			&dummy_sb_ops,
 	inode_ops:		&dummy_inode_ops,
 	file_ops:		&dummy_file_ops,
+	fown_ops:               &dummy_fown_ops,
 	task_ops:		&dummy_task_ops,
 	socket_ops:		&dummy_socket_ops,
 	module_ops:		&dummy_module_ops,
@@ -352,7 +437,7 @@
 /* mod_reg_security - this allows stacking security modules.
  * register security ops with primary security module
  */
-int mod_reg_security(const char *name, struct security_operations *ops)
+int mod_reg_security(struct security_operations *ops)
 {
 	if (verify(ops)) {
 		printk (KERN_INFO __FUNCTION__ " could not verify "
@@ -366,11 +451,11 @@
 		return -EINVAL;
 	}
 
-	return security_ops->register_security(name, ops);
+	return security_ops->register_security(ops);
 }
 
 /* mod_unreg_security - unregister security ops from primary security module */
-int mod_unreg_security(const char *name, struct security_operations *ops)
+int mod_unreg_security(struct security_operations *ops)
 {
 	if (ops == security_ops) {
 		printk (KERN_INFO __FUNCTION__ " invalid attempt to unregister "
@@ -378,12 +463,27 @@
 		return -EINVAL;
 	}
 
-	return security_ops->unregister_security(name, ops);
+	return security_ops->unregister_security(ops);
 }
 
 int capable (int cap)
 {
-	return security_ops->capable(cap) ? 0 : 1;
+	int retval = -EPERM;
+
+#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
+		retval = 0;
+
+	if (!security_ops->capable(cap, retval))
+	{
+		current->flags |= PF_SUPERPRIV;
+		return 1;
+	}
+	return 0;
+
 }
 
 EXPORT_SYMBOL(register_security);
diff -Naur -X ../dontdiff lsm/kernel/signal.c linux-2.4.5-lsm-nai/kernel/signal.c
--- lsm/kernel/signal.c	Fri Jun  8 10:19:08 2001
+++ linux-2.4.5-lsm-nai/kernel/signal.c	Tue Jun 12 09:25:42 2001
@@ -311,7 +311,7 @@
 	    && ((sig != SIGCONT) || (current->session != t->session))
 	    && (current->euid ^ t->suid) && (current->euid ^ t->uid)
 	    && (current->uid ^ t->suid) && (current->uid ^ t->uid)
-	    && security_ops->task_ops->kill(t, info, sig);
+	    && !capable(CAP_KILL);
 }
 
 /*
@@ -515,8 +515,11 @@
 	if (sig < 0 || sig > _NSIG)
 		goto out_nolock;
 	/* The somewhat baroque permissions check... */
-	ret = -EPERM;
+	ret = 0;
 	if (bad_signal(sig, info, t))
+		ret = -EPERM;
+	ret = security_ops->task_ops->kill(t, info, sig, ret);
+	if (ret)
 		goto out_nolock;
 
 	/* The null signal is a permissions and process existance probe.
diff -Naur -X ../dontdiff lsm/kernel/sys.c linux-2.4.5-lsm-nai/kernel/sys.c
--- lsm/kernel/sys.c	Fri Jun  8 10:19:08 2001
+++ linux-2.4.5-lsm-nai/kernel/sys.c	Tue Jun 12 09:25:42 2001
@@ -211,21 +211,23 @@
 
 	read_lock(&tasklist_lock);
 	for_each_task(p) {
-		int no_nice;
+		int no_nice = 0;
 		if (!proc_sel(p, which, who))
 			continue;
-		no_nice = security_ops->task_ops->setnice(p, niceval);
 		if (p->uid != current->euid &&
-			p->uid != current->uid && no_nice) {
-			error = -EPERM;
+			p->uid != current->uid && !capable(CAP_SYS_NICE)) {
+			no_nice = -EPERM;
+		}
+		if (!no_nice && niceval < p->nice && !capable(CAP_SYS_NICE))
+			no_nice = -EACCES;
+		no_nice = security_ops->task_ops->setnice(p, niceval, no_nice);
+		if (no_nice) {
+			error = no_nice;
 			continue;
 		}
 		if (error == -ESRCH)
 			error = 0;
-		if (niceval < p->nice && no_nice)
-			error = -EACCES;
-		else
-			p->nice = niceval;
+		p->nice = niceval;
 	}
 	read_unlock(&tasklist_lock);
 
@@ -272,12 +274,15 @@
 asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void * arg)
 {
 	char buffer[256];
-	int result;
+	int retval;
 
-	/* check that we have permission to do this */
-	result = security_ops->reboot(cmd);
-	if (result) {
-		return result;
+	/* We only trust the superuser with rebooting the system. */
+	retval = 0;
+	if (!capable(CAP_SYS_BOOT))
+		retval = -EPERM;
+	retval = security_ops->reboot(cmd, arg, retval);
+	if (retval) {
+		return retval;
 	}
 
 	/* For safety, we require "magic" arguments. */
@@ -384,13 +389,16 @@
 	int old_egid = current->egid;
 	int new_rgid = old_rgid;
 	int new_egid = old_egid;
-	int ok_to_setgid;
+	int retval = 0;
+
+	retval = security_ops->task_ops->setgid(rgid, egid, (gid_t)-1, LSM_SETID_RE);
+	if (retval)
+		return retval;
 
-	ok_to_setgid = !(security_ops->task_ops->setgid());
 	if (rgid != (gid_t) -1) {
 		if ((old_rgid == rgid) ||
 		    (current->egid==rgid) ||
-		    ok_to_setgid)
+		    capable(CAP_SETGID))
 			new_rgid = rgid;
 		else
 			return -EPERM;
@@ -399,7 +407,7 @@
 		if ((old_rgid == egid) ||
 		    (current->egid == egid) ||
 		    (current->sgid == egid) ||
-		    ok_to_setgid)
+		    capable(CAP_SETGID))
 			new_egid = egid;
 		else {
 			return -EPERM;
@@ -427,8 +435,13 @@
 asmlinkage long sys_setgid(gid_t gid)
 {
 	int old_egid = current->egid;
+	int retval;
 
-	if (!security_ops->task_ops->setgid())
+	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(old_egid != gid)
 		{
@@ -542,19 +555,21 @@
 asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
 {
 	int old_ruid, old_euid, old_suid, new_ruid, new_euid;
-	int no_setuid;
+	int retval;
+
+	retval = security_ops->task_ops->setuid(ruid, euid, (uid_t)-1, LSM_SETID_RE);
+	if (retval)
+		return retval;
 
 	new_ruid = old_ruid = current->uid;
 	new_euid = old_euid = current->euid;
 	old_suid = current->suid;
 
-	no_setuid = security_ops->task_ops->setuid();
-
 	if (ruid != (uid_t) -1) {
 		new_ruid = ruid;
 		if ((old_ruid != ruid) &&
 		    (current->euid != ruid) &&
-		    no_setuid)
+		    !capable(CAP_SETUID))
 			return -EPERM;
 	}
 
@@ -563,7 +578,7 @@
 		if ((old_ruid != euid) &&
 		    (current->euid != euid) &&
 		    (current->suid != euid) &&
-		    no_setuid)
+		    !capable(CAP_SETUID))
 			return -EPERM;
 	}
 
@@ -581,7 +596,6 @@
 		current->suid = current->euid;
 	current->fsuid = current->euid;
 
-	/* XXX need to fold this in to LSM hook -cmw */
 	if (!issecure(SECURE_NO_SETUID_FIXUP)) {
 		cap_emulate_setxuid(old_ruid, old_euid, old_suid);
 	}
@@ -606,12 +620,17 @@
 {
 	int old_euid = current->euid;
 	int old_ruid, old_suid, new_ruid, new_suid;
+	int retval;
+
+	retval = security_ops->task_ops->setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_ID);
+	if (retval)
+		return retval;
 
 	old_ruid = new_ruid = current->uid;
 	old_suid = current->suid;
 	new_suid = old_suid;
-	
-	if (!security_ops->task_ops->setuid()) {
+
+	if (capable(CAP_SETUID)) {
 		if (uid != old_ruid && set_user(uid, old_euid != uid) < 0)
 			return -EAGAIN;
 		new_suid = uid;
@@ -626,7 +645,6 @@
 	current->fsuid = current->euid = uid;
 	current->suid = new_suid;
 
-	/* XXX need to fold this in to LSM hook -cmw */
 	if (!issecure(SECURE_NO_SETUID_FIXUP)) {
 		cap_emulate_setxuid(old_ruid, old_euid, old_suid);
 	}
@@ -644,8 +662,13 @@
 	int old_ruid = current->uid;
 	int old_euid = current->euid;
 	int old_suid = current->suid;
+	int retval;
 
-	if (security_ops->task_ops->setuid()) {
+	retval = security_ops->task_ops->setuid(ruid, euid, suid, LSM_SETID_RES);
+	if (retval)
+		return retval;
+
+	if (!capable(CAP_SETUID)) {
 		if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
 		    (ruid != current->euid) && (ruid != current->suid))
 			return -EPERM;
@@ -672,7 +695,6 @@
 	if (suid != (uid_t) -1)
 		current->suid = suid;
 
-	/* XXX need to fold this in to LSM hook -cmw */
 	if (!issecure(SECURE_NO_SETUID_FIXUP)) {
 		cap_emulate_setxuid(old_ruid, old_euid, old_suid);
 	}
@@ -696,7 +718,13 @@
  */
 asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
 {
-	if (security_ops->task_ops->setgid()) {
+	int retval;
+
+	retval = security_ops->task_ops->setgid(rgid, egid, sgid, LSM_SETID_RES);
+	if (retval)
+		return retval;
+
+	if (!capable(CAP_SETGID)) {
 		if ((rgid != (gid_t) -1) && (rgid != current->gid) &&
 		    (rgid != current->egid) && (rgid != current->sgid))
 			return -EPERM;
@@ -744,11 +772,16 @@
 asmlinkage long sys_setfsuid(uid_t uid)
 {
 	int old_fsuid;
+	int retval;
+
+	retval = security_ops->task_ops->setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);
+	if (retval)
+		return retval;
 
 	old_fsuid = current->fsuid;
 	if (uid == current->uid || uid == current->euid ||
 	    uid == current->suid || uid == current->fsuid || 
-	    !security_ops->task_ops->setuid())
+	    capable(CAP_SETUID))
 	{
 		if (uid != old_fsuid)
 		{
@@ -767,7 +800,6 @@
 	 *          if not, we might be a bit too harsh here.
 	 */
 	
-	/* XXX need to fold this in to LSM hook -cmw */
 	if (!issecure(SECURE_NO_SETUID_FIXUP)) {
 		if (old_fsuid == 0 && current->fsuid != 0) {
 			cap_t(current->cap_effective) &= ~CAP_FS_MASK;
@@ -787,11 +819,16 @@
 asmlinkage long sys_setfsgid(gid_t gid)
 {
 	int old_fsgid;
+	int retval;
+
+	retval = security_ops->task_ops->setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS);
+	if (retval)
+		return retval;
 
 	old_fsgid = current->fsgid;
 	if (gid == current->gid || gid == current->egid ||
 	    gid == current->sgid || gid == current->fsgid || 
-	    !security_ops->task_ops->setgid())
+	    capable(CAP_SETGID))
 	{
 		if (gid != old_fsgid)
 		{
@@ -979,12 +1016,19 @@
  
 asmlinkage long sys_setgroups(int gidsetsize, gid_t *grouplist)
 {
-	if (security_ops->task_ops->setgroups())
+	gid_t groups[NGROUPS];
+	int retval;
+
+	if (!capable(CAP_SETGID))
 		return -EPERM;
 	if ((unsigned) gidsetsize > NGROUPS)
 		return -EINVAL;
-	if(copy_from_user(current->groups, grouplist, gidsetsize * sizeof(gid_t)))
+	if(copy_from_user(groups, grouplist, gidsetsize * sizeof(gid_t)))
 		return -EFAULT;
+	retval = security_ops->task_ops->setgroups(gidsetsize, groups);
+	if (retval)
+		return retval;
+	memcpy(current->groups, groups, gidsetsize * sizeof(gid_t));
 	current->ngroups = gidsetsize;
 	return 0;
 }
@@ -1039,21 +1083,25 @@
 
 asmlinkage long sys_sethostname(char *name, int len)
 {
+	char nodename[__NEW_UTS_LEN+1];
 	int errno;
 
-	if (security_ops->sethostname())
+	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 	if (len < 0 || len > __NEW_UTS_LEN)
 		return -EINVAL;
+	if (copy_from_user(nodename, name, len)) 
+		return -EFAULT;
+	nodename[len] = 0;
+
+	errno = security_ops->sethostname(nodename);
+	if (errno)
+		return errno;
 
 	down_write(&uts_sem);
-	errno = -EFAULT;
-	if (!copy_from_user(system_utsname.nodename, name, len)) {
-		system_utsname.nodename[len] = 0;
-		errno = 0;
-	}
+	memcpy(system_utsname.nodename, nodename, len+1);
 	up_write(&uts_sem);
-	return errno;
+	return 0;
 }
 
 asmlinkage long sys_gethostname(char *name, int len)
@@ -1079,19 +1127,23 @@
  */
 asmlinkage long sys_setdomainname(char *name, int len)
 {
+	char domainname[__NEW_UTS_LEN+1];
 	int errno;
 
-	if (security_ops->setdomainname())
+	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 	if (len < 0 || len > __NEW_UTS_LEN)
 		return -EINVAL;
+	if (copy_from_user(domainname, name, len)) 
+		return -EFAULT;
+	domainname[len] = 0;
+
+	errno = security_ops->setdomainname(domainname);
+	if (errno)
+		return errno;
 
 	down_write(&uts_sem);
-	errno = -EFAULT;
-	if (!copy_from_user(system_utsname.domainname, name, len)) {
-		errno = 0;
-		system_utsname.domainname[len] = 0;
-	}
+	memcpy(system_utsname.domainname, domainname, len+1);
 	up_write(&uts_sem);
 	return errno;
 }
@@ -1130,6 +1182,7 @@
 asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit *rlim)
 {
 	struct rlimit new_rlim, *old_rlim;
+	int retval;
 
 	if (resource >= RLIM_NLIMITS)
 		return -EINVAL;
@@ -1138,14 +1191,21 @@
 	if (new_rlim.rlim_cur < 0 || new_rlim.rlim_max < 0)
 		return -EINVAL;
 	old_rlim = current->rlim + resource;
+
+	retval = 0;
 	if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
 	     (new_rlim.rlim_max > old_rlim->rlim_max)) &&
-	    security_ops->task_ops->setrlimit(resource))
-		return -EPERM;
-	if (resource == RLIMIT_NOFILE) {
+	    !capable(CAP_SYS_RESOURCE))
+		retval = -EPERM;
+	if (!retval && resource == RLIMIT_NOFILE) {
 		if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN)
-			return -EPERM;
+			retval = -EPERM;
 	}
+
+	retval = security_ops->task_ops->setrlimit(resource, &new_rlim, retval);
+	if (retval)
+		return retval;
+
 	*old_rlim = new_rlim;
 	return 0;
 }
diff -Naur -X ../dontdiff lsm/kernel/sysctl.c linux-2.4.5-lsm-nai/kernel/sysctl.c
--- lsm/kernel/sysctl.c	Fri Jun  8 10:19:08 2001
+++ linux-2.4.5-lsm-nai/kernel/sysctl.c	Thu Apr 12 12:20:31 2001
@@ -942,7 +942,6 @@
 int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
 			void *buffer, size_t *lenp)
 {
-	/* XXX this is really capabilities specific -cmw */
 	if (!capable(CAP_SYS_MODULE)) {
 		return -EPERM;
 	}
diff -Naur -X ../dontdiff lsm/mm/mmap.c linux-2.4.5-lsm-nai/mm/mmap.c
--- lsm/mm/mmap.c	Fri Jun  8 10:19:08 2001
+++ linux-2.4.5-lsm-nai/mm/mmap.c	Tue Jun 12 09:25:42 2001
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/file.h>
 #include <linux/fs.h>
+#include <linux/security.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
@@ -251,6 +252,10 @@
 			return -EAGAIN;
 	}
 
+	error = security_ops->file_ops->mmap(file, flags, prot);
+	if (error)
+		return error;
+		
 	if (file) {
 		switch (flags & MAP_TYPE) {
 		case MAP_SHARED:
diff -Naur -X ../dontdiff lsm/mm/mprotect.c linux-2.4.5-lsm-nai/mm/mprotect.c
--- lsm/mm/mprotect.c	Fri Jun  8 10:19:08 2001
+++ linux-2.4.5-lsm-nai/mm/mprotect.c	Tue Jun 12 09:25:42 2001
@@ -7,6 +7,7 @@
 #include <linux/smp_lock.h>
 #include <linux/shm.h>
 #include <linux/mman.h>
+#include <linux/security.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
@@ -260,6 +261,10 @@
 			error = -EACCES;
 			break;
 		}
+
+		error = security_ops->file_ops->mprotect(vma, prot);
+		if (error)
+			break;
 
 		if (vma->vm_end >= end) {
 			error = mprotect_fixup(vma, nstart, end, newflags);
diff -Naur -X ../dontdiff lsm/security/Config.in linux-2.4.5-lsm-nai/security/Config.in
--- lsm/security/Config.in	Fri Jun  8 10:19:14 2001
+++ linux-2.4.5-lsm-nai/security/Config.in	Tue Jun 12 09:25:42 2001
@@ -3,6 +3,5 @@
 #
 mainmenu_option next_comment
 comment 'Security options'
-tristate '  Capabilities Support' CONFIG_CAPABILITIES
 
 endmenu