New LSM patch for consideration

From: Stephen Smalley (sdsat_private)
Date: Tue Jun 12 2001 - 09:10:39 PDT

  • Next message: Chris Wright: "Re: Some New Hooks"

    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.
    
    The attached patch differs from the old LSM patch in the following ways:
    
    1) All of the non-capable hooks are now either restrictive or
    authoritative.  I made the hook functions authoritative where
    there was existing base logic, the base logic was cleanly decoupled
    from the functional logic, and it was feasible to colocate the hook
    with the existing base logic.  I reverted the non-capable permissive hooks
    to capable() calls and added restrictive or authoritative hooks for those
    operations.  The following hooks were changed to be authoritative:  
    permission, setattr, send_sigiotask, kill, ptrace, setnice, setrlimit,
    setscheduler, ioperm, iopl, reboot.  There are probably other hooks that
    could be made authoritative without too much trouble.
    
    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.
    
    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.
    
    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.
    
    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.
    
    --
    Stephen D. Smalley, NAI Labs
    ssmalleyat_private
    
    
    
    
    diff -Nru linux/Makefile lsm-new/Makefile
    --- linux/Makefile	Fri May 25 12:51:33 2001
    +++ lsm-new/Makefile	Mon Jun 11 16:29:08 2001
    @@ -1,7 +1,7 @@
     VERSION = 2
     PATCHLEVEL = 4
     SUBLEVEL = 5
    -EXTRAVERSION =
    +EXTRAVERSION = -lsm
     
     KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
     
    @@ -227,6 +227,10 @@
     
     
     include arch/$(ARCH)/Makefile
    +
    +# if we have a StackGuard compiler, then we need to turn off the canary death handler stuff
    +CFLAGS	+= $(shell if $(CC) -fno-canary-all-functions -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-fno-canary-all-functions"; fi)
    +CFLAGS	+= $(shell if $(CC) -mno-terminator-canary -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-mno-terminator-canary"; fi)
     
     export	CPPFLAGS CFLAGS AFLAGS
     
    diff -Nru linux/arch/i386/boot/compressed/Makefile lsm-new/arch/i386/boot/compressed/Makefile
    --- linux/arch/i386/boot/compressed/Makefile	Tue Mar  7 14:04:12 2000
    +++ lsm-new/arch/i386/boot/compressed/Makefile	Mon Jun 11 16:29:08 2001
    @@ -12,6 +12,10 @@
     CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS
     ZLDFLAGS = -e startup_32
     
    +# if we have a StackGuard compiler, then we need to turn off the canary death handler stuff
    +CFLAGS += $(shell if $(CC) -fno-canary-all-functions -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-fno-canary-all-functions"; fi)
    +CFLAGS += $(shell if $(CC) -mno-terminator-canary -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-mno-terminator-canary"; fi)
    +
     #
     # ZIMAGE_OFFSET is the load offset of the compression loader
     # BZIMAGE_OFFSET is the load offset of the high loaded compression loader
    diff -Nru linux/arch/i386/config.in lsm-new/arch/i386/config.in
    --- linux/arch/i386/config.in	Thu May 24 18:14:08 2001
    +++ lsm-new/arch/i386/config.in	Mon Jun 11 16:29:08 2001
    @@ -381,3 +381,6 @@
     #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
     bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
     endmenu
    +
    +source security/Config.in
    +
    diff -Nru linux/arch/i386/kernel/entry.S lsm-new/arch/i386/kernel/entry.S
    --- linux/arch/i386/kernel/entry.S	Wed Nov  8 20:09:50 2000
    +++ lsm-new/arch/i386/kernel/entry.S	Mon Jun 11 16:29:08 2001
    @@ -646,6 +646,7 @@
     	.long SYMBOL_NAME(sys_getdents64)	/* 220 */
     	.long SYMBOL_NAME(sys_fcntl64)
     	.long SYMBOL_NAME(sys_ni_syscall)	/* reserved for TUX */
    +	.long SYMBOL_NAME(sys_ni_syscall)	/* reserved for LSM? */
     
     	/*
     	 * NOTE!! This doesn't have to be exact - we just have
    @@ -656,3 +657,4 @@
     	.rept NR_syscalls-221
     		.long SYMBOL_NAME(sys_ni_syscall)
     	.endr
    +
    diff -Nru linux/arch/i386/kernel/ioport.c lsm-new/arch/i386/kernel/ioport.c
    --- linux/arch/i386/kernel/ioport.c	Mon Jul 19 18:22:48 1999
    +++ lsm-new/arch/i386/kernel/ioport.c	Tue Jun 12 10:22:08 2001
    @@ -14,6 +14,7 @@
     #include <linux/smp.h>
     #include <linux/smp_lock.h>
     #include <linux/stddef.h>
    +#include <linux/security.h>
     
     /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
     static void set_bitmap(unsigned long *bitmap, short base, short extent, int new_value)
    @@ -56,11 +57,19 @@
     {
     	struct thread_struct * t = &current->thread;
     	struct tss_struct * tss = init_tss + smp_processor_id();
    +	int retval;
     
     	if ((from + num <= from) || (from + num > IO_BITMAP_SIZE*32))
     		return -EINVAL;
    +
    +	retval = 0;
     	if (turn_on && !capable(CAP_SYS_RAWIO))
    -		return -EPERM;
    +		retval = -EPERM;
    +	retval = security_ops->ioperm(from, num, turn_on, retval);
    +	if (retval) {
    +		return retval;
    +	}
    +
     	/*
     	 * If it's the first ioperm() call in this thread's lifetime, set the
     	 * IO bitmap up. ioperm() is much less timing critical than clone(),
    @@ -103,14 +112,21 @@
     	struct pt_regs * regs = (struct pt_regs *) &unused;
     	unsigned int level = regs->ebx;
     	unsigned int old = (regs->eflags >> 12) & 3;
    +	int retval;
     
     	if (level > 3)
     		return -EINVAL;
     	/* Trying to gain more privileges? */
    +	retval = 0;
     	if (level > old) {
     		if (!capable(CAP_SYS_RAWIO))
    -			return -EPERM;
    +			retval = -EPERM;
     	}
    +	retval = security_ops->iopl(old, level, retval);
    +	if (retval) {
    +		return retval;
    +	}
    +
     	regs->eflags = (regs->eflags & 0xffffcfff) | (level << 12);
     	return 0;
     }
    diff -Nru linux/arch/i386/kernel/ptrace.c lsm-new/arch/i386/kernel/ptrace.c
    --- linux/arch/i386/kernel/ptrace.c	Tue Mar  6 22:44:37 2001
    +++ lsm-new/arch/i386/kernel/ptrace.c	Mon Jun 11 16:29:08 2001
    @@ -13,6 +13,7 @@
     #include <linux/errno.h>
     #include <linux/ptrace.h>
     #include <linux/user.h>
    +#include <linux/security.h>
     
     #include <asm/uaccess.h>
     #include <asm/pgtable.h>
    @@ -146,6 +147,9 @@
     		/* are we already being traced? */
     		if (current->ptrace & PT_PTRACED)
     			goto out;
    +		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;
     		ret = 0;
    @@ -167,6 +171,7 @@
     	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) ||
    @@ -174,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 -Nru linux/fs/attr.c lsm-new/fs/attr.c
    --- linux/fs/attr.c	Mon Oct 16 16:00:53 2000
    +++ lsm-new/fs/attr.c	Mon Jun 11 16:29:09 2001
    @@ -11,6 +11,7 @@
     #include <linux/smp_lock.h>
     #include <linux/dnotify.h>
     #include <linux/fcntl.h>
    +#include <linux/security.h>
     
     /* Taken over from the old code... */
     
    @@ -120,10 +121,13 @@
     		attr->ia_mtime = now;
     
     	lock_kernel();
    -	if (inode->i_op && inode->i_op->setattr) 
    -		error = inode->i_op->setattr(dentry, attr);
    -	else {
    +	if (inode->i_op && inode->i_op->setattr) {
    +		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);
     	}
    diff -Nru linux/fs/exec.c lsm-new/fs/exec.c
    --- linux/fs/exec.c	Thu Apr 26 17:11:29 2001
    +++ lsm-new/fs/exec.c	Tue Jun 12 10:22:08 2001
    @@ -652,6 +652,10 @@
     			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? */
    +
     	memset(bprm->buf,0,BINPRM_BUF_SIZE);
     	return kernel_read(bprm->file,0,bprm->buf,BINPRM_BUF_SIZE);
     }
    @@ -720,6 +724,8 @@
     	if(do_unlock)
     		unlock_kernel();
     	current->keep_capabilities = 0;
    +
    +	security_ops->bprm_ops->compute_creds(bprm);
     }
     
     
    @@ -891,10 +897,16 @@
     	if (retval < 0) 
     		goto out; 
     
    +	retval = security_ops->task_ops->set_label(filename);
    +	if (retval)
    +		goto out;
    +
     	retval = search_binary_handler(&bprm,regs);
     	if (retval >= 0)
     		/* execve success */
     		return retval;
    +	else
    +		security_ops->task_ops->reset_label();
     
     out:
     	/* Something went wrong, return the inode and free the argument pages*/
    diff -Nru linux/fs/fcntl.c lsm-new/fs/fcntl.c
    --- linux/fs/fcntl.c	Tue May 22 12:26:06 2001
    +++ lsm-new/fs/fcntl.c	Tue Jun 12 10:22:08 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 -Nru linux/fs/file_table.c lsm-new/fs/file_table.c
    --- linux/fs/file_table.c	Wed Apr 18 14:49:12 2001
    +++ lsm-new/fs/file_table.c	Mon Jun 11 16:29:09 2001
    @@ -11,6 +11,7 @@
     #include <linux/init.h>
     #include <linux/module.h>
     #include <linux/smp_lock.h>
    +#include <linux/security.h>
     
     /* sysctl tunables... */
     struct files_stat_struct files_stat = {0, 0, NR_FILE};
    @@ -106,6 +107,8 @@
     		locks_remove_flock(file);
     		if (file->f_op && file->f_op->release)
     			file->f_op->release(inode, file);
    +		security_ops->file_ops->free_security (file);
    +
     		fops_put(file->f_op);
     		file->f_dentry = NULL;
     		file->f_vfsmnt = NULL;
    diff -Nru linux/fs/inode.c lsm-new/fs/inode.c
    --- linux/fs/inode.c	Tue May 22 12:35:42 2001
    +++ lsm-new/fs/inode.c	Mon Jun 11 16:29:09 2001
    @@ -15,6 +15,7 @@
     #include <linux/cache.h>
     #include <linux/swap.h>
     #include <linux/swapctl.h>
    +#include <linux/security.h>
     
     /*
      * New inode.c implementation.
    @@ -501,6 +502,7 @@
     		cdput(inode->i_cdev);
     		inode->i_cdev = NULL;
     	}
    +	security_ops->inode_ops->free_security(inode);
     	inode->i_state = I_CLEAR;
     }
     
    @@ -759,6 +761,7 @@
     	inode->i_data.host = inode;
     	inode->i_data.gfp_mask = GFP_HIGHUSER;
     	inode->i_mapping = &inode->i_data;
    +	security_ops->inode_ops->alloc_security(inode); /* hmm, no way to preserve error */
     }
     
     /**
    diff -Nru linux/fs/namei.c lsm-new/fs/namei.c
    --- linux/fs/namei.c	Sat May 19 21:02:45 2001
    +++ lsm-new/fs/namei.c	Tue Jun 12 10:29:24 2001
    @@ -22,6 +22,7 @@
     #include <linux/pagemap.h>
     #include <linux/dcache.h>
     #include <linux/dnotify.h>
    +#include <linux/security.h>
     
     #include <asm/uaccess.h>
     #include <asm/unaligned.h>
    @@ -182,14 +183,20 @@
     
     int permission(struct inode * inode,int mask)
     {
    +	int submask;
    +	int retval;
    +
    +	/* Ordinary permission routines do not understand MAY_APPEND. */
    +	submask = mask & ~MAY_APPEND;
    +
     	if (inode->i_op && inode->i_op->permission) {
    -		int retval;
     		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);
     }
     
     /*
    @@ -311,9 +318,12 @@
     
     static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd)
     {
    -	int err;
    +	int err = -ELOOP;
     	if (current->link_count >= 8)
     		goto loop;
    +	err = security_ops->inode_ops->follow_link(dentry, nd);
    +	if (err)
    +		goto loop;
     	current->link_count++;
     	UPDATE_ATIME(dentry->d_inode);
     	err = dentry->d_inode->i_op->follow_link(dentry, nd);
    @@ -321,7 +331,7 @@
     	return err;
     loop:
     	path_release(nd);
    -	return -ELOOP;
    +	return err;
     }
     
     static inline int __follow_up(struct vfsmount **mnt, struct dentry **base)
    @@ -435,6 +445,8 @@
     	if (current->link_count)
     		lookup_flags = LOOKUP_FOLLOW;
     
    +	security_ops->inode_ops->attach_pathlabel(nd->dentry, nd->mnt);
    +
     	/* At this point we know we have a real path component. */
     	for(;;) {
     		unsigned long hash;
    @@ -530,6 +542,9 @@
     		err = -ENOTDIR; 
     		if (!inode->i_op->lookup)
     			break;
    +
    +		security_ops->inode_ops->attach_pathlabel(nd->dentry, nd->mnt);
    +
     		continue;
     		/* here ends the main loop */
     
    @@ -584,6 +599,7 @@
     			if (!inode->i_op || !inode->i_op->lookup)
     				break;
     		}
    +		security_ops->inode_ops->attach_pathlabel(nd->dentry, nd->mnt);
     		goto return_base;
     no_inode:
     		err = -ENOENT;
    @@ -909,14 +925,20 @@
     	if (!dir->i_op || !dir->i_op->create)
     		goto exit_lock;
     
    +	error = security_ops->inode_ops->create(dir, dentry, mode);
    +	if (error)
    +		goto exit_lock;
    +
     	DQUOT_INIT(dir);
     	lock_kernel();
     	error = dir->i_op->create(dir, dentry, mode);
     	unlock_kernel();
     exit_lock:
     	up(&dir->i_zombie);
    -	if (!error)
    +	if (!error) {
     		inode_dir_notify(dir, DN_CREATE);
    +		security_ops->inode_ops->post_create(dir, dentry, mode);
    +	}
     	return error;
     }
     
    @@ -944,6 +966,11 @@
     
     	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.
     	 */
    @@ -987,6 +1014,7 @@
     	/* Negative dentry, just create the file */
     	if (!dentry->d_inode) {
     		error = vfs_create(dir->d_inode, dentry, mode);
    +		security_ops->inode_ops->attach_pathlabel(dentry, nd->mnt);
     		up(&dir->d_inode->i_sem);
     		dput(nd->dentry);
     		nd->dentry = dentry;
    @@ -996,7 +1024,8 @@
     		acc_mode = 0;
     		flag &= ~O_TRUNC;
     		goto ok;
    -	}
    +	} else
    +		security_ops->inode_ops->attach_pathlabel(dentry, nd->mnt);
     
     	/*
     	 * It already exists.
    @@ -1038,6 +1067,8 @@
     	if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE))
     		goto exit;
     
    +	security_ops->inode_ops->attach_pathlabel(dentry, nd->mnt);
    +
     	error = permission(inode,acc_mode);
     	if (error)
     		goto exit;
    @@ -1121,6 +1152,9 @@
     	 * stored in nd->last.name and we will have to putname() it when we
     	 * are done. Procfs-like symlinks just set LAST_BIND.
     	 */
    +	error = security_ops->inode_ops->follow_link(dentry, nd);
    +	if (error)
    +		goto exit_dput;
     	UPDATE_ATIME(dentry->d_inode);
     	error = dentry->d_inode->i_op->follow_link(dentry, nd);
     	dput(dentry);
    @@ -1189,14 +1223,20 @@
     	if (!dir->i_op || !dir->i_op->mknod)
     		goto exit_lock;
     
    +	error = security_ops->inode_ops->mknod(dir, dentry, mode, dev);
    +	if (error)
    +		goto exit_lock;
    +
     	DQUOT_INIT(dir);
     	lock_kernel();
     	error = dir->i_op->mknod(dir, dentry, mode, dev);
     	unlock_kernel();
     exit_lock:
     	up(&dir->i_zombie);
    -	if (!error)
    +	if (!error) {
     		inode_dir_notify(dir, DN_CREATE);
    +		security_ops->inode_ops->post_mknod(dir, dentry, mode, dev);
    +	}
     	return error;
     }
     
    @@ -1233,6 +1273,7 @@
     		default:
     			error = -EINVAL;
     		}
    +		security_ops->inode_ops->attach_pathlabel(dentry, nd.mnt);
     		dput(dentry);
     	}
     	up(&nd.dentry->d_inode->i_sem);
    @@ -1256,6 +1297,10 @@
     	if (!dir->i_op || !dir->i_op->mkdir)
     		goto exit_lock;
     
    +	error = security_ops->inode_ops->mkdir(dir, dentry, mode);
    +	if (error)
    +		goto exit_lock;
    +
     	DQUOT_INIT(dir);
     	mode &= (S_IRWXUGO|S_ISVTX) & ~current->fs->umask;
     	lock_kernel();
    @@ -1264,8 +1309,10 @@
     
     exit_lock:
     	up(&dir->i_zombie);
    -	if (!error)
    +	if (!error) {
     		inode_dir_notify(dir, DN_CREATE);
    +		security_ops->inode_ops->post_mkdir(dir,dentry, mode);
    +	}
     	return error;
     }
     
    @@ -1288,6 +1335,7 @@
     		error = PTR_ERR(dentry);
     		if (!IS_ERR(dentry)) {
     			error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
    +			security_ops->inode_ops->attach_pathlabel(dentry, nd.mnt);
     			dput(dentry);
     		}
     		up(&nd.dentry->d_inode->i_sem);
    @@ -1347,11 +1395,14 @@
     	else if (d_mountpoint(dentry))
     		error = -EBUSY;
     	else {
    -		lock_kernel();
    -		error = dir->i_op->rmdir(dir, dentry);
    -		unlock_kernel();
    -		if (!error)
    -			dentry->d_inode->i_flags |= S_DEAD;
    +		error = security_ops->inode_ops->rmdir(dir, dentry);
    +		if (!error) {
    +			lock_kernel();
    +			error = dir->i_op->rmdir(dir, dentry);
    +			unlock_kernel();
    +			if (!error)
    +				dentry->d_inode->i_flags |= S_DEAD;
    +		}
     	}
     	double_up(&dir->i_zombie, &dentry->d_inode->i_zombie);
     	if (!error) {
    @@ -1418,11 +1469,14 @@
     			if (d_mountpoint(dentry))
     				error = -EBUSY;
     			else {
    -				lock_kernel();
    -				error = dir->i_op->unlink(dir, dentry);
    -				unlock_kernel();
    -				if (!error)
    -					d_delete(dentry);
    +				error = security_ops->inode_ops->unlink(dir, dentry);
    +				if (!error) {
    +					lock_kernel();
    +					error = dir->i_op->unlink(dir, dentry);
    +					unlock_kernel();
    +					if (!error)
    +						d_delete(dentry);
    +				}
     			}
     		}
     	}
    @@ -1488,6 +1542,10 @@
     	if (!dir->i_op || !dir->i_op->symlink)
     		goto exit_lock;
     
    +	error = security_ops->inode_ops->symlink(dir, dentry, oldname);
    +	if (error)
    +		goto exit_lock;
    +
     	DQUOT_INIT(dir);
     	lock_kernel();
     	error = dir->i_op->symlink(dir, dentry, oldname);
    @@ -1495,8 +1553,10 @@
     
     exit_lock:
     	up(&dir->i_zombie);
    -	if (!error)
    +	if (!error) {
     		inode_dir_notify(dir, DN_CREATE);
    +		security_ops->inode_ops->post_symlink(dir, dentry, oldname);
    +	}
     	return error;
     }
     
    @@ -1562,6 +1622,10 @@
     	if (!dir->i_op || !dir->i_op->link)
     		goto exit_lock;
     
    +	error = security_ops->inode_ops->link(old_dentry, dir, new_dentry);
    +	if (error)
    +		goto exit_lock;
    +
     	DQUOT_INIT(dir);
     	lock_kernel();
     	error = dir->i_op->link(old_dentry, dir, new_dentry);
    @@ -1569,8 +1633,10 @@
     
     exit_lock:
     	up(&dir->i_zombie);
    -	if (!error)
    +	if (!error) {
     		inode_dir_notify(dir, DN_CREATE);
    +		security_ops->inode_ops->post_link(old_dentry, dir, new_dentry);
    +	}
     	return error;
     }
     
    @@ -1691,6 +1757,10 @@
     	if (error)
     		return error;
     
    +	error = security_ops->inode_ops->rename(old_dir, old_dentry, new_dir, new_dentry);
    +	if (error)
    +		return error;
    +
     	DQUOT_INIT(old_dir);
     	DQUOT_INIT(new_dir);
     	down(&old_dir->i_sb->s_vfs_rename_sem);
    @@ -1725,8 +1795,11 @@
     		double_up(&old_dir->i_zombie,
     			  &new_dir->i_zombie);
     		
    -	if (!error)
    +	if (!error) {
     		d_move(old_dentry,new_dentry);
    +		security_ops->inode_ops->post_rename(old_dir, old_dentry,
    +							new_dir, new_dentry);
    +	}
     out_unlock:
     	up(&old_dir->i_sb->s_vfs_rename_sem);
     	return error;
    @@ -1757,6 +1830,10 @@
     	if (!old_dir->i_op || !old_dir->i_op->rename)
     		return -EPERM;
     
    +	error = security_ops->inode_ops->rename(old_dir, old_dentry, new_dir, new_dentry);
    +	if (error)
    +		return error;
    +
     	DQUOT_INIT(old_dir);
     	DQUOT_INIT(new_dir);
     	double_down(&old_dir->i_zombie, &new_dir->i_zombie);
    @@ -1771,6 +1848,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);
     	return 0;
     }
     
    diff -Nru linux/fs/open.c lsm-new/fs/open.c
    --- linux/fs/open.c	Fri Feb  9 14:29:44 2001
    +++ lsm-new/fs/open.c	Mon Jun 11 16:29:09 2001
    @@ -14,6 +14,7 @@
     #include <linux/module.h>
     #include <linux/slab.h>
     #include <linux/tty.h>
    +#include <linux/security.h>
     
     #include <asm/uaccess.h>
     
    @@ -27,6 +28,9 @@
     		retval = -ENOSYS;
     		if (sb->s_op && sb->s_op->statfs) {
     			memset(buf, 0, sizeof(struct statfs));
    +			retval = security_ops->sb_ops->statfs(sb);
    +			if (retval)
    +				return retval;
     			lock_kernel();
     			retval = sb->s_op->statfs(sb, buf);
     			unlock_kernel();
    @@ -663,6 +667,10 @@
     	}
     	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
     
    +	error = -EACCES;
    +	if (security_ops->file_ops->alloc_security (f))
    +		goto cleanup_all;
    +	
     	return f;
     
     cleanup_all:
    diff -Nru linux/fs/proc/base.c lsm-new/fs/proc/base.c
    --- linux/fs/proc/base.c	Fri May  4 17:44:06 2001
    +++ lsm-new/fs/proc/base.c	Mon Jun 11 16:29:09 2001
    @@ -310,7 +310,7 @@
     };
     
     #define MAY_PTRACE(p) \
    -(p==current||(p->p_pptr==current&&(p->ptrace & PT_PTRACED)&&p->state==TASK_STOPPED))
    +(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 -Nru linux/fs/read_write.c lsm-new/fs/read_write.c
    --- linux/fs/read_write.c	Tue Apr 17 17:36:44 2001
    +++ lsm-new/fs/read_write.c	Mon Jun 11 16:29:09 2001
    @@ -11,6 +11,7 @@
     #include <linux/uio.h>
     #include <linux/smp_lock.h>
     #include <linux/dnotify.h>
    +#include <linux/security.h>
     
     #include <asm/uaccess.h>
     
    @@ -129,8 +130,11 @@
     			if (!ret) {
     				ssize_t (*read)(struct file *, char *, size_t, loff_t *);
     				ret = -EINVAL;
    -				if (file->f_op && (read = file->f_op->read) != NULL)
    -					ret = read(file, buf, count, &file->f_pos);
    +				if (file->f_op && (read = file->f_op->read) != NULL) {
    +					ret = security_ops->file_ops->permission (file, MAY_READ);
    +					if (!ret)
    +						ret = read(file, buf, count, &file->f_pos);
    +				}
     			}
     		}
     		if (ret > 0)
    @@ -156,8 +160,11 @@
     			if (!ret) {
     				ssize_t (*write)(struct file *, const char *, size_t, loff_t *);
     				ret = -EINVAL;
    -				if (file->f_op && (write = file->f_op->write) != NULL)
    -					ret = write(file, buf, count, &file->f_pos);
    +				if (file->f_op && (write = file->f_op->write) != NULL) {
    +					ret = security_ops->file_ops->permission (file, MAY_WRITE);
    +					if (!ret)
    +						ret = write(file, buf, count, &file->f_pos);
    +				}
     			}
     		}
     		if (ret > 0)
    @@ -283,8 +290,11 @@
     	if (!file)
     		goto bad_file;
     	if (file->f_op && (file->f_mode & FMODE_READ) &&
    -	    (file->f_op->readv || file->f_op->read))
    -		ret = do_readv_writev(VERIFY_WRITE, file, vector, count);
    +	    (file->f_op->readv || file->f_op->read)) {
    +		ret = security_ops->file_ops->permission (file, MAY_READ);
    +		if (!ret)
    +			ret = do_readv_writev(VERIFY_WRITE, file, vector, count);
    +	}
     	fput(file);
     
     bad_file:
    @@ -303,8 +313,11 @@
     	if (!file)
     		goto bad_file;
     	if (file->f_op && (file->f_mode & FMODE_WRITE) &&
    -	    (file->f_op->writev || file->f_op->write))
    -		ret = do_readv_writev(VERIFY_READ, file, vector, count);
    +	    (file->f_op->writev || file->f_op->write)) {
    +		ret = security_ops->file_ops->permission (file, MAY_WRITE);
    +		if (!ret)
    +			ret = do_readv_writev(VERIFY_READ, file, vector, count);
    +	}
     	fput(file);
     
     bad_file:
    @@ -337,6 +350,11 @@
     		goto out;
     	if (pos < 0)
     		goto out;
    +
    +	ret = security_ops->file_ops->permission (file, MAY_READ);
    +	if (ret)
    +		goto out;
    +
     	ret = read(file, buf, count, &pos);
     	if (ret > 0)
     		inode_dir_notify(file->f_dentry->d_parent->d_inode, DN_ACCESS);
    @@ -367,6 +385,10 @@
     	if (!file->f_op || !(write = file->f_op->write))
     		goto out;
     	if (pos < 0)
    +		goto out;
    +
    +	ret = security_ops->file_ops->permission (file, MAY_WRITE);
    +	if (ret)
     		goto out;
     
     	ret = write(file, buf, count, &pos);
    diff -Nru linux/fs/stat.c lsm-new/fs/stat.c
    --- linux/fs/stat.c	Wed Apr 18 14:49:12 2001
    +++ lsm-new/fs/stat.c	Mon Jun 11 16:29:09 2001
    @@ -10,6 +10,7 @@
     #include <linux/file.h>
     #include <linux/smp_lock.h>
     #include <linux/highuid.h>
    +#include <linux/security.h>
     
     #include <asm/uaccess.h>
     
    @@ -19,9 +20,14 @@
     static __inline__ int
     do_revalidate(struct dentry *dentry)
     {
    +	int error;
     	struct inode * inode = dentry->d_inode;
    -	if (inode->i_op && inode->i_op->revalidate)
    +	if (inode->i_op && inode->i_op->revalidate) {
    +		error = security_ops->inode_ops->revalidate(dentry);
    +		if (error)
    +			return error;
     		return inode->i_op->revalidate(dentry);
    +	}
     	return 0;
     }
     
    @@ -36,6 +42,11 @@
     {
     	static int warncount = 5;
     	struct __old_kernel_stat tmp;
    +	int retval;
    +
    +	retval = security_ops->inode_ops->stat(inode);
    +	if (retval)
    +		return retval;
     
     	if (warncount > 0) {
     		warncount--;
    @@ -70,6 +81,11 @@
     {
     	struct stat tmp;
     	unsigned int blocks, indirect;
    +	int retval;
    +
    +	retval = security_ops->inode_ops->stat(inode);
    +	if (retval)
    +		return retval;
     
     	memset(&tmp, 0, sizeof(tmp));
     	tmp.st_dev = kdev_t_to_nr(inode->i_dev);
    @@ -258,8 +274,11 @@
     		error = -EINVAL;
     		if (inode->i_op && inode->i_op->readlink &&
     		    !(error = do_revalidate(nd.dentry))) {
    -			UPDATE_ATIME(inode);
    -			error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
    +			error = security_ops->inode_ops->readlink(nd.dentry, buf, bufsiz);
    +			if (!error) {
    +				UPDATE_ATIME(inode);
    +				error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
    +			}
     		}
     		path_release(&nd);
     	}
    @@ -274,6 +293,11 @@
     {
     	struct stat64 tmp;
     	unsigned int blocks, indirect;
    +	int retval;
    +
    +	retval = security_ops->inode_ops->stat(inode);
    +	if (retval)
    +		return retval;
     
     	memset(&tmp, 0, sizeof(tmp));
     	tmp.st_dev = kdev_t_to_nr(inode->i_dev);
    diff -Nru linux/fs/super.c lsm-new/fs/super.c
    --- linux/fs/super.c	Fri May 25 15:38:52 2001
    +++ lsm-new/fs/super.c	Mon Jun 11 16:29:09 2001
    @@ -37,6 +37,7 @@
     #include <linux/nfs_fs.h>
     #include <linux/nfs_fs_sb.h>
     #include <linux/nfs_mount.h>
    +#include <linux/security.h>
     
     #include <linux/kmod.h>
     #define __NO_VERSION__
    @@ -672,6 +673,8 @@
     	     s  = sb_entry(s->s_list.next)) {
     		if (s->s_dev)
     			continue;
    +		if (security_ops->sb_ops->alloc_security(s))
    +			return NULL;
     		return s;
     	}
     	/* Need a new one... */
    @@ -681,6 +684,10 @@
     	if (s) {
     		nr_super_blocks++;
     		memset(s, 0, sizeof(struct super_block));
    +		if (security_ops->sb_ops->alloc_security(s)) {
    +			kfree(s);
    +			return NULL;
    +		}
     		INIT_LIST_HEAD(&s->s_dirty);
     		INIT_LIST_HEAD(&s->s_locked_inodes);
     		list_add (&s->s_list, super_blocks.prev);
    @@ -725,6 +732,7 @@
     	s->s_dev = 0;
     	s->s_bdev = 0;
     	s->s_type = NULL;
    +	security_ops->sb_ops->free_security(s);
     	unlock_super(s);
     	return NULL;
     }
    @@ -900,6 +908,7 @@
     	sb->s_bdev = NULL;
     	put_filesystem(fs);
     	sb->s_type = NULL;
    +	security_ops->sb_ops->free_security(sb);
     	unlock_super(sb);
     	up_write(&sb->s_umount);
     	if (bdev) {
    @@ -990,6 +999,11 @@
     {
     	struct super_block * sb = mnt->mnt_sb;
     	struct nameidata parent_nd;
    +	int retval;
    +
    +	retval = security_ops->umount(mnt, flags);
    +	if (retval)
    +		return retval;
     
     	/*
     	 * No sense to grab the lock for this test, but test itself looks
    @@ -1036,6 +1050,7 @@
     	 */
     	DQUOT_OFF(sb);
     	acct_auto_close(sb->s_dev);
    +	security_ops->umount_close(mnt);
     
     	/*
     	 * If we may have to abort operations to get out of this
    @@ -1055,6 +1070,7 @@
     	spin_lock(&dcache_lock);
     	if (atomic_read(&mnt->mnt_count) > 2) {
     		spin_unlock(&dcache_lock);
    +	        security_ops->umount_busy(mnt);
     		return -EBUSY;
     	}
     
    @@ -1209,11 +1225,18 @@
     				/*
     				 * Shrink the dcache and sync the device.
     				 */
    +				retval = security_ops->remount(nd.mnt, flags, data);
    +				if (retval) {
    +					path_release(&nd);
    +					return retval;
    +				}
     				shrink_dcache_sb(sb);
     				fsync_dev(sb->s_dev);
     				if (flags & MS_RDONLY)
     					acct_auto_close(sb->s_dev);
     				retval = do_remount_sb(sb, flags, data);
    +				if (!retval)
    +					security_ops->post_remount(nd.mnt, flags, data);
     			}
     		}
     		path_release(&nd);
    @@ -1321,6 +1344,10 @@
     	if (retval)
     		goto fs_out;
     
    +	retval = security_ops->mount(dev_name, &nd, type_page, flags, data_page);
    +	if (retval)
    +		goto fs_out;
    +
     	/* get superblock, locks mount_sem on success */
     	if (fstype->fs_flags & FS_NOMOUNT)
     		sb = ERR_PTR(-EINVAL);
    @@ -1350,6 +1377,11 @@
     		goto fail;
     	down(&nd.dentry->d_inode->i_zombie);
     	if (!IS_DEADDIR(nd.dentry->d_inode)) {
    +		retval = security_ops->add_vfsmnt(&nd, sb, dev_name);
    +		if (retval) {
    +			up(&nd.dentry->d_inode->i_zombie);
    +			goto fail;
    +		}
     		retval = -ENOMEM;
     		mnt = add_vfsmnt(&nd, sb->s_root, dev_name);
     	}
    diff -Nru linux/include/linux/binfmts.h lsm-new/include/linux/binfmts.h
    --- linux/include/linux/binfmts.h	Fri May 25 21:01:28 2001
    +++ lsm-new/include/linux/binfmts.h	Mon Jun 11 16:29:09 2001
    @@ -27,6 +27,7 @@
     	struct file * file;
     	int e_uid, e_gid;
     	kernel_cap_t cap_inheritable, cap_permitted, cap_effective;
    +	void *security;
     	int argc, envc;
     	char * filename;	/* Name of binary */
     	unsigned long loader, exec;
    diff -Nru linux/include/linux/fs.h lsm-new/include/linux/fs.h
    --- linux/include/linux/fs.h	Fri May 25 21:01:28 2001
    +++ lsm-new/include/linux/fs.h	Mon Jun 11 16:29:09 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
    @@ -449,6 +450,7 @@
     
     	atomic_t		i_writecount;
     	unsigned int		i_attr_flags;
    +	void			*i_security;
     	__u32			i_generation;
     	union {
     		struct minix_inode_info		minix_i;
    @@ -485,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 {
    @@ -505,6 +508,8 @@
     
     	/* needed for tty driver, and maybe others */
     	void			*private_data;
    +
    +	void			*f_security;
     };
     extern spinlock_t files_lock;
     #define file_list_lock() spin_lock(&files_lock);
    @@ -672,6 +677,7 @@
     	struct dentry		*s_root;
     	struct rw_semaphore	s_umount;
     	struct semaphore	s_lock;
    +	void                    *s_security;
     
     	struct list_head	s_dirty;	/* dirty inodes */
     	struct list_head	s_locked_inodes;/* inodes being synced */
    diff -Nru linux/include/linux/sched.h lsm-new/include/linux/sched.h
    --- linux/include/linux/sched.h	Fri May 25 21:01:28 2001
    +++ lsm-new/include/linux/sched.h	Tue Jun 12 11:33:38 2001
    @@ -393,6 +393,8 @@
     	void *notifier_data;
     	sigset_t *notifier_mask;
     	
    +	void *security;
    +
     /* Thread group tracking */
        	u32 parent_exec_id;
        	u32 self_exec_id;
    @@ -692,7 +694,9 @@
      * 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)
     {
     #if 1 /* ok now */
    @@ -706,6 +710,7 @@
     	}
     	return 0;
     }
    +#endif	/* if 0 */
     
     /*
      * Routines for handling mm_structs
    diff -Nru linux/include/linux/security.h lsm-new/include/linux/security.h
    --- linux/include/linux/security.h	Wed Dec 31 19:00:00 1969
    +++ lsm-new/include/linux/security.h	Tue Jun 12 11:36:39 2001
    @@ -0,0 +1,207 @@
    +/*
    + * Linux 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.
    + *
    + * 2001_Jun_12 Stephen Smalley <sdsat_private>, 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
    + *
    + * cmw	hacked for capabilites (eeww!)
    + */
    +
    +#ifndef __LINUX_SECURITY_H
    +#define __LINUX_SECURITY_H
    +
    +
    +#define SECURITY_SCAFFOLD_VERSION	"1.0.0"
    +
    +#ifdef __KERNEL__
    +
    +#include <linux/fs.h>
    +#include <linux/binfmts.h>
    +#include <linux/signal.h>
    +
    +
    +/* Security plug operations */
    +#define SECURITY_INTERFACE_VERSION	0x00000101	/* change this every time the security_operations structure changes */
    +
    +struct binprm_security_ops {
    +	int (* alloc_security)		(struct linux_binprm *bprm);	// create per binprm security
    +									// stuff
    +	void (* free_security)		(struct linux_binprm *bprm);	// free it
    +	void (* compute_creds)		(struct linux_binprm *bprm);	/* transfer credentials to current during exec */
    +};
    +
    +struct super_block_security_ops {
    +	int (* alloc_security)		(struct super_block *sb);
    +	void (* free_security)		(struct super_block *sb);
    +	int (* statfs)		        (struct super_block *sb);
    +};
    +
    +struct inode_security_ops {
    +	int  (* alloc_security)		(struct inode *inode);	// create per inode security stuff
    +	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);
    +	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);
    +	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);
    +	int (* mkdir)		(struct inode *dir, struct dentry *dentry, int mode);
    +	void (* post_mkdir)	(struct inode *dir, struct dentry *dentry, int mode);
    +	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);
    +	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);
    +	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 kern_retval);
    +	int (* revalidate)	(struct dentry *dentry);
    +	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);
    +};
    +
    +struct file_security_ops {
    +	int (* permission)		(struct file *, 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 *);	// need more than 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
    +#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);
    +	void (* reset_label)		(void);
    +
    +};
    +
    +struct socket_security_ops {
    +};
    +
    +struct module_security_ops {
    + 	int  (* create_module)		(const char *name_user, size_t size);			// CAP_SYS_MODULE
    + 	int  (* init_module)		(const char *name_user, struct module *mod_user);	// CAP_SYS_MODULE
    + 	int  (* delete_module)		(const char *name_user);				// CAP_SYS_MODULE
    +};
    +
    +struct msg_queue_security_ops {
    +	int (* create)			(key_t key);	// can i create
    +	int (* permission)		(void);		// CAP_SYS_ADMIN
    +	int (* setmaxqbytes)		(void);		// CAP_SYS_RESOURCE
    +	int (* setattr)			(void);		// can i set attributes
    +	int (* delete)			(void);		// can i delete
    +};
    +
    +struct shm_security_ops {
    +	int (* create)		(key_t key);
    +	int (* permission)	(void);
    +	int (* setattr)		(void);
    +	int (* delete)		(void);
    +};
    +
    +
    +struct security_operations {
    +	int	version;
    +	
    +	/* syscalls that are checked for permissions */
    +	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);	
    +	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)			(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)			(struct file *file);
    +	/* old capable call, catch all for capabilities. */
    +	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;
    +	struct msg_queue_security_ops	* msg_queue_ops;
    +	struct shm_security_ops		* shm_ops;
    +
    +	/* allow module stacking */
    +	int (* register_security)	(struct security_operations *ops);
    +	int (* unregister_security)	(struct security_operations *ops);
    +};
    +
    +
    +/* prototypes */
    +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	(struct security_operations *ops);
    +extern int mod_unreg_security	(struct security_operations *ops);
    +extern int capable		(int cap);
    +
    +/* global variables */
    +extern struct security_operations *security_ops;
    +
    +
    +#endif /* __KERNEL__ */
    +
    +#endif /* ! __LINUX_SECURITY_H */
    +
    +
    diff -Nru linux/init/main.c lsm-new/init/main.c
    --- linux/init/main.c	Tue May 22 12:35:42 2001
    +++ lsm-new/init/main.c	Mon Jun 11 16:29:09 2001
    @@ -28,6 +28,7 @@
     #include <linux/iobuf.h>
     #include <linux/bootmem.h>
     #include <linux/tty.h>
    +#include <linux/security.h>
     
     #include <asm/io.h>
     #include <asm/bugs.h>
    @@ -568,6 +569,7 @@
     	ccwcache_init();
     #endif
     	signals_init();
    +	security_scaffolding_startup();
     #ifdef CONFIG_PROC_FS
     	proc_root_init();
     #endif
    diff -Nru linux/kernel/Makefile lsm-new/kernel/Makefile
    --- linux/kernel/Makefile	Fri Dec 29 17:07:24 2000
    +++ lsm-new/kernel/Makefile	Mon Jun 11 16:29:09 2001
    @@ -9,12 +9,13 @@
     
     O_TARGET := kernel.o
     
    -export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o
    +export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o security.o
     
     obj-y     = sched.o dma.o fork.o exec_domain.o panic.o printk.o \
     	    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
    +	    signal.o sys.o kmod.o context.o \
    +	    security.o
     
     obj-$(CONFIG_UID16) += uid16.o
     obj-$(CONFIG_MODULES) += ksyms.o
    diff -Nru linux/kernel/acct.c lsm-new/kernel/acct.c
    --- linux/kernel/acct.c	Mon Mar 19 15:35:08 2001
    +++ lsm-new/kernel/acct.c	Mon Jun 11 16:29:09 2001
    @@ -182,6 +182,10 @@
     			goto out_err;
     	}
     
    +	error = security_ops->acct(file);
    +	if (error)
    +		goto out_err;
    +
     	error = 0;
     	lock_kernel();
     	if (acct_file) {
    diff -Nru linux/kernel/exit.c lsm-new/kernel/exit.c
    --- linux/kernel/exit.c	Fri May  4 17:44:06 2001
    +++ lsm-new/kernel/exit.c	Mon Jun 11 16:29:09 2001
    @@ -10,6 +10,7 @@
     #include <linux/smp_lock.h>
     #include <linux/module.h>
     #include <linux/tty.h>
    +#include <linux/security.h>
     #ifdef CONFIG_BSD_PROCESS_ACCT
     #include <linux/acct.h>
     #endif
    @@ -43,6 +44,7 @@
     		task_unlock(p);
     #endif
     		atomic_dec(&p->user->processes);
    +		security_ops->task_ops->free_security(p);
     		free_uid(p->user);
     		unhash_process(p);
     
    @@ -522,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 -Nru linux/kernel/fork.c lsm-new/kernel/fork.c
    --- linux/kernel/fork.c	Tue May  1 01:23:29 2001
    +++ lsm-new/kernel/fork.c	Mon Jun 11 16:29:09 2001
    @@ -18,6 +18,7 @@
     #include <linux/smp_lock.h>
     #include <linux/module.h>
     #include <linux/vmalloc.h>
    +#include <linux/security.h>
     
     #include <asm/pgtable.h>
     #include <asm/pgalloc.h>
    @@ -641,9 +642,11 @@
     	p->start_time = jiffies;
     
     	retval = -ENOMEM;
    +	if (security_ops->task_ops->alloc_security(p))
    +		goto bad_fork_cleanup;
     	/* copy all the process information */
     	if (copy_files(clone_flags, p))
    -		goto bad_fork_cleanup;
    +		goto bad_fork_cleanup_security;
     	if (copy_fs(clone_flags, p))
     		goto bad_fork_cleanup_files;
     	if (copy_sighand(clone_flags, p))
    @@ -714,6 +717,8 @@
     	exit_fs(p); /* blocking */
     bad_fork_cleanup_files:
     	exit_files(p); /* blocking */
    +bad_fork_cleanup_security:
    +	security_ops->task_ops->free_security(p);
     bad_fork_cleanup:
     	put_exec_domain(p->exec_domain);
     	if (p->binfmt && p->binfmt->module)
    diff -Nru linux/kernel/module.c lsm-new/kernel/module.c
    --- linux/kernel/module.c	Tue May  1 19:05:00 2001
    +++ lsm-new/kernel/module.c	Mon Jun 11 16:29:09 2001
    @@ -9,6 +9,7 @@
     #include <linux/init.h>
     #include <linux/slab.h>
     #include <linux/kmod.h>
    +#include <linux/security.h>
     
     /*
      * Originally by Anonymous (as far as I know...)
    @@ -312,6 +313,12 @@
     		error = -EEXIST;
     		goto err1;
     	}
    +
    +	/* check that we have permission to do this */
    +	error = security_ops->module_ops->create_module(name, size);
    +	if (error)
    +		goto err1;
    +
     	if ((mod = (struct module *)module_map(size)) == NULL) {
     		error = -ENOMEM;
     		goto err1;
    @@ -505,6 +512,12 @@
     		goto err3;
     	}
     
    +	/* check that we have permission to do this */
    +	error = security_ops->module_ops->init_module(name, mod);
    +	if (error)
    +		goto err3;
    +	error = -EINVAL;
    +
     	if (module_arch_init(mod))
     		goto err3;
     
    @@ -613,6 +626,14 @@
     	if (name_user) {
     		if ((error = get_mod_name(name_user, &name)) < 0)
     			goto out;
    +
    +		/* check that we have permission to do this */
    +		error = security_ops->module_ops->delete_module(name);
    +		if (error) {
    +			put_mod_name(name);
    +			goto out;
    +		}
    +
     		error = -ENOENT;
     		if ((mod = find_module(name)) == NULL) {
     			put_mod_name(name);
    diff -Nru linux/kernel/sched.c lsm-new/kernel/sched.c
    --- linux/kernel/sched.c	Fri Apr 20 21:26:16 2001
    +++ lsm-new/kernel/sched.c	Mon Jun 11 16:29:09 2001
    @@ -25,6 +25,7 @@
     #include <linux/smp_lock.h>
     #include <linux/interrupt.h>
     #include <linux/kernel_stat.h>
    +#include <linux/security.h>
     
     #include <asm/uaccess.h>
     #include <asm/mmu_context.h>
    @@ -841,6 +842,7 @@
     asmlinkage long sys_nice(int increment)
     {
     	long newprio;
    +	int retval = 0;
     
     	/*
     	 *	Setpriority might change our priority at the same moment.
    @@ -849,7 +851,7 @@
     	 */
     	if (increment < 0) {
     		if (!capable(CAP_SYS_NICE))
    -			return -EPERM;
    +			retval = -EPERM;
     		if (increment < -40)
     			increment = -40;
     	}
    @@ -861,6 +863,11 @@
     		newprio = -20;
     	if (newprio > 19)
     		newprio = 19;
    +
    +	retval = security_ops->task_ops->setnice(current, newprio, retval);
    +	if (retval)
    +		return retval;
    +	
     	current->nice = newprio;
     	return 0;
     }
    @@ -922,12 +929,16 @@
     	if ((policy == SCHED_OTHER) != (lp.sched_priority == 0))
     		goto out_unlock;
     
    -	retval = -EPERM;
    +	retval = 0;
     	if ((policy == SCHED_FIFO || policy == SCHED_RR) && 
     	    !capable(CAP_SYS_NICE))
    -		goto out_unlock;
    -	if ((current->euid != p->euid) && (current->euid != p->uid) &&
    +		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 -Nru linux/kernel/security.c lsm-new/kernel/security.c
    --- linux/kernel/security.c	Wed Dec 31 19:00:00 1969
    +++ lsm-new/kernel/security.c	Tue Jun 12 11:36:47 2001
    @@ -0,0 +1,493 @@
    +/*
    + * Linux 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.
    + *
    + * 2001_Jun_12 Stephen Smalley <sdsat_private>, 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
    + *
    + * 2001_Apr_12 greg k-h
    + *	created based on original immunix_scaffold.c code
    + */
    +
    +#include <linux/config.h>
    +#include <linux/module.h>
    +#include <linux/init.h>
    +#include <linux/kernel.h>
    +#include <linux/errno.h>
    +#include <linux/malloc.h>
    +#include <linux/smp_lock.h>
    +#include <linux/security.h>
    +
    +#include <linux/module.h>
    +#include <linux/sysctl.h>
    +
    +
    +
    +
    +struct security_operations *security_ops;	/* Initialized to NULL */
    +
    +
    +/* Stub functions for the default security function pointers in case no security model is loaded */
    +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;}
    +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 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		(struct file *file)
    +{
    +	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;}
    +static void dummy_binprm_compute_creds	(struct linux_binprm *bprm)	{return;}
    +
    +static int dummy_sb_alloc_security(struct super_block *sb)	{return 0;}
    +static void dummy_sb_free_security	(struct super_block *sb)		{return;}
    +static int dummy_sb_statfs	(struct super_block *sb)		{return 0;}
    +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 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 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 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 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 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 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, 
    +				  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, 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;}
    +
    +static int dummy_file_permission	(struct file *file, 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)	{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(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;}
    +
    +static int dummy_module_create_module	(const char *name_user, size_t size)			{return 0;}
    +static int dummy_module_init_module	(const char *name_user, struct module *mod_user)	{return 0;}
    +static int dummy_module_delete_module	(const char *name_user)					{return 0;}
    +
    +static int dummy_msg_queue_create	(key_t key)	{return 0;}
    +static int dummy_msg_queue_permission	(void)	{return 0;}
    +static int dummy_msg_queue_setmaxqbytes	(void)	{return 0;}
    +static int dummy_msg_queue_setattr	(void)	{return 0;}
    +static int dummy_msg_queue_delete	(void)	{return 0;}
    +
    +static int dummy_shm_create		(key_t key)	{return 0;}
    +static int dummy_shm_permission		(void)	{return 0;}
    +static int dummy_shm_setattr		(void)	{return 0;}
    +static int dummy_shm_delete		(void)	{return 0;}
    +
    +static int dummy_register		(struct security_operations *ops)
    +{return -EINVAL;}
    +static int dummy_unregister		(struct security_operations *ops)
    +{return -EINVAL;}
    +
    +static struct binprm_security_ops dummy_binprm_ops = {
    +	alloc_security:	dummy_binprm_alloc_security,
    +	free_security:	dummy_binprm_free_security,
    +	compute_creds:	dummy_binprm_compute_creds,
    +};
    +static struct super_block_security_ops dummy_sb_ops = {
    +	alloc_security:	dummy_sb_alloc_security,
    +	free_security:	dummy_sb_free_security,
    +	statfs:	        dummy_sb_statfs,
    +};
    +static struct inode_security_ops dummy_inode_ops = {
    +	alloc_security:	dummy_inode_alloc_security,
    +	free_security:	dummy_inode_free_security,
    +	create:		dummy_inode_create,
    +	post_create:	dummy_inode_post_create,
    +	link:		dummy_inode_link,
    +	post_link:	dummy_inode_post_link,
    +	unlink:		dummy_inode_unlink,
    +	symlink:	dummy_inode_symlink,
    +	post_symlink:	dummy_inode_post_symlink,
    +	mkdir:		dummy_inode_mkdir,
    +	post_mkdir:	dummy_inode_post_mkdir,
    +	rmdir:		dummy_inode_rmdir,
    +	mknod:		dummy_inode_mknod,
    +	post_mknod:	dummy_inode_post_mknod,
    +	rename:		dummy_inode_rename,
    +	post_rename:	dummy_inode_post_rename,
    +	readlink:	dummy_inode_readlink,
    +	follow_link:	dummy_inode_follow_link,
    +	truncate:	dummy_inode_truncate,
    +	permission:	dummy_inode_permission,
    +	revalidate:	dummy_inode_revalidate,
    +	setattr:	dummy_inode_setattr,
    +	attach_pathlabel:dummy_inode_attach_pathlabel,
    +	stat:           dummy_inode_stat,
    +};
    +
    +static struct file_security_ops	dummy_file_ops = {
    +	permission:	dummy_file_permission,
    +	alloc_security:	dummy_file_alloc_security,
    +	free_security:	dummy_file_free_security,
    +	llseek:		dummy_file_llseek,
    +	read:		dummy_file_read,
    +	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 = {
    +	create:		dummy_task_create,
    +	alloc_security:	dummy_task_alloc_security,
    +	free_security:	dummy_task_free_security,
    +	setuid:		dummy_task_setuid,
    +	setgid:		dummy_task_setgid,
    +	setgroups:	dummy_task_setgroups,
    +	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,
    +};
    +
    +static struct socket_security_ops dummy_socket_ops = {};
    +
    +static struct module_security_ops dummy_module_ops = {
    +	create_module:	dummy_module_create_module,
    +	init_module:	dummy_module_init_module,
    +	delete_module:	dummy_module_delete_module,
    +
    +};
    +
    +static struct msg_queue_security_ops dummy_msg_queue_ops = {
    +	create:		dummy_msg_queue_create,
    +	permission:	dummy_msg_queue_permission,
    +	setmaxqbytes:	dummy_msg_queue_setmaxqbytes,
    +	setattr:	dummy_msg_queue_setattr,
    +	delete:		dummy_msg_queue_delete,
    +};
    +
    +static struct shm_security_ops dummy_shm_ops = {
    +	create:		dummy_shm_create,
    +	permission:	dummy_shm_permission,
    +	setattr:	dummy_shm_setattr,
    +	delete:		dummy_shm_delete,
    +};
    +
    +static struct security_operations dummy_security_ops = {
    +        version:                SECURITY_INTERFACE_VERSION,
    +
    +	sethostname:		dummy_sethostname,
    +	setdomainname:		dummy_setdomainname,
    +	reboot:			dummy_reboot,
    +	mount:			dummy_mount,
    +	add_vfsmnt:             dummy_add_vfsmnt,
    +	umount:			dummy_umount,
    +	umount_close:		dummy_umount_close,
    +	umount_busy:		dummy_umount_busy,
    +	remount:		dummy_remount,
    +	post_remount:		dummy_post_remount,
    +	ioperm:			dummy_ioperm,
    +	iopl:			dummy_iopl,
    +	ptrace:			dummy_ptrace,
    +	setcapability:		dummy_setcapablity,
    +	acct:			dummy_acct,
    +	capable:		dummy_capable,
    +
    +	bprm_ops:		&dummy_binprm_ops,
    +	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,
    +	msg_queue_ops:		&dummy_msg_queue_ops,
    +	shm_ops:		&dummy_shm_ops,
    +	
    +	register_security:	dummy_register,
    +	unregister_security:	dummy_unregister,
    +};
    +
    +
    +
    +/**
    + *	security_scaffolding_startup - initialzes the security scaffolding framework
    + *
    + */
    +int security_scaffolding_startup (void)
    +{
    +	printk (KERN_INFO "Security Scaffold v" SECURITY_SCAFFOLD_VERSION " initialized\n");
    +	
    +	security_ops = &dummy_security_ops;
    +
    +	return 0;
    +}
    +
    +
    +static int inline verify(struct security_operations *ops)
    +{
    +	/* verify the security_operations structure exists */
    +	if (!ops) {
    +		printk (KERN_INFO "Passed a NULL security_operations "
    +			"pointer, " __FUNCTION__ " failed.\n");
    +		return -EINVAL;
    +	}
    +
    +	/* verify the version of the structure */
    +	if (ops->version != SECURITY_INTERFACE_VERSION) {
    +		printk (KERN_INFO "Mismatched version of security_operation "
    +			"structure used, " __FUNCTION__ " failed.\n");
    +		return -EINVAL;
    +	}
    +	
    +	/* Perform a little sanity checking on our inputs */
    +	if (!ops->bprm_ops || 
    +	     !ops->sb_ops ||
    +	     !ops->inode_ops ||
    +	     !ops->file_ops ||
    +	     !ops->task_ops ||
    +	     !ops->socket_ops ||
    +	     !ops->module_ops ||
    +	     !ops->msg_queue_ops ||
    +	     !ops->shm_ops
    +	     ) {
    +		printk (KERN_INFO "Not enough functions specified in the "
    +			"security_operation structure, " __FUNCTION__ 
    +			" failed.\n");
    +		return -EINVAL ;
    +	}
    +	return 0;
    +}
    +/**
    + *	register_security - registers a security framework with the kernel
    + */
    +int register_security (struct security_operations *ops)
    +{
    +
    +	if (verify(ops)) {
    +		printk (KERN_INFO __FUNCTION__ " could not verify "
    +			"security_operations structure.\n");
    +		return -EINVAL;
    +	}
    +	if (security_ops != &dummy_security_ops) {
    +		printk (KERN_INFO "There is already a security "
    +			"framework initialized, "
    +			__FUNCTION__ " failed.\n");
    +		return -EINVAL;
    +	}
    +
    +	security_ops = ops;
    +
    +	return 0 ;
    +}
    +
    +
    +/**
    + *	unregister_security - unregisters a security framework with the kernel
    + */
    +int unregister_security (struct security_operations *ops)
    +{
    +	if (ops != security_ops) {
    +		printk (KERN_INFO __FUNCTION__ ": trying to unregister "
    +			"a security_opts structure that is not "
    +			"registered, failing.\n");
    +		return -EINVAL;
    +	}
    +
    +	security_ops = &dummy_security_ops;
    +
    +	return 0;
    +}
    +
    +/* mod_reg_security - this allows stacking security modules.
    + * register security ops with primary security module
    + */
    +int mod_reg_security(struct security_operations *ops)
    +{
    +	if (verify(ops)) {
    +		printk (KERN_INFO __FUNCTION__ " could not verify "
    +			"security operations.\n");
    +		return -EINVAL;
    +	}
    +
    +	if(ops == security_ops) {
    +		printk (KERN_INFO __FUNCTION__ " security operations "
    +			"already registered.\n");
    +		return -EINVAL;
    +	}
    +
    +	return security_ops->register_security(ops);
    +}
    +
    +/* mod_unreg_security - unregister security ops from primary security module */
    +int mod_unreg_security(struct security_operations *ops)
    +{
    +	if (ops == security_ops) {
    +		printk (KERN_INFO __FUNCTION__ " invalid attempt to unregister "
    +			" primary security ops.\n");
    +		return -EINVAL;
    +	}
    +
    +	return security_ops->unregister_security(ops);
    +}
    +
    +int capable (int cap)
    +{
    +	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);
    +EXPORT_SYMBOL(unregister_security);
    +EXPORT_SYMBOL(mod_reg_security);
    +EXPORT_SYMBOL(mod_unreg_security);
    +EXPORT_SYMBOL(capable);
    diff -Nru linux/kernel/signal.c lsm-new/kernel/signal.c
    --- linux/kernel/signal.c	Wed Jan  3 23:45:26 2001
    +++ lsm-new/kernel/signal.c	Mon Jun 11 16:29:09 2001
    @@ -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 -Nru linux/kernel/sys.c lsm-new/kernel/sys.c
    --- linux/kernel/sys.c	Thu Apr 12 15:20:31 2001
    +++ lsm-new/kernel/sys.c	Tue Jun 12 10:22:08 2001
    @@ -14,6 +14,7 @@
     #include <linux/prctl.h>
     #include <linux/init.h>
     #include <linux/highuid.h>
    +#include <linux/security.h>
     
     #include <asm/uaccess.h>
     #include <asm/io.h>
    @@ -210,19 +211,23 @@
     
     	read_lock(&tasklist_lock);
     	for_each_task(p) {
    +		int no_nice = 0;
     		if (!proc_sel(p, which, who))
     			continue;
     		if (p->uid != current->euid &&
     			p->uid != current->uid && !capable(CAP_SYS_NICE)) {
    -			error = -EPERM;
    +			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 && !capable(CAP_SYS_NICE))
    -			error = -EACCES;
    -		else
    -			p->nice = niceval;
    +		p->nice = niceval;
     	}
     	read_unlock(&tasklist_lock);
     
    @@ -269,10 +274,16 @@
     asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void * arg)
     {
     	char buffer[256];
    +	int retval;
     
     	/* We only trust the superuser with rebooting the system. */
    +	retval = 0;
     	if (!capable(CAP_SYS_BOOT))
    -		return -EPERM;
    +		retval = -EPERM;
    +	retval = security_ops->reboot(cmd, arg, retval);
    +	if (retval) {
    +		return retval;
    +	}
     
     	/* For safety, we require "magic" arguments. */
     	if (magic1 != LINUX_REBOOT_MAGIC1 ||
    @@ -378,6 +389,11 @@
     	int old_egid = current->egid;
     	int new_rgid = old_rgid;
     	int new_egid = old_egid;
    +	int retval = 0;
    +
    +	retval = security_ops->task_ops->setgid(rgid, egid, (gid_t)-1, LSM_SETID_RE);
    +	if (retval)
    +		return retval;
     
     	if (rgid != (gid_t) -1) {
     		if ((old_rgid == rgid) ||
    @@ -419,6 +435,11 @@
     asmlinkage long sys_setgid(gid_t gid)
     {
     	int old_egid = current->egid;
    +	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))
     	{
    @@ -534,6 +555,11 @@
     asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
     {
     	int old_ruid, old_euid, old_suid, new_ruid, new_euid;
    +	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;
    @@ -594,11 +620,16 @@
     {
     	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 (capable(CAP_SETUID)) {
     		if (uid != old_ruid && set_user(uid, old_euid != uid) < 0)
     			return -EAGAIN;
    @@ -631,6 +662,11 @@
     	int old_ruid = current->uid;
     	int old_euid = current->euid;
     	int old_suid = current->suid;
    +	int retval;
    +
    +	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) &&
    @@ -682,6 +718,12 @@
      */
     asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
     {
    +	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))
    @@ -730,6 +772,11 @@
     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 ||
    @@ -772,6 +819,11 @@
     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 ||
    @@ -964,12 +1016,19 @@
      
     asmlinkage long sys_setgroups(int gidsetsize, gid_t *grouplist)
     {
    +	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;
     }
    @@ -1024,20 +1083,25 @@
     
     asmlinkage long sys_sethostname(char *name, int len)
     {
    +	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)) 
    +		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)
    @@ -1063,19 +1127,23 @@
      */
     asmlinkage long sys_setdomainname(char *name, int len)
     {
    +	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)) 
    +		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;
     }
    @@ -1114,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;
    @@ -1122,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)) &&
     	    !capable(CAP_SYS_RESOURCE))
    -		return -EPERM;
    -	if (resource == RLIMIT_NOFILE) {
    +		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 -Nru linux/mm/filemap.c lsm-new/mm/filemap.c
    --- linux/mm/filemap.c	Tue May 22 13:52:35 2001
    +++ lsm-new/mm/filemap.c	Mon Jun 11 16:29:09 2001
    @@ -22,6 +22,7 @@
     #include <linux/swapctl.h>
     #include <linux/init.h>
     #include <linux/mm.h>
    +#include <linux/security.h>
     
     #include <asm/pgalloc.h>
     #include <asm/uaccess.h>
    @@ -1368,6 +1369,10 @@
     	if (retval)
     		goto fput_in;
     
    +	retval = security_ops->file_ops->permission (in_file, MAY_READ);
    +	if (retval)
    +		goto fput_in;
    +
     	/*
     	 * Get output file, and verify that it is ok..
     	 */
    @@ -1382,6 +1387,10 @@
     		goto fput_out;
     	out_inode = out_file->f_dentry->d_inode;
     	retval = locks_verify_area(FLOCK_VERIFY_WRITE, out_inode, out_file, out_file->f_pos, count);
    +	if (retval)
    +		goto fput_out;
    +
    +	retval = security_ops->file_ops->permission (out_file, MAY_WRITE);
     	if (retval)
     		goto fput_out;
     
    diff -Nru linux/mm/memory.c lsm-new/mm/memory.c
    --- linux/mm/memory.c	Fri Apr 27 17:23:25 2001
    +++ lsm-new/mm/memory.c	Mon Jun 11 16:29:09 2001
    @@ -44,6 +44,7 @@
     #include <linux/iobuf.h>
     #include <linux/highmem.h>
     #include <linux/pagemap.h>
    +#include <linux/security.h>
     
     #include <asm/pgalloc.h>
     #include <asm/uaccess.h>
    @@ -1061,9 +1062,11 @@
     
     out_truncate:
     	if (inode->i_op && inode->i_op->truncate) {
    -		lock_kernel();
    -		inode->i_op->truncate(inode);
    -		unlock_kernel();
    +		if (!security_ops->inode_ops->truncate(inode)) {
    +			lock_kernel();
    +			inode->i_op->truncate(inode);
    +			unlock_kernel();
    +		}
     	}
     out:
     	return;
    diff -Nru linux/mm/mmap.c lsm-new/mm/mmap.c
    --- linux/mm/mmap.c	Thu May 24 18:20:18 2001
    +++ lsm-new/mm/mmap.c	Mon Jun 11 16:29:09 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 -Nru linux/mm/mprotect.c lsm-new/mm/mprotect.c
    --- linux/mm/mprotect.c	Mon Mar 19 15:35:08 2001
    +++ lsm-new/mm/mprotect.c	Mon Jun 11 16:29:09 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 -Nru linux/security/Config.in lsm-new/security/Config.in
    --- linux/security/Config.in	Wed Dec 31 19:00:00 1969
    +++ lsm-new/security/Config.in	Mon Jun 11 16:29:09 2001
    @@ -0,0 +1,7 @@
    +#
    +# Security configuration
    +#
    +mainmenu_option next_comment
    +comment 'Security options'
    +
    +endmenu
    
    _______________________________________________
    linux-security-module mailing list
    linux-security-moduleat_private
    http://mail.wirex.com/mailman/listinfo/linux-security-module
    



    This archive was generated by hypermail 2b30 : Tue Jun 12 2001 - 09:19:40 PDT