[LWN Logo]
[LWN.net]
From:	 richard offer <offer@sgi.com>
To:	 linux-security-module@wirex.com
Subject: Authoritative hooks updated to 2.4.13
Date:	 Thu, 25 Oct 2001 14:03:20 -0700


Attached is the auth patch brought upto date against 2.4.13 
    (ChangeSet@1.234, 2001-10-23 23:33:43-07:00, greg@desk.kroah.org).


With no subsequent discussion following posting of the last patch (which
incorporated changes to meet Chris's suggestions) all the issues appear to
have been put to bed so there should be no reason for not moving forward
with this.

richard.
===== fs/attr.c 1.9 vs edited =====
--- 1.9/fs/attr.c	Tue Oct 23 23:30:43 2001
+++ edited/fs/attr.c	Thu Oct 25 11:15:56 2001
@@ -115,7 +115,7 @@
 int notify_change(struct dentry * dentry, struct iattr * attr)
 {
 	struct inode *inode = dentry->d_inode;
-	int error;
+	int error=0;
 	time_t now = CURRENT_TIME;
 	unsigned int ia_valid = attr->ia_valid;
 
@@ -130,13 +130,12 @@
 
 	lock_kernel();
 	if (inode->i_op && inode->i_op->setattr) {
-		error = security_ops->inode_ops->setattr(dentry, attr);
+		error = security_ops->inode_ops->setattr(error,dentry, attr);
 		if (!error)
 			error = inode->i_op->setattr(dentry, attr);
 	} else {
 		error = inode_change_ok(inode, attr);
-		if (!error)
-			error = security_ops->inode_ops->setattr(dentry, attr);
+		error = security_ops->inode_ops->setattr(error,dentry, attr);
 		if (!error) {
 			if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
 			    (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid))
===== fs/fcntl.c 1.6 vs edited =====
--- 1.6/fs/fcntl.c	Sun Sep 23 17:37:50 2001
+++ edited/fs/fcntl.c	Thu Oct 25 11:15:57 2001
@@ -415,12 +415,14 @@
 			       int fd,
 			       int reason)
 {
+	int retval = 0;
+
 	if ((fown->euid != 0) &&
 	    (fown->euid ^ p->suid) && (fown->euid ^ p->uid) &&
 	    (fown->uid ^ p->suid) && (fown->uid ^ p->uid))
-		return;
+		retval = -EPERM;
 
-	if (security_ops->file_ops->send_sigiotask(p, fown, fd, reason))
+	if (security_ops->file_ops->send_sigiotask(retval, p, fown, fd, reason))
 		return;
 
 	switch (fown->signum) {
===== fs/namei.c 1.20 vs edited =====
--- 1.20/fs/namei.c	Tue Oct 23 23:30:44 2001
+++ edited/fs/namei.c	Thu Oct 25 11:15:58 2001
@@ -211,10 +211,8 @@
 	} else {
 		retval = vfs_permission(inode, submask);
 	}
-	if (retval)
-		return retval;
 
-	return security_ops->inode_ops->permission(inode, mask);
+	return security_ops->inode_ops->permission(retval, inode, mask);
 }
 
 /*
@@ -972,8 +970,8 @@
 	up(&dir->i_zombie);
 	if (!error) {
 		inode_dir_notify(dir, DN_CREATE);
-		security_ops->inode_ops->post_create(dir, dentry, mode);
 	}
+	security_ops->inode_ops->post_create(error, dir, dentry, mode);
 	return error;
 }
 
@@ -1265,8 +1263,8 @@
 	up(&dir->i_zombie);
 	if (!error) {
 		inode_dir_notify(dir, DN_CREATE);
-		security_ops->inode_ops->post_mknod(dir, dentry, mode, dev);
 	}
+	security_ops->inode_ops->post_mknod(error,dir, dentry, mode, dev);
 	return error;
 }
 
@@ -1342,8 +1340,8 @@
 	up(&dir->i_zombie);
 	if (!error) {
 		inode_dir_notify(dir, DN_CREATE);
-		security_ops->inode_ops->post_mkdir(dir,dentry, mode);
 	}
+	security_ops->inode_ops->post_mkdir(error, dir,dentry, mode);
 	return error;
 }
 
@@ -1586,8 +1584,8 @@
 	up(&dir->i_zombie);
 	if (!error) {
 		inode_dir_notify(dir, DN_CREATE);
-		security_ops->inode_ops->post_symlink(dir, dentry, oldname);
 	}
+	security_ops->inode_ops->post_symlink(error, dir, dentry, oldname);
 	return error;
 }
 
@@ -1666,8 +1664,8 @@
 	up(&dir->i_zombie);
 	if (!error) {
 		inode_dir_notify(dir, DN_CREATE);
-		security_ops->inode_ops->post_link(old_dentry, dir, new_dentry);
 	}
+	security_ops->inode_ops->post_link(error, old_dentry, dir, new_dentry);
 	return error;
 }
 
@@ -1832,9 +1830,9 @@

 	if (!error) {
 		d_move(old_dentry,new_dentry);
-		security_ops->inode_ops->post_rename(old_dir, old_dentry,
-							new_dir, new_dentry);
 	}
+	security_ops->inode_ops->post_rename(error,old_dir, old_dentry, 
+			new_dir, new_dentry);
 out_unlock:
 	up(&old_dir->i_sb->s_vfs_rename_sem);
 	return error;
@@ -1877,13 +1875,11 @@
 	else
 		error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
 	double_up(&old_dir->i_zombie, &new_dir->i_zombie);
-	if (error)
-		return error;
-	/* The following d_move() should become unconditional */
-	if (!(old_dir->i_sb->s_type->fs_flags & FS_ODD_RENAME)) {
+	/* The following d_move() should become unconditional (except for "error")*/
+	if (!error && !(old_dir->i_sb->s_type->fs_flags & FS_ODD_RENAME)) {
 		d_move(old_dentry, new_dentry);
 	}
-	security_ops->inode_ops->post_rename(old_dir, old_dentry, new_dir, new_dentry);
+	security_ops->inode_ops->post_rename(error, old_dir, old_dentry, new_dir, new_dentry);
 	return 0;
 }
 
===== fs/namespace.c 1.7 vs edited =====
--- 1.7/fs/namespace.c	Tue Oct 23 23:30:44 2001
+++ edited/fs/namespace.c	Thu Oct 25 11:15:59 2001
@@ -364,9 +364,6 @@
 	struct super_block * sb = mnt->mnt_sb;
 	int retval = 0;
 
-	retval = security_ops->sb_ops->umount(mnt, flags);
-	if (retval)
-		return retval;
 
 	/*
 	 * If we may have to abort operations to get out of this
@@ -463,8 +460,12 @@
 	if (!check_mnt(nd.mnt))
 		goto dput_and_out;
 
-	retval = -EPERM;
+	retval = 0;
 	if (!capable(CAP_SYS_ADMIN))
+		retval = -EPERM;
+
+	retval = security_ops->sb_ops->umount(retval, nd.mnt, flags);
+	if ( retval )
 		goto dput_and_out;
 
 	retval = do_umount(nd.mnt, flags);
@@ -618,25 +619,31 @@
 
 static int do_remount(struct nameidata *nd,int flags,int mnt_flags,void *data)
 {
-	int err;
+	int err=0;
 	struct super_block * sb = nd->mnt->mnt_sb;
 
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
+	if (!capable(CAP_SYS_ADMIN)) {
+		err = -EPERM;
+		goto out;
+	}
 
-	if (!check_mnt(nd->mnt))
-		return -EINVAL;
+	if (!check_mnt(nd->mnt)) {
+		err = -EINVAL;
+		goto out;
+	}
 
-	if (nd->dentry != nd->mnt->mnt_root)
-		return -EINVAL;
+	if (nd->dentry != nd->mnt->mnt_root) {
+		err = -EINVAL;
+		goto out;
+	}
 
 	down_write(&sb->s_umount);
 	err = do_remount_sb(sb, flags, data);
 	if (!err)
 		nd->mnt->mnt_flags=mnt_flags;
 	up_write(&sb->s_umount);
-	if (!err)
-		security_ops->sb_ops->post_remount(nd->mnt, flags, data);
+out:
+	security_ops->sb_ops->post_remount(err, nd->mnt, flags, data);
 	return err;
 }
 
@@ -667,8 +674,7 @@
 	if (err)
 		goto unlock;
 	err = graft_tree(mnt, nd);
-	if (!err)
-		security_ops->sb_ops->post_addmount(mnt, nd);
+	security_ops->sb_ops->post_addmount(err, mnt, nd);
 unlock:
 	up(&mount_sem);
 	mntput(mnt);
===== fs/proc/base.c 1.8 vs edited =====
--- 1.8/fs/proc/base.c	Thu Oct 11 08:36:33 2001
+++ edited/fs/proc/base.c	Thu Oct 25 11:16:00 2001
@@ -287,7 +287,7 @@
 };
 
 #define MAY_PTRACE(p) \
-(p==current||(p->p_pptr==current&&(p->ptrace & PT_PTRACED)&&p->state==TASK_STOPPED&&security_ops->ptrace(current,p)==0))
+(p==current||(p->p_pptr==current&&(p->ptrace & PT_PTRACED)&&p->state==TASK_STOPPED&&security_ops->ptrace(0,current,p)==0))
 
 
 static int mem_open(struct inode* inode, struct file* file)
===== kernel/acct.c 1.7 vs edited =====
--- 1.7/kernel/acct.c	Fri Aug 24 10:10:43 2001
+++ edited/kernel/acct.c	Thu Oct 25 11:16:01 2001
@@ -158,9 +158,6 @@
 	char *tmp;
 	int error;
 
-	if (!capable(CAP_SYS_PACCT))
-		return -EPERM;
-
 	if (name) {
 		tmp = getname(name);
 		error = PTR_ERR(tmp);
@@ -182,7 +179,11 @@
 			goto out_err;
 	}
 
-	error = security_ops->acct(file);
+	error = 0;
+	if (!capable(CAP_SYS_PACCT))
+		error = -EPERM;
+
+	error = security_ops->acct(error, file);
 	if (error)
 		goto out_err;
 
===== kernel/capability.c 1.3 vs edited =====
--- 1.3/kernel/capability.c	Thu Oct 11 23:28:13 2001
+++ edited/kernel/capability.c	Thu Oct 25 11:16:02 2001
@@ -140,9 +140,6 @@
      if (get_user(pid, &header->pid))
 	     return -EFAULT; 
 
-     if (pid && !capable(CAP_SETPCAP))
-             return -EPERM;
-
      if (copy_from_user(&effective, &data->effective, sizeof(effective)) ||
 	 copy_from_user(&inheritable, &data->inheritable, sizeof(inheritable)) ||
 	 copy_from_user(&permitted, &data->permitted, sizeof(permitted)))
@@ -162,7 +159,11 @@
              target = current;
      }
 
-     error = security_ops->capset_check(target, &effective, &inheritable, &permitted);
+     error = 0;
+     if (pid && !capable(CAP_SETPCAP))
+             error = -EPERM;
+
+     error = security_ops->capset_check(error, target, &effective, &inheritable, &permitted);
      if (error)
 	     goto out;
 
===== kernel/sys.c 1.18 vs edited =====
--- 1.18/kernel/sys.c	Sun Sep 23 17:21:24 2001
+++ edited/kernel/sys.c	Thu Oct 25 11:16:02 2001
@@ -212,25 +212,19 @@
 
 	read_lock(&tasklist_lock);
 	for_each_task(p) {
-		int no_nice;
 		if (!proc_sel(p, which, who))
 			continue;
+		error = 0;
 		if (p->uid != current->euid &&
 			p->uid != current->uid && !capable(CAP_SYS_NICE)) {
 			error = -EPERM;
-			continue;
 		}
-		if (niceval < p->nice && !capable(CAP_SYS_NICE)) {
+		if (!error && niceval < p->nice && !capable(CAP_SYS_NICE)) {
 			error = -EACCES;
-			continue;
 		}
-		no_nice = security_ops->task_ops->setnice(p, niceval);
-		if (no_nice) {
-			error = no_nice;
+		error = security_ops->task_ops->setnice(error, p, niceval);
+		if (error)
 			continue;
-		}
-		if (error == -ESRCH)
-			error = 0;
 		p->nice = niceval;
 	}
 	read_unlock(&tasklist_lock);
@@ -278,16 +272,7 @@
 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. */
-	if (!capable(CAP_SYS_BOOT))
-		return -EPERM;
-
-	retval = security_ops->reboot(cmd);
-	if (retval) {
-		return retval;
-	}
+	int retval = 0;
 
 	/* For safety, we require "magic" arguments. */
 	if (magic1 != LINUX_REBOOT_MAGIC1 ||
@@ -295,6 +280,14 @@
 			magic2 != LINUX_REBOOT_MAGIC2B))
 		return -EINVAL;
 
+	/* We only trust the superuser with rebooting the system. */
+	if (!capable(CAP_SYS_BOOT))
+		retval = -EPERM;
+
+	retval = security_ops->reboot(retval, cmd);
+	if (retval)
+		return retval;
+
 	lock_kernel();
 	switch (cmd) {
 	case LINUX_REBOOT_CMD_RESTART:
@@ -820,6 +813,10 @@
 	if (!p)
 		goto out;
 
+	err = security_ops->task_ops->setpgid(p, pgid);
+	if (err)
+		goto out;
+
 	if (p->p_pptr == current || p->p_opptr == current) {
 		err = -EPERM;
 		if (p->session != current->session)
@@ -843,10 +840,6 @@
 	}
 
 ok_pgid:
-	err = security_ops->task_ops->setpgid(p, pgid);
-	if (err)
-		goto out;
-
 	p->pgrp = pgid;
 	err = 0;
 out:
@@ -958,15 +951,15 @@
 asmlinkage long sys_setgroups(int gidsetsize, gid_t *grouplist)
 {
 	gid_t groups[NGROUPS];
-	int retval;
+	int retval = 0;
 
-	if (!capable(CAP_SETGID))
-		return -EPERM;
 	if ((unsigned) gidsetsize > NGROUPS)
 		return -EINVAL;
 	if(copy_from_user(groups, grouplist, gidsetsize * sizeof(gid_t)))
 		return -EFAULT;
-	retval = security_ops->task_ops->setgroups(gidsetsize, groups);
+	if (!capable(CAP_SETGID))
+		retval = -EPERM;
+	retval = security_ops->task_ops->setgroups(retval, gidsetsize, groups);
 	if (retval)
 		return retval;
 	memcpy(current->groups, groups, gidsetsize * sizeof(gid_t));
@@ -1025,17 +1018,17 @@
 asmlinkage long sys_sethostname(char *name, int len)
 {
 	char nodename[__NEW_UTS_LEN+1];
-	int errno;
+	int errno = 0;
 
-	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 (!capable(CAP_SYS_ADMIN))
+		errno = -EPERM;
+	errno = security_ops->sethostname(errno, nodename);
 	if (errno)
 		return errno;
 
@@ -1069,17 +1062,17 @@
 asmlinkage long sys_setdomainname(char *name, int len)
 {
 	char domainname[__NEW_UTS_LEN+1];
-	int errno;
+	int errno = 0;
 
-	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 (!capable(CAP_SYS_ADMIN))
+		errno = -EPERM;
+	errno = security_ops->setdomainname(errno, domainname);
 	if (errno)
 		return errno;
 
@@ -1123,7 +1116,7 @@
 asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit *rlim)
 {
 	struct rlimit new_rlim, *old_rlim;
-	int retval;
+	int retval = 0;
 
 	if (resource >= RLIM_NLIMITS)
 		return -EINVAL;
@@ -1133,13 +1126,13 @@
 	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 = security_ops->task_ops->setrlimit(retval, resource, &new_rlim);
 	if (retval)
 		return retval;
 
===== kernel/module.c 1.16 vs edited =====
--- 1.16/kernel/module.c	Thu Oct  4 18:34:23 2001
+++ edited/kernel/module.c	Thu Oct 25 11:16:03 2001
@@ -292,12 +292,10 @@
 sys_create_module(const char *name_user, size_t size)
 {
 	char *name;
-	long namelen, error;
+	long namelen, error = 0;
 	struct module *mod;
 	unsigned long flags;
 
-	if (!capable(CAP_SYS_MODULE))
-		return -EPERM;
 	lock_kernel();
 	if ((namelen = get_mod_name(name_user, &name)) < 0) {
 		error = namelen;
@@ -313,7 +311,9 @@
 	}
 
 	/* check that we have permission to do this */
-	error = security_ops->module_ops->create_module(name, size);
+	if (!capable(CAP_SYS_MODULE))
+		error = -EPERM;
+	error = security_ops->module_ops->create_module(error, name, size);
 	if (error)
 		goto err1;
 
@@ -353,12 +353,10 @@
 {
 	struct module mod_tmp, *mod;
 	char *name, *n_name, *name_tmp = NULL;
-	long namelen, n_namelen, i, error;
+	long namelen, n_namelen, i, error=0;
 	unsigned long mod_user_size;
 	struct module_ref *dep;
 
-	if (!capable(CAP_SYS_MODULE))
-		return -EPERM;
 	lock_kernel();
 	if ((namelen = get_mod_name(name_user, &name)) < 0) {
 		error = namelen;
@@ -369,6 +367,14 @@
 		goto err1;
 	}
 
+	/* check that we have permission to do this */
+	if (!capable(CAP_SYS_MODULE))
+		error = -EPERM;
+
+	error = security_ops->module_ops->init_module(error,mod);
+	if (error)
+		goto err1;
+
 	/* Check module header size.  We allow a bit of slop over the
 	   size we are familiar with to cope with a version of insmod
 	   for a newer kernel.  But don't over do it. */
@@ -504,10 +510,6 @@
 		goto err3;
 	}
 
-	/* check that we have permission to do this */
-	error = security_ops->module_ops->init_module(mod);
-	if (error)
-		goto err3;
 	error = -EINVAL;
 
 	if (module_arch_init(mod))
@@ -611,9 +613,6 @@
 	long error;
 	int something_changed;
 
-	if (!capable(CAP_SYS_MODULE))
-		return -EPERM;
-
 	lock_kernel();
 	if (name_user) {
 		if ((error = get_mod_name(name_user, &name)) < 0)
@@ -632,7 +631,11 @@
 		spin_lock(&unload_lock);
 		if (!__MOD_IN_USE(mod)) {
 			/* check that we have permission to do this */
-			error = security_ops->module_ops->delete_module(mod);
+			error = 0;
+			if (!capable(CAP_SYS_MODULE))
+				error = -EPERM;
+
+			error = security_ops->module_ops->delete_module(error,mod);
 			if (error) {
 				spin_unlock(&unload_lock);
 				goto out;
@@ -645,7 +648,12 @@
 			spin_unlock(&unload_lock);
 		}
 		goto out;
-	}
+	} 
+
+	/* check that we have permission to do this */
+	error = -EPERM;
+	if (!capable(CAP_SYS_MODULE))
+		goto out;
 
 	/* Do automatic reaping */
 restart:
@@ -668,7 +676,7 @@
 				/* check that we have permission to do this
 				 * an error is not propagated if perm fails
 				 */
-				if (security_ops->module_ops->delete_module(mod)) {
+				if (security_ops->module_ops->delete_module(0,mod)) {
 					spin_unlock(&unload_lock);
 					continue;
 				}
===== kernel/ptrace.c 1.6 vs edited =====
--- 1.6/kernel/ptrace.c	Sun Sep 23 17:21:24 2001
+++ edited/kernel/ptrace.c	Thu Oct 25 11:16:04 2001
@@ -27,20 +27,24 @@
 		goto bad;
 	if (!task->mm)
 		goto bad;
+	/* messier than it should be to ensure we have a code path identical to 
+	 * that pre-LSM */
+	retval = 0;
 	if(((current->uid != task->euid) ||
 	    (current->uid != task->suid) ||
 	    (current->uid != task->uid) ||
  	    (current->gid != task->egid) ||
  	    (current->gid != task->sgid) ||
  	    (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
-		goto bad;
-	rmb();
-	if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
-		goto bad;
+		retval = -EPERM;
+	if ( ! retval )
+		rmb();
+	if (!retval && !task->mm->dumpable && !capable(CAP_SYS_PTRACE))
+		retval = -EPERM;
 	/* the same process cannot be attached many times */
 	if (task->ptrace & PT_PTRACED)
 		goto bad;
-	retval = security_ops->ptrace(current, task);
+	retval = security_ops->ptrace(retval, current, task);
 	if (retval)
 		goto bad;
 
===== kernel/sched.c 1.17 vs edited =====
--- 1.17/kernel/sched.c	Tue Oct 23 23:30:45 2001
+++ edited/kernel/sched.c	Thu Oct 25 11:16:05 2001
@@ -873,7 +873,7 @@
 asmlinkage long sys_nice(int increment)
 {
 	long newprio;
-	int retval;
+	int retval = 0;
 
 	/*
 	 *	Setpriority might change our priority at the same moment.
@@ -882,7 +882,7 @@
 	 */
 	if (increment < 0) {
 		if (!capable(CAP_SYS_NICE))
-			return -EPERM;
+			retval = -EPERM;
 		if (increment < -40)
 			increment = -40;
 	}
@@ -895,7 +895,7 @@
 	if (newprio > 19)
 		newprio = 19;
 
-	retval = security_ops->task_ops->setnice(current, newprio);
+	retval = security_ops->task_ops->setnice(retval, current, newprio);
 	if (retval)
 		return retval;

@@ -960,15 +960,15 @@
 	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))
-		goto out_unlock;
+		retval = -EPERM;
 
-	retval = security_ops->task_ops->setscheduler(p, policy, &lp);
+	retval = security_ops->task_ops->setscheduler(retval, p, policy, &lp);
 	if (retval)
 		goto out_unlock;
 
===== kernel/signal.c 1.4 vs edited =====
--- 1.4/kernel/signal.c	Sun Sep 23 17:21:24 2001
+++ edited/kernel/signal.c	Thu Oct 25 11:16:06 2001
@@ -515,10 +515,10 @@
 	if (sig < 0 || sig > _NSIG)
 		goto out_nolock;
 	/* The somewhat baroque permissions check... */
-	ret = -EPERM;
+	ret = 0;
 	if (bad_signal(sig, info, t))
-		goto out_nolock;
-	ret = security_ops->task_ops->kill(t, info, sig);
+		ret = -EPERM;
+	ret = security_ops->task_ops->kill(ret, t, info, sig);
 	if (ret)
 		goto out_nolock;
 
===== kernel/sysctl.c 1.12 vs edited =====
--- 1.12/kernel/sysctl.c	Tue Oct  9 23:16:36 2001
+++ edited/kernel/sysctl.c	Thu Oct 25 11:16:07 2001
@@ -386,11 +386,8 @@
 static inline int ctl_perm(ctl_table *table, int op)
 {
 	int error;
-	error = security_ops->sysctl(table, op);
-	if(error) {
-		return error;
-	}
-	return test_perm(table->mode, op);
+	error = test_perm(table->mode, op);
+	return security_ops->sysctl(error,table, op);
 }
 
 static int parse_table(int *name, int nlen,
===== include/linux/security.h 1.93 vs edited =====
--- 1.93/include/linux/security.h	Tue Oct 23 09:35:04 2001
+++ edited/include/linux/security.h	Thu Oct 25 11:20:54 2001
@@ -206,10 +206,12 @@
 
 	/**
 	 * umount - check permission when unmounting a file system
+	 * @kerror: error value of kernel checks.
 	 * @mnt:  the mounted file system
 	 * @flags: unmount flags, e.g. MNT_FORCE
 	 *
 	 * called: do_umount <fs/namespace.c>
+	 * authoritative: yes
 	 *
 	 * lock:  The mount semaphore and the big kernel lock are 
 	 *        held by sys_umount.
@@ -217,7 +219,7 @@
 	 * Check permission before the @mnt file system is
 	 * unmounted.  Return 0 if permission is granted.
 	 */
-	int (* umount) (struct vfsmount *mnt, int flags);
+	int (* umount) (int kerror, struct vfsmount *mnt, int flags);
 
 	/**
 	 * umount_close - close any files in a mounted filesystem held open by the security module
@@ -253,6 +255,7 @@
 
 	/**
 	 * post_remount - Update module state when a filesystem is remounted
+	 * @kerror: error value of kernel checks.
 	 * @mnt:  the mounted file system
 	 * @flags: new filesystem flags
 	 * @data:  filesystem-specific data
@@ -262,9 +265,8 @@
 	 * lock:  The big kernel lock is held by sys_mount.
 	 *
 	 * Update the security module's state when a filesystem is remounted.
-	 * This hook is only called if the remount was successful.
 	 */
-	void (* post_remount) (struct vfsmount *mnt, unsigned long flags,
+	void (* post_remount) (int kerror, struct vfsmount *mnt, unsigned long flags,
 			       void *data);
 
 	/**
@@ -280,6 +282,7 @@
 
 	/**
 	 * post_addmount - Update module state when a non-root filesystem is mounted
+	 * @kerror: error value of kernel checks.
 	 * @mnt:  the mounted filesystem
 	 * @mountpoint_nd:  the nameidata structure for the mount point
 	 *
@@ -290,7 +293,7 @@
 	 * Update the security module's state when a non-root filesystem is
 	 * mounted.  This hook is not called after a loopback/bind mount.
 	 */
-	void (* post_addmount) (struct vfsmount *mnt, struct nameidata
+	void (* post_addmount) (int kerror, struct vfsmount *mnt, struct nameidata
 				*mountpoint_nd);
 };
 
@@ -339,6 +342,7 @@
 
 	/**
 	 * post_create - set the security attributes on a newly created file
+	 * @kerror: error value of kernel checks.
 	 * @dir: inode structure of the parent directory of the new file
 	 * @dentry: the dentry structure for the newly created file
 	 * @mode: the file mode 
@@ -348,9 +352,10 @@
 	 * lock: The @dir i_sem semaphore is held.
 	 *
 	 * Set the security attributes on a newly created regular file.
-	 * This hook is called after a file has been successfully created.
+	 * If the inode is to be notified that will happen before this hook is 
+	 * called.
 	 */
-	void (* post_create) (struct inode *dir, struct dentry *dentry, 
+	void (* post_create) (int kerror, struct inode *dir, struct dentry *dentry, 
 			      int mode);
 
 	/**
@@ -372,6 +377,7 @@
 
 	/**
 	 * post_link - set security attributes for a new file link
+	 * @kerror: error value of kernel checks.
 	 * @old_dentry: dentry structure for the existing link
 	 * @dir: the inode structure of the parent directory of the new file
 	 * @new_dentry: dentry structure for the new file link
@@ -381,9 +387,11 @@
 	 * lock: The @dir i_sem semaphore is held.
 	 * 
 	 * Set security attributes for a new hard link to a file.
+	 * If the inode is to be notified that will happen before this hook is 
+	 * called.
 	 */
-	void (* post_link) (struct dentry *old_dentry, struct inode *dir, 
-			    struct dentry *new_dentry);
+	void (* post_link) (int kerror, struct dentry *old_dentry, 
+			struct inode *dir, struct dentry *new_dentry);
 
 	/**
 	 * unlink - check permissions when unlinking a file
@@ -419,6 +427,7 @@
 
 	/**
 	 * post_symlink - set security attributes on a new symbolic link
+	 * @kerror: error value of kernel checks.
 	 * @dir: inode structure of the parent directory of the new link
 	 * @dentry: dentry structure of new symbolic link
 	 * @old_name: pathname of file
@@ -430,9 +439,11 @@
 	 * Set security attributes for a newly created symbolic link.
 	 * Note that @dentry->d_inode may be NULL, since the filesystem
 	 * might not instantiate the dentry (e.g. NFS).
+	 * If the inode is to be notified that will happen before this hook is 
+	 * called.
 	 */
-	void (* post_symlink) (struct inode *dir, struct dentry *dentry, 
-			       const char *old_name);
+	void (* post_symlink) (int kerror, struct inode *dir, 
+			struct dentry *dentry, const char *old_name);
 
 	/**
 	 * mkdir - check permissions when creating a directory
@@ -453,6 +464,7 @@
 
 	/**
 	 * post_mkdir - set security attributes on new directory
+	 * @kerror: error value of kernel checks.
 	 * @dir: inode structure of parent of the directory to be created
 	 * @dentry: dentry structure of new directory
 	 * @mode: mode of new directory
@@ -462,8 +474,10 @@
 	 * lock: The @dir i_sem semaphore is held.
 	 *
 	 * Set security attributes on a newly created directory.
+	 * If the inode is to be notified that will happen before this hook is 
+	 * called.
 	 */
-	void (* post_mkdir) (struct inode *dir, struct dentry *dentry, 
+	void (* post_mkdir) (int kerror, struct inode *dir, struct dentry *dentry, 
 			     int mode);
 
 	/**
@@ -505,6 +519,7 @@
 
 	/**
 	 * post_mknod - set security attributes on a special file
+	 * @kerror: error value of kernel checks.
 	 * @dir: inode structure of parent of the new node
 	 * @dentry: dentry structure of the new node
 	 * @mode: mode of the new node
@@ -516,8 +531,10 @@
 	 *
 	 * Set security attributes on a newly created special file
 	 * (or socket or fifo file created via the mknod system call).
+	 * If the inode is to be notified that will happen before this hook is 
+	 * called.
 	 */
-	void (* post_mknod) (struct inode *dir, struct dentry *dentry, 
+	void (* post_mknod) (int kerror, struct inode *dir, struct dentry *dentry, 
 			     int mode, dev_t dev);
 
 	/**
@@ -542,6 +559,7 @@
  
 	/**
 	 * post_rename - set security attributes on newly renamed file or directory
+	 * @kerror: error value of kernel checks.
 	 * @old_dir: inode structure for parent of the old link
 	 * @old_dentry: dentry structure of the old link
 	 * @new_dir: inode structure for parent of the new link
@@ -554,9 +572,12 @@
 	 * lock: The @old_dir->i_sb->s_vfs_rename_sem semaphore is held.
 	 *
 	 * Set security attributes on a renamed file or directory.
+	 * If the dcache is to be updated, that will happen before this hook is
+	 * called. 
 	 */
-	void (* post_rename) (struct inode *old_dir, struct dentry *old_dentry,
-			      struct inode *new_dir, struct dentry *new_dentry);
+	void (* post_rename) (int kerror, struct inode *old_dir, 
+			struct dentry *old_dentry, struct inode *new_dir, 
+			struct dentry *new_dentry);
 
 	/**
 	 * readlink - check permissions when reading a symbolic link
@@ -584,10 +605,12 @@
 
 	/**
 	 * permission - check permission when accessing an inode
+	 * @kerror: error value of kernel checks.
 	 * @inode: inode structure to check
 	 * @mask: permission mask
 	 * 
 	 * called: permission <fs/namei.c>
+	 * authoritative: yes
 	 * 
 	 * Check permission before accessing an inode.  This hook
 	 * is called by the existing Linux permission function,
@@ -599,7 +622,7 @@
 	 * operations are performed.
 	 * Return 0 if permission is granted.
 	 */
-	int (* permission) (struct inode *inode, int mask);
+	int (* permission) (int kerror, struct inode *inode, int mask);
 
 	/**
 	 * revalidate - revalidate the inode attributes
@@ -616,10 +639,12 @@
 
 	/**
 	 * setattr - check permissions to set file attributes
+	 * @kerror: error value of kernel checks.
 	 * @dentry: dentry structure for the file
 	 * @attr: iattr structure containing the new file attributes
 	 * 
 	 * called: notify_change <fs/attr.c>
+	 * authoritative: yes
 	 *
 	 * lock:  The big kernel lock is held by notify_change
 	 *
@@ -629,7 +654,7 @@
 	 * is truncated, chown/chmod operations, transferring disk quotas, 
 	 * etc).   Return 0 if permission is granted.
 	 */
-	int (* setattr)	(struct dentry *dentry, struct iattr *attr);
+	int (* setattr)	(int kerror, struct dentry *dentry, struct iattr *attr);
 
 	/**
 	 * stat - check permissions to get file attributes
@@ -842,12 +867,14 @@
 
 	/**
 	 * send_sigiotask - check permission to send SIGIO
+	 * @kerror: error value of kernel checks
 	 * @tsk: structure of task receiving signal
 	 * @fown: file owner information
 	 * @fd: file descriptor
 	 * @reason: operational flags
 	 *
 	 * called: send_sigio_to_task <fs/fcntl.c>
+	 * authoritative: yes
 	 *
 	 * Check permission for the file owner @fown to send
 	 * SIGIO to the process @tsk.  Note that this hook is always
@@ -858,7 +885,7 @@
 	 *     (struct file *)((long)fown - offsetof(struct file,f_owner));
 	 * Return 0 if permission is granted.
 	 */
-	int (*send_sigiotask) (struct task_struct * tsk,
+	int (*send_sigiotask) (int kerror, struct task_struct * tsk,
 			       struct fown_struct * fown, int fd, int reason);
 
 	/**
@@ -985,6 +1012,7 @@
 	 * @pgid: new pgid
 	 *
 	 * called: sys_setpgid <kernel/sys.c>
+	 * authoritative: yes
 	 *
 	 * lock:  tasklist_lock is read-locked.
 	 *
@@ -1022,38 +1050,44 @@
 
 	/**
 	 * setgroups - check permission when setting supplementary group set
+	 * @kerror: error value of kernel checks
 	 * @gidsetsize: number of elements in @grouplist
 	 * @grouplist: array of gids
 	 *
 	 * called: sys_setgroups <kernel/sys.c>
+	 * authoritative: yes
 	 *
 	 * Check permission before setting the supplementary group set
 	 * of the current process to @grouplist.  Return 0 if permission 
 	 * is granted.
 	 */
-	int (* setgroups) (int gidsetsize, gid_t *grouplist);
+	int (* setgroups) (int kerror, int gidsetsize, gid_t *grouplist);
 
 	/**
 	 * setnice - check permission when setting process nice value
+	 * @kerror: error value of kernel checks
 	 * @p: task_struct of process
 	 * @nice: new nice value
 	 *
 	 * called: sys_setpriority <kernel/sys.c>
 	 * called: sys_nice <kernel/sched.c>
+	 * authoritative: yes
 	 *
 	 * lock: the tasklist_lock is read-locked in sys_setpriority.
 	 *
 	 * Check permission before setting the nice value of @p
 	 * to @nice.  Return 0 if permission is granted.
 	 */
-	int (* setnice)	(struct task_struct *p, int nice);
+	int (* setnice)	(int kerror, struct task_struct *p, int nice);
 
 	/**
 	 * setrlimit - check permission when setting resource limits
+	 * @kerror: error value of kernel checks
 	 * @resource: resource whose limit is being set
 	 * @new_rlim: new limits for @resource
 	 *
 	 * called: sys_setrlimit <kernel/sys.c>
+	 * authoritative: yes
 	 *
 	 * Check permission before setting the resource limits
 	 * of the current process for @resource to @new_rlim.
@@ -1061,15 +1095,17 @@
 	 * dereferencing (current->rlim + resource).
 	 * Return 0 if permission is granted.
 	 */
-	int (* setrlimit) (unsigned int resource, struct rlimit *new_rlim);
+	int (* setrlimit) (int kerror, unsigned int resource, struct rlimit *new_rlim);
 
 	/**
 	 * setscheduler - check permission when setting scheduling info
+	 * @kerror: error value of kernel checks
 	 * @p: task_struct for process
 	 * @policy: scheduling policy
 	 * @lp: scheduling parameters
 	 *
 	 * called: setscheduler <kernel/sched.c>
+	 * authoritative: yes
 	 *
 	 * lock:  tasklist_lock is read-locked, and runqueue_lock is locked.
 	 *
@@ -1077,7 +1113,7 @@
 	 * and/or parameters of process @p based on @policy
 	 * and @lp.  Return 0 if permission is granted.
 	 */
-	int (* setscheduler) (struct task_struct *p, int policy, 
+	int (* setscheduler) (int kerror, struct task_struct *p, int policy, 
 			      struct sched_param *lp);
 
 	/**
@@ -1097,11 +1133,13 @@
 
 	/**
 	 * kill - check permission when sending a signal
+	 * @kerror: error value of kernel checks
 	 * @p: task_struct for process
 	 * @info: signal information
 	 * @sig: signal value
 	 *
 	 * called: send_sig_info <kernel/signal.c>
+	 * authoritative: yes
 	 *
 	 * lock:  tasklist_lock may be read-locked by the caller.
 	 *
@@ -1115,7 +1153,7 @@
 	 * SIGIO signals are handled separately by the send_sigiotask
 	 * hook in file_security_ops.
 	 */
-	int (* kill) (struct task_struct *p, struct siginfo *info, int sig);
+	int (* kill) (int kerror, struct task_struct *p, struct siginfo *info, int sig);
 
 	/**
 	 * wait - check permission when reaping a child process
@@ -1650,17 +1688,19 @@
 struct module_security_ops {
 	/**
 	 * create_module - check permission when allocating space for a module
+	 * @kerror: error value of kernel checks
 	 * @name: module name
 	 * @size: module size
 	 *
 	 * called: sys_create_module <kernel/module.c>
+ 	 * authoritative: yes
 	 *
 	 * lock:  The big kernel lock is held.
 	 *
 	 * Check permission before allocating space for a kernel module.
 	 * Return 0 if permission is granted.
 	 */
- 	int  (* create_module) (const char *name, size_t size);
+ 	int  (* create_module) (int kerror, const char *name, size_t size);
 
 	/**
 	 * init_module - check permission when initializing a module
@@ -1672,14 +1712,18 @@
 	 *
 	 * Check permission before initializing a kernel module.
 	 * Return 0 if permission is granted.
+	 * @mod has not yet been validated for whether entries are in-bounds, 
+	 * @mod->name should be good.
 	 */
- 	int  (* init_module) (struct module *mod);
+ 	int  (* init_module) (int kerror, struct module *mod);
 
 	/**
 	 * delete_module - check permission when removing a module
+	 * @kerror: error value of kernel checks
 	 * @mod: module being deleted
 	 *
 	 * called: sys_delete_module <kernel/module.c>
+ 	 * authoritative: yes
 	 *
 	 * lock:  The big kernel lock is held.
 	 * lock:  unload_lock is held.
@@ -1687,7 +1731,7 @@
 	 * Check permission before removing a kernel module.
 	 * Return 0 if permission is granted.
 	 */
- 	int  (* delete_module) (const struct module *mod);
+ 	int  (* delete_module) (int kerror, const struct module *mod);
 };
 
 /**
@@ -1696,6 +1740,7 @@
 struct ipc_security_ops {
 	/**
 	 * permission - check IPC permissions
+	 * @kerror: error value of kernel checks
 	 * @ipcp: IPC permission set
 	 * @flag: desired (requested) permission set
 	 *
@@ -1704,7 +1749,7 @@
 	 * Check user, group, and other permissions for access to ipc
 	 * resources.  Return 0 if permission is granted.  
 	 */
-	int (* permission) (struct kern_ipc_perm *ipcp, short flag);
+	int (* permission) (int kerror, struct kern_ipc_perm *ipcp, short flag);
 
 	/**
 	 * getinfo - check retrieval permission
@@ -2037,40 +2082,47 @@

 	/**
 	 * sethostname - check permission when setting the hostname
+	 * @kerror: error value of kernel checks
 	 * @hostname: new hostname
 	 *
 	 * called: sys_sethostname <kernel/sys.c>
+	 * authoritative: yes
 	 *
 	 * Check permission before the hostname is set to @hostname.
 	 * Return 0 if permission is granted.
 	 */
-	int (* sethostname) (char *hostname);
+	int (* sethostname) (int kerror, char *hostname);
 
 	/**
 	 * setdomainname - check permission when setting the domainname
+	 * @kerror: error value of kernel checks
 	 * @domainname: new domainname
 	 *
 	 * called: sys_setdomainname <kernel/sys.c>
+	 * authoritative: yes
 	 *
 	 * Check permission before the domainname is set to @domainname.
 	 * Return 0 if permission is granted.
 	 */
-	int (* setdomainname) (char *domainname);
+	int (* setdomainname) (int kerror, char *domainname);
 
 	/**
 	 * reboot - check permission when rebooting or enabling/disabling Ctrl-Alt-Del
+	 * @kerror: error value of kernel checks
 	 * @cmd: reboot command
 	 *
 	 * called: sys_reboot <kernel/sys.c>
+	 * authoritative: yes
 	 *
 	 * Check permission before rebooting or enabling/disabling the
 	 * Ctrl-Alt-Del key sequence.  Return 0 if permission is granted.
 	 * The values for @cmd are defined in the reboot(2) manual page.
 	 */
-	int (* reboot) (unsigned int cmd);
+	int (* reboot) (int kerror, unsigned int cmd);
 
 	/**
 	 * ioperm - check permission when setting port input/output permissions
+	 * @kerror: error value of kernel checks
 	 * @from: starting port address
 	 * @num:  number of bytes starting from @from
 	 * @turn_on: permissions value
@@ -2081,10 +2133,11 @@
 	 * for the process for @num bytes starting from the port address 
 	 * @from to the value @turn_on.  Return 0 if permission is granted.
 	 */
-	int (* ioperm) (unsigned long from, unsigned long num, int turn_on);
+	int (* ioperm) (int kerror, unsigned long from, unsigned long num, int turn_on);
 
 	/**
 	 * iopl - check permission when changing input/output privilege level
+	 * @kerror: error value of kernel checks
 	 * @old: old level
 	 * @level: new level
 	 *
@@ -2095,10 +2148,11 @@
 	 * current process from @old to @level.  Return 0 if permission is
 	 * granted.
 	 */
-	int (* iopl) (unsigned int old, unsigned int level);
+	int (* iopl) (int kerror, unsigned int old, unsigned int level);
 
 	/**
 	 * ptrace - check permission when tracing a process
+	 * @kerror: error value of kernel checks
 	 * @parent: task_struct structure for parent process 
 	 * @child:  task_struct structure for child process 
 	 *
@@ -2106,6 +2160,7 @@
 	 * called: sys_ptrace <arch/i386/kernel/ptrace.c>
 	 * called: sys_ptrace <arch/ia64/kernel/ptrace.c>
 	 * called: MAY_PTRACE <fs/proc/base.c>
+	 * authoritative: yes (but maybe bypassed)
 	 *
 	 * locks:  task_lock is called by ptrace_attach on the child task.
 	 *         The big kernel lock is held by sys_ptrace.
@@ -2118,7 +2173,7 @@
 	 * hooks of binprm_security_ops if the process is being traced
 	 * and its security attributes would be changed by the execve.
 	 */
-	int (* ptrace) (struct task_struct *parent, struct task_struct *child);
+	int (* ptrace) (int kerror, struct task_struct *parent, struct task_struct *child);
 
 	/**
 	 * capget - get the capability sets for a process
@@ -2144,12 +2199,14 @@
 
 	/**
 	 * capset_check - check permission when setting capability sets 
+	 * @kerror: error value of kernel checks
 	 * @target: task_struct structure for target process 
 	 * @effective:  effective capability set
 	 * @inheritable:  inheritable capability set
 	 * @permitted:  permitted capability set
 	 *
 	 * called: sys_capset <kernel/capability.c>
+	 * authoritative: yes
 	 *
 	 * locks:  The task_capability_lock is held by sys_capset.
 	 *         The tasklist_lock is read-locked by sys_capset if
@@ -2165,7 +2222,7 @@
 	 * a particular process group).  Hence, the capset_set hook may need 
 	 * to revalidate permission to the actual target process.
 	 */
-	int (*capset_check) (struct task_struct *target,
+	int (*capset_check) (int kerror, struct task_struct *target,
 			     kernel_cap_t *effective, 
 			     kernel_cap_t *inheritable,
 			     kernel_cap_t *permitted);
@@ -2199,28 +2256,32 @@
 
 	/**
 	 * acct - Check permission when enabling or disabling process accounting
+	 * @kerror: error value of kernel checks
 	 * @file: file structure for the accounting file (may be NULL)
 	 *
 	 * called: sys_acct <kernel/acct.c>
+	 * authoritative: yes
 	 *
 	 * Check permission before enabling or disabling process accounting.
 	 * If accounting is being enabled, then @file refers to the open
 	 * file used to store accounting records.  If accounting is being
 	 * disabled, then @file is NULL.  Return 0 if permission is granted.
 	 */
-	int (* acct) (struct file *file);
+	int (* acct) (int kerror, struct file *file);
 
 	/**
 	 * sysctl - Check permission when accessing a sysctl variable
+	 * @kerror: error value of kernel checks
 	 * @table: the ctl_table structure for the sysctl variable
 	 * @op:  the operation (001 = search, 002 = write, 004 = read)
 	 *
 	 * called: ctl_perm <kernel/sysctl.c>
+	 * authoritative: yes
 	 *
 	 * Check permission before accessing the @table sysctl variable
 	 * in the manner specified by @op.  Return 0 if permission is granted.
 	 */
-	int (* sysctl) (ctl_table * table, int op);
+	int (* sysctl) (int kerror, ctl_table * table, int op);
 
 	/**
 	 * capable - Check a particular capability for a process
===== security/capability_plug.c 1.69 vs edited =====
--- 1.69/security/capability_plug.c	Tue Oct 23 09:35:04 2001
+++ edited/security/capability_plug.c	Thu Oct 25 11:16:11 2001
@@ -21,29 +21,29 @@
 /* flag to keep track of how we were registered */
 static int secondary;
 
-static int cap_sethostname (char *hostname)
+static int cap_sethostname (int kerror, char *hostname)
 {
-	return 0;
+	return kerror;
 }
 
-static int cap_setdomainname (char *domainname)
+static int cap_setdomainname (int kerror, char *domainname)
 {
-	return 0;
+	return kerror;
 }
 
-static int cap_reboot (unsigned int cmd)
+static int cap_reboot (int kerror, unsigned int cmd)
 {
-	return 0;
+	return kerror;
 }
 
-static int cap_ioperm (unsigned long from, unsigned long num, int turn_on)
+static int cap_ioperm (int kerror, unsigned long from, unsigned long num, int turn_on)
 {
-	return 0;
+	return kerror;
 }
 
-static int cap_iopl (unsigned int old, unsigned int level)
+static int cap_iopl (int kerror, unsigned int old, unsigned int level)
 {
-	return 0;
+	return kerror;
 }
 
 static int cap_capable (struct task_struct *tsk, int cap)
@@ -109,10 +109,12 @@
 	return 0;
 }
 
-static int cap_ptrace (struct task_struct *parent, struct task_struct *child)
+static int cap_ptrace (int kerror, struct task_struct *parent, struct task_struct *child)
 {
+	if ( kerror )
+		return kerror;
 	/* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */
-	if (!cap_issubset (child->cap_permitted, current->cap_permitted) &&
+	else if (!cap_issubset (child->cap_permitted, current->cap_permitted) &&
 	    !capable (CAP_SYS_PTRACE))
 		return -EPERM;
 	else
@@ -129,11 +131,14 @@
 	return 0;
 }
 
-static int cap_capset_check (struct task_struct *target,
+static int cap_capset_check (int kerror, struct task_struct *target,
 			     kernel_cap_t * effective,
 			     kernel_cap_t * inheritable,
 			     kernel_cap_t * permitted)
 {
+	if ( kerror )
+		return kerror;
+
 	/* Derived from kernel/capability.c:sys_capset. */
 	/* verify restrictions on target's new Inheritable set */
 	if (!cap_issubset (*inheritable,
@@ -167,14 +172,14 @@
 	target->cap_permitted = *permitted;
 }
 
-static int cap_acct (struct file *file)
+static int cap_acct (int kerror, struct file *file)
 {
-	return 0;
+	return kerror;
 }
 
-static int cap_sysctl (ctl_table * table, int op)
+static int cap_sysctl (int kerror, ctl_table * table, int op)
 {
-	return 0;
+	return kerror;
 }
 
 static int cap_binprm_alloc_security (struct linux_binprm *bprm)
@@ -293,9 +298,9 @@
 	return 0;
 }
 
-static int cap_umount (struct vfsmount *mnt, int flags)
+static int cap_umount (int kerror, struct vfsmount *mnt, int flags)
 {
-	return 0;
+	return kerror;
 }
 
 static void cap_umount_close (struct vfsmount *mnt)
@@ -308,7 +313,7 @@
 	return;
 }
 
-static void cap_post_remount (struct vfsmount *mnt, unsigned long flags,
+static void cap_post_remount (int kerror, struct vfsmount *mnt, unsigned long flags,
 			      void *data)
 {
 	return;
@@ -319,7 +324,7 @@
 	return;
 }
 
-static void cap_post_addmount (struct vfsmount *mnt, struct nameidata *nd)
+static void cap_post_addmount (int kerror, struct vfsmount *mnt, struct nameidata *nd)
 {
 	return;
 }
@@ -340,7 +345,7 @@
 	return 0;
 }
 
-static void cap_inode_post_create (struct inode *inode, struct dentry *dentry,
+static void cap_inode_post_create (int kerror, struct inode *inode, struct dentry *dentry,
 				   int mask)
 {
 	return;
@@ -352,8 +357,8 @@
 	return 0;
 }
 
-static void cap_inode_post_link (struct dentry *old_dentry, struct inode *inode,
-				 struct dentry *new_dentry)
+static void cap_inode_post_link (int kerror, struct dentry *old_dentry, 
+		struct inode *inode, struct dentry *new_dentry)
 {
 	return;
 }
@@ -369,8 +374,8 @@
 	return 0;
 }
 
-static void cap_inode_post_symlink (struct inode *inode, struct dentry *dentry,
-				    const char *name)
+static void cap_inode_post_symlink (int kerror, struct inode *inode, 
+		struct dentry *dentry, const char *name)
 {
 	return;
 }
@@ -381,8 +386,8 @@
 	return 0;
 }
 
-static void cap_inode_post_mkdir (struct inode *inode, struct dentry *dentry,
-				  int mask)
+static void cap_inode_post_mkdir (int kerror, struct inode *inode, 
+		struct dentry *dentry, int mask)
 {
 	return;
 }
@@ -398,8 +403,8 @@
 	return 0;
 }
 
-static void cap_inode_post_mknod (struct inode *inode, struct dentry *dentry,
-				  int major, dev_t minor)
+static void cap_inode_post_mknod (int kerror, struct inode *inode, 
+		struct dentry *dentry, int major, dev_t minor)
 {
 	return;
 }
@@ -410,7 +415,7 @@
 	return 0;
 }
 
-static void cap_inode_post_rename (struct inode *old_inode,
+static void cap_inode_post_rename (int kerror, struct inode *old_inode,
 				   struct dentry *old_dentry,
 				   struct inode *new_inode,
 				   struct dentry *new_dentry)
@@ -429,9 +434,9 @@
 	return 0;
 }
 
-static int cap_inode_permission (struct inode *inode, int mask)
+static int cap_inode_permission (int kerror, struct inode *inode, int mask)
 {
-	return 0;
+	return kerror;
 }
 
 static int cap_inode_revalidate (struct dentry *inode)
@@ -439,9 +444,9 @@
 	return 0;
 }
 
-static int cap_inode_setattr (struct dentry *dentry, struct iattr *iattr)
+static int cap_inode_setattr (int kerror, struct dentry *dentry, struct iattr *iattr)
 {
-	return 0;
+	return kerror;
 }
 
 static int cap_inode_stat (struct inode *inode)
@@ -512,11 +517,11 @@
 	return 0;
 }
 
-static int cap_file_send_sigiotask (struct task_struct *tsk,
+static int cap_file_send_sigiotask (int kerror, struct task_struct *tsk,
 				    struct fown_struct *fown, int fd,
 				    int reason)
 {
-	return 0;
+	return kerror;
 }
 
 static int cap_file_receive (struct file *file)
@@ -654,25 +659,25 @@
 	return 0;
 }
 
-static int cap_task_setgroups (int gidsetsize, gid_t * grouplist)
+static int cap_task_setgroups (int kerror, int gidsetsize, gid_t * grouplist)
 {
-	return 0;
+	return kerror;
 }
 
-static int cap_task_setnice (struct task_struct *p, int nice)
+static int cap_task_setnice (int kerror, struct task_struct *p, int nice)
 {
-	return 0;
+	return kerror;
 }
 
-static int cap_task_setrlimit (unsigned int resource, struct rlimit *new_rlim)
+static int cap_task_setrlimit (int kerror, unsigned int resource, struct rlimit *new_rlim)
 {
-	return 0;
+	return kerror;
 }
 
-static int cap_task_setscheduler (struct task_struct *p, int policy,
+static int cap_task_setscheduler (int kerror, struct task_struct *p, int policy,
 				  struct sched_param *lp)
 {
-	return 0;
+	return kerror;
 }
 
 static int cap_task_getscheduler (struct task_struct *p)
@@ -685,9 +690,9 @@
 	return 0;
 }
 
-static int cap_task_kill (struct task_struct *p, struct siginfo *info, int sig)
+static int cap_task_kill (int kerror, struct task_struct *p, struct siginfo *info, int sig)
 {
-	return 0;
+	return kerror;
 }
 
 static int cap_task_prctl (int option, unsigned long arg2, unsigned long arg3,
@@ -914,24 +919,24 @@
 	return 0;
 }
 
-static int cap_module_create_module (const char *name_user, size_t size)
+static int cap_module_create_module (int kerror, const char *name_user, size_t size)
 {
-	return 0;
+	return kerror;
 }
 
-static int cap_module_init_module (struct module *mod_user)
+static int cap_module_init_module (int kerror, struct module *mod_user)
 {
-	return 0;
+	return kerror;
 }
 
-static int cap_module_delete_module (const struct module *mod)
+static int cap_module_delete_module (int kerror, const struct module *mod)
 {
-	return 0;
+	return kerror;
 }
 
-static int cap_ipc_permission (struct kern_ipc_perm *ipcp, short flag)
+static int cap_ipc_permission (int kerror, struct kern_ipc_perm *ipcp, short flag)
 {
-	return 0;
+	return kerror;
 }
 
 static int cap_ipc_getinfo (int id, int cmd)
===== security/dummy.c 1.7 vs edited =====
--- 1.7/security/dummy.c	Tue Oct 23 09:35:04 2001
+++ edited/security/dummy.c	Thu Oct 25 11:16:13 2001
@@ -19,34 +19,34 @@
 #include <linux/netfilter.h>
 #include <linux/netlink.h>
 
-static int dummy_sethostname (char *hostname)
+static int dummy_sethostname (int kerror, char *hostname)
 {
-	return 0;
+	return kerror;
 }
 
-static int dummy_setdomainname (char *domainname)
+static int dummy_setdomainname (int kerror, char *domainname)
 {
-	return 0;
+	return kerror;
 }
 
-static int dummy_reboot (unsigned int cmd)
+static int dummy_reboot (int kerror, unsigned int cmd)
 {
-	return 0;
+	return kerror;
 }
 
-static int dummy_ioperm (unsigned long from, unsigned long num, int turn_on)
+static int dummy_ioperm (int kerror, unsigned long from, unsigned long num, int turn_on)
 {
-	return 0;
+	return kerror;
 }
 
-static int dummy_iopl (unsigned int old, unsigned int level)
+static int dummy_iopl (int kerror, unsigned int old, unsigned int level)
 {
-	return 0;
+	return kerror;
 }
 
-static int dummy_ptrace (struct task_struct *parent, struct task_struct *child)
+static int dummy_ptrace (int kerror, struct task_struct *parent, struct task_struct *child)
 {
-	return 0;
+	return kerror;
 }
 
 static int dummy_capget (struct task_struct *target, kernel_cap_t * effective,
@@ -55,12 +55,12 @@
 	return 0;
 }
 
-static int dummy_capset_check (struct task_struct *target,
+static int dummy_capset_check (int kerror, struct task_struct *target,
 			       kernel_cap_t * effective,
 			       kernel_cap_t * inheritable,
 			       kernel_cap_t * permitted)
 {
-	return 0;
+	return kerror;
 }
 
 static void dummy_capset_set (struct task_struct *target,
@@ -71,9 +71,9 @@
 	return;
 }
 
-static int dummy_acct (struct file *file)
+static int dummy_acct (int kerror, struct file *file)
 {
-	return 0;
+	return kerror;
 }
 
 static int dummy_capable (struct task_struct *tsk, int cap)
@@ -86,9 +86,9 @@
 	return -EPERM;
 }
 
-static int dummy_sysctl (ctl_table * table, int op)
+static int dummy_sysctl (int kerror, ctl_table * table, int op)
 {
-	return 0;
+	return kerror;
 }
 
 static int dummy_sys_security (unsigned int id, unsigned int call,
@@ -194,9 +194,9 @@
 	return 0;
 }
 
-static int dummy_umount (struct vfsmount *mnt, int flags)
+static int dummy_umount (int kerror, struct vfsmount *mnt, int flags)
 {
-	return 0;
+	return kerror;
 }
 
 static void dummy_umount_close (struct vfsmount *mnt)
@@ -209,7 +209,7 @@
 	return;
 }
 
-static void dummy_post_remount (struct vfsmount *mnt, unsigned long flags,
+static void dummy_post_remount (int kerror, struct vfsmount *mnt, unsigned long flags,
 				void *data)
 {
 	return;
@@ -221,7 +221,7 @@
 	return;
 }
 
-static void dummy_post_addmount (struct vfsmount *mnt, struct nameidata *nd)
+static void dummy_post_addmount (int kerror, struct vfsmount *mnt, struct nameidata *nd)
 {
 	return;
 }
@@ -242,8 +242,8 @@
 	return 0;
 }
 
-static void dummy_inode_post_create (struct inode *inode, struct dentry *dentry,
-				     int mask)
+static void dummy_inode_post_create (int kerror, struct inode *inode, 
+		struct dentry *dentry, int mask)
 {
 	return;
 }
@@ -254,7 +254,7 @@
 	return 0;
 }
 
-static void dummy_inode_post_link (struct dentry *old_dentry,
+static void dummy_inode_post_link (int kerror, struct dentry *old_dentry,
 				   struct inode *inode,
 				   struct dentry *new_dentry)
 {
@@ -272,7 +272,7 @@
 	return 0;
 }
 
-static void dummy_inode_post_symlink (struct inode *inode,
+static void dummy_inode_post_symlink (int kerror, struct inode *inode,
 				      struct dentry *dentry, const char *name)
 {
 	return;
@@ -284,8 +284,8 @@
 	return 0;
 }
 
-static void dummy_inode_post_mkdir (struct inode *inode, struct dentry *dentry,
-				    int mask)
+static void dummy_inode_post_mkdir (int kerror, struct inode *inode, 
+		struct dentry *dentry, int mask)
 {
 	return;
 }
@@ -301,8 +301,8 @@
 	return 0;
 }
 
-static void dummy_inode_post_mknod (struct inode *inode, struct dentry *dentry,
-				    int major, dev_t minor)
+static void dummy_inode_post_mknod (int kerror, struct inode *inode, 
+		struct dentry *dentry, int major, dev_t minor)
 {
 	return;
 }
@@ -315,7 +315,7 @@
 	return 0;
 }
 
-static void dummy_inode_post_rename (struct inode *old_inode,
+static void dummy_inode_post_rename (int kerror, struct inode *old_inode,
 				     struct dentry *old_dentry,
 				     struct inode *new_inode,
 				     struct dentry *new_dentry)
@@ -334,9 +334,9 @@
 	return 0;
 }
 
-static int dummy_inode_permission (struct inode *inode, int mask)
+static int dummy_inode_permission (int kerror, struct inode *inode, int mask)
 {
-	return 0;
+	return kerror;
 }
 
 static int dummy_inode_revalidate (struct dentry *inode)
@@ -344,9 +344,9 @@
 	return 0;
 }
 
-static int dummy_inode_setattr (struct dentry *dentry, struct iattr *iattr)
+static int dummy_inode_setattr (int kerror, struct dentry *dentry, struct iattr *iattr)
 {
-	return 0;
+	return kerror;
 }
 
 static int dummy_inode_stat (struct inode *inode)
@@ -417,11 +417,11 @@
 	return 0;
 }
 
-static int dummy_file_send_sigiotask (struct task_struct *tsk,
+static int dummy_file_send_sigiotask (int kerror, struct task_struct *tsk,
 				      struct fown_struct *fown, int fd,
 				      int reason)
 {
-	return 0;
+	return kerror;
 }
 
 static int dummy_file_receive (struct file *file)
@@ -474,25 +474,25 @@
 	return 0;
 }
 
-static int dummy_task_setgroups (int gidsetsize, gid_t * grouplist)
+static int dummy_task_setgroups (int kerror, int gidsetsize, gid_t * grouplist)
 {
-	return 0;
+	return kerror;
 }
 
-static int dummy_task_setnice (struct task_struct *p, int nice)
+static int dummy_task_setnice (int kerror, struct task_struct *p, int nice)
 {
-	return 0;
+	return kerror;
 }
 
-static int dummy_task_setrlimit (unsigned int resource, struct rlimit *new_rlim)
+static int dummy_task_setrlimit (int kerror, unsigned int resource, struct rlimit *new_rlim)
 {
-	return 0;
+	return kerror;
 }
 
-static int dummy_task_setscheduler (struct task_struct *p, int policy,
+static int dummy_task_setscheduler (int kerror, struct task_struct *p, int policy,
 				    struct sched_param *lp)
 {
-	return 0;
+	return kerror;
 }
 
 static int dummy_task_getscheduler (struct task_struct *p)
@@ -505,10 +505,10 @@
 	return 0;
 }
 
-static int dummy_task_kill (struct task_struct *p, struct siginfo *info,
+static int dummy_task_kill (int kerror, struct task_struct *p, struct siginfo *info,
 			    int sig)
 {
-	return 0;
+	return kerror;
 }
 
 static int dummy_task_prctl (int option, unsigned long arg2, unsigned long arg3,
@@ -735,24 +735,24 @@
 	return 0;
 }
 
-static int dummy_module_create_module (const char *name_user, size_t size)
+static int dummy_module_create_module (int kerror, const char *name_user, size_t size)
 {
-	return 0;
+	return kerror;
 }
 
-static int dummy_module_init_module (struct module *mod_user)
+static int dummy_module_init_module (int kerror, struct module *mod_user)
 {
-	return 0;
+	return kerror;
 }
 
-static int dummy_module_delete_module (const struct module *mod)
+static int dummy_module_delete_module (int kerror, const struct module *mod)
 {
-	return 0;
+	return kerror;
 }
 
-static int dummy_ipc_permission (struct kern_ipc_perm *ipcp, short flag)
+static int dummy_ipc_permission (int kerror, struct kern_ipc_perm *ipcp, short flag)
 {
-	return 0;
+	return kerror;
 }
 
 static int dummy_ipc_getinfo (int id, int cmd)
===== ipc/util.c 1.4 vs edited =====
--- 1.4/ipc/util.c	Thu Aug 16 12:27:23 2001
+++ edited/ipc/util.c	Thu Oct 25 11:16:13 2001
@@ -252,6 +252,7 @@
 int ipcperms (struct kern_ipc_perm *ipcp, short flag)
 {	/* flag will most probably be 0 or S_...UGO from <linux/stat.h> */
 	int requested_mode, granted_mode;
+	int retval = 0;
 
 	requested_mode = (flag >> 6) | (flag >> 3) | flag;
 	granted_mode = ipcp->mode;
@@ -262,9 +263,9 @@
 	/* is there some bit set in requested_mode but not in granted_mode? */
 	if ((requested_mode & ~granted_mode & 0007) && 
 	    !capable(CAP_IPC_OWNER))
-		return -1;
+		retval = -EPERM;
 
-	return security_ops->ipc_ops->permission(ipcp, flag);
+	return security_ops->ipc_ops->permission(retval, ipcp, flag);
 }
 
 /*
===== arch/i386/kernel/ioport.c 1.6 vs edited =====
--- 1.6/arch/i386/kernel/ioport.c	Mon Jun 18 06:22:04 2001
+++ edited/arch/i386/kernel/ioport.c	Thu Oct 25 11:16:14 2001
@@ -57,17 +57,16 @@
 {
 	struct thread_struct * t = &current->thread;
 	struct tss_struct * tss = init_tss + smp_processor_id();
-	int retval;
+	int retval = 0;
 
 	if ((from + num <= from) || (from + num > IO_BITMAP_SIZE*32))
 		return -EINVAL;
 	if (turn_on && !capable(CAP_SYS_RAWIO))
-		return -EPERM;
+		retval = -EPERM;
 
-	retval = security_ops->ioperm(from, num, turn_on);
-	if (retval) {
+	retval = security_ops->ioperm(retval, from, num, turn_on);
+	if (retval)
 		return retval;
-	}
 
 	/*
 	 * If it's the first ioperm() call in this thread's lifetime, set the
@@ -111,19 +110,18 @@
 	struct pt_regs * regs = (struct pt_regs *) &unused;
 	unsigned int level = regs->ebx;
 	unsigned int old = (regs->eflags >> 12) & 3;
-	int retval;
+	int retval = 0;
 
 	if (level > 3)
 		return -EINVAL;
 	/* Trying to gain more privileges? */
 	if (level > old) {
 		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
+			retval = -EPERM;
 	}
-	retval = security_ops->iopl(old, level);
-	if (retval) {
+	retval = security_ops->iopl(retval, old, level);
+	if (retval)
 		return retval;
-	}
 
 	regs->eflags = (regs->eflags & 0xffffcfff) | (level << 12);
 	return 0;
===== arch/i386/kernel/ptrace.c 1.13 vs edited =====
--- 1.13/arch/i386/kernel/ptrace.c	Sun Sep 23 17:21:21 2001
+++ edited/arch/i386/kernel/ptrace.c	Thu Oct 25 11:16:15 2001
@@ -160,7 +160,7 @@
 		/* are we already being traced? */
 		if (current->ptrace & PT_PTRACED)
 			goto out;
-		ret = security_ops->ptrace(current->p_pptr, current);
+		ret = security_ops->ptrace(0, current->p_pptr, current);
 		if (ret)
 			goto out;
 		/* set the ptrace bit in the process flags. */
===== arch/ia64/ia32/sys_ia32.c 1.9 vs edited =====
--- 1.9/arch/ia64/ia32/sys_ia32.c	Thu Aug 16 12:27:22 2001
+++ edited/arch/ia64/ia32/sys_ia32.c	Thu Oct 25 11:16:16 2001
@@ -2586,7 +2586,7 @@
 	unsigned int old;
 	unsigned long addr;
 	mm_segment_t old_fs = get_fs ();
-	int retval;
+	int retval = 0;
 
 	if (level != 3)
 		return(-EINVAL);
@@ -2594,12 +2594,11 @@
 	asm volatile ("mov %0=ar.eflag ;;" : "=r"(old));
 	if (level > ((old >> 12) & 3)) {
 		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
+			retval = -EPERM;
 	}
-	retval = security_ops->iopl(old,level);
-	if (retval) {
+	retval = security_ops->iopl(retval, old, level);
+	if (retval)
 		return retval;
-	}
 
 	set_fs(KERNEL_DS);
 	fd = sys_open("/dev/mem", O_SYNC | O_RDWR, 0);
===== arch/ia64/kernel/ptrace.c 1.9 vs edited =====
--- 1.9/arch/ia64/kernel/ptrace.c	Sun Sep 23 17:21:21 2001
+++ edited/arch/ia64/kernel/ptrace.c	Thu Oct 25 11:16:17 2001
@@ -821,7 +821,7 @@
 		/* are we already being traced? */
 		if (current->ptrace & PT_PTRACED)
 			goto out;
-		ret = security_ops->ptrace(current->p_pptr, current);
+		ret = security_ops->ptrace(0, current->p_pptr, current);
 		if (ret)
 			goto out;
 		current->ptrace |= PT_PTRACED;