[LWN Logo]
[LWN.net]
From:	 Greg KH <greg@wirex.com>
To:	 linux-security-module@wirex.com
Subject: 2001_04_22 patch against 2.4.3
Date:	 Mon, 23 Apr 2001 09:29:09 -0700

Here's the latest patch that people have been asking about.  It does not
have any of the capabilities functionality moved into a module yet, as
Chris hasn't checked any of that work into our tree (hint :)

It is basically my previous patch, with a few changes that people
suggested.  I haven't done much to add much more than those suggestions
at this time.  Hopefully I can get to the LIDS and RSBAC needs this
week.

I'm also working today to get a web site up for the project.

thanks,

greg k-h

# This is a BitKeeper generated patch for the following project:
# Project Name: Linux 2.4.x
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.2.1.3 -> 1.34   
#	arch/i386/boot/compressed/Makefile	1.1     -> 1.2    
#	 include/linux/elf.h	1.2.1.1 -> 1.4    
#	          fs/super.c	1.3.1.1 -> 1.10   
#	        kernel/sys.c	1.1.1.1 -> 1.7    
#	 arch/i386/config.in	1.2     -> 1.3    
#	         mm/memory.c	1.4     -> 1.6    
#	arch/i386/kernel/ioport.c	1.1     -> 1.5    
#	          fs/inode.c	1.4     -> 1.5    
#	arch/i386/kernel/ptrace.c	1.1.1.1 -> 1.6    
#	include/linux/sysctl.h	1.1.1.1 -> 1.4    
#	     kernel/Makefile	1.1     -> 1.3    
#	     kernel/sysctl.c	1.2     -> 1.4    
#	  include/linux/fs.h	1.3.1.1 -> 1.8    
#	        mm/filemap.c	1.3.1.1 -> 1.10   
#	       kernel/fork.c	1.3.1.1 -> 1.9    
#	     fs/file_table.c	1.1     -> 1.6    
#	            Makefile	1.2.1.2 -> 1.6    
#	           fs/open.c	1.2     -> 1.7    
#	     fs/read_write.c	1.2     -> 1.8    
#	Documentation/Configure.help	1.2.1.2 -> 1.6    
#	include/linux/sched.h	1.2.1.2 -> 1.6    
#	         fs/Makefile	1.2.1.1 -> 1.6    
#	         init/main.c	1.2     -> 1.4    
#	           fs/attr.c	1.1     -> 1.2    
#	arch/i386/kernel/entry.S	1.1     -> 1.3    
#	     fs/binfmt_elf.c	1.2.1.1 -> 1.11   
#	       kernel/exit.c	1.2     -> 1.4    
#	          fs/namei.c	1.2     -> 1.4    
#	           fs/stat.c	1.1     -> 1.2    
#	     kernel/module.c	1.2     -> 1.8    
#	               (new)	        -> 1.3     security/Config.in
#	               (new)	        -> 1.12    include/linux/security.h
#	               (new)	        -> 1.9     kernel/security.c
#	               (new)	        -> 1.2     kernel/capability_plug.c
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 01/03/31	greg@soap.int.wirex.com	1.15
# Merge
# --------------------------------------------
# 01/04/04	greg@blue.int.wirex.com	1.16
# super.c 	got rid of #defines
# read_write.c	got rid of #defines
# immunix_scaffold.c	tweaked
# open.c  	got rid of #defines
# file_table.c	got rid of defines
# binfmt_elf.c	got rid of #defined
# Makefile	moved immunix_scaffold.o to aloways be compiled in
# --------------------------------------------
# 01/04/06	greg@blue.int.wirex.com	1.17
# More removals of #ifdefs
# --------------------------------------------
# 01/04/09	greg@blue.int.wirex.com	1.18
# removed all codomain_ops checks throughout the code, adding a dummy scaffolding of 
# empty functions to handle it when there isn't a codomain or crypomark module loaded.
# --------------------------------------------
# 01/04/09	greg@blue.int.wirex.com	1.19
# turned off the logging for every process ran :(
# Fixed memory leak.
# --------------------------------------------
# 01/04/11	greg@desk.kroah.org	1.20
# first cut at moving some of the subdomain specific logic into a more generic type of interface
# --------------------------------------------
# 01/04/12	greg@blue.int.wirex.com	1.21
# changed lots of subdomin specific logic with a more generic security call structure.
# --------------------------------------------
# 01/04/12	greg@blue.int.wirex.com	1.22
# more cleanups from subdomain logic to generic logic.
# --------------------------------------------
# 01/04/13	greg@blue.int.wirex.com	1.23
# Added the capability plug framework to the makefiles and the config.
# --------------------------------------------
# 01/04/13	greg@blue.int.wirex.com	1.24
# removed WireX specific options from Configure.help and 
# removed the immunix.h and immunix_scaffold.c files from the tree.
# --------------------------------------------
# 01/04/13	chris@figure1.int.wirex.com	1.22.1.1
# Changed to per kernel object stuff.
# --------------------------------------------
# 01/04/13	chris@figure1.int.wirex.com	1.25
# Merge bk://zeus/work/bk/linux
# into figure1.int.wirex.com:/home/chris/bitkeeper/linux-2.4
# --------------------------------------------
# 01/04/13	chris@figure1.int.wirex.com	1.26
# got rid of copyright
# --------------------------------------------
# 01/04/16	greg@desk.kroah.org	1.27
# Got security.h to compile properly
# fixes due to security_ops structure changes
# Will OOPS, do not try to run, security.c needs lots of changes, you have been warned :)
# --------------------------------------------
# 01/04/18	greg@desk.kroah.org	1.28
# fixed a spelling error in security.h
# added the rest of the stub functions for security.c so the kernel does not oops anymore.
# --------------------------------------------
# 01/04/18	greg@desk.kroah.org	1.29
# added i_security to the struct inode and the hooks to create and destroy it.
# --------------------------------------------
# 01/04/18	greg@desk.kroah.org	1.30
# added hooks to the kernel for all of the inode_ops functions.
# --------------------------------------------
# 01/04/18	steve@kryten.int.wirex.com	1.31
# changed dep_tristate to tristate (dep_tristate broke make xconfig)
# --------------------------------------------
# 01/04/19	greg@blue.int.wirex.com	1.32
# added hooks for:
# 	attach_pathlabel
# 
# added paramaters for:
# 	create_module
# 	init_module
# 	delete_module
# 	mount
# --------------------------------------------
# 01/04/19	greg@blue.int.wirex.com	1.33
# Added check for return value of inode_ops->truncate
# --------------------------------------------
# 01/04/19	greg@blue.int.wirex.com	1.34
# added hook for sys_umount
# --------------------------------------------
#
diff -Nru a/Makefile b/Makefile
--- a/Makefile	Mon Apr 23 09:04:14 2001
+++ b/Makefile	Mon Apr 23 09:04:14 2001
@@ -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 a/arch/i386/boot/compressed/Makefile b/arch/i386/boot/compressed/Makefile
--- a/arch/i386/boot/compressed/Makefile	Mon Apr 23 09:04:14 2001
+++ b/arch/i386/boot/compressed/Makefile	Mon Apr 23 09:04:14 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 a/arch/i386/config.in b/arch/i386/config.in
--- a/arch/i386/config.in	Mon Apr 23 09:04:14 2001
+++ b/arch/i386/config.in	Mon Apr 23 09:04:14 2001
@@ -367,3 +367,6 @@
 #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
 endmenu
+
+source security/Config.in
+
diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
--- a/arch/i386/kernel/entry.S	Mon Apr 23 09:04:14 2001
+++ b/arch/i386/kernel/entry.S	Mon Apr 23 09:04:14 2001
@@ -656,3 +656,4 @@
 	.rept NR_syscalls-221
 		.long SYMBOL_NAME(sys_ni_syscall)
 	.endr
+
diff -Nru a/arch/i386/kernel/ioport.c b/arch/i386/kernel/ioport.c
--- a/arch/i386/kernel/ioport.c	Mon Apr 23 09:04:14 2001
+++ b/arch/i386/kernel/ioport.c	Mon Apr 23 09:04:14 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;
 	if (turn_on && !capable(CAP_SYS_RAWIO))
 		return -EPERM;
+
+	/* check that we have permission to do this */
+	retval = security_ops->ioperm();
+	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,6 +112,7 @@
 	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;
@@ -111,6 +121,13 @@
 		if (!capable(CAP_SYS_RAWIO))
 			return -EPERM;
 	}
+
+	/* check that we have permission to do this */
+	retval = security_ops->ioperm();
+	if (retval) {
+		return retval;
+	}
+
 	regs->eflags = (regs->eflags & 0xffffcfff) | (level << 12);
 	return 0;
 }
diff -Nru a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
--- a/arch/i386/kernel/ptrace.c	Mon Apr 23 09:04:14 2001
+++ b/arch/i386/kernel/ptrace.c	Mon Apr 23 09:04:14 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>
@@ -139,6 +140,12 @@
 	struct task_struct *child;
 	struct user * dummy = NULL;
 	int i, ret;
+
+	/* check that we have permission to do this */
+	ret = security_ops->ptrace();
+	if (ret) {
+		return ret;
+	}
 
 	lock_kernel();
 	ret = -EPERM;
diff -Nru a/fs/attr.c b/fs/attr.c
--- a/fs/attr.c	Mon Apr 23 09:04:14 2001
+++ b/fs/attr.c	Mon Apr 23 09:04:14 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,9 +121,11 @@
 		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);
+		if (!error)
+			error = inode->i_op->setattr(dentry, attr);
+	} else {
 		error = inode_change_ok(inode, attr);
 		if (!error)
 			inode_setattr(inode, attr);
diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c
--- a/fs/binfmt_elf.c	Mon Apr 23 09:04:14 2001
+++ b/fs/binfmt_elf.c	Mon Apr 23 09:04:14 2001
@@ -39,6 +39,7 @@
 #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*);
@@ -651,6 +652,17 @@
 			elf_brk = k;
 	}
 	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;
diff -Nru a/fs/file_table.c b/fs/file_table.c
--- a/fs/file_table.c	Mon Apr 23 09:04:14 2001
+++ b/fs/file_table.c	Mon Apr 23 09:04:14 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 a/fs/inode.c b/fs/inode.c
--- a/fs/inode.c	Mon Apr 23 09:04:14 2001
+++ b/fs/inode.c	Mon Apr 23 09:04:14 2001
@@ -13,6 +13,7 @@
 #include <linux/quotaops.h>
 #include <linux/slab.h>
 #include <linux/cache.h>
+#include <linux/security.h>
 
 /*
  * New inode.c implementation.
@@ -389,6 +390,7 @@
 		bdput(inode->i_bdev);
 		inode->i_bdev = NULL;
 	}
+	security_ops->inode_ops->free_security(inode->i_security);
 	inode->i_state = I_CLEAR;
 }
 
@@ -615,6 +617,7 @@
 	inode->i_data.host = inode;
 	inode->i_data.gfp_mask = GFP_HIGHUSER;
 	inode->i_mapping = &inode->i_data;
+	inode->i_security = security_ops->inode_ops->alloc_security();
 }
 
 /**
diff -Nru a/fs/namei.c b/fs/namei.c
--- a/fs/namei.c	Mon Apr 23 09:04:14 2001
+++ b/fs/namei.c	Mon Apr 23 09:04:14 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,8 +183,13 @@
 
 int permission(struct inode * inode,int mask)
 {
+	int retval;
+
+	retval = security_ops->inode_ops->permission(inode, mask);
+	if (retval)
+		return retval;
+
 	if (inode->i_op && inode->i_op->permission) {
-		int retval;
 		lock_kernel();
 		retval = inode->i_op->permission(inode, mask);
 		unlock_kernel();
@@ -311,9 +317,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 +330,7 @@
 	return err;
 loop:
 	path_release(nd);
-	return -ELOOP;
+	return err;
 }
 
 static inline int __follow_up(struct vfsmount **mnt, struct dentry **base)
@@ -435,6 +444,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 +541,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 +598,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;
@@ -911,6 +926,10 @@
 	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);
@@ -989,6 +1008,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;
@@ -998,7 +1018,8 @@
 		acc_mode = 0;
 		flag &= ~O_TRUNC;
 		goto ok;
-	}
+	} else
+		security_ops->inode_ops->attach_pathlabel(dentry, nd->mnt);
 
 	/*
 	 * It already exists.
@@ -1040,6 +1061,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;
@@ -1123,6 +1146,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);
@@ -1191,6 +1217,10 @@
 	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);
@@ -1235,6 +1265,7 @@
 		default:
 			error = -EINVAL;
 		}
+		security_ops->inode_ops->attach_pathlabel(dentry, nd.mnt);
 		dput(dentry);
 	}
 	up(&nd.dentry->d_inode->i_sem);
@@ -1258,6 +1289,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();
@@ -1290,6 +1325,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);
@@ -1349,11 +1385,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) {
@@ -1420,11 +1459,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);
+				}
 			}
 		}
 	}
@@ -1490,6 +1532,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);
@@ -1564,6 +1610,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);
@@ -1693,6 +1743,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);
@@ -1758,6 +1812,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);
diff -Nru a/fs/open.c b/fs/open.c
--- a/fs/open.c	Mon Apr 23 09:04:14 2001
+++ b/fs/open.c	Mon Apr 23 09:04:14 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>
 
@@ -663,6 +664,8 @@
 	}
 	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
 
+	f->f_security = security_ops->file_ops->alloc_security (f);
+	
 	return f;
 
 cleanup_all:
diff -Nru a/fs/read_write.c b/fs/read_write.c
--- a/fs/read_write.c	Mon Apr 23 09:04:14 2001
+++ b/fs/read_write.c	Mon Apr 23 09:04:14 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 a/fs/stat.c b/fs/stat.c
--- a/fs/stat.c	Mon Apr 23 09:04:14 2001
+++ b/fs/stat.c	Mon Apr 23 09:04:14 2001
@@ -9,6 +9,7 @@
 #include <linux/file.h>
 #include <linux/smp_lock.h>
 #include <linux/highuid.h>
+#include <linux/security.h>
 
 #include <asm/uaccess.h>
 
@@ -18,9 +19,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;
 }
 
@@ -257,8 +263,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);
 	}
diff -Nru a/fs/super.c b/fs/super.c
--- a/fs/super.c	Mon Apr 23 09:04:14 2001
+++ b/fs/super.c	Mon Apr 23 09:04:14 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__
@@ -1137,6 +1138,11 @@
 	retval = -EPERM;
 	if (!capable(CAP_SYS_ADMIN) && current->uid!=nd.mnt->mnt_owner)
 		goto dput_and_out;
+	
+	retval = security_ops->umount(name, flags);
+	if (retval) {
+		return retval;
+	}
 
 	dput(nd.dentry);
 	/* puts nd.mnt */
@@ -1427,6 +1433,12 @@
 	unsigned long type_page;
 	unsigned long dev_page;
 	char *dir_page;
+
+	/* check that we have permission to do this */
+	retval = security_ops->mount(dev_name, dir_name, type, flags, data);
+	if (retval) {
+		return retval;
+	}
 
 	retval = copy_mount_options (type, &type_page);
 	if (retval < 0)
diff -Nru a/include/linux/elf.h b/include/linux/elf.h
--- a/include/linux/elf.h	Mon Apr 23 09:04:14 2001
+++ b/include/linux/elf.h	Mon Apr 23 09:04:14 2001
@@ -510,7 +510,7 @@
 #define SHN_HIRESERVE	0xffff
 #define SHN_MIPS_ACCOMON	0xff00
  
-typedef struct {
+typedef struct elf32_shdr {
   Elf32_Word	sh_name;
   Elf32_Word	sh_type;
   Elf32_Word	sh_flags;
@@ -597,6 +597,7 @@
 #define elfhdr		elf32_hdr
 #define elf_phdr	elf32_phdr
 #define elf_note	elf32_note
+#define elf_shdr	elf32_shdr
 
 #else
 
@@ -604,6 +605,7 @@
 #define elfhdr		elf64_hdr
 #define elf_phdr	elf64_phdr
 #define elf_note	elf64_note
+#define elf_shdr	elf64_shdr
 
 #endif
 
diff -Nru a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h	Mon Apr 23 09:04:14 2001
+++ b/include/linux/fs.h	Mon Apr 23 09:04:14 2001
@@ -439,6 +439,7 @@
 
 	atomic_t		i_writecount;
 	unsigned int		i_attr_flags;
+	void			*i_security;
 	__u32			i_generation;
 	union {
 		struct minix_inode_info		minix_i;
@@ -495,6 +496,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);
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h	Mon Apr 23 09:04:14 2001
+++ b/include/linux/sched.h	Mon Apr 23 09:04:14 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;
diff -Nru a/include/linux/security.h b/include/linux/security.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/linux/security.h	Mon Apr 23 09:04:14 2001
@@ -0,0 +1,152 @@
+/*
+ * 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_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>
+
+
+/* Security plug operations */
+#define SECURITY_INTERFACE_VERSION	0x00000101	/* change this every time the security_operations structure changes */
+
+struct inode_security_ops {
+	void * (* alloc_security)	(void);		// create per inode security stuff
+	void (* free_security)		(void *i_security);	// free it
+	
+	int (* create)		(struct inode *dir, struct dentry *dentry, int mode);
+	int (* 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);
+	int (* 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);
+	int (* 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 (* revalidate)	(struct dentry *dentry);
+	int (* setattr)		(struct dentry *dentry, struct iattr *attr); // CAP_CHOWN
+	void (* attach_pathlabel)(struct dentry *dentry, struct vfsmount *mnt);	// DTE project needs this
+};
+
+struct file_security_ops {
+	int (* permission)		(struct file *, int);
+	void * (* 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 *);
+	int (* lock)			(struct file *);
+	int (* readv)			(struct file *);
+	int (* writev)			(struct file *);
+};
+
+struct task_security_ops {
+	int (* create)			(void);
+	void * (* alloc_security)	(void);		// create per process security stuff
+	void (* free_security)		(void *);	// free it
+	int (* setuid)			(void);		// CAP_SETUID
+	int (* setgid)			(void);		// CAP_SETGID
+	int (* setpriority)		(void);		// CAP_NICE
+	int (* kill)			(void);		// CAP_KILL
+};
+
+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)		(void);
+	int  (* setdomainname)		(void);
+	int  (* reboot)			(void);		// CAP_SYS_BOOT
+	int  (* mount)			(char * dev_name, char * dir_name, 
+					 char * type, unsigned long flags, 
+					 void * data);			// part of CAP_SYS_ADMIN
+	int  (* umount)			(char * name, int flags);	// part of CAP_SYS_ADMIN
+	int  (* ioperm)			(void);		// part of CAP_RAWIO
+	int  (* iopl)			(void);		// part of CAP_RAWIO
+	int  (* ptrace)			(void);		// CAP_PTRACE
+	int  (* setcapability)		(void);		// CAP_SETPCAP
+
+	/* cmw: this should allow you to know if two permissions
+	 * stuctures are the same, subset, or superset
+	 * returns 0 when same, 1 when perm1 is superset of perm2 and
+	 * -1 when perm1 is subset of perm2...hmmm what if they have no
+	 * relation?  need better type than void* ;-/
+	 * at least subset is needed for capabilities
+	 */
+	int (* perm_comp)		(void * perm1, void * perm2);
+	void (* init_perm)		(void * perm);
+	int (* change_perm)		(void * perm);
+	
+	struct inode_security_ops	* inode_ops;
+	struct file_security_ops	* file_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;
+	
+};
+
+
+/* prototypes */
+extern int security_scaffolding_startup	(void);
+extern int register_security	(struct security_operations *ops);
+extern int unregister_security	(struct security_operations *ops);
+
+/* global variables */
+extern struct security_operations *security_ops;
+
+
+#endif /* __KERNEL__ */
+
+#endif /* ! __LINUX_SECURITY_H */
+
+
diff -Nru a/include/linux/sysctl.h b/include/linux/sysctl.h
--- a/include/linux/sysctl.h	Mon Apr 23 09:04:14 2001
+++ b/include/linux/sysctl.h	Mon Apr 23 09:04:14 2001
@@ -117,6 +117,10 @@
 	KERN_OVERFLOWGID=47,	/* int: overflow GID */
 	KERN_SHMPATH=48,	/* string: path to shm fs */
 	KERN_HOTPLUG=49,	/* string: path to hotplug policy agent */
+
+/* Don't ifdef this -- user level programs use it */
+	KERN_CODOMAIN=69,	/* struct: subdomain stuff */
+	KERN_COD_PARANOID=70,	/* int: paranoid mode */
 };
 
 
@@ -643,6 +647,8 @@
 extern ctl_handler sysctl_string;
 extern ctl_handler sysctl_intvec;
 extern ctl_handler sysctl_jiffies;
+
+extern ctl_handler sysctl_codomain;
 
 
 /*
diff -Nru a/init/main.c b/init/main.c
--- a/init/main.c	Mon Apr 23 09:04:14 2001
+++ b/init/main.c	Mon Apr 23 09:04:14 2001
@@ -27,6 +27,7 @@
 #include <linux/hdreg.h>
 #include <linux/iobuf.h>
 #include <linux/bootmem.h>
+#include <linux/security.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -595,6 +596,8 @@
 #endif
 	check_bugs();
 	printk("POSIX conformance testing by UNIFIX\n");
+
+	security_scaffolding_startup();
 
 	/* 
 	 *	We count on the initial thread going ok 
diff -Nru a/kernel/Makefile b/kernel/Makefile
--- a/kernel/Makefile	Mon Apr 23 09:04:14 2001
+++ b/kernel/Makefile	Mon Apr 23 09:04:14 2001
@@ -14,11 +14,13 @@
 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
 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 -Nru a/kernel/capability_plug.c b/kernel/capability_plug.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/kernel/capability_plug.c	Mon Apr 23 09:04:14 2001
@@ -0,0 +1,45 @@
+/*
+ *  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/mm.h>
+#include <asm/uaccess.h>
+
+
+static struct security_operations capability_ops;
+
+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");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+
+static void __exit capability_plug_exit (void)
+{
+	/* remove ourselves from the security framework */
+	if (unregister_security (&capability_ops)) {
+		printk (KERN_INFO "Failuer unretistering capabilities with the kernel\n");
+	}
+}
+
+
+module_init (capability_plug_init);
+module_exit (capability_plug_exit);
+
diff -Nru a/kernel/exit.c b/kernel/exit.c
--- a/kernel/exit.c	Mon Apr 23 09:04:14 2001
+++ b/kernel/exit.c	Mon Apr 23 09:04:14 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->security);
 		free_uid(p->user);
 		unhash_process(p);
 
diff -Nru a/kernel/fork.c b/kernel/fork.c
--- a/kernel/fork.c	Mon Apr 23 09:04:14 2001
+++ b/kernel/fork.c	Mon Apr 23 09:04:14 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>
@@ -640,6 +641,8 @@
 	p->lock_depth = -1;		/* -1 = no lock */
 	p->start_time = jiffies;
 
+	p->security = security_ops->task_ops->alloc_security();
+	
 	retval = -ENOMEM;
 	/* copy all the process information */
 	if (copy_files(clone_flags, p))
diff -Nru a/kernel/module.c b/kernel/module.c
--- a/kernel/module.c	Mon Apr 23 09:04:14 2001
+++ b/kernel/module.c	Mon Apr 23 09:04:14 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...)
@@ -296,9 +297,17 @@
 	long namelen, error;
 	struct module *mod;
 	unsigned long flags;
+	int result;
 
 	if (!capable(CAP_SYS_MODULE))
 		return -EPERM;
+
+	/* check that we have permission to do this */
+	result = security_ops->module_ops->create_module(name_user, size);
+	if (result) {
+		return result;
+	}
+
 	lock_kernel();
 	if ((namelen = get_mod_name(name_user, &name)) < 0) {
 		error = namelen;
@@ -351,9 +360,17 @@
 	long namelen, n_namelen, i, error;
 	unsigned long mod_user_size;
 	struct module_ref *dep;
+	int result;
 
 	if (!capable(CAP_SYS_MODULE))
 		return -EPERM;
+
+	/* check that we have permission to do this */
+	result = security_ops->module_ops->init_module(name_user, mod_user);
+	if (result) {
+		return result;
+	}
+
 	lock_kernel();
 	if ((namelen = get_mod_name(name_user, &name)) < 0) {
 		error = namelen;
@@ -605,9 +622,16 @@
 	char *name;
 	long error;
 	int something_changed;
+	int result;
 
 	if (!capable(CAP_SYS_MODULE))
 		return -EPERM;
+
+	/* check that we have permission to do this */
+	result = security_ops->module_ops->delete_module(name_user);
+	if (result) {
+		return result;
+	}
 
 	lock_kernel();
 	if (name_user) {
diff -Nru a/kernel/security.c b/kernel/security.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/kernel/security.c	Mon Apr 23 09:04:14 2001
@@ -0,0 +1,264 @@
+/*
+ * 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_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	(void)	{return 0;}
+static int dummy_setdomainname	(void)	{return 0;}
+static int dummy_reboot		(void)	{return 0;}
+static int dummy_mount		(char * dev_name, char * dir_name, char * type, unsigned long flags, void * data)	{return 0;}
+static int dummy_umount		(char * name, int flags)	{return 0;}
+static int dummy_ioperm		(void)	{return 0;}
+static int dummy_iopl		(void)	{return 0;}
+static int dummy_ptrace		(void)	{return 0;}
+static int dummy_setcapablity	(void)	{return 0;}
+static int dummy_perm_comp	(void * perm1, void * perm2) 	{return 0;}
+static void dummy_init_perm	(void * perm)	{return;}
+static int dummy_change_perm	(void * perm)	{return 0;}
+
+static void *dummy_inode_alloc_security	(void)	{return NULL;}
+static void dummy_inode_free_security	(void *i_security)	{return;}
+static int dummy_inode_create		(struct inode *inode, struct dentry *dentry, int mask) {return 0;}
+static int dummy_inode_link		(struct dentry *old_dentry, struct inode *inode, struct dentry *new_dentry) {return 0;}
+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 int dummy_inode_mkdir		(struct inode *inode, struct dentry *dentry, int mask) {return 0;}
+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, int minor) {return 0;}
+static int dummy_inode_rename		(struct inode *old_inode, struct dentry *old_dentry, struct inode *new_inode, struct dentry *new_dentry) {return 0;}
+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_revalidate	(struct dentry *inode) {return 0;}
+static int dummy_inode_setattr		(struct dentry *dentry, struct iattr *iattr) {return 0;}
+static void dummy_inode_attach_pathlabel(struct dentry *dentry, struct vfsmount *mnt) {return;}
+
+static int dummy_file_permission	(struct file *file, int mask)	{return 0;}
+static void * dummy_file_alloc_security	(struct file *file)	{return NULL;}
+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)	{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_task_create		(void)	{return 0;}
+static void * dummy_task_alloc_security	(void)		{return NULL;}
+static void dummy_task_free_security	(void *data)	{return;}
+static int dummy_task_setuid		(void)	{return 0;}
+static int dummy_task_setgid		(void)	{return 0;}
+static int dummy_task_setpriority	(void)	{return 0;}
+static int dummy_task_kill		(void)	{return 0;}
+
+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 struct inode_security_ops dummy_inode_ops = {
+	alloc_security:	dummy_inode_alloc_security,
+	free_security:	dummy_inode_free_security,
+	create:		dummy_inode_create,
+	link:		dummy_inode_link,
+	unlink:		dummy_inode_unlink,
+	symlink:	dummy_inode_symlink,
+	mkdir:		dummy_inode_mkdir,
+	rmdir:		dummy_inode_rmdir,
+	mknod:		dummy_inode_mknod,
+	rename:		dummy_inode_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,
+};
+
+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,
+	lock:		dummy_file_lock,
+	readv:		dummy_file_readv,
+	writev:		dummy_file_writev,
+};
+
+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,
+	setpriority:	dummy_task_setpriority,
+	kill:		dummy_task_kill,
+};
+
+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,
+	umount:			dummy_umount,
+	ioperm:			dummy_ioperm,
+	iopl:			dummy_iopl,
+	ptrace:			dummy_ptrace,
+	setcapability:		dummy_setcapablity,
+	perm_comp:		dummy_perm_comp,
+	init_perm:		dummy_init_perm,
+	change_perm:		dummy_change_perm,
+
+	inode_ops:		&dummy_inode_ops,
+	file_ops:		&dummy_file_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,
+};
+
+
+
+/**
+ *	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;
+}
+
+
+/**
+ *	register_security - registers a security framework with the kernel
+ */
+int register_security (struct security_operations *ops)
+{
+	/* verify the version of the structure matches what we think it should be */
+	if (ops->version != SECURITY_INTERFACE_VERSION) {
+		printk (KERN_INFO "Mismatched version of security_operation structure used, " __FUNCTION__ " failed.");
+		return -EINVAL;
+	}
+
+	if (ops != &dummy_security_ops) {
+		printk (KERN_INFO "There is already a security framework initialized, " __FUNCTION__ " failed.");
+		return -EINVAL;
+	}
+	
+	/* Perform a little sanity checking on our inputs */
+	if ( !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.");
+		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.");
+		return -EINVAL;
+	}
+
+	security_ops = &dummy_security_ops;
+
+	return 0;
+}
+
+EXPORT_SYMBOL(register_security);
+EXPORT_SYMBOL(unregister_security);
+
diff -Nru a/kernel/sys.c b/kernel/sys.c
--- a/kernel/sys.c	Mon Apr 23 09:04:14 2001
+++ b/kernel/sys.c	Mon Apr 23 09:04:14 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>
@@ -269,11 +270,18 @@
 asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void * arg)
 {
 	char buffer[256];
+	int result;
 
 	/* We only trust the superuser with rebooting the system. */
 	if (!capable(CAP_SYS_BOOT))
 		return -EPERM;
 
+	/* check that we have permission to do this */
+	result = security_ops->reboot();
+	if (result) {
+		return result;
+	}
+
 	/* For safety, we require "magic" arguments. */
 	if (magic1 != LINUX_REBOOT_MAGIC1 ||
 	    (magic2 != LINUX_REBOOT_MAGIC2 && magic2 != LINUX_REBOOT_MAGIC2A &&
@@ -1030,6 +1038,13 @@
 		return -EPERM;
 	if (len < 0 || len > __NEW_UTS_LEN)
 		return -EINVAL;
+
+	/* check that we have permission to do this */
+	errno = security_ops->sethostname();
+	if (errno) {
+		return errno;
+	}
+
 	down_write(&uts_sem);
 	errno = -EFAULT;
 	if (!copy_from_user(system_utsname.nodename, name, len)) {
@@ -1069,6 +1084,12 @@
 		return -EPERM;
 	if (len < 0 || len > __NEW_UTS_LEN)
 		return -EINVAL;
+
+	/* check that we have permission to do this */
+	errno = security_ops->setdomainname();
+	if (errno) {
+		return errno;
+	}
 
 	down_write(&uts_sem);
 	errno = -EFAULT;
diff -Nru a/mm/filemap.c b/mm/filemap.c
--- a/mm/filemap.c	Mon Apr 23 09:04:14 2001
+++ b/mm/filemap.c	Mon Apr 23 09:04:14 2001
@@ -21,6 +21,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>
@@ -1311,6 +1312,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..
 	 */
@@ -1327,6 +1332,10 @@
 	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_in;
 
 	retval = 0;
 	if (count) {
diff -Nru a/mm/memory.c b/mm/memory.c
--- a/mm/memory.c	Mon Apr 23 09:04:14 2001
+++ b/mm/memory.c	Mon Apr 23 09:04:14 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>
@@ -969,8 +970,10 @@
 out_unlock:
 	spin_unlock(&mapping->i_shared_lock);
 	truncate_inode_pages(mapping, offset);
-	if (inode->i_op && inode->i_op->truncate)
-		inode->i_op->truncate(inode);
+	if (inode->i_op && inode->i_op->truncate) {
+		if (!security_ops->inode_ops->truncate(inode))
+			inode->i_op->truncate(inode);
+	}
 	return;
 
 do_expand:
@@ -986,8 +989,10 @@
 		}
 	}
 	inode->i_size = offset;
-	if (inode->i_op && inode->i_op->truncate)
-		inode->i_op->truncate(inode);
+	if (inode->i_op && inode->i_op->truncate) {
+		if (!security_ops->inode_ops->truncate(inode))
+			inode->i_op->truncate(inode);
+	}
 out:
 	return;
 }
diff -Nru a/security/Config.in b/security/Config.in
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/security/Config.in	Mon Apr 23 09:04:14 2001
@@ -0,0 +1,8 @@
+#
+# Security configuration
+#
+mainmenu_option next_comment
+comment 'Security options'
+tristate '  Capabilities Support' CONFIG_CAPABILITIES
+
+endmenu