public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [patch 0/15] lsm stacking v0.3: intro
@ 2005-07-27 18:17 serue
  2005-07-27 18:19 ` [patch 1/15] lsm stacking v0.3: introduce securityfs serue
                   ` (2 more replies)
  0 siblings, 3 replies; 39+ messages in thread
From: serue @ 2005-07-27 18:17 UTC (permalink / raw)
  To: lkml
  Cc: Chris Wright, Stephen Smalley, James Morris, Andrew Morton,
	Michael Halcrow

Hi,

The set of patches to follow introduces support for stacking LSMs.  This
is its third posting to lkml.  I am sending it out in the hopes of
soliciting more widespread feedback and testing, with the obvious eventual
goal of mainline adoption.

Any feedback from people actually using this patch is appreciated.  Even
better would be posts of (stackable) LSMs for upstream inclusion :)

The patches mainly do the following:

   1. Introduce the stacker LSM.
   2. Change the kernel object void * security fields to be hlists,
      and introduce an api for modules to share these.
   3. Modify SELinux to make use of stacker.
   4. Modify seclvl to use stacker.

Motivation:

The purpose of these patches is to enable stacking multiple security
modules.  There are several cases where this would be very useful.  It
eases the testing of new modules with distro kernels, as it makes it
possible to stack new modules with selinux and capabilities -- for
instance if a user is running fedora.  Second, it enables running
selinux (or LIDS, etc) with integrity verification modules.  (Digsig is
an example of these, and within a few months hopefully the TPM-enabled
slim+evm modules, which verifies integrity of file contents and extended
attributes such as selinux contexts
(http://www.acsac.org/2004/workshop/David-Safford.pdf) will be released
for mainline inclusion).  Thirdly, there are systems where running
selinux is not practical for footprint reasons, and the security goals
are easily expressed as a very small module.  For instance, it might
be desirable to confine a web browser on a zaurus, or to implement a
site security policy on old hardware as per
http://mail.wirex.com/pipermail/linux-security-module/2005-May/6071.html

Performance impact of the actual stacker module is negligable.  The
security_{get,set,del,add}_value API does have a small performance
impact.  Please see
http://marc.theaimsgroup.com/?l=linux-security-module&m=111820455332752&w=2
and
http://marc.theaimsgroup.com/?l=linux-security-module&m=111824326500837&w=2
if interested in the performance results.  I am certainly interested in
ways to further speed up security_get_value.

This version adds support for safe unloading of LSMs.  This is documented
in the stacker-doc.patch.  Included below are performance results
comparing the last version of stacker to this version.

Tests run were dbench, kernbench, reaim, and tbench.  These were run
in the following configurations:
	16-way ppc with old patchset ("16-plain")
	16-way ppc with this patchset ("16-new")
	16-way ppc with this patchset, but without the
		security_{del,unlink}_value race fix ("16-test")
		(note - there may be a faster way to do this anyway)
	4-way P-III with old patchset ("4-plain")
	4-way P-III with this patchset ("4-new")
dbench and tbench were run 50 times each (48 for tbench for 16-new due to
mis-set timeout), kernbench and reaim 10 times.  The numbers here are
mean +/- 95% confidence half-interval.

Results:

dbench (throughput, larger is better):
	16-plain: 1560.825000 +/- 9.844956
	16-new:   1555.401800 +/- 4.083806        
	16-test:  1558.164400 +/- 4.685493
	4-plain:  351.299100 +/- 5.941376
	4-new:    361.487720 +/- 1.624589
	
tbench (throughput, larger is better)
	16-plain: 142.822420 +/- 2.504416
	16-new:   142.671510 +/- 3.149260
	16-test:  147.186280 +/- 3.548984
	4-plain:  37.011122 +/- 0.038450
	4-new:    37.014408 +/- 0.038272

kernbench (smaller is better):
	16-plain: 52.376000 +/- 0.108133
	16-new:   52.378000 +/- 0.119692
	16-test:  52.368000 +/- 0.173884
	4-plain:  91.739000 +/- 0.349240
	4-new:    91.437000 +/- 0.443560

reaim (number of clients versus jobs/minute (+/- CI, larger is better):
16-plain:
1 104040.000000 4614.800612
3 306000.000000 0.000000
5 480857.144000 26914.062669
7 673200.000000 37679.689215
9 878657.142000 45316.443392
11 977742.861000 36259.146697
13 1122364.287000 32138.790300
15 1233107.142000 76974.633465

16-new:
1 100542.857000 3296.286475
3 306000.000000 0.000000
5 495428.572000 21975.240148
7 673200.000000 37679.689215
9 813085.712000 39555.434680
11 961714.290000 0.000000
13 1065535.715000 53564.650500
15 1134750.000000 28842.503826

16-test:
1 104622.857000 7448.926210
3 306000.000000 0.000000
5 495428.572000 21975.240148
7 693600.000000 30765.337414
9 813085.712000 39555.434680
11 1025828.574000 59210.938611
13 1122364.287000 32138.790300
15 1163892.857000 37083.218881

4-plain:
1 45104.176000 1612.185481
3 126771.430000 3296.287229
5 124676.143000 4423.046551
7 154852.416000 4062.286334
9 148950.244000 2664.391611
11 164234.214000 1911.366919
13 161290.790000 4651.698507
15 165440.327000 1813.071866

4-new:
1 46068.131000 1161.957518
3 125022.858000 3021.097148
5 126014.348000 2531.399484
7 158797.437000 3438.066799
9 148186.835000 3186.764542
11 164234.214000 1911.366919
13 160272.056000 4139.820526
15 165748.837000 2045.298142

thanks,
-serge

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [patch 1/15] lsm stacking v0.3: introduce securityfs
  2005-07-27 18:17 [patch 0/15] lsm stacking v0.3: intro serue
@ 2005-07-27 18:19 ` serue
  2005-07-27 18:20   ` [patch 2/15] lsm stacking v0.3: add module * to security_ops serue
                     ` (13 more replies)
  2005-07-27 19:34 ` [patch 0/15] lsm stacking v0.3: intro James Morris
  2005-07-30  5:07 ` Tony Jones
  2 siblings, 14 replies; 39+ messages in thread
From: serue @ 2005-07-27 18:19 UTC (permalink / raw)
  To: lkml
  Cc: Chris Wright, Stephen Smalley, James Morris, Andrew Morton,
	Michael Halcrow, David Safford, Reiner Sailer, Gerrit Huizenga,
	Emily Ratliff

This patch from Greg KH is in -mm, and implements the securityfs which is
now used by stacker.

--
 include/linux/security.h |    5 
 security/Makefile        |    2 
 security/inode.c         |  347 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 353 insertions(+), 1 deletion(-)

Index: linux-2.6.13-rc3/security/Makefile
===================================================================
--- linux-2.6.13-rc3.orig/security/Makefile	2005-06-17 14:48:29.000000000 -0500
+++ linux-2.6.13-rc3/security/Makefile	2005-07-18 15:48:39.000000000 -0500
@@ -11,7 +11,7 @@ obj-y		+= commoncap.o
 endif
 
 # Object file lists
-obj-$(CONFIG_SECURITY)			+= security.o dummy.o
+obj-$(CONFIG_SECURITY)			+= security.o dummy.o inode.o
 # Must precede capability.o in order to stack properly.
 obj-$(CONFIG_SECURITY_SELINUX)		+= selinux/built-in.o
 obj-$(CONFIG_SECURITY_CAPABILITIES)	+= commoncap.o capability.o
Index: linux-2.6.13-rc3/security/inode.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.13-rc3/security/inode.c	2005-07-18 15:48:39.000000000 -0500
@@ -0,0 +1,347 @@
+/*
+ *  inode.c - securityfs
+ *
+ *  Copyright (C) 2005 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License version
+ *	2 as published by the Free Software Foundation.
+ *
+ *  Based on fs/debugfs/inode.c which had the following copyright notice:
+ *    Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
+ *    Copyright (C) 2004 IBM Inc.
+ */
+
+/* #define DEBUG */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/pagemap.h>
+#include <linux/init.h>
+#include <linux/namei.h>
+#include <linux/security.h>
+
+#define SECURITYFS_MAGIC	0x73636673
+
+static struct vfsmount *mount;
+static int mount_count;
+
+/*
+ * TODO:
+ *   I think I can get rid of these default_file_ops, but not quite sure...
+ */
+static ssize_t default_read_file(struct file *file, char __user *buf,
+				 size_t count, loff_t *ppos)
+{
+	return 0;
+}
+
+static ssize_t default_write_file(struct file *file, const char __user *buf,
+				   size_t count, loff_t *ppos)
+{
+	return count;
+}
+
+static int default_open(struct inode *inode, struct file *file)
+{
+	if (inode->u.generic_ip)
+		file->private_data = inode->u.generic_ip;
+
+	return 0;
+}
+
+static struct file_operations default_file_ops = {
+	.read =		default_read_file,
+	.write =	default_write_file,
+	.open =		default_open,
+};
+
+static struct inode *get_inode(struct super_block *sb, int mode, dev_t dev)
+{
+	struct inode *inode = new_inode(sb);
+
+	if (inode) {
+		inode->i_mode = mode;
+		inode->i_uid = 0;
+		inode->i_gid = 0;
+		inode->i_blksize = PAGE_CACHE_SIZE;
+		inode->i_blocks = 0;
+		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+		switch (mode & S_IFMT) {
+		default:
+			init_special_inode(inode, mode, dev);
+			break;
+		case S_IFREG:
+			inode->i_fop = &default_file_ops;
+			break;
+		case S_IFDIR:
+			inode->i_op = &simple_dir_inode_operations;
+			inode->i_fop = &simple_dir_operations;
+
+			/* directory inodes start off with i_nlink == 2 (for "." entry) */
+			inode->i_nlink++;
+			break;
+		}
+	}
+	return inode;
+}
+
+/* SMP-safe */
+static int mknod(struct inode *dir, struct dentry *dentry,
+			 int mode, dev_t dev)
+{
+	struct inode *inode;
+	int error = -EPERM;
+
+	if (dentry->d_inode)
+		return -EEXIST;
+
+	inode = get_inode(dir->i_sb, mode, dev);
+	if (inode) {
+		d_instantiate(dentry, inode);
+		dget(dentry);
+		error = 0;
+	}
+	return error;
+}
+
+static int mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+	int res;
+
+	mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
+	res = mknod(dir, dentry, mode, 0);
+	if (!res)
+		dir->i_nlink++;
+	return res;
+}
+
+static int create(struct inode *dir, struct dentry *dentry, int mode)
+{
+	mode = (mode & S_IALLUGO) | S_IFREG;
+	return mknod(dir, dentry, mode, 0);
+}
+
+static inline int positive(struct dentry *dentry)
+{
+	return dentry->d_inode && !d_unhashed(dentry);
+}
+
+static int fill_super(struct super_block *sb, void *data, int silent)
+{
+	static struct tree_descr files[] = {{""}};
+
+	return simple_fill_super(sb, SECURITYFS_MAGIC, files);
+}
+
+static struct super_block *get_sb(struct file_system_type *fs_type,
+				        int flags, const char *dev_name,
+					void *data)
+{
+	return get_sb_single(fs_type, flags, data, fill_super);
+}
+
+static struct file_system_type fs_type = {
+	.owner =	THIS_MODULE,
+	.name =		"securityfs",
+	.get_sb =	get_sb,
+	.kill_sb =	kill_litter_super,
+};
+
+static int create_by_name(const char *name, mode_t mode,
+			  struct dentry *parent,
+			  struct dentry **dentry)
+{
+	int error = 0;
+
+	*dentry = NULL;
+
+	/* If the parent is not specified, we create it in the root.
+	 * We need the root dentry to do this, which is in the super
+	 * block. A pointer to that is in the struct vfsmount that we
+	 * have around.
+	 */
+	if (!parent ) {
+		if (mount && mount->mnt_sb) {
+			parent = mount->mnt_sb->s_root;
+		}
+	}
+	if (!parent) {
+		pr_debug("securityfs: Ah! can not find a parent!\n");
+		return -EFAULT;
+	}
+
+	down(&parent->d_inode->i_sem);
+	*dentry = lookup_one_len(name, parent, strlen(name));
+	if (!IS_ERR(dentry)) {
+		if ((mode & S_IFMT) == S_IFDIR)
+			error = mkdir(parent->d_inode, *dentry, mode);
+		else
+			error = create(parent->d_inode, *dentry, mode);
+	} else
+		error = PTR_ERR(dentry);
+	up(&parent->d_inode->i_sem);
+
+	return error;
+}
+
+/**
+ * securityfs_create_file - create a file in the securityfs filesystem
+ *
+ * @name: a pointer to a string containing the name of the file to create.
+ * @mode: the permission that the file should have
+ * @parent: a pointer to the parent dentry for this file.  This should be a
+ *          directory dentry if set.  If this paramater is NULL, then the
+ *          file will be created in the root of the securityfs filesystem.
+ * @data: a pointer to something that the caller will want to get to later
+ *        on.  The inode.u.generic_ip pointer will point to this value on
+ *        the open() call.
+ * @fops: a pointer to a struct file_operations that should be used for
+ *        this file.
+ *
+ * This is the basic "create a file" function for securityfs.  It allows for a
+ * wide range of flexibility in createing a file, or a directory (if you
+ * want to create a directory, the securityfs_create_dir() function is
+ * recommended to be used instead.)
+ *
+ * This function will return a pointer to a dentry if it succeeds.  This
+ * pointer must be passed to the securityfs_remove() function when the file is
+ * to be removed (no automatic cleanup happens if your module is unloaded,
+ * you are responsible here.)  If an error occurs, NULL will be returned.
+ *
+ * If securityfs is not enabled in the kernel, the value -ENODEV will be
+ * returned.  It is not wise to check for this value, but rather, check for
+ * NULL or !NULL instead as to eliminate the need for #ifdef in the calling
+ * code.
+ */
+struct dentry *securityfs_create_file(const char *name, mode_t mode,
+				   struct dentry *parent, void *data,
+				   struct file_operations *fops)
+{
+	struct dentry *dentry = NULL;
+	int error;
+
+	pr_debug("securityfs: creating file '%s'\n",name);
+
+	error = simple_pin_fs("securityfs", &mount, &mount_count);
+	if (error) {
+		dentry = ERR_PTR(error);
+		goto exit;
+	}
+
+	error = create_by_name(name, mode, parent, &dentry);
+	if (error) {
+		dentry = ERR_PTR(error);
+		simple_release_fs(&mount, &mount_count);
+		goto exit;
+	}
+
+	if (dentry->d_inode) {
+		if (fops)
+			dentry->d_inode->i_fop = fops;
+		if (data)
+			dentry->d_inode->u.generic_ip = data;
+	}
+exit:
+	return dentry;
+}
+EXPORT_SYMBOL_GPL(securityfs_create_file);
+
+/**
+ * securityfs_create_dir - create a directory in the securityfs filesystem
+ *
+ * @name: a pointer to a string containing the name of the directory to
+ *        create.
+ * @parent: a pointer to the parent dentry for this file.  This should be a
+ *          directory dentry if set.  If this paramater is NULL, then the
+ *          directory will be created in the root of the securityfs filesystem.
+ *
+ * This function creates a directory in securityfs with the given name.
+ *
+ * This function will return a pointer to a dentry if it succeeds.  This
+ * pointer must be passed to the securityfs_remove() function when the file is
+ * to be removed (no automatic cleanup happens if your module is unloaded,
+ * you are responsible here.)  If an error occurs, NULL will be returned.
+ *
+ * If securityfs is not enabled in the kernel, the value -ENODEV will be
+ * returned.  It is not wise to check for this value, but rather, check for
+ * NULL or !NULL instead as to eliminate the need for #ifdef in the calling
+ * code.
+ */
+struct dentry *securityfs_create_dir(const char *name, struct dentry *parent)
+{
+	return securityfs_create_file(name,
+				      S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
+				      parent, NULL, NULL);
+}
+EXPORT_SYMBOL_GPL(securityfs_create_dir);
+
+/**
+ * securityfs_remove - removes a file or directory from the securityfs filesystem
+ *
+ * @dentry: a pointer to a the dentry of the file or directory to be
+ *          removed.
+ *
+ * This function removes a file or directory in securityfs that was previously
+ * created with a call to another securityfs function (like
+ * securityfs_create_file() or variants thereof.)
+ *
+ * This function is required to be called in order for the file to be
+ * removed, no automatic cleanup of files will happen when a module is
+ * removed, you are responsible here.
+ */
+void securityfs_remove(struct dentry *dentry)
+{
+	struct dentry *parent;
+
+	if (!dentry)
+		return;
+
+	parent = dentry->d_parent;
+	if (!parent || !parent->d_inode)
+		return;
+
+	down(&parent->d_inode->i_sem);
+	if (positive(dentry)) {
+		if (dentry->d_inode) {
+			if (S_ISDIR(dentry->d_inode->i_mode))
+				simple_rmdir(parent->d_inode, dentry);
+			else
+				simple_unlink(parent->d_inode, dentry);
+			dput(dentry);
+		}
+	}
+	up(&parent->d_inode->i_sem);
+	simple_release_fs(&mount, &mount_count);
+}
+EXPORT_SYMBOL_GPL(securityfs_remove);
+
+static decl_subsys(security, NULL, NULL);
+
+static int __init securityfs_init(void)
+{
+	int retval;
+
+	kset_set_kset_s(&security_subsys, kernel_subsys);
+	retval = subsystem_register(&security_subsys);
+	if (retval)
+		return retval;
+
+	retval = register_filesystem(&fs_type);
+	if (retval)
+		subsystem_unregister(&security_subsys);
+	return retval;
+}
+
+static void __exit securityfs_exit(void)
+{
+	simple_release_fs(&mount, &mount_count);
+	unregister_filesystem(&fs_type);
+	subsystem_unregister(&security_subsys);
+}
+
+core_initcall(securityfs_init);
+module_exit(securityfs_exit);
+MODULE_LICENSE("GPL");
+
Index: linux-2.6.13-rc3/include/linux/security.h
===================================================================
--- linux-2.6.13-rc3.orig/include/linux/security.h	2005-06-17 14:48:29.000000000 -0500
+++ linux-2.6.13-rc3/include/linux/security.h	2005-07-18 15:48:39.000000000 -0500
@@ -1983,6 +1983,11 @@ extern int register_security	(struct sec
 extern int unregister_security	(struct security_operations *ops);
 extern int mod_reg_security	(const char *name, struct security_operations *ops);
 extern int mod_unreg_security	(const char *name, struct security_operations *ops);
+extern struct dentry *securityfs_create_file(const char *name, mode_t mode,
+					     struct dentry *parent, void *data,
+					     struct file_operations *fops);
+extern struct dentry *securityfs_create_dir(const char *name, struct dentry *parent);
+extern void securityfs_remove(struct dentry *dentry);
 
 
 #else /* CONFIG_SECURITY */

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [patch 2/15] lsm stacking v0.3: add module * to security_ops
  2005-07-27 18:19 ` [patch 1/15] lsm stacking v0.3: introduce securityfs serue
@ 2005-07-27 18:20   ` serue
  2005-07-27 18:21   ` [patch 3/15] lsm stacking v0.3: don't default to dummy_##hook serue
                     ` (12 subsequent siblings)
  13 siblings, 0 replies; 39+ messages in thread
From: serue @ 2005-07-27 18:20 UTC (permalink / raw)
  To: lkml
  Cc: Chris Wright, Stephen Smalley, James Morris, Andrew Morton,
	Michael Halcrow, David Safford, Reiner Sailer, Gerrit Huizenga,
	Emily Ratliff

Add the owning module to the security_operations struct.  This will allow
stacker to module_get the LSM to prevent its premature unloading.

Signed-off-by: Serge Hallyn <serue@us.ibm.com>
--
 include/linux/security.h |    7 +++++++
 security/capability.c    |    1 +
 security/root_plug.c     |    2 ++
 security/seclvl.c        |    1 +
 security/selinux/hooks.c |    2 ++
 5 files changed, 13 insertions(+)

Index: linux-2.6.13-rc3/include/linux/security.h
===================================================================
--- linux-2.6.13-rc3.orig/include/linux/security.h	2005-07-18 15:49:52.000000000 -0500
+++ linux-2.6.13-rc3/include/linux/security.h	2005-07-18 15:51:36.000000000 -0500
@@ -32,6 +32,7 @@
 #include <linux/sched.h>
 
 struct ctl_table;
+struct module;
 
 /*
  * These functions are in security/capability.c and are used
@@ -94,6 +95,10 @@ struct swap_info_struct;
  *
  * Security hooks for program execution operations.
  *
+ *
+ * @owner:
+ *	Module owning this security_operations.  NULL if not a module.
+ *
  * @bprm_alloc_security:
  *	Allocate and attach a security structure to the @bprm->security field.
  *	The security field is initialized to NULL when the bprm structure is
@@ -1027,6 +1032,8 @@ struct swap_info_struct;
  * This is the main security structure.
  */
 struct security_operations {
+	struct module *owner;
+
 	int (*ptrace) (struct task_struct * parent, struct task_struct * child);
 	int (*capget) (struct task_struct * target,
 		       kernel_cap_t * effective,
Index: linux-2.6.13-rc3/security/capability.c
===================================================================
--- linux-2.6.13-rc3.orig/security/capability.c	2005-07-18 15:49:52.000000000 -0500
+++ linux-2.6.13-rc3/security/capability.c	2005-07-18 15:51:36.000000000 -0500
@@ -25,6 +25,7 @@
 #include <linux/moduleparam.h>
 
 static struct security_operations capability_ops = {
+	.owner =			THIS_MODULE,
 	.ptrace =			cap_ptrace,
 	.capget =			cap_capget,
 	.capset_check =			cap_capset_check,
Index: linux-2.6.13-rc3/security/root_plug.c
===================================================================
--- linux-2.6.13-rc3.orig/security/root_plug.c	2005-07-18 15:49:52.000000000 -0500
+++ linux-2.6.13-rc3/security/root_plug.c	2005-07-18 15:51:36.000000000 -0500
@@ -83,6 +83,8 @@ static int rootplug_bprm_check_security 
 }
 
 static struct security_operations rootplug_security_ops = {
+	.owner =			THIS_MODULE,
+
 	/* Use the capability functions for some of the hooks */
 	.ptrace =			cap_ptrace,
 	.capget =			cap_capget,
Index: linux-2.6.13-rc3/security/seclvl.c
===================================================================
--- linux-2.6.13-rc3.orig/security/seclvl.c	2005-07-18 15:49:52.000000000 -0500
+++ linux-2.6.13-rc3/security/seclvl.c	2005-07-18 15:51:36.000000000 -0500
@@ -591,6 +591,7 @@ static int seclvl_umount(struct vfsmount
 }
 
 static struct security_operations seclvl_ops = {
+	.owner = THIS_MODULE,
 	.ptrace = seclvl_ptrace,
 	.capable = seclvl_capable,
 	.inode_permission = seclvl_inode_permission,
Index: linux-2.6.13-rc3/security/selinux/hooks.c
===================================================================
--- linux-2.6.13-rc3.orig/security/selinux/hooks.c	2005-07-18 15:49:52.000000000 -0500
+++ linux-2.6.13-rc3/security/selinux/hooks.c	2005-07-18 15:51:36.000000000 -0500
@@ -4265,6 +4265,8 @@ static int selinux_setprocattr(struct ta
 }
 
 static struct security_operations selinux_ops = {
+	.owner =			THIS_MODULE,
+
 	.ptrace =			selinux_ptrace,
 	.capget =			selinux_capget,
 	.capset_check =			selinux_capset_check,

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [patch 3/15] lsm stacking v0.3: don't default to dummy_##hook
  2005-07-27 18:19 ` [patch 1/15] lsm stacking v0.3: introduce securityfs serue
  2005-07-27 18:20   ` [patch 2/15] lsm stacking v0.3: add module * to security_ops serue
@ 2005-07-27 18:21   ` serue
  2005-07-27 18:23   ` [patch 4/15] lsm stacking v0.3: swith ->security to hlist serue
                     ` (11 subsequent siblings)
  13 siblings, 0 replies; 39+ messages in thread
From: serue @ 2005-07-27 18:21 UTC (permalink / raw)
  To: lkml
  Cc: Chris Wright, Stephen Smalley, James Morris, Andrew Morton,
	Michael Halcrow, David Safford, Reiner Sailer, Gerrit Huizenga,
	Emily Ratliff

When stacking multiple LSMs, we do not want hooks which are undefined to
be substituted with the dummy_##hook.

Signed-off-by: Serge Hallyn <serue@us.ibm.com>
--
 security.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

Index: linux-2.6.13-rc3/security/security.c
===================================================================
--- linux-2.6.13-rc3.orig/security/security.c	2005-07-18 15:49:52.000000000 -0500
+++ linux-2.6.13-rc3/security/security.c	2005-07-18 15:51:40.000000000 -0500
@@ -81,15 +81,15 @@ int __init security_init(void)
  */
 int register_security(struct security_operations *ops)
 {
+	if (security_ops != &dummy_security_ops)
+		return -EAGAIN;
+
 	if (verify(ops)) {
 		printk(KERN_DEBUG "%s could not verify "
 		       "security_operations structure.\n", __FUNCTION__);
 		return -EINVAL;
 	}
 
-	if (security_ops != &dummy_security_ops)
-		return -EAGAIN;
-
 	security_ops = ops;
 
 	return 0;
@@ -134,9 +134,9 @@ int unregister_security(struct security_
  */
 int mod_reg_security(const char *name, struct security_operations *ops)
 {
-	if (verify(ops)) {
-		printk(KERN_INFO "%s could not verify "
-		       "security operations.\n", __FUNCTION__);
+	if (!ops) {
+		printk(KERN_INFO "%s received NULL security operations",
+						       __FUNCTION__);
 		return -EINVAL;
 	}
 

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [patch 4/15] lsm stacking v0.3: swith ->security to hlist
  2005-07-27 18:19 ` [patch 1/15] lsm stacking v0.3: introduce securityfs serue
  2005-07-27 18:20   ` [patch 2/15] lsm stacking v0.3: add module * to security_ops serue
  2005-07-27 18:21   ` [patch 3/15] lsm stacking v0.3: don't default to dummy_##hook serue
@ 2005-07-27 18:23   ` serue
  2005-07-27 18:24   ` [patch 5/15] lsm stacking v0.3: introduce security_*_value API serue
                     ` (10 subsequent siblings)
  13 siblings, 0 replies; 39+ messages in thread
From: serue @ 2005-07-27 18:23 UTC (permalink / raw)
  To: lkml
  Cc: Chris Wright, Stephen Smalley, James Morris, Andrew Morton,
	Michael Halcrow, David Safford, Reiner Sailer, Gerrit Huizenga,
	Emily Ratliff

Replace kernel object ->security void*'s with hlists.  This will permit
multiple LSMs to each store information under one kernel object.

Signed-off-by: Serge Hallyn <serue@us.ibm.com>
 fs/compat.c             |    4 ++--
 fs/exec.c               |    4 ++--
 fs/inode.c              |    2 +-
 include/linux/binfmts.h |    2 +-
 include/linux/fs.h      |    8 ++++----
 include/linux/ipc.h     |    3 ++-
 include/linux/msg.h     |    2 +-
 include/linux/sched.h   |    2 +-
 include/net/sock.h      |    2 +-
 ipc/msg.c               |    2 +-
 ipc/msgutil.c           |    2 +-
 ipc/sem.c               |    2 +-
 ipc/shm.c               |    2 +-
 kernel/fork.c           |    2 +-
 14 files changed, 20 insertions(+), 19 deletions(-)

Index: linux-2.6.13-rc3/fs/compat.c
===================================================================
--- linux-2.6.13-rc3.orig/fs/compat.c	2005-07-18 15:49:49.000000000 -0500
+++ linux-2.6.13-rc3/fs/compat.c	2005-07-18 15:51:45.000000000 -0500
@@ -1523,6 +1523,7 @@ int compat_do_execve(char * filename,
 	bprm->file = file;
 	bprm->filename = filename;
 	bprm->interp = filename;
+	INIT_HLIST_HEAD(&bprm->security);
 	bprm->mm = mm_alloc();
 	retval = -ENOMEM;
 	if (!bprm->mm)
@@ -1579,8 +1580,7 @@ out:
 			__free_page(page);
 	}
 
-	if (bprm->security)
-		security_bprm_free(bprm);
+	security_bprm_free(bprm);
 
 out_mm:
 	if (bprm->mm)
Index: linux-2.6.13-rc3/fs/exec.c
===================================================================
--- linux-2.6.13-rc3.orig/fs/exec.c	2005-07-18 15:49:49.000000000 -0500
+++ linux-2.6.13-rc3/fs/exec.c	2005-07-18 15:51:45.000000000 -0500
@@ -1166,6 +1166,7 @@ int do_execve(char * filename,
 	bprm->file = file;
 	bprm->filename = filename;
 	bprm->interp = filename;
+	INIT_HLIST_HEAD(&bprm->security);
 	bprm->mm = mm_alloc();
 	retval = -ENOMEM;
 	if (!bprm->mm)
@@ -1224,8 +1225,7 @@ out:
 			__free_page(page);
 	}
 
-	if (bprm->security)
-		security_bprm_free(bprm);
+	security_bprm_free(bprm);
 
 out_mm:
 	if (bprm->mm)
Index: linux-2.6.13-rc3/fs/inode.c
===================================================================
--- linux-2.6.13-rc3.orig/fs/inode.c	2005-07-18 15:49:49.000000000 -0500
+++ linux-2.6.13-rc3/fs/inode.c	2005-07-18 15:51:45.000000000 -0500
@@ -133,7 +133,7 @@ static struct inode *alloc_inode(struct 
 		inode->i_bdev = NULL;
 		inode->i_cdev = NULL;
 		inode->i_rdev = 0;
-		inode->i_security = NULL;
+		INIT_HLIST_HEAD(&inode->i_security);
 		inode->dirtied_when = 0;
 		if (security_inode_alloc(inode)) {
 			if (inode->i_sb->s_op->destroy_inode)
Index: linux-2.6.13-rc3/include/linux/binfmts.h
===================================================================
--- linux-2.6.13-rc3.orig/include/linux/binfmts.h	2005-07-18 15:49:49.000000000 -0500
+++ linux-2.6.13-rc3/include/linux/binfmts.h	2005-07-18 15:51:45.000000000 -0500
@@ -29,7 +29,7 @@ struct linux_binprm{
 	struct file * file;
 	int e_uid, e_gid;
 	kernel_cap_t cap_inheritable, cap_permitted, cap_effective;
-	void *security;
+	struct hlist_head security;
 	int argc, envc;
 	char * filename;	/* Name of binary as seen by procps */
 	char * interp;		/* Name of the binary really executed. Most
Index: linux-2.6.13-rc3/include/linux/fs.h
===================================================================
--- linux-2.6.13-rc3.orig/include/linux/fs.h	2005-07-18 15:49:49.000000000 -0500
+++ linux-2.6.13-rc3/include/linux/fs.h	2005-07-18 15:51:45.000000000 -0500
@@ -485,7 +485,7 @@ struct inode {
 	unsigned int		i_flags;
 
 	atomic_t		i_writecount;
-	void			*i_security;
+	struct hlist_head	i_security;
 	union {
 		void		*generic_ip;
 	} u;
@@ -559,7 +559,7 @@ struct fown_struct {
 	rwlock_t lock;          /* protects pid, uid, euid fields */
 	int pid;		/* pid or -pgrp where SIGIO should be sent */
 	uid_t uid, euid;	/* uid/euid of process setting the owner */
-	void *security;
+	struct hlist_head security;
 	int signum;		/* posix.1b rt signal to be delivered on IO */
 };
 
@@ -596,7 +596,7 @@ struct file {
 
 	size_t			f_maxcount;
 	unsigned long		f_version;
-	void			*f_security;
+	struct hlist_head	f_security;
 
 	/* needed for tty driver, and maybe others */
 	void			*private_data;
@@ -783,7 +783,7 @@ struct super_block {
 	int			s_syncing;
 	int			s_need_sync_fs;
 	atomic_t		s_active;
-	void                    *s_security;
+ 	struct hlist_head	s_security;
 	struct xattr_handler	**s_xattr;
 
 	struct list_head	s_inodes;	/* all inodes */
Index: linux-2.6.13-rc3/include/linux/ipc.h
===================================================================
--- linux-2.6.13-rc3.orig/include/linux/ipc.h	2005-07-18 15:49:49.000000000 -0500
+++ linux-2.6.13-rc3/include/linux/ipc.h	2005-07-18 15:51:45.000000000 -0500
@@ -2,6 +2,7 @@
 #define _LINUX_IPC_H
 
 #include <linux/types.h>
+#include <linux/list.h>
 
 #define IPC_PRIVATE ((__kernel_key_t) 0)  
 
@@ -65,7 +66,7 @@ struct kern_ipc_perm
 	gid_t		cgid;
 	mode_t		mode; 
 	unsigned long	seq;
-	void		*security;
+	struct hlist_head security;
 };
 
 #endif /* __KERNEL__ */
Index: linux-2.6.13-rc3/include/linux/msg.h
===================================================================
--- linux-2.6.13-rc3.orig/include/linux/msg.h	2005-07-18 15:49:49.000000000 -0500
+++ linux-2.6.13-rc3/include/linux/msg.h	2005-07-18 15:51:45.000000000 -0500
@@ -70,7 +70,7 @@ struct msg_msg {
 	long  m_type;          
 	int m_ts;           /* message text size */
 	struct msg_msgseg* next;
-	void *security;
+	struct hlist_head security;
 	/* the actual message follows immediately */
 };
 
Index: linux-2.6.13-rc3/include/linux/sched.h
===================================================================
--- linux-2.6.13-rc3.orig/include/linux/sched.h	2005-07-18 15:49:49.000000000 -0500
+++ linux-2.6.13-rc3/include/linux/sched.h	2005-07-18 15:51:45.000000000 -0500
@@ -721,7 +721,7 @@ struct task_struct {
 	void *notifier_data;
 	sigset_t *notifier_mask;
 	
-	void *security;
+	struct hlist_head security;
 	struct audit_context *audit_context;
 	seccomp_t seccomp;
 
Index: linux-2.6.13-rc3/include/net/sock.h
===================================================================
--- linux-2.6.13-rc3.orig/include/net/sock.h	2005-07-18 15:49:49.000000000 -0500
+++ linux-2.6.13-rc3/include/net/sock.h	2005-07-18 15:51:45.000000000 -0500
@@ -240,7 +240,7 @@ struct sock {
 	struct sk_buff		*sk_send_head;
 	__u32			sk_sndmsg_off;
 	int			sk_write_pending;
-	void			*sk_security;
+	struct hlist_head	sk_security;
 	void			(*sk_state_change)(struct sock *sk);
 	void			(*sk_data_ready)(struct sock *sk, int bytes);
 	void			(*sk_write_space)(struct sock *sk);
Index: linux-2.6.13-rc3/ipc/msg.c
===================================================================
--- linux-2.6.13-rc3.orig/ipc/msg.c	2005-07-18 15:49:49.000000000 -0500
+++ linux-2.6.13-rc3/ipc/msg.c	2005-07-18 15:51:45.000000000 -0500
@@ -99,7 +99,7 @@ static int newque (key_t key, int msgflg
 	msq->q_perm.mode = (msgflg & S_IRWXUGO);
 	msq->q_perm.key = key;
 
-	msq->q_perm.security = NULL;
+	INIT_HLIST_HEAD(&msq->q_perm.security);
 	retval = security_msg_queue_alloc(msq);
 	if (retval) {
 		ipc_rcu_putref(msq);
Index: linux-2.6.13-rc3/ipc/msgutil.c
===================================================================
--- linux-2.6.13-rc3.orig/ipc/msgutil.c	2005-07-18 15:49:49.000000000 -0500
+++ linux-2.6.13-rc3/ipc/msgutil.c	2005-07-18 15:51:45.000000000 -0500
@@ -41,7 +41,7 @@ struct msg_msg *load_msg(const void __us
 		return ERR_PTR(-ENOMEM);
 
 	msg->next = NULL;
-	msg->security = NULL;
+	INIT_HLIST_HEAD(&msg->security);
 
 	if (copy_from_user(msg + 1, src, alen)) {
 		err = -EFAULT;
Index: linux-2.6.13-rc3/ipc/sem.c
===================================================================
--- linux-2.6.13-rc3.orig/ipc/sem.c	2005-07-18 15:49:49.000000000 -0500
+++ linux-2.6.13-rc3/ipc/sem.c	2005-07-18 15:51:45.000000000 -0500
@@ -178,7 +178,7 @@ static int newary (key_t key, int nsems,
 	sma->sem_perm.mode = (semflg & S_IRWXUGO);
 	sma->sem_perm.key = key;
 
-	sma->sem_perm.security = NULL;
+	INIT_HLIST_HEAD(&sma->sem_perm.security);
 	retval = security_sem_alloc(sma);
 	if (retval) {
 		ipc_rcu_putref(sma);
Index: linux-2.6.13-rc3/ipc/shm.c
===================================================================
--- linux-2.6.13-rc3.orig/ipc/shm.c	2005-07-18 15:49:49.000000000 -0500
+++ linux-2.6.13-rc3/ipc/shm.c	2005-07-18 15:51:45.000000000 -0500
@@ -199,7 +199,7 @@ static int newseg (key_t key, int shmflg
 	shp->shm_flags = (shmflg & S_IRWXUGO);
 	shp->mlock_user = NULL;
 
-	shp->shm_perm.security = NULL;
+	INIT_HLIST_HEAD(&shp->shm_perm.security);
 	error = security_shm_alloc(shp);
 	if (error) {
 		ipc_rcu_putref(shp);
Index: linux-2.6.13-rc3/kernel/fork.c
===================================================================
--- linux-2.6.13-rc3.orig/kernel/fork.c	2005-07-18 15:49:49.000000000 -0500
+++ linux-2.6.13-rc3/kernel/fork.c	2005-07-18 15:51:45.000000000 -0500
@@ -941,7 +941,7 @@ static task_t *copy_process(unsigned lon
 
 	p->lock_depth = -1;		/* -1 = no lock */
 	do_posix_clock_monotonic_gettime(&p->start_time);
-	p->security = NULL;
+	INIT_HLIST_HEAD(&p->security);
 	p->io_context = NULL;
 	p->io_wait = NULL;
 	p->audit_context = NULL;

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [patch 5/15] lsm stacking v0.3: introduce security_*_value API
  2005-07-27 18:19 ` [patch 1/15] lsm stacking v0.3: introduce securityfs serue
                     ` (2 preceding siblings ...)
  2005-07-27 18:23   ` [patch 4/15] lsm stacking v0.3: swith ->security to hlist serue
@ 2005-07-27 18:24   ` serue
  2005-07-27 18:24   ` [patch 6/15] lsm stacking v0.3: stacker documentation serue
                     ` (9 subsequent siblings)
  13 siblings, 0 replies; 39+ messages in thread
From: serue @ 2005-07-27 18:24 UTC (permalink / raw)
  To: lkml
  Cc: Chris Wright, Stephen Smalley, James Morris, Andrew Morton,
	Michael Halcrow, David Safford, Reiner Sailer, Gerrit Huizenga,
	Emily Ratliff

Define the functions to be used by LSMs to add, retrieve, and remove
elements to the kernel object ->security hlists.

Changelog:

	[July 26] Fixed prototypes which did not specify fastcall.

	[July 26] Added security_unlink_value, for use by modules
		to free data when they are unloaded, and
		security_disown_value, which is used when a module
		has not freed it's object->security data when object
		is being freed.

Signed-off-by: Serge Hallyn <serue@us.ibm.com>
 include/linux/security-stack.h |   25 +++++++
 include/linux/security.h       |   32 ++++++++++
 security/security.c            |  130 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 187 insertions(+)

Index: linux-2.6.13-rc3/include/linux/security-stack.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.13-rc3/include/linux/security-stack.h	2005-07-25 14:50:44.000000000 -0500
@@ -0,0 +1,25 @@
+/*
+ * security-stack.h
+ *
+ * Contains function prototypes or inline definitions for the
+ * function which manipulate kernel object security annotations.
+ *
+ * If stacker is compiled in, then we use the full functions as
+ * defined in security/security.c.  Otherwise we use the #defines
+ * here.
+ */
+
+extern fastcall struct security_list *security_get_value(
+			struct hlist_head *head,
+			int security_id);
+
+extern fastcall struct security_list *security_set_value(
+			struct hlist_head *head,
+			int security_id, struct security_list *obj_node);
+extern fastcall struct security_list *security_add_value(
+			struct hlist_head *head,
+			int security_id, struct security_list *obj_node);
+extern int security_unlink_value(struct hlist_node *n);
+extern fastcall struct security_list *security_del_value(
+			struct hlist_head *head,
+			int security_id);
Index: linux-2.6.13-rc3/include/linux/security.h
===================================================================
--- linux-2.6.13-rc3.orig/include/linux/security.h	2005-07-25 14:40:42.000000000 -0500
+++ linux-2.6.13-rc3/include/linux/security.h	2005-07-25 14:55:20.000000000 -0500
@@ -35,6 +35,38 @@ struct ctl_table;
 struct module;
 
 /*
+ * structure to be embedded at top of each LSM's security
+ * objects.
+ */
+struct security_list {
+	struct hlist_node list;
+	int security_id;
+};
+
+
+/*
+ * These #defines present more convenient interfaces to
+ * LSMs for using the security{g,d,s}et_value functions.
+ */
+#define security_get_value_type(head, id, type) ( { \
+	struct security_list *v = security_get_value((head), id); \
+	v ? hlist_entry(v, type, lsm_list) : NULL; } )
+
+#define security_set_value_type(head, id, value) \
+	security_set_value((head), id, &(value)->lsm_list);
+
+#define security_add_value_type(head, id, value) \
+	security_add_value((head), id, &(value)->lsm_list);
+
+#define security_del_value_type(head, id, type) ( { \
+	struct security_list *v; \
+	v = security_del_value((head), id); \
+	v ? hlist_entry(v, type, lsm_list) : NULL; } )
+
+/* security_disown_value is really only to be used by stacker */
+extern void security_disown_value(struct hlist_head *);
+
+/*
  * These functions are in security/capability.c and are used
  * as the default capabilities functions
  */
Index: linux-2.6.13-rc3/security/security.c
===================================================================
--- linux-2.6.13-rc3.orig/security/security.c	2005-07-25 14:40:42.000000000 -0500
+++ linux-2.6.13-rc3/security/security.c	2005-07-25 14:50:34.000000000 -0500
@@ -20,6 +20,136 @@
 
 #define SECURITY_FRAMEWORK_VERSION	"1.0.0"
 
+fastcall struct security_list *
+security_get_value(struct hlist_head *head, int security_id)
+{
+	struct security_list *e, *ret = NULL;
+	struct hlist_node *tmp;
+
+	rcu_read_lock();
+	for (tmp = head->first; tmp;
+			 tmp = rcu_dereference(tmp->next)) {
+		e = hlist_entry(tmp, struct security_list, list);
+		if (e->security_id == security_id) {
+			ret = e;
+			goto out;
+		}
+	}
+
+out:
+	rcu_read_unlock();
+	return ret;
+}
+
+/*
+ * Only to be called from security_*_alloc hooks, so there is
+ * no locking as it is naturally serialized.
+ */
+fastcall void
+security_set_value(struct hlist_head *head, int security_id,
+	struct security_list *obj_node)
+{
+
+	obj_node->security_id = security_id;
+	hlist_add_head(&obj_node->list, head);
+}
+
+static DEFINE_SPINLOCK(stacker_value_spinlock);
+
+/*
+ * Used outside of security_*_alloc hooks, so we need to
+ * lock.  Hopefully this won't be used much, so we use a
+ * spinlock for now.
+ */
+fastcall void
+security_add_value(struct hlist_head *head, int security_id,
+	struct security_list *obj_node)
+{
+
+	spin_lock(&stacker_value_spinlock);
+	obj_node->security_id = security_id;
+	hlist_add_head_rcu(&obj_node->list, head);
+	spin_unlock(&stacker_value_spinlock);
+}
+
+/*
+ * Unlink a security value from object->security, at a time other
+ * than when the object is being destroyed.  Note that you MUST
+ * wait a full rcu cycle before deleting the object.  If you are
+ * deleting a lot of objects (ie when unloading an LSM), then you
+ * likely will want to build a list of objects to be deleted as
+ * you remove them using this function, wait an rcu cycle, and then
+ * delete all the objects in your list.
+ * NOTE you obviously can't use the .next pointer for the to-be-
+ * deleted list, but you should be able to use the .prev pointer.
+ *
+ * XXX TODO - switch this to take a type, and deref
+ * obj->lsm_list.list here.
+ */
+int security_unlink_value(struct hlist_node *n)
+{
+	int ret = 0;
+	spin_lock(&stacker_value_spinlock);
+	if (n->pprev == LIST_POISON2) {
+		ret = 1;
+		goto out;
+	}
+	hlist_del_rcu(n);
+
+out:
+	spin_unlock(&stacker_value_spinlock);
+	return ret;
+}
+
+/*
+ * When a security module is unloaded, it is first removed from
+ * the list of callable modules
+ * (echo -n lsmname > /security/stacker/unload).  Then at some
+ * later time the module's exit function will be called, which
+ * may try to free memory attached to kernel objects.  The kernel
+ * objects may be deleted during this time.  If that happens,
+ * then stacker will call security_disown_value so that the
+ * in-limbo LSM's data can be safely deleted.  The LSM calls
+ * security_unlink_value() to remove the item from the list.
+ * security_unlink_value() will check whether
+ * lsm_list.pprev == LIST_POISON2.  If not, then it removes the
+ * item from the (valid) list, else it simply returns, as there
+ * is no more list.
+ */
+void security_disown_value(struct hlist_head *h)
+{
+	spin_lock(&stacker_value_spinlock);
+	if (h->first)
+		h->first->pprev = LIST_POISON2;
+	h->first = NULL;
+	spin_unlock(&stacker_value_spinlock);
+}
+
+/* No locking needed: only called during object_destroy */
+fastcall struct security_list *
+security_del_value(struct hlist_head *head, int security_id)
+{
+	struct security_list *e;
+	struct hlist_node *tmp;
+
+	for (tmp = head->first; tmp; tmp = tmp->next) {
+		e = hlist_entry(tmp, struct security_list, list);
+		if (e->security_id == security_id) {
+			hlist_del(&e->list);
+			return e;
+		}
+	}
+
+	return NULL;
+}
+
+EXPORT_SYMBOL_GPL(security_get_value);
+EXPORT_SYMBOL_GPL(security_set_value);
+EXPORT_SYMBOL_GPL(security_add_value);
+EXPORT_SYMBOL_GPL(security_unlink_value);
+EXPORT_SYMBOL_GPL(security_disown_value);
+EXPORT_SYMBOL_GPL(security_del_value);
+
 /* things that live in dummy.c */
 extern struct security_operations dummy_security_ops;
 extern void security_fixup_ops(struct security_operations *ops);

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [patch 6/15] lsm stacking v0.3: stacker documentation
  2005-07-27 18:19 ` [patch 1/15] lsm stacking v0.3: introduce securityfs serue
                     ` (3 preceding siblings ...)
  2005-07-27 18:24   ` [patch 5/15] lsm stacking v0.3: introduce security_*_value API serue
@ 2005-07-27 18:24   ` serue
  2005-07-27 18:24   ` [patch 7/15] lsm stacking v0.3: actual stacker module serue
                     ` (8 subsequent siblings)
  13 siblings, 0 replies; 39+ messages in thread
From: serue @ 2005-07-27 18:24 UTC (permalink / raw)
  To: lkml
  Cc: Chris Wright, Stephen Smalley, James Morris, Andrew Morton,
	Michael Halcrow, David Safford, Reiner Sailer, Gerrit Huizenga,
	Emily Ratliff

Add documentation about stacker and its usage.

Changelog:

	[Jul 26]: Update with information regarding safe LSM unloading,
		and added the stacker locking rationale.

Signed-off-by: Serge Hallyn <serue@us.ibm.com>
 LSM-stacker-locking.txt |   77 ++++++++++++++++++++++
 LSM-stacking.txt        |  166 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 243 insertions(+)

Index: linux-2.6.13-rc3/Documentation/LSM-stacking.txt
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.13-rc3/Documentation/LSM-stacking.txt	2005-07-27 16:19:06.000000000 -0500
@@ -0,0 +1,166 @@
+------------
+LSM stacking
+------------
+
+This document consists of two parts.  The first describes the stacker LSM.
+The second describes what is needed from an LSM in order to permit it to
+stack with other LSMs.
+
+--------------------------------------------------------
+stacker LSM - enable stacking multiple security modules.
+--------------------------------------------------------
+
+Stacker is compiled into the kernel.  Find the "Stacker" option under
+the Security submenu, and say 'Y'.  Now, any security modules which are
+loaded or compiled into the kernel will be managed by stacker.
+
+You may interact with stacker through its securityfs interface, located
+under /sys/kernel/security/stacker/ (henceforth simply /security/stacker).
+This consists of the following files:
+
+/security/stacker/lockdown:
+Once you write to this file, you will no longer be able to load
+LSMs.
+
+/security/stacker/list_modules:
+Reading this file will show which LSMs are being stacked.
+
+/security/stacker/stop_responding:
+Unregisters the /security/stacker directory, so that you can no longer
+interact with stacker.
+
+/security/stacker/unload:
+Disables the specified module.  The module will actually still be
+loaded, but will no longer be asked to mediate accesses or update
+security information.  Stacker will release it's refcount on the
+module, so that after this you are able to rmmod the module.  By
+separating unload into these two steps, no cpu should be executing
+any of the module's hooks by the time you rmmod, so that the module
+can be safely freed.
+
+---------------------------------------------
+Readying an LSM for stacking with other LSMs.
+---------------------------------------------
+
+LSM stacking is not a simple matter.  You must consider the cumulative
+behavior of all stacked LSMs very carefully, as well as certain subtle
+effects of the LSM implementation.  Please do not try to stack arbitrary
+modules!  For instance, while SELinux and cap-stack should always be
+used together, SELinux cannot be combined with the original capability
+module.  The reason for this is that capability enforces that a process
+must have CAP_SYS_ADMIN when writing "security.*" extended attributes.
+However selinux requires that non-CAP_SYS_ADMIN processes be able to
+write security.selinux attributes, instead enforcing its own permission
+check.  More subtle interactions are certainly imaginable, such as a
+first security module updating state on a kernel object such that a
+second security module denies or allows the action when it otherwise
+would not have.
+
+If you have any questions about the proper or actual behavior of
+modules, whether existing or ones to be written by yourself, a good
+place to engage in discussion is the lsm mailing list,
+linux-security-module@wirex.com.  Information about the mailing list can
+be found at lsm.immunix.org.
+
+If your module will be annotating security information to kernel
+objects, then you must use the provided API.  The functions intended
+for use by modules are defined in include/linux/security.h.  A
+good example of a user of these functions is the SELinux module.  The
+following describes the API usage.
+
+Assume you wish to annotate an instance of the following struct to an
+inode:
+
+struct my_security_info {
+	int a;
+	struct list_head some_list;
+	spinlock_t lock;
+};
+
+At the top of the struct, you must add a struct security_list lsm_list,
+as follows:
+
+struct my_security_info {
++	struct security_list lsm_list;
+	int count;
+	struct list_head some_list;
+	spinlock_t lock;
+};
+
+This will add the information which the API will need to tell your
+information apart from that of other modules.  You also need to define a
+unique ID to distinguish information owned by your module.  Usually
+people "echo <module_name> | sha1sum" and use the first several digits.
+For instance, if
+#echo seclvl | sha1sum | awk --field-separator="" '{ print \
+$1$2$3$4$5$6$7$8 '}
+40e81e47
+
+then in your my_lsm.h, add
+#define MY_LSM_ID 0x40e81e47
+
+Do make sure that no other module happens to have the same ID.
+
+Now when the kernel object is created, you may use
+security_set_value_type() to append the struct to the object's list of
+security information.  Note that you may ONLY use this while the kernel
+object is being created, ie during the security_<KERNEL_OBJECT>_alloc
+function.  Since you are appending my_security_info to the inode, you
+will do so during the security_inode_alloc() hook.  For instance,
+
+static inline int my_inode_alloc(struct inode *inode)
+{
+	struct my_security_info *my_data;
+
+	my_data = kmalloc(sizeof(struct my_security_info), GFP_KERNEL);
+	if (!my_data)
+		return -ENOMEM;
+	init_inode_data(my_data);
+
+	security_set_value_type(&inode->i_security, MY_LSM_ID, my_data);
+}
+
+If you need to append your information after the kernel object has been
+created, you may do so using security_add_value_type() hook.  However,
+for both performance and security reasons, it is preferable to compile
+your module into the kernel and always append your info while the object
+is created.  See security/seclvl.c or the digsig stacking patch for
+examples of this usage.
+
+To get your information back, you may use security_get_value_type().
+For instance,
+
+static inline int my_inode_create(struct inode *dir,
+				  struct dentry *dentry,
+				  int mode)
+{
+	struct my_security_info *my_data;
+
+	my_data = security_get_value_type(&dir->i_security,
+			MY_LSM_ID, struct my_security_info);
+	if (!my_data || my_data->count)
+		return -EPERM;
+	return 0;
+}
+
+There are two ways of removing kernel object data for freeing.
+If you can wait until security_<object>_free(), ie security_inode_free,()
+then you may use
+
+	my_data = security_del_value_type(&dir->i_security,
+			MY_LSM_ID, struct my_security_info);
+	kfree(my_data);
+
+See security/selinux/hooks.c for example usage.
+
+If you must free the data before the object is freed, because your
+module is being unloaded, then you must use
+
+	security_unlink_value(&dir->i_security->lsm_list.list);
+
+and wait a full rcu cycle before freeing the data in order to
+ensure proper locking.  See security/seclvl.c and the digsig
+stacking patch for sample usage.  Both of these modules simply
+link together all the objects in one list_head chain, and, if
+unloaded, unlink each object from the object, wait a full rcu
+cycle, then walk the same chain again to free the objects.
Index: linux-2.6.13-rc3/Documentation/LSM-stacker-locking.txt
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.13-rc3/Documentation/LSM-stacker-locking.txt	2005-07-27 16:59:45.000000000 -0500
@@ -0,0 +1,77 @@
+The following describes the locking used by the lsm stacker as of
+July 1, 2005:
+
+Things which require locking include:
+
+	1. module list
+	2. per-kernel-object security lists
+
+Clearly, the safety of the data being appended itself is up to
+the module.  For instance, digsig uses a single spinlock to
+protect the inode security data, while securelevel uses a
+spinlock located in the inode security object itself.
+
+The module list is protected as follows:
+
+	Walking the list is done under a partial rcu_read_lock.  We
+	cannot hold the rcu_read_lock while calling a
+	module_entry->lsm_hook(), as these are very likely to sleep.
+	Therefore we call rcu_read_lock() only when we rcu_dereference
+	module_entry->next.
+
+	We must be careful about deleting module_entries.  Stacker does
+	a try_module_get() on each LSM as it is stacked, to prevent its
+	being unloaded.  It will module_put the LSM when stacker_unload
+	is called for the module.  At that time the module is removed
+	from the stacked_modules list.  The forward pointer on the
+	struct module_entry is not changed, so that any stacker hook
+	which is currently on module_entry can safely and correctly
+	dereference module_entry->next.  The module_entry remains on the
+	all_modules list, which is used to find the module when it is
+	actually unregistered.  In this way any task which is executing
+	any of the module's hooks should have finished execution between
+	stacker_unload() and stacker_unregister(), making it safe to
+	delete the module_entry.
+
+The kernel object security lists are protected as follows:
+
+	The security_set_value and security_del_value are only to
+	be called during security_alloc_object and security_del_object,
+	respectively.  Since these are automatically safe from
+	concurrent accesses, no locking is required here.
+
+	The security_add_value() function is protected from concurrent
+	access using the stacker_value_spinlock.  security_get_value()
+	is protected from security_add_value() using rcu.
+
+	To allow module deletion, it is desirable for modules to be
+	able to delete kernel object security entries at any time.
+	This is supported using security_unlink_value().  This
+	function will remove the object under the
+	stacker_value_spinlock.  In order to protect racing readers,
+	however, the module must wait an rcu cycle before deleting
+	the object, either using call_rcu to call the deletion
+	function, or simply calling synchronize_rcu() as is done by
+	digsig.  In order to minimize the performance impact, both
+	digsig and securelevel call security_unlink_value() on each
+	to be deleted item in a loop, then wait an rcu cycle, and
+	then delete the objects.
+
+	This dynamic object deletion scheme still has one potential
+	race.  In order to minimize the performance impact on the
+	expected case, security_del_value() does not take the
+	stacker_value_spinlock.  This is generally safe because this
+	function must only be called while the kernel object is being
+	freed, so that this function is naturally serialized with
+	respect to write (no writes are possible).  However, the
+	following may be possible:
+
+	1. echo -n lsm1 > /security/stacker/unload  (CPU 0)
+	2. rmmod lsm1  (CPU 0)
+	At the same time, a file object is being freed on CPU 1.
+	While lsm2 is calling security_del_value() on the file, lsm1
+	is calling security_unlink_value().
+
+	One solution is to call the spinlock during the object
+	deletion.  The performance of this approach will be
+	measured.

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [patch 7/15] lsm stacking v0.3: actual stacker module
  2005-07-27 18:19 ` [patch 1/15] lsm stacking v0.3: introduce securityfs serue
                     ` (4 preceding siblings ...)
  2005-07-27 18:24   ` [patch 6/15] lsm stacking v0.3: stacker documentation serue
@ 2005-07-27 18:24   ` serue
  2005-07-27 18:25   ` [patch 8/15] lsm stacking v0.3: stackable capabilities lsm serue
                     ` (7 subsequent siblings)
  13 siblings, 0 replies; 39+ messages in thread
From: serue @ 2005-07-27 18:24 UTC (permalink / raw)
  To: lkml
  Cc: Chris Wright, Stephen Smalley, James Morris, Andrew Morton,
	Michael Halcrow, David Safford, Reiner Sailer, Gerrit Huizenga,
	Emily Ratliff

Adds the actual stacker LSM.

Changelog:
	
	[July 26]:

	sparse fixes - make dentries static, add __user to shmaddr in
		stacker_shm_shmat.

	security_disown_value after calling all modules' free function
	for any freed kernel object.  It is expected that any LSM
	being unloaded will eventually call security_unlink_value(),
	which is safe only if we disown.

	Fixed stacker_inode_{get,set,list}security bug pointed out by
	Stephen Smalley.

	Switched to using securityfs.

	vm_enough_memory was calling dummy_capable rather than
	stacker_capable.

	try_module_get any loaded LSMs until someone asks for it
	to be unloaded, so that we can give time for all the LSMs
	functions to finish running before the module is freed.

	Load dummy module if no modules have yet been stacked.

	Share procattr among multiple LSMs, instead of only supporting
	SELinux.  Data is now expected to be of the form
		"data (module_name)"
	If the "(module_name)" part is missing, we assume the data is
	intended for SELinux.

	Support unloading of LSMs.

Signed-off-by: Serge Hallyn <serue@us.ibm.com>
--
 Kconfig   |    6 
 Makefile  |    1 
 stacker.c | 1664 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1671 insertions(+)

Index: linux-2.6.13-rc3/security/Kconfig
===================================================================
--- linux-2.6.13-rc3.orig/security/Kconfig	2005-07-27 16:09:28.000000000 -0500
+++ linux-2.6.13-rc3/security/Kconfig	2005-07-27 17:02:17.000000000 -0500
@@ -87,5 +87,11 @@ config SECURITY_SECLVL
 
 source security/selinux/Kconfig
 
+config SECURITY_STACKER
+	boolean "LSM Stacking"
+	depends on SECURITY
+	help
+	  Stack multiple LSMs.
+
 endmenu
 
Index: linux-2.6.13-rc3/security/Makefile
===================================================================
--- linux-2.6.13-rc3.orig/security/Makefile	2005-07-27 16:09:28.000000000 -0500
+++ linux-2.6.13-rc3/security/Makefile	2005-07-27 17:02:17.000000000 -0500
@@ -3,6 +3,7 @@
 #
 
 obj-$(CONFIG_KEYS)			+= keys/
+obj-$(CONFIG_SECURITY_STACKER)		+= stacker.o
 subdir-$(CONFIG_SECURITY_SELINUX)	+= selinux
 
 # if we don't select a security model, use the default capabilities
Index: linux-2.6.13-rc3/security/stacker.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.13-rc3/security/stacker.c	2005-07-27 17:07:22.000000000 -0500
@@ -0,0 +1,1664 @@
+/* "Stacker" Linux security module (LSM).
+ *
+ * Allows you to load (stack) multiple (additional) security modules.
+ *
+ * Copyright (C) 2002,2003,2004,2005 Serge E. Hallyn <serue@us.ibm.com>
+ * Copyright (C) 2002 David A. Wheeler <dwheeler@dwheeler.com>.
+ *  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/security.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/capability.h>
+#include <linux/rwsem.h>
+#include <linux/netdevice.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <net/sock.h>
+#include <asm/system.h>
+
+/* A module entry keeps track of one of the stacked modules
+ * Note that module_operations is aggregated instead of being pointed to -
+ * it's one less allocation and one less pointer to follow. */
+
+struct module_entry {
+	struct list_head lsm_list;  /* list of active lsms */
+	struct list_head all_lsms;  /* list of active lsms */
+	char *module_name;
+	int namelen;
+	struct security_operations module_operations;
+	struct module *owner;
+	struct rcu_head m_rcu;
+};
+static LIST_HEAD(stacked_modules);  /* list of stacked modules */
+static LIST_HEAD(all_modules);      /* all modules, including unloaded */
+
+static spinlock_t stacker_lock;
+static int forbid_stacker_register;     /* = 0; if 1, can't register */
+
+/*
+ * when !modules_registered, the default_module, defined
+ * below, will be stacked
+ */
+static short modules_registered;
+ 
+/*
+ * Workarounds for the fact that get and setprocattr are used only by
+ * selinux.  (Maybe)
+ */
+static struct module_entry *selinux_module;
+static struct module_entry default_module;
+
+/* Maximum number of characters in a stacked LSM module name */
+#define MAX_MODULE_NAME_LEN 128
+
+static int debug = 0;
+
+module_param(debug, bool, 0600);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+#define MY_NAME "stacker"
+#define stacker_dbg(fmt, arg...)					\
+	do {							\
+		if (debug)					\
+			printk(KERN_DEBUG "%s: %s: " fmt ,	\
+				MY_NAME , __FUNCTION__ , 	\
+				## arg);			\
+	} while (0)
+
+static void stacker_del_module(struct rcu_head *head)
+{
+	struct module_entry *m;
+
+	m = container_of(head, struct module_entry, m_rcu);
+	kfree(m->module_name);
+	kfree(m);
+}
+
+/* Walk through the list of modules in stacked_modules
+ * and ask each (in turn) for their results, then return the
+ * results.  If more than one module reports an error, return
+ * the FIRST error code.
+ *
+ * We return as soon as an error is returned.
+ */
+
+#define stack_for_each_entry(pos, head, member)				\
+	for (pos = list_entry((head)->next, typeof(*pos), member);	\
+		&pos->member != (head);					\
+		pos = rcu_dereference(list_entry(pos->member.next, 	\
+				typeof(*pos), member)))
+
+/* to make this safe for module deletion, we would need to
+ * add a reference count to m as we had before
+ */
+#define RETURN_ERROR_IF_ANY_ERROR(BASE_FUNC, FUNC_WITH_ARGS) do { \
+	int result = 0; \
+	struct module_entry *m; \
+	rcu_read_lock(); \
+	stack_for_each_entry(m, &stacked_modules, lsm_list) { \
+		if (!m->module_operations.BASE_FUNC) \
+			continue; \
+		rcu_read_unlock(); \
+		result = m->module_operations.FUNC_WITH_ARGS; \
+		rcu_read_lock(); \
+		if (result) \
+			break; \
+	} \
+	rcu_read_unlock(); \
+	return result; \
+} while (0)
+
+/* Call all modules in stacked_modules' routine */
+#define CALL_ALL(BASE_FUNC, FUNC_WITH_ARGS) do { \
+	struct module_entry *m; \
+	rcu_read_lock(); \
+	stack_for_each_entry(m, &stacked_modules, lsm_list) { \
+		if (m->module_operations.BASE_FUNC) { \
+			rcu_read_unlock(); \
+			m->module_operations.FUNC_WITH_ARGS; \
+			rcu_read_lock(); \
+		} \
+	} \
+	rcu_read_unlock(); \
+} while (0)
+
+#define FREE_ALL(BASE_FREE,FREE_WITH_ARGS) do { \
+	struct module_entry *m; \
+	rcu_read_lock(); \
+	stack_for_each_entry(m, &stacked_modules, lsm_list ) { \
+		if (m->module_operations.BASE_FREE) { \
+			rcu_read_unlock(); \
+			m->module_operations.FREE_WITH_ARGS; \
+			rcu_read_lock(); \
+		} \
+	} \
+	rcu_read_unlock(); \
+} while (0)
+
+#define ALLOC_SECURITY(BASE_FUNC,FUNC_WITH_ARGS,BASE_FREE,FREE_WITH_ARGS) do { \
+	int result; \
+	struct module_entry *m, *m2; \
+	rcu_read_lock(); \
+	stack_for_each_entry(m, &stacked_modules, lsm_list) { \
+		if (!m->module_operations.BASE_FUNC) \
+			continue; \
+		rcu_read_unlock(); \
+		result = m->module_operations.FUNC_WITH_ARGS; \
+		rcu_read_lock(); \
+		if (result) \
+			goto bad; \
+	} \
+	rcu_read_unlock(); \
+	return 0; \
+bad: \
+	stack_for_each_entry(m2, &stacked_modules, lsm_list) { \
+		if (m == m2) \
+			break; \
+		if (!m2->module_operations.BASE_FREE) \
+			continue; \
+		rcu_read_unlock(); \
+		m2->module_operations.FREE_WITH_ARGS; \
+		rcu_read_lock(); \
+	} \
+	rcu_read_unlock(); \
+	return result; \
+} while (0)
+
+/*
+ * The list of functions for stacker_ops
+ */
+static int stacker_ptrace (struct task_struct *parent, struct task_struct *child)
+{
+	RETURN_ERROR_IF_ANY_ERROR(ptrace,ptrace(parent, child));
+}
+
+static int stacker_capget (struct task_struct *target, kernel_cap_t * effective,
+			 kernel_cap_t * inheritable, kernel_cap_t * permitted)
+{
+	RETURN_ERROR_IF_ANY_ERROR(capget,capget(target, effective, inheritable, permitted));
+}
+
+static int stacker_capset_check (struct task_struct *target,
+			       kernel_cap_t * effective,
+			       kernel_cap_t * inheritable,
+			       kernel_cap_t * permitted)
+{
+	RETURN_ERROR_IF_ANY_ERROR(capset_check,capset_check(target, effective, inheritable, permitted));
+}
+
+static void stacker_capset_set (struct task_struct *target,
+			      kernel_cap_t * effective,
+			      kernel_cap_t * inheritable,
+			      kernel_cap_t * permitted)
+{
+	CALL_ALL(capset_set,capset_set(target, effective, inheritable, permitted));
+}
+
+static int stacker_acct (struct file *file)
+{
+	RETURN_ERROR_IF_ANY_ERROR(acct,acct(file));
+}
+
+static int stacker_capable (struct task_struct *tsk, int cap)
+{
+	RETURN_ERROR_IF_ANY_ERROR(capable,capable(tsk,cap));
+}
+
+
+static int stacker_sysctl (struct ctl_table * table, int op)
+{
+	RETURN_ERROR_IF_ANY_ERROR(sysctl,sysctl(table, op));
+}
+
+static int stacker_quotactl (int cmds, int type, int id, struct super_block *sb)
+{
+	RETURN_ERROR_IF_ANY_ERROR(quotactl,quotactl(cmds,type,id,sb));
+}
+
+static int stacker_quota_on (struct dentry *dentry)
+{
+	RETURN_ERROR_IF_ANY_ERROR(quota_on,quota_on(dentry));
+}
+
+static int stacker_syslog (int type)
+{
+	RETURN_ERROR_IF_ANY_ERROR(syslog,syslog(type));
+}
+
+static int stacker_settime(struct timespec *ts, struct timezone *tz)
+{
+	RETURN_ERROR_IF_ANY_ERROR(settime,settime(ts,tz));
+}
+
+/*
+ * vm_enough_memory performs actual updates of vm state.  Most
+ * modules, including dummy, use the __vm_enough_memory helper
+ * to do this for them.
+ * This means we can't call more than one module's vm_enough.
+ * So we call the first module's, or if no modules are loaded,
+ * we call dummy_vm_enough_memory.
+ */
+static int stacker_vm_enough_memory(long pages)
+{
+	int result;
+	struct module_entry *m;
+	int cap_sys_admin = 0;
+
+	if (unlikely(list_empty(&stacked_modules)))
+		goto no_module_vmenough;
+
+	rcu_read_lock();
+	stack_for_each_entry(m, &stacked_modules, lsm_list) {
+		if (!m->module_operations.vm_enough_memory)
+			continue;
+		rcu_read_unlock();
+		result = m->module_operations.vm_enough_memory(pages);
+		return result;
+	}
+	rcu_read_unlock();
+
+no_module_vmenough:
+	if (stacker_capable(current, CAP_SYS_ADMIN) == 0)
+		cap_sys_admin = 1;
+	result = __vm_enough_memory(pages, cap_sys_admin);
+	return result;
+}
+
+/*
+ * Each module may have it's own idea of how to set netlink perms.
+ * We use the intersection of all as the final alloted perms.
+ */
+static int stacker_netlink_send (struct sock *sk, struct sk_buff *skb)
+{
+	kernel_cap_t tmpcap = ~0;
+	int result = 0;
+	struct module_entry *m;
+
+	rcu_read_lock();
+	stack_for_each_entry(m, &stacked_modules, lsm_list) {
+		if (!m->module_operations.netlink_send)
+			continue;
+		NETLINK_CB(skb).eff_cap = ~0;
+		rcu_read_unlock();
+		result = m->module_operations.netlink_send(sk, skb);
+		rcu_read_lock();
+		tmpcap &= NETLINK_CB(skb).eff_cap;
+		if (result)
+			break;
+	}
+	rcu_read_unlock();
+
+	NETLINK_CB(skb).eff_cap = tmpcap;
+	return result;
+}
+
+
+static int stacker_netlink_recv (struct sk_buff *skb)
+{
+	RETURN_ERROR_IF_ANY_ERROR(netlink_recv,netlink_recv(skb));
+}
+
+static int stacker_bprm_alloc_security (struct linux_binprm *bprm)
+{
+	ALLOC_SECURITY(bprm_alloc_security,bprm_alloc_security(bprm),bprm_free_security,bprm_free_security(bprm));
+}
+
+static void stacker_bprm_free_security (struct linux_binprm *bprm)
+{
+	FREE_ALL(bprm_free_security,bprm_free_security(bprm));
+	if (unlikely(!hlist_empty(&bprm->security)))
+		security_disown_value(&bprm->security);
+}
+
+static void stacker_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
+{
+	CALL_ALL(bprm_apply_creds,bprm_apply_creds(bprm, unsafe));
+}
+
+static void stacker_bprm_post_apply_creds (struct linux_binprm * bprm)
+{
+	CALL_ALL(bprm_post_apply_creds,bprm_post_apply_creds(bprm));
+}
+
+static int stacker_bprm_set_security (struct linux_binprm *bprm)
+{
+	RETURN_ERROR_IF_ANY_ERROR(bprm_set_security,bprm_set_security(bprm));
+}
+
+static int stacker_bprm_check_security (struct linux_binprm *bprm)
+{
+	RETURN_ERROR_IF_ANY_ERROR(bprm_check_security,bprm_check_security(bprm));
+}
+
+static int stacker_bprm_secureexec (struct linux_binprm *bprm)
+{
+	RETURN_ERROR_IF_ANY_ERROR(bprm_secureexec,bprm_secureexec(bprm));
+}
+
+static int stacker_sb_alloc_security (struct super_block *sb)
+{
+	ALLOC_SECURITY(sb_alloc_security,sb_alloc_security(sb),sb_free_security,sb_free_security(sb));
+}
+
+static void stacker_sb_free_security (struct super_block *sb)
+{
+	FREE_ALL(sb_free_security,sb_free_security(sb));
+	if (unlikely(!hlist_empty(&sb->s_security)))
+		security_disown_value(&sb->s_security);
+}
+
+static int stacker_sb_copy_data (struct file_system_type *type,
+			void *orig, void *copy)
+{
+	RETURN_ERROR_IF_ANY_ERROR(sb_copy_data,sb_copy_data(type,orig,copy));
+}
+
+static int stacker_sb_kern_mount (struct super_block *sb, void *data)
+{
+	RETURN_ERROR_IF_ANY_ERROR(sb_kern_mount,sb_kern_mount(sb, data));
+}
+
+static int stacker_sb_statfs (struct super_block *sb)
+{
+	RETURN_ERROR_IF_ANY_ERROR(sb_statfs,sb_statfs(sb));
+}
+
+static int stacker_mount (char *dev_name, struct nameidata *nd, char *type,
+			unsigned long flags, void *data)
+{
+	RETURN_ERROR_IF_ANY_ERROR(sb_mount,sb_mount(dev_name, nd, type, flags, data));
+}
+
+static int stacker_check_sb (struct vfsmount *mnt, struct nameidata *nd)
+{
+	RETURN_ERROR_IF_ANY_ERROR(sb_check_sb,sb_check_sb(mnt, nd));
+}
+
+static int stacker_umount (struct vfsmount *mnt, int flags)
+{
+	RETURN_ERROR_IF_ANY_ERROR(sb_umount,sb_umount(mnt, flags));
+}
+
+static void stacker_umount_close (struct vfsmount *mnt)
+{
+	CALL_ALL(sb_umount_close,sb_umount_close(mnt));
+}
+
+static void stacker_umount_busy (struct vfsmount *mnt)
+{
+	CALL_ALL(sb_umount_busy,sb_umount_busy(mnt));
+}
+
+static void stacker_post_remount (struct vfsmount *mnt, unsigned long flags,
+				void *data)
+{
+	CALL_ALL(sb_post_remount,sb_post_remount(mnt, flags, data));
+}
+
+
+static void stacker_post_mountroot (void)
+{
+	CALL_ALL(sb_post_mountroot,sb_post_mountroot());
+}
+
+static void stacker_post_addmount (struct vfsmount *mnt, struct nameidata *nd)
+{
+	CALL_ALL(sb_post_addmount,sb_post_addmount(mnt, nd));
+}
+
+static int stacker_pivotroot (struct nameidata *old_nd, struct nameidata *new_nd)
+{
+	RETURN_ERROR_IF_ANY_ERROR(sb_pivotroot,sb_pivotroot(old_nd, new_nd));
+}
+
+static void stacker_post_pivotroot (struct nameidata *old_nd, struct nameidata *new_nd)
+{
+	CALL_ALL(sb_post_pivotroot,sb_post_pivotroot(old_nd, new_nd));
+}
+
+static int stacker_inode_alloc_security (struct inode *inode)
+{
+	ALLOC_SECURITY(inode_alloc_security,inode_alloc_security(inode),inode_free_security,inode_free_security(inode));
+}
+
+static void stacker_inode_free_security (struct inode *inode)
+{
+	FREE_ALL(inode_free_security,inode_free_security(inode));
+	if (unlikely(!hlist_empty(&inode->i_security)))
+		security_disown_value(&inode->i_security);
+}
+
+static int stacker_inode_create (struct inode *inode, struct dentry *dentry,
+			       int mask)
+{
+	RETURN_ERROR_IF_ANY_ERROR(inode_create,inode_create(inode, dentry, mask));
+}
+
+static void stacker_inode_post_create (struct inode *inode,
+	    struct dentry *dentry, int mask)
+{
+	CALL_ALL(inode_post_create,inode_post_create(inode, dentry, mask));
+}
+
+static int stacker_inode_link (struct dentry *old_dentry, struct inode *inode,
+			     struct dentry *new_dentry)
+{
+	RETURN_ERROR_IF_ANY_ERROR(inode_link,inode_link(old_dentry, inode, new_dentry));
+}
+
+static void stacker_inode_post_link (struct dentry *old_dentry,
+				   struct inode *inode,
+				   struct dentry *new_dentry)
+{
+	CALL_ALL(inode_post_link,inode_post_link(old_dentry, inode, new_dentry));
+}
+
+static int stacker_inode_unlink (struct inode *inode, struct dentry *dentry)
+{
+	RETURN_ERROR_IF_ANY_ERROR(inode_unlink,inode_unlink(inode, dentry));
+}
+
+static int stacker_inode_symlink (struct inode *inode, struct dentry *dentry,
+				const char *name)
+{
+	RETURN_ERROR_IF_ANY_ERROR(inode_symlink,inode_symlink(inode, dentry, name));
+}
+
+static void stacker_inode_post_symlink (struct inode *inode,
+				      struct dentry *dentry, const char *name)
+{
+	CALL_ALL(inode_post_symlink,inode_post_symlink(inode, dentry, name));
+}
+
+static int stacker_inode_mkdir (struct inode *inode, struct dentry *dentry,
+			      int mask)
+{
+	RETURN_ERROR_IF_ANY_ERROR(inode_mkdir,inode_mkdir(inode, dentry, mask));
+}
+
+static void stacker_inode_post_mkdir (struct inode *inode,
+	    	struct dentry *dentry, int mask)
+{
+	CALL_ALL(inode_post_mkdir,inode_post_mkdir(inode, dentry, mask));
+}
+
+static int stacker_inode_rmdir (struct inode *inode, struct dentry *dentry)
+{
+	RETURN_ERROR_IF_ANY_ERROR(inode_rmdir,inode_rmdir(inode, dentry));
+}
+
+static int stacker_inode_mknod (struct inode *inode, struct dentry *dentry,
+			      int major, dev_t minor)
+{
+	RETURN_ERROR_IF_ANY_ERROR(inode_mknod,inode_mknod(inode, dentry, major, minor));
+}
+
+static void stacker_inode_post_mknod (struct inode *inode,
+	       	struct dentry *dentry, int major, dev_t minor)
+{
+	CALL_ALL(inode_post_mknod,inode_post_mknod(inode, dentry, major, minor));
+}
+
+static int stacker_inode_rename (struct inode *old_inode,
+			       struct dentry *old_dentry,
+			       struct inode *new_inode,
+			       struct dentry *new_dentry)
+{
+	RETURN_ERROR_IF_ANY_ERROR(inode_rename,inode_rename(old_inode, old_dentry,
+				  new_inode, new_dentry));
+}
+
+static void stacker_inode_post_rename (struct inode *old_inode,
+				     struct dentry *old_dentry,
+				     struct inode *new_inode,
+				     struct dentry *new_dentry)
+{
+	CALL_ALL(inode_post_rename,inode_post_rename(old_inode, old_dentry,
+				  new_inode, new_dentry));
+}
+
+static int stacker_inode_readlink (struct dentry *dentry)
+{
+	RETURN_ERROR_IF_ANY_ERROR(inode_readlink,inode_readlink(dentry));
+}
+
+static int stacker_inode_follow_link (struct dentry *dentry,
+				    struct nameidata *nameidata)
+{
+	RETURN_ERROR_IF_ANY_ERROR(inode_follow_link,inode_follow_link(dentry, nameidata));
+}
+
+static int stacker_inode_permission (struct inode *inode, int mask,
+		struct nameidata *nd)
+{
+	RETURN_ERROR_IF_ANY_ERROR(inode_permission,inode_permission(inode, mask, nd));
+}
+
+static int stacker_inode_setattr (struct dentry *dentry, struct iattr *iattr)
+{
+	RETURN_ERROR_IF_ANY_ERROR(inode_setattr,inode_setattr(dentry, iattr));
+}
+
+static int stacker_inode_getattr (struct vfsmount *mnt, struct dentry *dentry)
+{
+	RETURN_ERROR_IF_ANY_ERROR(inode_getattr,inode_getattr(mnt,dentry));
+}
+
+static void stacker_inode_delete (struct inode *ino)
+{
+	CALL_ALL(inode_delete,inode_delete(ino));
+}
+
+static int stacker_inode_setxattr (struct dentry *dentry, char *name,
+	        	void *value, size_t size, int flags)
+{
+	RETURN_ERROR_IF_ANY_ERROR(inode_setxattr,inode_setxattr(dentry,name,value,size,flags));
+}
+
+static void stacker_inode_post_setxattr (struct dentry *dentry, char *name, void *value,
+				       size_t size, int flags)
+{
+	CALL_ALL(inode_post_setxattr,inode_post_setxattr(dentry,name,value,size,flags));
+}
+
+static int stacker_inode_getxattr (struct dentry *dentry, char *name)
+{
+	RETURN_ERROR_IF_ANY_ERROR(inode_getxattr,inode_getxattr(dentry,name));
+}
+
+static int stacker_inode_listxattr (struct dentry *dentry)
+{
+	RETURN_ERROR_IF_ANY_ERROR(inode_listxattr,inode_listxattr(dentry));
+}
+
+static int stacker_inode_removexattr (struct dentry *dentry, char *name)
+{
+	RETURN_ERROR_IF_ANY_ERROR(inode_removexattr,inode_removexattr(dentry,name));
+}
+
+/*
+ * inode_getsecurity: We loop through all modules until one does not return
+ * -EOPNOTSUPP.
+ * Note that if some LSM returns -EPERM, stacker assumes the LSM knows what
+ * it's doing.  If you don't want to control the name, then return
+ * -EOPNOTSUPP!
+ */
+static int stacker_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size)
+{
+	struct module_entry *m;
+	int ret = -EOPNOTSUPP;
+
+	rcu_read_lock();
+	stack_for_each_entry(m, &stacked_modules, lsm_list) {
+		if (!m->module_operations.inode_getsecurity)
+			continue;
+		rcu_read_unlock();
+		ret = m->module_operations.inode_getsecurity(inode,name,buffer,size);
+		rcu_read_lock();
+		if (ret != -EOPNOTSUPP)
+			break;
+	}
+	rcu_read_unlock();
+
+	return ret;
+}
+
+/*
+ * inode_setsecurity: We loop through all modules until one does not return
+ * -EOPNOTSUPP.
+ * Note that if some LSM returns -EPERM, stacker assumes the LSM knows what
+ * it's doing.  If you don't want to control the name, then return
+ * -EOPNOTSUPP!
+ */
+static int stacker_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)
+{
+	struct module_entry *m;
+	int ret = -EOPNOTSUPP;
+
+	rcu_read_lock();
+	stack_for_each_entry(m, &stacked_modules, lsm_list) {
+		if (!m->module_operations.inode_setsecurity)
+			continue;
+		rcu_read_unlock();
+		ret = m->module_operations.inode_setsecurity(inode, name,
+						value, size, flags);
+		rcu_read_lock();
+		if (ret != -EOPNOTSUPP)
+			break;
+	}
+	rcu_read_unlock();
+
+	return ret;
+}
+
+/*
+ * inode_listsecurity: We loop through all modules appending to buffer, and return
+ * the \0-separated list of security names defined for this inode.
+ */
+static int stacker_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
+{
+	int ret = 0;
+	struct module_entry *m;
+
+	rcu_read_lock();
+	stack_for_each_entry(m, &stacked_modules, lsm_list) {
+		int thislen;
+
+		if (!m->module_operations.inode_listsecurity)
+			continue;
+		rcu_read_unlock();
+		thislen = m->module_operations.inode_listsecurity(inode,
+				buffer+ret, buffer_size-ret);
+		rcu_read_lock();
+		if (thislen < 0)
+			continue;
+		ret += thislen;
+		if (ret >= buffer_size) {
+			ret = -ERANGE;
+			break;
+		}
+	}
+	rcu_read_unlock();
+
+	return ret;
+}
+
+static int stacker_file_permission (struct file *file, int mask)
+{
+	RETURN_ERROR_IF_ANY_ERROR(file_permission,file_permission(file,mask));
+}
+
+static int stacker_file_alloc_security (struct file *file)
+{
+	ALLOC_SECURITY(file_alloc_security,file_alloc_security(file),file_free_security,file_free_security(file));
+}
+
+static void stacker_file_free_security (struct file *file)
+{
+	FREE_ALL(file_free_security,file_free_security(file));
+	if (unlikely(!hlist_empty(&file->f_security)))
+		security_disown_value(&file->f_security);
+}
+
+static int stacker_file_ioctl (struct file *file, unsigned int command,
+			     unsigned long arg)
+{
+	RETURN_ERROR_IF_ANY_ERROR(file_ioctl,file_ioctl(file,command,arg));
+}
+
+static int stacker_file_mmap (struct file *file, unsigned long reqprot,
+			    unsigned long prot, unsigned long flags)
+{
+	RETURN_ERROR_IF_ANY_ERROR(file_mmap,file_mmap(file, reqprot, prot, flags));
+}
+
+static int stacker_file_mprotect (struct vm_area_struct *vma,
+	       	unsigned long reqprot, unsigned long prot)
+{
+	RETURN_ERROR_IF_ANY_ERROR(file_mprotect,file_mprotect(vma,reqprot,prot));
+}
+
+static int stacker_file_lock (struct file *file, unsigned int cmd)
+{
+	RETURN_ERROR_IF_ANY_ERROR(file_lock,file_lock(file,cmd));
+}
+
+static int stacker_file_fcntl (struct file *file, unsigned int cmd,
+			     unsigned long arg)
+{
+	RETURN_ERROR_IF_ANY_ERROR(file_fcntl,file_fcntl(file,cmd,arg));
+}
+
+static int stacker_file_set_fowner (struct file *file)
+{
+	RETURN_ERROR_IF_ANY_ERROR(file_set_fowner,file_set_fowner(file));
+}
+
+static int stacker_file_send_sigiotask (struct task_struct *tsk,
+				      struct fown_struct *fown, int sig)
+{
+	RETURN_ERROR_IF_ANY_ERROR(file_send_sigiotask,file_send_sigiotask(tsk,fown,sig));
+}
+
+static int stacker_file_receive (struct file *file)
+{
+	RETURN_ERROR_IF_ANY_ERROR(file_receive,file_receive(file));
+}
+
+static int stacker_task_create (unsigned long clone_flags)
+{
+	RETURN_ERROR_IF_ANY_ERROR(task_create,task_create(clone_flags));
+}
+
+static int stacker_task_alloc_security (struct task_struct *p)
+{
+	ALLOC_SECURITY(task_alloc_security,task_alloc_security(p),task_free_security,task_free_security(p));
+}
+
+static void stacker_task_free_security (struct task_struct *p)
+{
+	FREE_ALL(task_free_security,task_free_security(p));
+	if (unlikely(!hlist_empty(&p->security)))
+		security_disown_value(&p->security);
+}
+
+static int stacker_task_setuid (uid_t id0, uid_t id1, uid_t id2, int flags)
+{
+	RETURN_ERROR_IF_ANY_ERROR(task_setuid,task_setuid(id0,id1,id2,flags));
+}
+
+static int stacker_task_post_setuid (uid_t id0, uid_t id1, uid_t id2, int flags)
+{
+	RETURN_ERROR_IF_ANY_ERROR(task_post_setuid,task_post_setuid(id0,id1,id2,flags));
+}
+
+static int stacker_task_setgid (gid_t id0, gid_t id1, gid_t id2, int flags)
+{
+	RETURN_ERROR_IF_ANY_ERROR(task_setgid,task_setgid(id0,id1,id2,flags));
+}
+
+static int stacker_task_setpgid (struct task_struct *p, pid_t pgid)
+{
+	RETURN_ERROR_IF_ANY_ERROR(task_setpgid,task_setpgid(p,pgid));
+}
+
+static int stacker_task_getpgid (struct task_struct *p)
+{
+	RETURN_ERROR_IF_ANY_ERROR(task_getpgid,task_getpgid(p));
+}
+
+static int stacker_task_getsid (struct task_struct *p)
+{
+	RETURN_ERROR_IF_ANY_ERROR(task_getsid,task_getsid(p));
+}
+
+static int stacker_task_setgroups (struct group_info *group_info)
+{
+	RETURN_ERROR_IF_ANY_ERROR(task_setgroups,task_setgroups(group_info));
+}
+
+static int stacker_task_setnice (struct task_struct *p, int nice)
+{
+	RETURN_ERROR_IF_ANY_ERROR(task_setnice,task_setnice(p,nice));
+}
+
+static int stacker_task_setrlimit (unsigned int resource, struct rlimit *new_rlim)
+{
+	RETURN_ERROR_IF_ANY_ERROR(task_setrlimit,task_setrlimit(resource,new_rlim));
+}
+
+static int stacker_task_setscheduler (struct task_struct *p, int policy,
+				    struct sched_param *lp)
+{
+	RETURN_ERROR_IF_ANY_ERROR(task_setscheduler,task_setscheduler(p,policy,lp));
+}
+
+static int stacker_task_getscheduler (struct task_struct *p)
+{
+	RETURN_ERROR_IF_ANY_ERROR(task_getscheduler,task_getscheduler(p));
+}
+
+static int stacker_task_wait (struct task_struct *p)
+{
+	RETURN_ERROR_IF_ANY_ERROR(task_wait,task_wait(p));
+}
+
+static int stacker_task_kill (struct task_struct *p, struct siginfo *info,
+			    int sig)
+{
+	RETURN_ERROR_IF_ANY_ERROR(task_kill,task_kill(p,info,sig));
+}
+
+static int stacker_task_prctl (int option, unsigned long arg2, unsigned long arg3,
+			     unsigned long arg4, unsigned long arg5)
+{
+	RETURN_ERROR_IF_ANY_ERROR(task_prctl,task_prctl(option,arg2,arg3,arg4,arg5));
+}
+
+static void stacker_task_reparent_to_init (struct task_struct *p)
+{
+	/* Note that the dummy version of this hook would call:
+	 *	p->euid = p->fsuid = 0; */
+
+	CALL_ALL(task_reparent_to_init,task_reparent_to_init(p));
+}
+
+static void stacker_task_to_inode(struct task_struct *p, struct inode *inode)
+{
+	CALL_ALL(task_to_inode,task_to_inode(p, inode));
+}
+
+#ifdef CONFIG_SECURITY_NETWORK
+static int stacker_socket_create (int family, int type, int protocol, int kern)
+{
+	RETURN_ERROR_IF_ANY_ERROR(socket_create,socket_create(family,type,protocol,kern));
+}
+
+static void stacker_socket_post_create (struct socket *sock, int family,
+	       			int type, int protocol, int kern)
+{
+	CALL_ALL(socket_post_create,socket_post_create(sock,family,type,protocol,kern));
+}
+
+static int stacker_socket_bind (struct socket *sock, struct sockaddr *address,
+			      int addrlen)
+{
+	RETURN_ERROR_IF_ANY_ERROR(socket_bind,socket_bind(sock,address,addrlen));
+}
+
+static int stacker_socket_connect (struct socket *sock,
+	       	struct sockaddr *address, int addrlen)
+{
+	RETURN_ERROR_IF_ANY_ERROR(socket_connect,socket_connect(sock,address,addrlen));
+}
+
+static int stacker_socket_listen (struct socket *sock, int backlog)
+{
+	RETURN_ERROR_IF_ANY_ERROR(socket_listen,socket_listen(sock,backlog));
+}
+
+static int stacker_socket_accept (struct socket *sock, struct socket *newsock)
+{
+	RETURN_ERROR_IF_ANY_ERROR(socket_accept,socket_accept(sock,newsock));
+}
+
+static void stacker_socket_post_accept (struct socket *sock,
+				      struct socket *newsock)
+{
+	CALL_ALL(socket_post_accept,socket_post_accept(sock,newsock));
+}
+
+static int stacker_socket_sendmsg (struct socket *sock, struct msghdr *msg,
+				 int size)
+{
+	RETURN_ERROR_IF_ANY_ERROR(socket_sendmsg,socket_sendmsg(sock,msg,size));
+}
+
+static int stacker_socket_recvmsg (struct socket *sock, struct msghdr *msg,
+				 int size, int flags)
+{
+	RETURN_ERROR_IF_ANY_ERROR(socket_recvmsg,socket_recvmsg(sock,msg,size,flags));
+}
+
+static int stacker_socket_getsockname (struct socket *sock)
+{
+	RETURN_ERROR_IF_ANY_ERROR(socket_getsockname,socket_getsockname(sock));
+}
+
+static int stacker_socket_getpeername (struct socket *sock)
+{
+	RETURN_ERROR_IF_ANY_ERROR(socket_getpeername,socket_getpeername(sock));
+}
+
+static int stacker_socket_setsockopt (struct socket *sock, int level, int optname)
+{
+	RETURN_ERROR_IF_ANY_ERROR(socket_setsockopt,socket_setsockopt(sock,level,optname));
+}
+
+static int stacker_socket_getsockopt (struct socket *sock, int level, int optname)
+{
+	RETURN_ERROR_IF_ANY_ERROR(socket_getsockopt,socket_getsockopt(sock,level,optname));
+}
+
+static int stacker_socket_shutdown (struct socket *sock, int how)
+{
+	RETURN_ERROR_IF_ANY_ERROR(socket_shutdown,socket_shutdown(sock,how));
+}
+
+static int stacker_socket_sock_rcv_skb (struct sock *sk, struct sk_buff *skb)
+{
+	RETURN_ERROR_IF_ANY_ERROR(socket_sock_rcv_skb,socket_sock_rcv_skb(sk,skb));
+}
+
+static int stacker_unix_stream_connect (struct socket *sock,
+			     struct socket *other, struct sock *newsk)
+{
+	RETURN_ERROR_IF_ANY_ERROR(unix_stream_connect,unix_stream_connect(sock,other,newsk));
+}
+
+static int stacker_unix_may_send (struct socket *sock,
+				       struct socket *other)
+{
+	RETURN_ERROR_IF_ANY_ERROR(unix_may_send,unix_may_send(sock,other));
+}
+
+static int stacker_socket_getpeersec(struct socket *sock,
+	char __user *optval, int __user *optlen, unsigned len)
+{
+	RETURN_ERROR_IF_ANY_ERROR(socket_getpeersec,socket_getpeersec(sock,optval,optlen,len));
+}
+
+static int stacker_sk_alloc_security(struct sock *sk, int family,
+			int priority)
+{
+	ALLOC_SECURITY(sk_alloc_security,sk_alloc_security(sk,family,priority),sk_free_security,sk_free_security(sk));
+}
+
+static void stacker_sk_free_security (struct sock *sk)
+{
+	FREE_ALL(sk_free_security,sk_free_security(sk));
+	if (unlikely(!hlist_empty(&sk->sk_security)))
+		security_disown_value(&sk->sk_security);
+}
+
+#endif
+
+static int stacker_ipc_permission (struct kern_ipc_perm *ipcp, short flag)
+{
+	RETURN_ERROR_IF_ANY_ERROR(ipc_permission,ipc_permission(ipcp,flag));
+}
+
+static int stacker_msg_msg_alloc_security (struct msg_msg *msg)
+{
+	ALLOC_SECURITY(msg_msg_alloc_security,msg_msg_alloc_security(msg),msg_msg_free_security,msg_msg_free_security(msg));
+}
+
+static void stacker_msg_msg_free_security (struct msg_msg *msg)
+{
+	FREE_ALL(msg_msg_free_security,msg_msg_free_security(msg));
+	if (unlikely(!hlist_empty(&msg->security)))
+		security_disown_value(&msg->security);
+}
+
+static int stacker_msg_queue_alloc_security (struct msg_queue *msq)
+{
+	ALLOC_SECURITY(msg_queue_alloc_security,msg_queue_alloc_security(msq),msg_queue_free_security,msg_queue_free_security(msq));
+}
+
+static void stacker_msg_queue_free_security (struct msg_queue *msq)
+{
+	FREE_ALL(msg_queue_free_security,msg_queue_free_security(msq));
+	if (unlikely(!hlist_empty(&msq->q_perm.security)))
+		security_disown_value(&msq->q_perm.security);
+}
+
+static int stacker_msg_queue_associate (struct msg_queue *msq, int msqflg)
+{
+	RETURN_ERROR_IF_ANY_ERROR(msg_queue_associate,msg_queue_associate(msq,msqflg));
+}
+
+static int stacker_msg_queue_msgctl (struct msg_queue *msq, int cmd)
+{
+	RETURN_ERROR_IF_ANY_ERROR(msg_queue_msgctl,msg_queue_msgctl(msq,cmd));
+}
+
+static int stacker_msg_queue_msgsnd (struct msg_queue *msq, struct msg_msg *msg,
+				   int msgflg)
+{
+	RETURN_ERROR_IF_ANY_ERROR(msg_queue_msgsnd,msg_queue_msgsnd(msq,msg,msgflg));
+}
+
+static int stacker_msg_queue_msgrcv (struct msg_queue *msq, struct msg_msg *msg,
+				   struct task_struct *target, long type,
+				   int mode)
+{
+	RETURN_ERROR_IF_ANY_ERROR(msg_queue_msgrcv,msg_queue_msgrcv(msq,msg,target,type,mode));
+}
+
+static int stacker_shm_alloc_security (struct shmid_kernel *shp)
+{
+	ALLOC_SECURITY(shm_alloc_security,shm_alloc_security(shp),shm_free_security,shm_free_security(shp));
+}
+
+static void stacker_shm_free_security (struct shmid_kernel *shp)
+{
+	FREE_ALL(shm_free_security,shm_free_security(shp));
+	if (unlikely(!hlist_empty(&shp->shm_perm.security)))
+		security_disown_value(&shp->shm_perm.security);
+}
+
+static int stacker_shm_associate (struct shmid_kernel *shp, int shmflg)
+{
+	RETURN_ERROR_IF_ANY_ERROR(shm_associate,shm_associate(shp,shmflg));
+}
+
+static int stacker_shm_shmctl (struct shmid_kernel *shp, int cmd)
+{
+	RETURN_ERROR_IF_ANY_ERROR(shm_shmctl,shm_shmctl(shp,cmd));
+}
+
+static int stacker_shm_shmat (struct shmid_kernel *shp,
+		char __user *shmaddr, int shmflg)
+{
+	RETURN_ERROR_IF_ANY_ERROR(shm_shmat,shm_shmat(shp,shmaddr,shmflg));
+}
+
+static int stacker_sem_alloc_security (struct sem_array *sma)
+{
+	ALLOC_SECURITY(sem_alloc_security,sem_alloc_security(sma),sem_free_security,sem_free_security(sma));
+}
+
+static void stacker_sem_free_security (struct sem_array *sma)
+{
+	FREE_ALL(sem_free_security,sem_free_security(sma));
+	if (unlikely(!hlist_empty(&sma->sem_perm.security)))
+		security_disown_value(&sma->sem_perm.security);
+}
+
+static int stacker_sem_associate (struct sem_array *sma, int semflg)
+{
+	RETURN_ERROR_IF_ANY_ERROR(sem_associate,sem_associate(sma,semflg));
+}
+
+static int stacker_sem_semctl (struct sem_array *sma, int cmd)
+{
+	RETURN_ERROR_IF_ANY_ERROR(sem_semctl,sem_semctl(sma,cmd));
+}
+
+static int stacker_sem_semop (struct sem_array *sma,
+			    struct sembuf *sops, unsigned nsops, int alter)
+{
+	RETURN_ERROR_IF_ANY_ERROR(sem_semop,sem_semop(sma,sops,nsops,alter));
+}
+
+static void stacker_d_instantiate (struct dentry *dentry, struct inode *inode)
+{
+	CALL_ALL(d_instantiate,d_instantiate(dentry,inode));
+}
+
+/*
+ * Query all LSMs.
+ * If all return EINVAL, we return EINVAL.  If any returns any other
+ * error, then we return that error.  Otherwise, we concatenate all
+ * modules' results.
+ */
+static int
+stacker_getprocattr(struct task_struct *p, char *name, void *value, size_t size)
+{
+	struct module_entry *m;
+	int len = 0, ret;
+	int found_noneinval = 0;
+
+
+	if (list_empty(&stacked_modules))
+		return -EINVAL;
+
+	rcu_read_lock();
+	stack_for_each_entry(m, &stacked_modules, lsm_list) {
+		if (!m->module_operations.getprocattr)
+			continue;
+		rcu_read_unlock();
+		ret = m->module_operations.getprocattr(p, name,
+					value+len, size-len);
+		rcu_read_lock();
+		if (ret == -EINVAL)
+			continue;
+		found_noneinval = 1;
+		if (ret < 0) {
+			memset(value, 0, len);
+			len = ret;
+			break;
+		}
+		if (ret == 0)
+			continue;
+		len += ret;
+		if (len+m->namelen+4 < size) {
+			char *v = value;
+			if (v[len-1]=='\n')
+				len--;
+			len += sprintf(value+len, " (%s)\n", m->module_name);
+		}
+	}
+	rcu_read_unlock();
+
+	return found_noneinval ? len : -EINVAL;
+}
+
+static struct module_entry *
+find_active_lsm(const char *name, int len)
+{
+	struct module_entry *m, *ret = NULL;
+
+	rcu_read_lock();
+	stack_for_each_entry(m, &stacked_modules, lsm_list) {
+		if (m->namelen == len && !strncmp(m->module_name, name, len)) {
+			ret = m;
+			break;
+		}
+	}
+
+	rcu_read_unlock();
+	return ret;
+}
+
+/*
+ * We assume input will be either
+ * "data" - in which case it goes to selinux, or
+ * "data (mod_name)" in which case the data goes to module mod_name.
+ */
+static int
+stacker_setprocattr(struct task_struct *p, char *name, void *value, size_t size)
+{
+	struct module_entry *callm = selinux_module;
+	char *realv = (char *)value;
+	size_t dsize = size;
+	int loc = 0, end_data = size;
+
+	if (list_empty(&stacked_modules))
+		return -EINVAL;
+
+	if (dsize && realv[dsize-1] == '\n')
+		dsize--;
+
+	if (!dsize || realv[dsize-1]!=')')
+		goto call;
+
+	dsize--;
+	loc = dsize-1;
+	while (loc && realv[loc]!='(')
+		loc--;
+	if (!loc)
+		goto call;
+
+	callm = find_active_lsm(realv+loc+1, dsize-loc-1);
+	if (!callm)
+		goto call;
+
+
+	loc--;
+	while (loc && realv[loc]==' ')
+		loc--;
+
+	end_data = loc+1;
+call:
+	if (!callm || !callm->module_operations.setprocattr)
+		return -EINVAL;
+
+	return callm->module_operations.setprocattr(p, name, value, end_data) +
+			(size-end_data);
+}
+
+/*
+ * Add the stacked module (as specified by name and ops).
+ * If the module is not compiled in, the symbol_get at the end will
+ * prevent the the module from being unloaded.
+*/
+static int stacker_register (const char *name, struct security_operations *ops)
+{
+	char *new_module_name;
+	struct module_entry *new_module_entry;
+	int namelen = strnlen(name, MAX_MODULE_NAME_LEN);
+	int ret = 0;
+
+	spin_lock(&stacker_lock);
+
+	if (forbid_stacker_register) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	new_module_name = kmalloc(namelen+1, GFP_KERNEL);
+	new_module_entry = kmalloc(sizeof(struct module_entry), GFP_KERNEL);
+	if (!new_module_name || !new_module_entry) {
+		printk(KERN_WARNING
+			"%s: Failure registering module - out of memory\n",
+			__FUNCTION__);
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	memset(new_module_entry, 0, sizeof(struct module_entry));
+	strncpy(new_module_name, name, namelen);
+	new_module_name[namelen] = '\0';
+	memcpy(&new_module_entry->module_operations, ops,
+			sizeof(struct security_operations));
+
+	new_module_entry->module_name = new_module_name;
+	new_module_entry->namelen = namelen;
+
+	if (!try_module_get(ops->owner)) {
+		printk(KERN_WARNING "%s: Error: could not module_get %s\n",
+				__FUNCTION__, name);
+	}
+	new_module_entry->owner = ops->owner;
+
+	INIT_LIST_HEAD(&new_module_entry->lsm_list);
+	INIT_LIST_HEAD(&new_module_entry->all_lsms);
+
+	rcu_read_lock();
+	if (!modules_registered) {
+		modules_registered++;
+		list_del_rcu(&default_module.lsm_list);
+	}
+	list_add_tail_rcu(&new_module_entry->lsm_list, &stacked_modules);
+	list_add_tail_rcu(&new_module_entry->all_lsms, &all_modules);
+	if (strcmp(name, "selinux") == 0)
+		selinux_module = new_module_entry;
+	rcu_read_unlock();
+
+	printk(KERN_INFO "%s: registered %s module\n", __FUNCTION__,
+		new_module_entry->module_name);
+
+	symbol_get(ops);
+
+out:
+	spin_unlock(&stacker_lock);
+	return ret;
+}
+
+/*
+ * find_lsm_module_by_name:
+ * Find a module by name.  Used by stacker_unregister.  Called with
+ * stacker spinlock held.
+ */
+static struct module_entry *
+find_lsm_with_namelen(const char *name, int len)
+{
+	struct module_entry *m, *ret = NULL;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(m, &all_modules, all_lsms) {
+		if (m->namelen == len && !strncmp(m->module_name, name, len)) {
+			ret = m;
+			break;
+		}
+	}
+	rcu_read_unlock();
+
+	return ret;
+}
+
+/*
+ * XXX TODO I need an all_modules list again to use here
+ */
+static int stacker_unregister (const char *name, struct security_operations *ops)
+{
+	struct module_entry *m;
+	int len = strnlen(name, MAX_MODULE_NAME_LEN);
+	int ret = 0;
+
+	spin_lock(&stacker_lock);
+	m = find_lsm_with_namelen(name, len);
+	if (!m) {
+		printk(KERN_WARNING "%s: could not find module %s.\n",
+				__FUNCTION__, name);
+		ret = -ENOENT;
+		goto out;
+	}
+	list_del_rcu(&m->all_lsms);
+	call_rcu(&m->m_rcu, stacker_del_module);
+
+out:
+	spin_unlock(&stacker_lock);
+	return 0;
+}
+
+static struct security_operations stacker_ops = {
+	.owner				= THIS_MODULE,
+	.ptrace				= stacker_ptrace,
+	.capget				= stacker_capget,
+	.capset_check			= stacker_capset_check,
+	.capset_set			= stacker_capset_set,
+	.acct				= stacker_acct,
+	.sysctl				= stacker_sysctl,
+	.capable			= stacker_capable,
+	.quotactl			= stacker_quotactl,
+	.quota_on			= stacker_quota_on,
+	.syslog				= stacker_syslog,
+	.settime			= stacker_settime,
+	.vm_enough_memory		= stacker_vm_enough_memory,
+
+	.bprm_alloc_security		= stacker_bprm_alloc_security,
+	.bprm_free_security		= stacker_bprm_free_security,
+	.bprm_apply_creds		= stacker_bprm_apply_creds,
+	.bprm_post_apply_creds		= stacker_bprm_post_apply_creds,
+	.bprm_set_security		= stacker_bprm_set_security,
+	.bprm_check_security		= stacker_bprm_check_security,
+	.bprm_secureexec		= stacker_bprm_secureexec,
+
+	.sb_alloc_security		= stacker_sb_alloc_security,
+	.sb_free_security		= stacker_sb_free_security,
+	.sb_copy_data			= stacker_sb_copy_data,
+	.sb_kern_mount			= stacker_sb_kern_mount,
+	.sb_statfs			= stacker_sb_statfs,
+	.sb_mount			= stacker_mount,
+	.sb_check_sb			= stacker_check_sb,
+	.sb_umount			= stacker_umount,
+	.sb_umount_close		= stacker_umount_close,
+	.sb_umount_busy			= stacker_umount_busy,
+	.sb_post_remount		= stacker_post_remount,
+	.sb_post_mountroot		= stacker_post_mountroot,
+	.sb_post_addmount		= stacker_post_addmount,
+	.sb_pivotroot			= stacker_pivotroot,
+	.sb_post_pivotroot		= stacker_post_pivotroot,
+
+	.inode_alloc_security		= stacker_inode_alloc_security,
+	.inode_free_security		= stacker_inode_free_security,
+	.inode_create			= stacker_inode_create,
+	.inode_post_create		= stacker_inode_post_create,
+	.inode_link			= stacker_inode_link,
+	.inode_post_link		= stacker_inode_post_link,
+	.inode_unlink			= stacker_inode_unlink,
+	.inode_symlink			= stacker_inode_symlink,
+	.inode_post_symlink		= stacker_inode_post_symlink,
+	.inode_mkdir			= stacker_inode_mkdir,
+	.inode_post_mkdir		= stacker_inode_post_mkdir,
+	.inode_rmdir			= stacker_inode_rmdir,
+	.inode_mknod			= stacker_inode_mknod,
+	.inode_post_mknod		= stacker_inode_post_mknod,
+	.inode_rename			= stacker_inode_rename,
+	.inode_post_rename		= stacker_inode_post_rename,
+	.inode_readlink			= stacker_inode_readlink,
+	.inode_follow_link		= stacker_inode_follow_link,
+	.inode_permission		= stacker_inode_permission,
+
+	.inode_setattr			= stacker_inode_setattr,
+	.inode_getattr			= stacker_inode_getattr,
+	.inode_delete			= stacker_inode_delete,
+	.inode_setxattr			= stacker_inode_setxattr,
+	.inode_post_setxattr		= stacker_inode_post_setxattr,
+	.inode_getxattr			= stacker_inode_getxattr,
+	.inode_listxattr		= stacker_inode_listxattr,
+	.inode_removexattr		= stacker_inode_removexattr,
+	.inode_getsecurity		= stacker_inode_getsecurity,
+	.inode_setsecurity		= stacker_inode_setsecurity,
+	.inode_listsecurity		= stacker_inode_listsecurity,
+
+	.file_permission		= stacker_file_permission,
+	.file_alloc_security		= stacker_file_alloc_security,
+	.file_free_security		= stacker_file_free_security,
+	.file_ioctl			= stacker_file_ioctl,
+	.file_mmap			= stacker_file_mmap,
+	.file_mprotect			= stacker_file_mprotect,
+	.file_lock			= stacker_file_lock,
+	.file_fcntl			= stacker_file_fcntl,
+	.file_set_fowner		= stacker_file_set_fowner,
+	.file_send_sigiotask		= stacker_file_send_sigiotask,
+	.file_receive			= stacker_file_receive,
+
+	.task_create			= stacker_task_create,
+	.task_alloc_security		= stacker_task_alloc_security,
+	.task_free_security		= stacker_task_free_security,
+	.task_setuid			= stacker_task_setuid,
+	.task_post_setuid		= stacker_task_post_setuid,
+	.task_setgid			= stacker_task_setgid,
+	.task_setpgid			= stacker_task_setpgid,
+	.task_getpgid			= stacker_task_getpgid,
+	.task_getsid			= stacker_task_getsid,
+	.task_setgroups			= stacker_task_setgroups,
+	.task_setnice			= stacker_task_setnice,
+	.task_setrlimit			= stacker_task_setrlimit,
+	.task_setscheduler		= stacker_task_setscheduler,
+	.task_getscheduler		= stacker_task_getscheduler,
+	.task_kill			= stacker_task_kill,
+	.task_wait			= stacker_task_wait,
+	.task_prctl			= stacker_task_prctl,
+	.task_reparent_to_init		= stacker_task_reparent_to_init,
+	.task_to_inode			= stacker_task_to_inode,
+
+	.ipc_permission			= stacker_ipc_permission,
+
+	.msg_msg_alloc_security		= stacker_msg_msg_alloc_security,
+	.msg_msg_free_security		= stacker_msg_msg_free_security,
+	.msg_queue_alloc_security	= stacker_msg_queue_alloc_security,
+	.msg_queue_free_security	= stacker_msg_queue_free_security,
+	.msg_queue_associate		= stacker_msg_queue_associate,
+	.msg_queue_msgctl		= stacker_msg_queue_msgctl,
+	.msg_queue_msgsnd		= stacker_msg_queue_msgsnd,
+	.msg_queue_msgrcv		= stacker_msg_queue_msgrcv,
+	.shm_alloc_security		= stacker_shm_alloc_security,
+	.shm_free_security		= stacker_shm_free_security,
+	.shm_associate			= stacker_shm_associate,
+	.shm_shmctl			= stacker_shm_shmctl,
+	.shm_shmat			= stacker_shm_shmat,
+
+	.sem_alloc_security		= stacker_sem_alloc_security,
+	.sem_free_security		= stacker_sem_free_security,
+	.sem_associate			= stacker_sem_associate,
+	.sem_semctl			= stacker_sem_semctl,
+	.sem_semop			= stacker_sem_semop,
+
+	.netlink_send			= stacker_netlink_send,
+	.netlink_recv			= stacker_netlink_recv,
+
+	.register_security		= stacker_register,
+	.unregister_security		= stacker_unregister,
+
+	.d_instantiate			= stacker_d_instantiate,
+	.getprocattr			= stacker_getprocattr,
+	.setprocattr			= stacker_setprocattr,
+
+#ifdef CONFIG_SECURITY_NETWORK
+	.unix_stream_connect		= stacker_unix_stream_connect,
+	.unix_may_send			= stacker_unix_may_send,
+	.socket_create			= stacker_socket_create,
+	.socket_post_create		= stacker_socket_post_create,
+	.socket_bind			= stacker_socket_bind,
+	.socket_connect			= stacker_socket_connect,
+	.socket_listen			= stacker_socket_listen,
+	.socket_accept			= stacker_socket_accept,
+	.socket_post_accept		= stacker_socket_post_accept,
+	.socket_sendmsg			= stacker_socket_sendmsg,
+	.socket_recvmsg			= stacker_socket_recvmsg,
+	.socket_getsockname		= stacker_socket_getsockname,
+	.socket_getpeername		= stacker_socket_getpeername,
+	.socket_getsockopt		= stacker_socket_getsockopt,
+	.socket_setsockopt		= stacker_socket_setsockopt,
+	.socket_shutdown		= stacker_socket_shutdown,
+	.socket_sock_rcv_skb		= stacker_socket_sock_rcv_skb,
+	.socket_getpeersec		= stacker_socket_getpeersec,
+	.sk_alloc_security		= stacker_sk_alloc_security,
+	.sk_free_security		= stacker_sk_free_security,
+#endif
+};
+
+
+static u64 stacker_u8_get(void *data)
+{
+	return *(u8 *)data;
+}
+
+static void lockdown_write(void *data, u64 val)
+{
+	forbid_stacker_register = 1;
+}
+
+/* respond to a request to unload a module */
+static ssize_t stacker_unload_write (struct file * file,
+			     const char __user * user_buf, size_t count,
+			     loff_t *ppos)
+{
+	struct module_entry *m;
+	int ret;
+	char *page;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (count <= 0 || count >= PAGE_SIZE)
+		return -EINVAL;
+
+	if (!modules_registered)
+		return -EINVAL;
+
+	if (*ppos != 0) /* No partial writes. */
+		return -EINVAL;
+
+	page = (char*)get_zeroed_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+
+	if (copy_from_user(page, user_buf, count)) {
+		ret = -EFAULT;
+		goto out_free;
+	}
+
+	spin_lock(&stacker_lock);
+	ret = strnlen(page, MAX_MODULE_NAME_LEN);
+	m = find_active_lsm(page, ret);
+
+	if (!m) {
+		printk(KERN_INFO "%s: could not find module %s.\n",
+			__FUNCTION__, page);
+		ret = -ENOENT;
+		goto out;
+	}
+
+	if (strcmp(m->module_name, "selinux") == 0)
+		selinux_module = NULL;
+
+	rcu_read_lock();
+	list_del_rcu(&m->lsm_list);
+	if (list_empty(&stacked_modules)) {
+		INIT_LIST_HEAD(&default_module.lsm_list);
+		list_add_tail_rcu(&default_module.lsm_list, &stacked_modules);
+		modules_registered = 0;
+	}
+	rcu_read_unlock();
+	module_put(m->owner);
+
+	ret = count;
+
+out:
+	spin_unlock(&stacker_lock);
+out_free:
+	free_page((unsigned long)page);
+
+	return ret;
+}
+
+static struct file_operations unload_fops = {
+	.write = stacker_unload_write,
+};
+ 
+DEFINE_SIMPLE_ATTRIBUTE(lockdown_fops, stacker_u8_get, lockdown_write, "%llu\n");
+
+/* list modules */
+static ssize_t listmodules_read ( struct file *filp, char __user *user_buf,
+				       size_t count, loff_t *ppos)
+{
+	ssize_t len = 0;
+	struct module_entry *m;
+	char *page;
+
+	page = (char *)__get_free_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+
+	rcu_read_lock();
+	stack_for_each_entry(m, &stacked_modules, lsm_list) {
+		len += snprintf(page+len, PAGE_SIZE - len, "%s\n",
+			m->module_name);
+	}
+	rcu_read_unlock();
+
+	if (len >= 0)
+		len = simple_read_from_buffer(user_buf, count, ppos, page, len);
+	free_page((unsigned long)page);
+
+	return len;
+ }
+
+static struct file_operations listmodules_fops = {
+	.read =		listmodules_read,
+};
+
+static void unregister_stacker_files(void);
+
+static void stop_responding_write(void *data, u64 val)
+{
+	unregister_stacker_files();
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(stopresp_fops, NULL, stop_responding_write, "%llu\n");
+
+static struct dentry	* stacker_dir_ino,
+			* lockdown_ino,
+			* listmodules_ino,
+			* stopresp_ino,
+			* modunload_ino;
+
+static void unregister_stacker_files(void)
+{
+	securityfs_remove(stacker_dir_ino);
+	securityfs_remove(lockdown_ino);
+	securityfs_remove(listmodules_ino);
+	securityfs_remove(stopresp_ino);
+	securityfs_remove(modunload_ino);
+}
+
+static int register_stacker_files(void)
+{
+	stacker_dir_ino = securityfs_create_dir("stacker", NULL);
+	if (!stacker_dir_ino)
+		return -EFAULT;
+
+	lockdown_ino = securityfs_create_file("lockdown", S_IRUGO | S_IWUSR,
+				stacker_dir_ino, &forbid_stacker_register,
+				&lockdown_fops);
+	listmodules_ino = securityfs_create_file("listmodules", S_IRUGO,
+				stacker_dir_ino, NULL, &listmodules_fops);
+	stopresp_ino = securityfs_create_file("stop_responding", S_IWUSR,
+				stacker_dir_ino, NULL, &stopresp_fops);
+	modunload_ino = securityfs_create_file("unload", S_IWUSR,
+				stacker_dir_ino, NULL, &unload_fops);
+
+	if (!lockdown_ino || !listmodules_ino || !stopresp_ino ||
+					!modunload_ino) {
+		unregister_stacker_files();
+		return -EFAULT;
+	}
+	return 0;
+}
+
+module_init(register_stacker_files);
+
+extern struct security_operations dummy_security_ops;
+#define DEFAULT_MODULE_NAME "dummy"
+
+static int __init stacker_init (void)
+{
+	forbid_stacker_register = 0;
+	spin_lock_init(&stacker_lock);
+
+	default_module.module_name = DEFAULT_MODULE_NAME;
+	default_module.namelen = strlen(DEFAULT_MODULE_NAME);
+	memcpy(&default_module.module_operations, &dummy_security_ops,
+			sizeof(struct security_operations));
+	INIT_LIST_HEAD(&default_module.lsm_list);
+	list_add_tail(&default_module.lsm_list, &stacked_modules);
+
+	if (register_security (&stacker_ops)) {
+		/*
+		 * stacking stacker is just a stupid idea, so don't ask
+		 * the current module to load us.
+		 */
+		printk (KERN_WARNING "Failure registering stacker module "
+			"as primary security module.\n");
+		return -EINVAL;
+	}
+
+	printk(KERN_NOTICE "LSM stacker registered as the primary "
+			   "security module\n");
+	return 0;
+}
+
+static void __exit stacker_exit (void)
+{
+	/*
+	 * Since we have no return value, we can't just say no.
+	 * Should probably force all child modules to exit somehow...
+	 */
+
+	unregister_stacker_files();
+	if (unregister_security (&stacker_ops))
+		printk(KERN_WARNING "Error unregistering LSM stacker.\n");
+	else
+		printk(KERN_WARNING "LSM stacker removed.\n");
+}
+
+security_initcall (stacker_init);
+module_exit (stacker_exit);
+
+MODULE_DESCRIPTION("LSM stacker - supports multiple simultaneous LSM modules");
+MODULE_AUTHOR("David A. Wheeler, Serge Hallyn");
+MODULE_LICENSE("GPL");

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [patch 8/15] lsm stacking v0.3: stackable capabilities lsm
  2005-07-27 18:19 ` [patch 1/15] lsm stacking v0.3: introduce securityfs serue
                     ` (5 preceding siblings ...)
  2005-07-27 18:24   ` [patch 7/15] lsm stacking v0.3: actual stacker module serue
@ 2005-07-27 18:25   ` serue
  2005-07-27 18:26   ` [patch 9/15] lsm stacking v0.3: selinux: update ->security structs serue
                     ` (6 subsequent siblings)
  13 siblings, 0 replies; 39+ messages in thread
From: serue @ 2005-07-27 18:25 UTC (permalink / raw)
  To: lkml
  Cc: Chris Wright, Stephen Smalley, James Morris, Andrew Morton,
	Michael Halcrow, David Safford, Reiner Sailer, Gerrit Huizenga,
	Emily Ratliff

This patch adds a version of the capability module which is safe to
stack with SELinux.  It notably does not define the inode_setxattr
and inode_removexattr hooks, as these otherwise prevent selinux from
saving file types to disk.

Signed-off-by: Serge Hallyn <serue@us.ibm.com>
--
 Kconfig         |   21 +++++++++++
 Makefile        |    1 
 cap_stack.c     |  101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 selinux/Kconfig |    2 +
 4 files changed, 124 insertions(+), 1 deletion(-)

Index: linux-2.6.13-rc3/security/Kconfig
===================================================================
--- linux-2.6.13-rc3.orig/security/Kconfig	2005-07-25 14:55:27.000000000 -0500
+++ linux-2.6.13-rc3/security/Kconfig	2005-07-25 14:55:32.000000000 -0500
@@ -56,10 +56,29 @@ config SECURITY_NETWORK
 config SECURITY_CAPABILITIES
 	tristate "Default Linux Capabilities"
 	depends on SECURITY
+	depends on SECURITY_SELINUX=n && SECURITY_CAP_STACK=n
 	help
-	  This enables the "default" Linux capabilities functionality.
+	  This enables the default Linux capabilities functionality.
+	  This module may not be used in conjunction with the stackable
+	  capabilities or SELinux modules.
+
 	  If you are unsure how to answer this question, answer Y.
 
+	  If you are using SELinux, answer N here and look at the
+	  Stackable Linux Capabilities instead.
+
+config SECURITY_CAP_STACK
+	tristate "Stackable Linux Capabilities"
+	depends on SECURITY
+	help
+	  This enables the "stackable" Linux capabilities functionality.
+
+	  If you are using SELinux, this option will be automatically
+	  enabled.
+
+	  If you are not using any other LSMs, answer N here and see above
+	  for the Default Linux Capabilities.
+
 config SECURITY_ROOTPLUG
 	tristate "Root Plug Support"
 	depends on USB && SECURITY
Index: linux-2.6.13-rc3/security/Makefile
===================================================================
--- linux-2.6.13-rc3.orig/security/Makefile	2005-07-25 14:55:27.000000000 -0500
+++ linux-2.6.13-rc3/security/Makefile	2005-07-25 14:55:32.000000000 -0500
@@ -16,5 +16,6 @@ obj-$(CONFIG_SECURITY)			+= security.o d
 # Must precede capability.o in order to stack properly.
 obj-$(CONFIG_SECURITY_SELINUX)		+= selinux/built-in.o
 obj-$(CONFIG_SECURITY_CAPABILITIES)	+= commoncap.o capability.o
+obj-$(CONFIG_SECURITY_CAP_STACK)	+= commoncap.o cap_stack.o
 obj-$(CONFIG_SECURITY_ROOTPLUG)		+= commoncap.o root_plug.o
 obj-$(CONFIG_SECURITY_SECLVL)		+= seclvl.o
Index: linux-2.6.13-rc3/security/cap_stack.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.13-rc3/security/cap_stack.c	2005-07-25 14:55:32.000000000 -0500
@@ -0,0 +1,101 @@
+/*
+ *  Capabilities Linux Security Module
+ *
+ *	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/security.h>
+#include <linux/file.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/pagemap.h>
+#include <linux/swap.h>
+#include <linux/smp_lock.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/ptrace.h>
+#include <linux/moduleparam.h>
+
+static struct security_operations capability_ops = {
+	.ptrace =			cap_ptrace,
+	.capget =			cap_capget,
+	.capset_check =			cap_capset_check,
+	.capset_set =			cap_capset_set,
+	.capable =			cap_capable,
+	.settime =			cap_settime,
+	.netlink_send =			cap_netlink_send,
+	.netlink_recv =			cap_netlink_recv,
+
+	.bprm_apply_creds =		cap_bprm_apply_creds,
+	.bprm_set_security =		cap_bprm_set_security,
+	.bprm_secureexec =		cap_bprm_secureexec,
+
+	.task_post_setuid =		cap_task_post_setuid,
+	.task_reparent_to_init =	cap_task_reparent_to_init,
+
+	.syslog =                       cap_syslog,
+
+	.vm_enough_memory =             cap_vm_enough_memory,
+};
+
+#define MY_NAME __stringify(KBUILD_MODNAME)
+
+/* flag to keep track of how we were registered */
+static int secondary;
+
+static int capability_disable;
+module_param_named(disable, capability_disable, int, 0);
+MODULE_PARM_DESC(disable, "To disable capabilities module set disable = 1");
+
+static int __init capability_init (void)
+{
+	if (capability_disable) {
+		printk(KERN_INFO "Capabilities disabled at initialization\n");
+		return 0;
+	}
+	/* register ourselves with the security framework */
+	if (register_security (&capability_ops)) {
+		/* try registering with primary module */
+		if (mod_reg_security (MY_NAME, &capability_ops)) {
+			printk (KERN_INFO "Failure registering capabilities "
+				"with primary security module.\n");
+			return -EINVAL;
+		}
+		secondary = 1;
+	}
+	printk (KERN_INFO "Capability LSM initialized%s\n",
+		secondary ? " as secondary" : "");
+	return 0;
+}
+
+static void __exit capability_exit (void)
+{
+	if (capability_disable)
+		return;
+	/* remove ourselves from the security framework */
+	if (secondary) {
+		if (mod_unreg_security (MY_NAME, &capability_ops))
+			printk (KERN_INFO "Failure unregistering capabilities "
+				"with primary module.\n");
+		return;
+	}
+
+	if (unregister_security (&capability_ops)) {
+		printk (KERN_INFO
+			"Failure unregistering capabilities with the kernel\n");
+	}
+}
+
+security_initcall (capability_init);
+module_exit (capability_exit);
+
+MODULE_DESCRIPTION("Standard Linux Capabilities Security Module");
+MODULE_LICENSE("GPL");
Index: linux-2.6.13-rc3/security/selinux/Kconfig
===================================================================
--- linux-2.6.13-rc3.orig/security/selinux/Kconfig	2005-06-17 14:48:29.000000000 -0500
+++ linux-2.6.13-rc3/security/selinux/Kconfig	2005-07-25 14:55:32.000000000 -0500
@@ -2,6 +2,8 @@ config SECURITY_SELINUX
 	bool "NSA SELinux Support"
 	depends on SECURITY && NET && INET
 	default n
+	select SECURITY_CAP_STACK
+	select SECURITY_STACKER
 	help
 	  This selects NSA Security-Enhanced Linux (SELinux).
 	  You will also need a policy configuration and a labeled filesystem.

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [patch 9/15] lsm stacking v0.3: selinux: update ->security structs
  2005-07-27 18:19 ` [patch 1/15] lsm stacking v0.3: introduce securityfs serue
                     ` (6 preceding siblings ...)
  2005-07-27 18:25   ` [patch 8/15] lsm stacking v0.3: stackable capabilities lsm serue
@ 2005-07-27 18:26   ` serue
  2005-07-27 18:26   ` [patch 10/15] lsm stacking v0.3: selinux: use security_*_value API serue
                     ` (5 subsequent siblings)
  13 siblings, 0 replies; 39+ messages in thread
From: serue @ 2005-07-27 18:26 UTC (permalink / raw)
  To: lkml
  Cc: Chris Wright, Stephen Smalley, James Morris, Andrew Morton,
	Michael Halcrow, David Safford, Reiner Sailer, Gerrit Huizenga,
	Emily Ratliff

Add the struct security_list lsm_list; to each structure which SELinux will be
appending to a kernel object.

Signed-off-by: Serge Hallyn <serue@us.ibm.com>
--
 objsec.h |   19 +++++++++++--------
 1 files changed, 11 insertions(+), 8 deletions(-)

Index: linux-2.6.13-rc3/security/selinux/include/objsec.h
===================================================================
--- linux-2.6.13-rc3.orig/security/selinux/include/objsec.h	2005-06-17 14:48:29.000000000 -0500
+++ linux-2.6.13-rc3/security/selinux/include/objsec.h	2005-07-25 14:55:34.000000000 -0500
@@ -23,11 +23,14 @@
 #include <linux/fs.h>
 #include <linux/binfmts.h>
 #include <linux/in.h>
+#include <linux/security.h>
 #include "flask.h"
 #include "avc.h"
 
+#define SELINUX_LSM_ID 0xB65
+
 struct task_security_struct {
-        unsigned long magic;           /* magic number for this module */
+	struct security_list lsm_list; /* chained security objects */
 	struct task_struct *task;      /* back pointer to task object */
 	u32 osid;            /* SID prior to last execve */
 	u32 sid;             /* current SID */
@@ -37,7 +40,7 @@ struct task_security_struct {
 };
 
 struct inode_security_struct {
-	unsigned long magic;           /* magic number for this module */
+	struct security_list lsm_list; /* chained security objects */
         struct inode *inode;           /* back pointer to inode object */
 	struct list_head list;         /* list of inode_security_struct */
 	u32 task_sid;        /* SID of creating task */
@@ -49,14 +52,14 @@ struct inode_security_struct {
 };
 
 struct file_security_struct {
-	unsigned long magic;            /* magic number for this module */
+	struct security_list lsm_list; /* chained security objects */
 	struct file *file;              /* back pointer to file object */
 	u32 sid;              /* SID of open file description */
 	u32 fown_sid;         /* SID of file owner (for SIGIO) */
 };
 
 struct superblock_security_struct {
-	unsigned long magic;            /* magic number for this module */
+	struct security_list lsm_list; /* chained security objects */
 	struct super_block *sb;         /* back pointer to sb object */
 	struct list_head list;          /* list of superblock_security_struct */
 	u32 sid;              /* SID of file system */
@@ -70,20 +73,20 @@ struct superblock_security_struct {
 };
 
 struct msg_security_struct {
-        unsigned long magic;		/* magic number for this module */
+ 	struct security_list lsm_list; /* chained security objects */
 	struct msg_msg *msg;		/* back pointer */
 	u32 sid;              /* SID of message */
 };
 
 struct ipc_security_struct {
-        unsigned long magic;		/* magic number for this module */
+ 	struct security_list lsm_list; /* chained security objects */
 	struct kern_ipc_perm *ipc_perm; /* back pointer */
 	u16 sclass;	/* security class of this object */
 	u32 sid;              /* SID of IPC resource */
 };
 
 struct bprm_security_struct {
-	unsigned long magic;           /* magic number for this module */
+	struct security_list lsm_list; /* chained security objects */
 	struct linux_binprm *bprm;     /* back pointer to bprm object */
 	u32 sid;                       /* SID for transformed process */
 	unsigned char set;
@@ -102,7 +105,7 @@ struct netif_security_struct {
 };
 
 struct sk_security_struct {
-	unsigned long magic;		/* magic number for this module */
+	struct security_list lsm_list; /* chained security objects */
 	struct sock *sk;		/* back pointer to sk object */
 	u32 peer_sid;			/* SID of peer */
 };

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [patch 10/15] lsm stacking v0.3: selinux: use security_*_value API
  2005-07-27 18:19 ` [patch 1/15] lsm stacking v0.3: introduce securityfs serue
                     ` (7 preceding siblings ...)
  2005-07-27 18:26   ` [patch 9/15] lsm stacking v0.3: selinux: update ->security structs serue
@ 2005-07-27 18:26   ` serue
  2005-07-27 18:27   ` [patch 11/15] lsm stacking v0.3: selinux: remove secondary support serue
                     ` (4 subsequent siblings)
  13 siblings, 0 replies; 39+ messages in thread
From: serue @ 2005-07-27 18:26 UTC (permalink / raw)
  To: lkml
  Cc: Chris Wright, Stephen Smalley, James Morris, Andrew Morton,
	Michael Halcrow, David Safford, Reiner Sailer, Gerrit Huizenga,
	Emily Ratliff

Convert SELinux to use the security_*_value_type API for storing and using
information appended to kernel objects, instead of directly using the void*.

Signed-off-by: Serge Hallyn <serue@us.ibm.com>
--
 hooks.c     |  446 +++++++++++++++++++++++++++++++++++++++---------------------
 selinuxfs.c |   10 -
 2 files changed, 300 insertions(+), 156 deletions(-)

Index: linux-2.6.13-rc3/security/selinux/hooks.c
===================================================================
--- linux-2.6.13-rc3.orig/security/selinux/hooks.c	2005-07-25 14:40:42.000000000 -0500
+++ linux-2.6.13-rc3/security/selinux/hooks.c	2005-07-25 14:55:39.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/security.h>
+#include <linux/security-stack.h>
 #include <linux/xattr.h>
 #include <linux/capability.h>
 #include <linux/unistd.h>
@@ -127,30 +128,30 @@ static int task_alloc_security(struct ta
 		return -ENOMEM;
 
 	memset(tsec, 0, sizeof(struct task_security_struct));
-	tsec->magic = SELINUX_MAGIC;
 	tsec->task = task;
 	tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;
-	task->security = tsec;
+	security_set_value_type(&task->security, SELINUX_LSM_ID, tsec);
 
 	return 0;
 }
 
 static void task_free_security(struct task_struct *task)
 {
-	struct task_security_struct *tsec = task->security;
-
-	if (!tsec || tsec->magic != SELINUX_MAGIC)
-		return;
+	struct task_security_struct *tsec;
+	
+	tsec = security_del_value_type(&task->security, SELINUX_LSM_ID,
+		struct task_security_struct);
 
-	task->security = NULL;
 	kfree(tsec);
 }
 
 static int inode_alloc_security(struct inode *inode)
 {
-	struct task_security_struct *tsec = current->security;
+	struct task_security_struct *tsec;
 	struct inode_security_struct *isec;
 
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
 	isec = kmalloc(sizeof(struct inode_security_struct), GFP_KERNEL);
 	if (!isec)
 		return -ENOMEM;
@@ -158,68 +159,71 @@ static int inode_alloc_security(struct i
 	memset(isec, 0, sizeof(struct inode_security_struct));
 	init_MUTEX(&isec->sem);
 	INIT_LIST_HEAD(&isec->list);
-	isec->magic = SELINUX_MAGIC;
 	isec->inode = inode;
 	isec->sid = SECINITSID_UNLABELED;
 	isec->sclass = SECCLASS_FILE;
-	if (tsec && tsec->magic == SELINUX_MAGIC)
+	if (tsec)
 		isec->task_sid = tsec->sid;
 	else
 		isec->task_sid = SECINITSID_UNLABELED;
-	inode->i_security = isec;
+	security_set_value_type(&inode->i_security, SELINUX_LSM_ID, isec);
 
 	return 0;
 }
 
 static void inode_free_security(struct inode *inode)
 {
-	struct inode_security_struct *isec = inode->i_security;
-	struct superblock_security_struct *sbsec = inode->i_sb->s_security;
+	struct inode_security_struct *isec;
+	struct superblock_security_struct *sbsec;
 
-	if (!isec || isec->magic != SELINUX_MAGIC)
+	isec = security_del_value_type(&inode->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct);
+	if (!isec)
 		return;
 
+	sbsec = security_get_value_type(&inode->i_sb->s_security,
+		SELINUX_LSM_ID, struct superblock_security_struct);
+
 	spin_lock(&sbsec->isec_lock);
 	if (!list_empty(&isec->list))
 		list_del_init(&isec->list);
 	spin_unlock(&sbsec->isec_lock);
 
-	inode->i_security = NULL;
 	kfree(isec);
 }
 
 static int file_alloc_security(struct file *file)
 {
-	struct task_security_struct *tsec = current->security;
+	struct task_security_struct *tsec;
 	struct file_security_struct *fsec;
 
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
 	fsec = kmalloc(sizeof(struct file_security_struct), GFP_ATOMIC);
 	if (!fsec)
 		return -ENOMEM;
 
 	memset(fsec, 0, sizeof(struct file_security_struct));
-	fsec->magic = SELINUX_MAGIC;
 	fsec->file = file;
-	if (tsec && tsec->magic == SELINUX_MAGIC) {
+	if (tsec) {
 		fsec->sid = tsec->sid;
 		fsec->fown_sid = tsec->sid;
 	} else {
 		fsec->sid = SECINITSID_UNLABELED;
 		fsec->fown_sid = SECINITSID_UNLABELED;
 	}
-	file->f_security = fsec;
+	security_set_value_type(&file->f_security, SELINUX_LSM_ID, fsec);
 
 	return 0;
 }
 
 static void file_free_security(struct file *file)
 {
-	struct file_security_struct *fsec = file->f_security;
+	struct file_security_struct *fsec;
 
-	if (!fsec || fsec->magic != SELINUX_MAGIC)
-		return;
+	fsec = security_del_value_type(&file->f_security, SELINUX_LSM_ID,
+		struct file_security_struct);
 
-	file->f_security = NULL;
 	kfree(fsec);
 }
 
@@ -236,20 +240,21 @@ static int superblock_alloc_security(str
 	INIT_LIST_HEAD(&sbsec->list);
 	INIT_LIST_HEAD(&sbsec->isec_head);
 	spin_lock_init(&sbsec->isec_lock);
-	sbsec->magic = SELINUX_MAGIC;
 	sbsec->sb = sb;
 	sbsec->sid = SECINITSID_UNLABELED;
 	sbsec->def_sid = SECINITSID_FILE;
-	sb->s_security = sbsec;
+	security_set_value_type(&sb->s_security, SELINUX_LSM_ID, sbsec);
 
 	return 0;
 }
 
 static void superblock_free_security(struct super_block *sb)
 {
-	struct superblock_security_struct *sbsec = sb->s_security;
+	struct superblock_security_struct *sbsec;
 
-	if (!sbsec || sbsec->magic != SELINUX_MAGIC)
+	sbsec = security_del_value_type(&sb->s_security, SELINUX_LSM_ID,
+		struct superblock_security_struct);
+	if (!sbsec)
 		return;
 
 	spin_lock(&sb_security_lock);
@@ -257,7 +262,6 @@ static void superblock_free_security(str
 		list_del_init(&sbsec->list);
 	spin_unlock(&sb_security_lock);
 
-	sb->s_security = NULL;
 	kfree(sbsec);
 }
 
@@ -274,22 +278,23 @@ static int sk_alloc_security(struct sock
 		return -ENOMEM;
 
 	memset(ssec, 0, sizeof(*ssec));
-	ssec->magic = SELINUX_MAGIC;
 	ssec->sk = sk;
 	ssec->peer_sid = SECINITSID_UNLABELED;
-	sk->sk_security = ssec;
+	security_set_value_type(&sk->sk_security, SELINUX_LSM_ID, ssec);
 
 	return 0;
 }
 
 static void sk_free_security(struct sock *sk)
 {
-	struct sk_security_struct *ssec = sk->sk_security;
+	struct sk_security_struct *ssec;
 
-	if (sk->sk_family != PF_UNIX || ssec->magic != SELINUX_MAGIC)
+	if (sk->sk_family != PF_UNIX)
 		return;
 
-	sk->sk_security = NULL;
+	ssec = security_del_value_type(&sk->sk_security, SELINUX_LSM_ID,
+		struct sk_security_struct);
+
 	kfree(ssec);
 }
 #endif	/* CONFIG_SECURITY_NETWORK */
@@ -336,8 +341,13 @@ static int try_context_mount(struct supe
 	const char *name;
 	u32 sid;
 	int alloc = 0, rc = 0, seen = 0;
-	struct task_security_struct *tsec = current->security;
-	struct superblock_security_struct *sbsec = sb->s_security;
+	struct task_security_struct *tsec;
+	struct superblock_security_struct *sbsec;
+
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	sbsec = security_get_value_type(&sb->s_security, SELINUX_LSM_ID,
+		struct superblock_security_struct);
 
 	if (!data)
 		goto out;
@@ -503,11 +513,14 @@ out:
 
 static int superblock_doinit(struct super_block *sb, void *data)
 {
-	struct superblock_security_struct *sbsec = sb->s_security;
+	struct superblock_security_struct *sbsec;
 	struct dentry *root = sb->s_root;
 	struct inode *inode = root->d_inode;
 	int rc = 0;
 
+	sbsec = security_get_value_type(&sb->s_security, SELINUX_LSM_ID,
+		struct superblock_security_struct);
+
 	down(&sbsec->sem);
 	if (sbsec->initialized)
 		goto out;
@@ -732,7 +745,7 @@ static int selinux_proc_get_sid(struct p
 static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
 {
 	struct superblock_security_struct *sbsec = NULL;
-	struct inode_security_struct *isec = inode->i_security;
+	struct inode_security_struct *isec;
 	u32 sid;
 	struct dentry *dentry;
 #define INITCONTEXTLEN 255
@@ -741,6 +754,9 @@ static int inode_doinit_with_dentry(stru
 	int rc = 0;
 	int hold_sem = 0;
 
+	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct);
+
 	if (isec->initialized)
 		goto out;
 
@@ -749,7 +765,8 @@ static int inode_doinit_with_dentry(stru
 	if (isec->initialized)
 		goto out;
 
-	sbsec = inode->i_sb->s_security;
+	sbsec = security_get_value_type(&inode->i_sb->s_security,
+		SELINUX_LSM_ID, struct superblock_security_struct);
 	if (!sbsec->initialized) {
 		/* Defer initialization until selinux_complete_init,
 		   after the initial policy is loaded and the security
@@ -923,8 +940,10 @@ static int task_has_perm(struct task_str
 {
 	struct task_security_struct *tsec1, *tsec2;
 
-	tsec1 = tsk1->security;
-	tsec2 = tsk2->security;
+	tsec1 = security_get_value_type(&tsk1->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	tsec2 = security_get_value_type(&tsk2->security, SELINUX_LSM_ID,
+		struct task_security_struct);
 	return avc_has_perm(tsec1->sid, tsec2->sid,
 			    SECCLASS_PROCESS, perms, NULL);
 }
@@ -936,7 +955,8 @@ static int task_has_capability(struct ta
 	struct task_security_struct *tsec;
 	struct avc_audit_data ad;
 
-	tsec = tsk->security;
+	tsec = security_get_value_type(&tsk->security, SELINUX_LSM_ID,
+		struct task_security_struct);
 
 	AVC_AUDIT_DATA_INIT(&ad,CAP);
 	ad.tsk = tsk;
@@ -952,7 +972,8 @@ static int task_has_system(struct task_s
 {
 	struct task_security_struct *tsec;
 
-	tsec = tsk->security;
+	tsec = security_get_value_type(&tsk->security, SELINUX_LSM_ID,
+		struct task_security_struct);
 
 	return avc_has_perm(tsec->sid, SECINITSID_KERNEL,
 			    SECCLASS_SYSTEM, perms, NULL);
@@ -970,8 +991,10 @@ static int inode_has_perm(struct task_st
 	struct inode_security_struct *isec;
 	struct avc_audit_data ad;
 
-	tsec = tsk->security;
-	isec = inode->i_security;
+	tsec = security_get_value_type(&tsk->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct);
 
 	if (!adp) {
 		adp = &ad;
@@ -1010,14 +1033,19 @@ static inline int file_has_perm(struct t
 				struct file *file,
 				u32 av)
 {
-	struct task_security_struct *tsec = tsk->security;
-	struct file_security_struct *fsec = file->f_security;
+	struct task_security_struct *tsec;
+	struct file_security_struct *fsec;
 	struct vfsmount *mnt = file->f_vfsmnt;
 	struct dentry *dentry = file->f_dentry;
 	struct inode *inode = dentry->d_inode;
 	struct avc_audit_data ad;
 	int rc;
 
+	tsec = security_get_value_type(&tsk->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	fsec = security_get_value_type(&file->f_security, SELINUX_LSM_ID,
+		struct file_security_struct);
+
 	AVC_AUDIT_DATA_INIT(&ad, FS);
 	ad.u.fs.mnt = mnt;
 	ad.u.fs.dentry = dentry;
@@ -1050,9 +1078,12 @@ static int may_create(struct inode *dir,
 	struct avc_audit_data ad;
 	int rc;
 
-	tsec = current->security;
-	dsec = dir->i_security;
-	sbsec = dir->i_sb->s_security;
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	dsec = security_get_value_type(&dir->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct);
+	sbsec = security_get_value_type(&dir->i_sb->s_security, SELINUX_LSM_ID,
+		struct superblock_security_struct);
 
 	AVC_AUDIT_DATA_INIT(&ad, FS);
 	ad.u.fs.dentry = dentry;
@@ -1097,9 +1128,12 @@ static int may_link(struct inode *dir,
 	u32 av;
 	int rc;
 
-	tsec = current->security;
-	dsec = dir->i_security;
-	isec = dentry->d_inode->i_security;
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	dsec = security_get_value_type(&dir->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct);
+	isec = security_get_value_type(&dentry->d_inode->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct);
 
 	AVC_AUDIT_DATA_INIT(&ad, FS);
 	ad.u.fs.dentry = dentry;
@@ -1141,11 +1175,15 @@ static inline int may_rename(struct inod
 	int old_is_dir, new_is_dir;
 	int rc;
 
-	tsec = current->security;
-	old_dsec = old_dir->i_security;
-	old_isec = old_dentry->d_inode->i_security;
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	old_dsec = security_get_value_type(&old_dir->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct);
+	old_isec = security_get_value_type(&old_dentry->d_inode->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct);
 	old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
-	new_dsec = new_dir->i_security;
+	new_dsec = security_get_value_type(&new_dir->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct);
 
 	AVC_AUDIT_DATA_INIT(&ad, FS);
 
@@ -1173,7 +1211,8 @@ static inline int may_rename(struct inod
 	if (rc)
 		return rc;
 	if (new_dentry->d_inode) {
-		new_isec = new_dentry->d_inode->i_security;
+		new_isec = security_get_value_type(&new_dentry->d_inode->i_security,
+			SELINUX_LSM_ID, struct inode_security_struct);
 		new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
 		rc = avc_has_perm(tsec->sid, new_isec->sid,
 				  new_isec->sclass,
@@ -1194,8 +1233,10 @@ static int superblock_has_perm(struct ta
 	struct task_security_struct *tsec;
 	struct superblock_security_struct *sbsec;
 
-	tsec = tsk->security;
-	sbsec = sb->s_security;
+	tsec = security_get_value_type(&tsk->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	sbsec = security_get_value_type(&sb->s_security, SELINUX_LSM_ID,
+		struct superblock_security_struct);
 	return avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
 			    perms, ad);
 }
@@ -1248,8 +1289,13 @@ static inline u32 file_to_av(struct file
 /* Set an inode's SID to a specified value. */
 static int inode_security_set_sid(struct inode *inode, u32 sid)
 {
-	struct inode_security_struct *isec = inode->i_security;
-	struct superblock_security_struct *sbsec = inode->i_sb->s_security;
+	struct inode_security_struct *isec;
+	struct superblock_security_struct *sbsec;
+
+	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct);
+	sbsec = security_get_value_type(&inode->i_sb->s_security,
+		SELINUX_LSM_ID, struct superblock_security_struct);
 
 	if (!sbsec->initialized) {
 		/* Defer initialization to selinux_complete_init. */
@@ -1278,9 +1324,12 @@ static int post_create(struct inode *dir
 	unsigned int len;
 	int rc;
 
-	tsec = current->security;
-	dsec = dir->i_security;
-	sbsec = dir->i_sb->s_security;
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	dsec = security_get_value_type(&dir->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct);
+	sbsec = security_get_value_type(&dir->i_sb->s_security, SELINUX_LSM_ID,
+		struct superblock_security_struct);
 
 	inode = dentry->d_inode;
 	if (!inode) {
@@ -1347,13 +1396,17 @@ static int post_create(struct inode *dir
 
 static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
 {
-	struct task_security_struct *psec = parent->security;
-	struct task_security_struct *csec = child->security;
+	struct task_security_struct *psec;
+	struct task_security_struct *csec;
 	int rc;
 
 	rc = secondary_ops->ptrace(parent,child);
 	if (rc)
 		return rc;
+	psec = security_get_value_type(&parent->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	csec = security_get_value_type(&child->security, SELINUX_LSM_ID,
+		struct task_security_struct);
 
 	rc = task_has_perm(parent, child, PROCESS__PTRACE);
 	/* Save the SID of the tracing process for later use in apply_creds. */
@@ -1415,7 +1468,8 @@ static int selinux_sysctl(ctl_table *tab
 	if (rc)
 		return rc;
 
-	tsec = current->security;
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
 
 	rc = selinux_proc_get_sid(table->de, (op == 001) ?
 	                          SECCLASS_DIR : SECCLASS_FILE, &tsid);
@@ -1550,12 +1604,11 @@ static int selinux_bprm_alloc_security(s
 		return -ENOMEM;
 
 	memset(bsec, 0, sizeof *bsec);
-	bsec->magic = SELINUX_MAGIC;
 	bsec->bprm = bprm;
 	bsec->sid = SECINITSID_UNLABELED;
 	bsec->set = 0;
 
-	bprm->security = bsec;
+	security_set_value_type(&bprm->security, SELINUX_LSM_ID, bsec);
 	return 0;
 }
 
@@ -1573,13 +1626,16 @@ static int selinux_bprm_set_security(str
 	if (rc)
 		return rc;
 
-	bsec = bprm->security;
+	bsec = security_get_value_type(&bprm->security, SELINUX_LSM_ID,
+		struct bprm_security_struct);
 
 	if (bsec->set)
 		return 0;
 
-	tsec = current->security;
-	isec = inode->i_security;
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct);
 
 	/* Default to the current task SID. */
 	bsec->sid = tsec->sid;
@@ -1642,9 +1698,11 @@ static int selinux_bprm_check_security (
 
 static int selinux_bprm_secureexec (struct linux_binprm *bprm)
 {
-	struct task_security_struct *tsec = current->security;
+	struct task_security_struct *tsec;
 	int atsecure = 0;
 
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
 	if (tsec->osid != tsec->sid) {
 		/* Enable secure mode for SIDs transitions unless
 		   the noatsecure permission is granted between
@@ -1659,8 +1717,11 @@ static int selinux_bprm_secureexec (stru
 
 static void selinux_bprm_free_security(struct linux_binprm *bprm)
 {
-	kfree(bprm->security);
-	bprm->security = NULL;
+ 	struct bprm_security_struct *bsec;
+
+ 	bsec = security_del_value_type(&bprm->security, SELINUX_LSM_ID,
+ 			struct bprm_security_struct);
+	kfree(bsec);
 }
 
 extern struct vfsmount *selinuxfs_mount;
@@ -1757,9 +1818,10 @@ static void selinux_bprm_apply_creds(str
 
 	secondary_ops->bprm_apply_creds(bprm, unsafe);
 
-	tsec = current->security;
-
-	bsec = bprm->security;
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	bsec = security_get_value_type(&bprm->security, SELINUX_LSM_ID,
+		struct bprm_security_struct);
 	sid = bsec->sid;
 
 	tsec->osid = tsec->sid;
@@ -1802,8 +1864,10 @@ static void selinux_bprm_post_apply_cred
 	struct bprm_security_struct *bsec;
 	int rc, i;
 
-	tsec = current->security;
-	bsec = bprm->security;
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	bsec = security_get_value_type(&bprm->security, SELINUX_LSM_ID,
+		struct bprm_security_struct);
 
 	if (bsec->unsafe) {
 		force_sig_specific(SIGKILL, current);
@@ -2163,9 +2227,9 @@ static int selinux_inode_getattr(struct 
 
 static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags)
 {
-	struct task_security_struct *tsec = current->security;
+	struct task_security_struct *tsec;
 	struct inode *inode = dentry->d_inode;
-	struct inode_security_struct *isec = inode->i_security;
+	struct inode_security_struct *isec;
 	struct superblock_security_struct *sbsec;
 	struct avc_audit_data ad;
 	u32 newsid;
@@ -2185,7 +2249,8 @@ static int selinux_inode_setxattr(struct
 		return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
 	}
 
-	sbsec = inode->i_sb->s_security;
+	sbsec = security_get_value_type(&inode->i_sb->s_security,
+		SELINUX_LSM_ID, struct superblock_security_struct);
 	if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
 		return -EOPNOTSUPP;
 
@@ -2195,6 +2260,10 @@ static int selinux_inode_setxattr(struct
 	AVC_AUDIT_DATA_INIT(&ad,FS);
 	ad.u.fs.dentry = dentry;
 
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct);
 	rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass,
 			  FILE__RELABELFROM, &ad);
 	if (rc)
@@ -2225,10 +2294,13 @@ static void selinux_inode_post_setxattr(
                                         void *value, size_t size, int flags)
 {
 	struct inode *inode = dentry->d_inode;
-	struct inode_security_struct *isec = inode->i_security;
+	struct inode_security_struct *isec;
 	u32 newsid;
 	int rc;
 
+	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct);
+
 	if (strcmp(name, XATTR_NAME_SELINUX)) {
 		/* Not an attribute we recognize, so nothing to do. */
 		return;
@@ -2248,7 +2320,10 @@ static void selinux_inode_post_setxattr(
 static int selinux_inode_getxattr (struct dentry *dentry, char *name)
 {
 	struct inode *inode = dentry->d_inode;
-	struct superblock_security_struct *sbsec = inode->i_sb->s_security;
+	struct superblock_security_struct *sbsec;
+	
+	sbsec = security_get_value_type(&inode->i_sb->s_security,
+		SELINUX_LSM_ID, struct superblock_security_struct);
 
 	if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
 		return -EOPNOTSUPP;
@@ -2285,7 +2360,7 @@ static int selinux_inode_removexattr (st
 
 static int selinux_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size)
 {
-	struct inode_security_struct *isec = inode->i_security;
+	struct inode_security_struct *isec;
 	char *context;
 	unsigned len;
 	int rc;
@@ -2295,6 +2370,9 @@ static int selinux_inode_getsecurity(str
 	if (strcmp(name, XATTR_SELINUX_SUFFIX))
 		return -EOPNOTSUPP;
 
+	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct);
+
 	rc = security_sid_to_context(isec->sid, &context, &len);
 	if (rc)
 		return rc;
@@ -2315,13 +2393,16 @@ static int selinux_inode_getsecurity(str
 static int selinux_inode_setsecurity(struct inode *inode, const char *name,
                                      const void *value, size_t size, int flags)
 {
-	struct inode_security_struct *isec = inode->i_security;
+	struct inode_security_struct *isec;
 	u32 newsid;
 	int rc;
 
 	if (strcmp(name, XATTR_SELINUX_SUFFIX))
 		return -EOPNOTSUPP;
 
+	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct);
+
 	if (!value || !size)
 		return -EACCES;
 
@@ -2568,8 +2649,10 @@ static int selinux_file_set_fowner(struc
 	struct task_security_struct *tsec;
 	struct file_security_struct *fsec;
 
-	tsec = current->security;
-	fsec = file->f_security;
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	fsec = security_get_value_type(&file->f_security, SELINUX_LSM_ID,
+		struct file_security_struct);
 	fsec->fown_sid = tsec->sid;
 
 	return 0;
@@ -2586,8 +2669,10 @@ static int selinux_file_send_sigiotask(s
 	/* struct fown_struct is never outside the context of a struct file */
         file = (struct file *)((long)fown - offsetof(struct file,f_owner));
 
-	tsec = tsk->security;
-	fsec = file->f_security;
+	tsec = security_get_value_type(&tsk->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	fsec = security_get_value_type(&file->f_security, SELINUX_LSM_ID,
+		struct file_security_struct);
 
 	if (!signum)
 		perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
@@ -2621,12 +2706,14 @@ static int selinux_task_alloc_security(s
 	struct task_security_struct *tsec1, *tsec2;
 	int rc;
 
-	tsec1 = current->security;
+	tsec1 = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
 
 	rc = task_alloc_security(tsk);
 	if (rc)
 		return rc;
-	tsec2 = tsk->security;
+	tsec2 = security_get_value_type(&tsk->security, SELINUX_LSM_ID,
+		struct task_security_struct);
 
 	tsec2->osid = tsec1->osid;
 	tsec2->sid = tsec1->sid;
@@ -2779,7 +2866,8 @@ static void selinux_task_reparent_to_ini
 
 	secondary_ops->task_reparent_to_init(p);
 
-	tsec = p->security;
+	tsec = security_get_value_type(&p->security, SELINUX_LSM_ID,
+		struct task_security_struct);
 	tsec->osid = tsec->sid;
 	tsec->sid = SECINITSID_KERNEL;
 	return;
@@ -2788,8 +2876,13 @@ static void selinux_task_reparent_to_ini
 static void selinux_task_to_inode(struct task_struct *p,
 				  struct inode *inode)
 {
-	struct task_security_struct *tsec = p->security;
-	struct inode_security_struct *isec = inode->i_security;
+	struct task_security_struct *tsec;
+	struct inode_security_struct *isec;
+
+	tsec = security_get_value_type(&p->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct);
 
 	isec->sid = tsec->sid;
 	isec->initialized = 1;
@@ -2957,8 +3050,10 @@ static int socket_has_perm(struct task_s
 	struct avc_audit_data ad;
 	int err = 0;
 
-	tsec = task->security;
-	isec = SOCK_INODE(sock)->i_security;
+	tsec = security_get_value_type(&task->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	isec = security_get_value_type(&SOCK_INODE(sock)->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct);
 
 	if (isec->sid == SECINITSID_KERNEL)
 		goto out;
@@ -2980,7 +3075,8 @@ static int selinux_socket_create(int fam
 	if (kern)
 		goto out;
 
-	tsec = current->security;
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
 	err = avc_has_perm(tsec->sid, tsec->sid,
 			   socket_type_to_security_class(family, type,
 			   protocol), SOCKET__CREATE, NULL);
@@ -2995,9 +3091,11 @@ static void selinux_socket_post_create(s
 	struct inode_security_struct *isec;
 	struct task_security_struct *tsec;
 
-	isec = SOCK_INODE(sock)->i_security;
+	isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct);
 
-	tsec = current->security;
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
 	isec->sclass = socket_type_to_security_class(family, type, protocol);
 	isec->sid = kern ? SECINITSID_KERNEL : tsec->sid;
 	isec->initialized = 1;
@@ -3035,8 +3133,10 @@ static int selinux_socket_bind(struct so
 		struct sock *sk = sock->sk;
 		u32 sid, node_perm, addrlen;
 
-		tsec = current->security;
-		isec = SOCK_INODE(sock)->i_security;
+		tsec = security_get_value_type(&current->security,
+			SELINUX_LSM_ID, struct task_security_struct);
+		isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
+			SELINUX_LSM_ID, struct inode_security_struct);
 
 		if (family == PF_INET) {
 			addr4 = (struct sockaddr_in *)address;
@@ -3114,7 +3214,8 @@ static int selinux_socket_connect(struct
 	/*
 	 * If a TCP socket, check name_connect permission for the port.
 	 */
-	isec = SOCK_INODE(sock)->i_security;
+	isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct);
 	if (isec->sclass == SECCLASS_TCP_SOCKET) {
 		struct sock *sk = sock->sk;
 		struct avc_audit_data ad;
@@ -3168,9 +3269,11 @@ static int selinux_socket_accept(struct 
 	if (err)
 		return err;
 
-	newisec = SOCK_INODE(newsock)->i_security;
+	newisec = security_get_value_type(&SOCK_INODE(newsock)->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct);
 
-	isec = SOCK_INODE(sock)->i_security;
+	isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct);
 	newisec->sclass = isec->sclass;
 	newisec->sid = isec->sid;
 	newisec->initialized = 1;
@@ -3230,8 +3333,10 @@ static int selinux_socket_unix_stream_co
 	if (err)
 		return err;
 
-	isec = SOCK_INODE(sock)->i_security;
-	other_isec = SOCK_INODE(other)->i_security;
+	isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct);
+	other_isec = security_get_value_type(&SOCK_INODE(other)->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct);
 
 	AVC_AUDIT_DATA_INIT(&ad,NET);
 	ad.u.net.sk = other->sk;
@@ -3243,11 +3348,13 @@ static int selinux_socket_unix_stream_co
 		return err;
 
 	/* connecting socket */
-	ssec = sock->sk->sk_security;
+	ssec = security_get_value_type(&sock->sk->sk_security, SELINUX_LSM_ID,
+		struct sk_security_struct);
 	ssec->peer_sid = other_isec->sid;
 	
 	/* server child socket */
-	ssec = newsk->sk_security;
+	ssec = security_get_value_type(&newsk->sk_security, SELINUX_LSM_ID,
+		struct sk_security_struct);
 	ssec->peer_sid = isec->sid;
 	
 	return 0;
@@ -3261,8 +3368,10 @@ static int selinux_socket_unix_may_send(
 	struct avc_audit_data ad;
 	int err;
 
-	isec = SOCK_INODE(sock)->i_security;
-	other_isec = SOCK_INODE(other)->i_security;
+	isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct);
+	other_isec = security_get_value_type(&SOCK_INODE(other)->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct);
 
 	AVC_AUDIT_DATA_INIT(&ad,NET);
 	ad.u.net.sk = other->sk;
@@ -3302,7 +3411,8 @@ static int selinux_socket_sock_rcv_skb(s
  		inode = SOCK_INODE(sock);
  		if (inode) {
  			struct inode_security_struct *isec;
- 			isec = inode->i_security;
+			isec = security_get_value_type(&inode->i_security,
+				SELINUX_LSM_ID, struct inode_security_struct);
  			sock_sid = isec->sid;
  			sock_class = isec->sclass;
  		}
@@ -3385,13 +3495,15 @@ static int selinux_socket_getpeersec(str
 	struct sk_security_struct *ssec;
 	struct inode_security_struct *isec;
 
-	isec = SOCK_INODE(sock)->i_security;
+	isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct);
 	if (isec->sclass != SECCLASS_UNIX_STREAM_SOCKET) {
 		err = -ENOPROTOOPT;
 		goto out;
 	}
 
-	ssec = sock->sk->sk_security;
+	ssec = security_get_value_type(&sock->sk->sk_security, SELINUX_LSM_ID,
+		struct sk_security_struct);
 	
 	err = security_sid_to_context(ssec->peer_sid, &scontext, &scontext_len);
 	if (err)
@@ -3430,7 +3542,10 @@ static int selinux_nlmsg_perm(struct soc
 	u32 perm;
 	struct nlmsghdr *nlh;
 	struct socket *sock = sk->sk_socket;
-	struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
+	struct inode_security_struct *isec;
+	
+	isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct);
 	
 	if (skb->len < NLMSG_SPACE(0)) {
 		err = -EINVAL;
@@ -3496,7 +3611,8 @@ static unsigned int selinux_ip_postroute
 	if (err)
 		goto out;
 
-	isec = inode->i_security;
+	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct);
 	
 	switch (isec->sclass) {
 	case SECCLASS_UDP_SOCKET:
@@ -3606,7 +3722,8 @@ static int selinux_netlink_send(struct s
 	if (err)
 		return err;
 
-	tsec = current->security;
+	tsec = security_get_value_type(&current->security,
+		SELINUX_LSM_ID, struct task_security_struct);
 
 	avd.allowed = 0;
 	avc_has_perm_noaudit(tsec->sid, tsec->sid,
@@ -3630,15 +3747,17 @@ static int ipc_alloc_security(struct tas
 			      struct kern_ipc_perm *perm,
 			      u16 sclass)
 {
-	struct task_security_struct *tsec = task->security;
+	struct task_security_struct *tsec;
 	struct ipc_security_struct *isec;
 
+	tsec = security_get_value_type(&task->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+
 	isec = kmalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
 	if (!isec)
 		return -ENOMEM;
 
 	memset(isec, 0, sizeof(struct ipc_security_struct));
-	isec->magic = SELINUX_MAGIC;
 	isec->sclass = sclass;
 	isec->ipc_perm = perm;
 	if (tsec) {
@@ -3646,18 +3765,18 @@ static int ipc_alloc_security(struct tas
 	} else {
 		isec->sid = SECINITSID_UNLABELED;
 	}
-	perm->security = isec;
+	security_set_value_type(&perm->security, SELINUX_LSM_ID, isec);
 
 	return 0;
 }
 
 static void ipc_free_security(struct kern_ipc_perm *perm)
 {
-	struct ipc_security_struct *isec = perm->security;
-	if (!isec || isec->magic != SELINUX_MAGIC)
-		return;
+	struct ipc_security_struct *isec;
+	
+	isec = security_del_value_type(&perm->security, SELINUX_LSM_ID,
+		struct ipc_security_struct);
 
-	perm->security = NULL;
 	kfree(isec);
 }
 
@@ -3670,21 +3789,20 @@ static int msg_msg_alloc_security(struct
 		return -ENOMEM;
 
 	memset(msec, 0, sizeof(struct msg_security_struct));
-	msec->magic = SELINUX_MAGIC;
 	msec->msg = msg;
 	msec->sid = SECINITSID_UNLABELED;
-	msg->security = msec;
+	security_set_value_type(&msg->security, SELINUX_LSM_ID, msec);
 
 	return 0;
 }
 
 static void msg_msg_free_security(struct msg_msg *msg)
 {
-	struct msg_security_struct *msec = msg->security;
-	if (!msec || msec->magic != SELINUX_MAGIC)
-		return;
+	struct msg_security_struct *msec;
+	
+	msec = security_del_value_type(&msg->security, SELINUX_LSM_ID,
+		struct msg_security_struct);
 
-	msg->security = NULL;
 	kfree(msec);
 }
 
@@ -3695,8 +3813,10 @@ static int ipc_has_perm(struct kern_ipc_
 	struct ipc_security_struct *isec;
 	struct avc_audit_data ad;
 
-	tsec = current->security;
-	isec = ipc_perms->security;
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	isec = security_get_value_type(&ipc_perms->security, SELINUX_LSM_ID,
+		struct ipc_security_struct);
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
 	ad.u.ipc_id = ipc_perms->key;
@@ -3726,8 +3846,10 @@ static int selinux_msg_queue_alloc_secur
 	if (rc)
 		return rc;
 
-	tsec = current->security;
-	isec = msq->q_perm.security;
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	isec = security_get_value_type(&msq->q_perm.security, SELINUX_LSM_ID,
+		struct ipc_security_struct);
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
  	ad.u.ipc_id = msq->q_perm.key;
@@ -3752,8 +3874,10 @@ static int selinux_msg_queue_associate(s
 	struct ipc_security_struct *isec;
 	struct avc_audit_data ad;
 
-	tsec = current->security;
-	isec = msq->q_perm.security;
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	isec = security_get_value_type(&msq->q_perm.security, SELINUX_LSM_ID,
+		struct ipc_security_struct);
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
 	ad.u.ipc_id = msq->q_perm.key;
@@ -3798,9 +3922,12 @@ static int selinux_msg_queue_msgsnd(stru
 	struct avc_audit_data ad;
 	int rc;
 
-	tsec = current->security;
-	isec = msq->q_perm.security;
-	msec = msg->security;
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	isec = security_get_value_type(&msq->q_perm.security, SELINUX_LSM_ID,
+		struct ipc_security_struct);
+	msec = security_get_value_type(&msg->security, SELINUX_LSM_ID,
+		struct msg_security_struct);
 
 	/*
 	 * First time through, need to assign label to the message
@@ -3846,9 +3973,12 @@ static int selinux_msg_queue_msgrcv(stru
 	struct avc_audit_data ad;
 	int rc;
 
-	tsec = target->security;
-	isec = msq->q_perm.security;
-	msec = msg->security;
+	tsec = security_get_value_type(&target->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	isec = security_get_value_type(&msq->q_perm.security, SELINUX_LSM_ID,
+		struct ipc_security_struct);
+	msec = security_get_value_type(&msg->security, SELINUX_LSM_ID,
+		struct msg_security_struct);
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
  	ad.u.ipc_id = msq->q_perm.key;
@@ -3873,8 +4003,10 @@ static int selinux_shm_alloc_security(st
 	if (rc)
 		return rc;
 
-	tsec = current->security;
-	isec = shp->shm_perm.security;
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	isec = security_get_value_type(&shp->shm_perm.security, SELINUX_LSM_ID,
+		struct ipc_security_struct);
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
  	ad.u.ipc_id = shp->shm_perm.key;
@@ -3899,8 +4031,10 @@ static int selinux_shm_associate(struct 
 	struct ipc_security_struct *isec;
 	struct avc_audit_data ad;
 
-	tsec = current->security;
-	isec = shp->shm_perm.security;
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	isec = security_get_value_type(&shp->shm_perm.security, SELINUX_LSM_ID,
+		struct ipc_security_struct);
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
 	ad.u.ipc_id = shp->shm_perm.key;
@@ -3972,8 +4106,10 @@ static int selinux_sem_alloc_security(st
 	if (rc)
 		return rc;
 
-	tsec = current->security;
-	isec = sma->sem_perm.security;
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	isec = security_get_value_type(&sma->sem_perm.security, SELINUX_LSM_ID,
+		struct ipc_security_struct);
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
  	ad.u.ipc_id = sma->sem_perm.key;
@@ -3998,8 +4134,10 @@ static int selinux_sem_associate(struct 
 	struct ipc_security_struct *isec;
 	struct avc_audit_data ad;
 
-	tsec = current->security;
-	isec = sma->sem_perm.security;
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
+	isec = security_get_value_type(&sma->sem_perm.security, SELINUX_LSM_ID,
+		struct ipc_security_struct);
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
 	ad.u.ipc_id = sma->sem_perm.key;
@@ -4133,7 +4271,8 @@ static int selinux_getprocattr(struct ta
 	if (!size)
 		return -ERANGE;
 
-	tsec = p->security;
+	tsec = security_get_value_type(&p->security, SELINUX_LSM_ID,
+		struct task_security_struct);
 
 	if (!strcmp(name, "current"))
 		sid = tsec->sid;
@@ -4208,7 +4347,8 @@ static int selinux_setprocattr(struct ta
 	   operation.  See selinux_bprm_set_security for the execve
 	   checks and may_create for the file creation checks. The
 	   operation will then fail if the context is not permitted. */
-	tsec = p->security;
+	tsec = security_get_value_type(&p->security, SELINUX_LSM_ID,
+		struct task_security_struct);
 	if (!strcmp(name, "exec"))
 		tsec->exec_sid = sid;
 	else if (!strcmp(name, "fscreate"))
Index: linux-2.6.13-rc3/security/selinux/selinuxfs.c
===================================================================
--- linux-2.6.13-rc3.orig/security/selinux/selinuxfs.c	2005-07-25 14:40:12.000000000 -0500
+++ linux-2.6.13-rc3/security/selinux/selinuxfs.c	2005-07-25 14:55:39.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/security.h>
+#include <linux/security-stack.h>
 #include <linux/major.h>
 #include <linux/seq_file.h>
 #include <linux/percpu.h>
@@ -59,7 +60,8 @@ static int task_has_security(struct task
 {
 	struct task_security_struct *tsec;
 
-	tsec = tsk->security;
+	tsec = security_get_value_type(&tsk->security, SELINUX_LSM_ID,
+			struct task_security_struct);
 	if (!tsec)
 		return -EACCES;
 
@@ -982,7 +984,8 @@ static int sel_make_bools(void)
 			ret = -ENAMETOOLONG;
 			goto err;
 		}
-		isec = (struct inode_security_struct*)inode->i_security;
+		isec = security_get_value_type(&inode->i_security,
+				SELINUX_LSM_ID, struct inode_security_struct);
 		if ((ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid)))
 			goto err;
 		isec->sid = sid;
@@ -1267,7 +1270,8 @@ static int sel_fill_super(struct super_b
 	inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO);
 	if (!inode)
 		goto out;
-	isec = (struct inode_security_struct*)inode->i_security;
+	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
+			struct inode_security_struct);
 	isec->sid = SECINITSID_DEVNULL;
 	isec->sclass = SECCLASS_CHR_FILE;
 	isec->initialized = 1;

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [patch 11/15] lsm stacking v0.3: selinux: remove secondary support
  2005-07-27 18:19 ` [patch 1/15] lsm stacking v0.3: introduce securityfs serue
                     ` (8 preceding siblings ...)
  2005-07-27 18:26   ` [patch 10/15] lsm stacking v0.3: selinux: use security_*_value API serue
@ 2005-07-27 18:27   ` serue
  2005-07-27 18:27   ` [patch 12/15] lsm stacking v0.3: hook completeness verification script serue
                     ` (3 subsequent siblings)
  13 siblings, 0 replies; 39+ messages in thread
From: serue @ 2005-07-27 18:27 UTC (permalink / raw)
  To: lkml
  Cc: Chris Wright, Stephen Smalley, James Morris, Andrew Morton,
	Michael Halcrow, David Safford, Reiner Sailer, Gerrit Huizenga,
	Emily Ratliff

Remove the SELinux support for secondary modules.  This is no longer necessary
as SELinux can now be simply stacked with the cap-stack module.

Signed-off-by: Serge Hallyn <serue@us.ibm.com>
--
 hooks.c |  266 ++++++++--------------------------------------------------------
 1 files changed, 35 insertions(+), 231 deletions(-)

Index: linux-2.6.13-rc3/security/selinux/hooks.c
===================================================================
--- linux-2.6.13-rc3.orig/security/selinux/hooks.c	2005-07-25 14:55:39.000000000 -0500
+++ linux-2.6.13-rc3/security/selinux/hooks.c	2005-07-25 14:55:52.000000000 -0500
@@ -81,6 +81,8 @@
 extern unsigned int policydb_loaded_version;
 extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
 
+static int secondary;  /* how were we registered? */
+
 #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
 int selinux_enforcing = 0;
 
@@ -103,15 +105,6 @@ static int __init selinux_enabled_setup(
 __setup("selinux=", selinux_enabled_setup);
 #endif
 
-/* Original (dummy) security module. */
-static struct security_operations *original_ops = NULL;
-
-/* Minimal support for a secondary security module,
-   just to allow the use of the dummy or capability modules.
-   The owlsm module can alternatively be used as a secondary
-   module as long as CONFIG_OWLSM_FD is not enabled. */
-static struct security_operations *secondary_ops = NULL;
-
 /* Lists of inode and superblock security structures initialized
    before the policy was loaded. */
 static LIST_HEAD(superblock_security_head);
@@ -1400,9 +1393,6 @@ static int selinux_ptrace(struct task_st
 	struct task_security_struct *csec;
 	int rc;
 
-	rc = secondary_ops->ptrace(parent,child);
-	if (rc)
-		return rc;
 	psec = security_get_value_type(&parent->security, SELINUX_LSM_ID,
 		struct task_security_struct);
 	csec = security_get_value_type(&child->security, SELINUX_LSM_ID,
@@ -1418,41 +1408,17 @@ static int selinux_ptrace(struct task_st
 static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
                           kernel_cap_t *inheritable, kernel_cap_t *permitted)
 {
-	int error;
-
-	error = task_has_perm(current, target, PROCESS__GETCAP);
-	if (error)
-		return error;
-
-	return secondary_ops->capget(target, effective, inheritable, permitted);
+	return task_has_perm(current, target, PROCESS__GETCAP);
 }
 
 static int selinux_capset_check(struct task_struct *target, kernel_cap_t *effective,
                                 kernel_cap_t *inheritable, kernel_cap_t *permitted)
 {
-	int error;
-
-	error = secondary_ops->capset_check(target, effective, inheritable, permitted);
-	if (error)
-		return error;
-
 	return task_has_perm(current, target, PROCESS__SETCAP);
 }
 
-static void selinux_capset_set(struct task_struct *target, kernel_cap_t *effective,
-                               kernel_cap_t *inheritable, kernel_cap_t *permitted)
-{
-	secondary_ops->capset_set(target, effective, inheritable, permitted);
-}
-
 static int selinux_capable(struct task_struct *tsk, int cap)
 {
-	int rc;
-
-	rc = secondary_ops->capable(tsk, cap);
-	if (rc)
-		return rc;
-
 	return task_has_capability(tsk,cap);
 }
 
@@ -1464,10 +1430,6 @@ static int selinux_sysctl(ctl_table *tab
 	u32 tsid;
 	int rc;
 
-	rc = secondary_ops->sysctl(table, op);
-	if (rc)
-		return rc;
-
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
 		struct task_security_struct);
 
@@ -1535,11 +1497,7 @@ static int selinux_quota_on(struct dentr
 
 static int selinux_syslog(int type)
 {
-	int rc;
-
-	rc = secondary_ops->syslog(type);
-	if (rc)
-		return rc;
+	int rc = 0;
 
 	switch (type) {
 		case 3:         /* Read last kernel messages */
@@ -1563,36 +1521,6 @@ static int selinux_syslog(int type)
 	return rc;
 }
 
-/*
- * Check that a process has enough memory to allocate a new virtual
- * mapping. 0 means there is enough memory for the allocation to
- * succeed and -ENOMEM implies there is not.
- *
- * Note that secondary_ops->capable and task_has_perm_noaudit return 0
- * if the capability is granted, but __vm_enough_memory requires 1 if
- * the capability is granted.
- *
- * Do not audit the selinux permission check, as this is applied to all
- * processes that allocate mappings.
- */
-static int selinux_vm_enough_memory(long pages)
-{
-	int rc, cap_sys_admin = 0;
-	struct task_security_struct *tsec = current->security;
-
-	rc = secondary_ops->capable(current, CAP_SYS_ADMIN);
-	if (rc == 0)
-		rc = avc_has_perm_noaudit(tsec->sid, tsec->sid,
-					SECCLASS_CAPABILITY,
-					CAP_TO_MASK(CAP_SYS_ADMIN),
-					NULL);
-
-	if (rc == 0)
-		cap_sys_admin = 1;
-
-	return __vm_enough_memory(pages, cap_sys_admin);
-}
-
 /* binprm security operations */
 
 static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
@@ -1622,10 +1550,6 @@ static int selinux_bprm_set_security(str
 	struct avc_audit_data ad;
 	int rc;
 
-	rc = secondary_ops->bprm_set_security(bprm);
-	if (rc)
-		return rc;
-
 	bsec = security_get_value_type(&bprm->security, SELINUX_LSM_ID,
 		struct bprm_security_struct);
 
@@ -1690,12 +1614,6 @@ static int selinux_bprm_set_security(str
 	return 0;
 }
 
-static int selinux_bprm_check_security (struct linux_binprm *bprm)
-{
-	return secondary_ops->bprm_check_security(bprm);
-}
-
-
 static int selinux_bprm_secureexec (struct linux_binprm *bprm)
 {
 	struct task_security_struct *tsec;
@@ -1712,7 +1630,7 @@ static int selinux_bprm_secureexec (stru
 					 PROCESS__NOATSECURE, NULL);
 	}
 
-	return (atsecure || secondary_ops->bprm_secureexec(bprm));
+	return atsecure;
 }
 
 static void selinux_bprm_free_security(struct linux_binprm *bprm)
@@ -1816,8 +1734,6 @@ static void selinux_bprm_apply_creds(str
 	u32 sid;
 	int rc;
 
-	secondary_ops->bprm_apply_creds(bprm, unsafe);
-
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
 		struct task_security_struct);
 	bsec = security_get_value_type(&bprm->security, SELINUX_LSM_ID,
@@ -2043,12 +1959,6 @@ static int selinux_mount(char * dev_name
                          unsigned long flags,
                          void * data)
 {
-	int rc;
-
-	rc = secondary_ops->sb_mount(dev_name, nd, type, flags, data);
-	if (rc)
-		return rc;
-
 	if (flags & MS_REMOUNT)
 		return superblock_has_perm(current, nd->mnt->mnt_sb,
 		                           FILESYSTEM__REMOUNT, NULL);
@@ -2059,12 +1969,6 @@ static int selinux_mount(char * dev_name
 
 static int selinux_umount(struct vfsmount *mnt, int flags)
 {
-	int rc;
-
-	rc = secondary_ops->sb_umount(mnt, flags);
-	if (rc)
-		return rc;
-
 	return superblock_has_perm(current,mnt->mnt_sb,
 	                           FILESYSTEM__UNMOUNT,NULL);
 }
@@ -2093,11 +1997,6 @@ static void selinux_inode_post_create(st
 
 static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
 {
-	int rc;
-
-	rc = secondary_ops->inode_link(old_dentry,dir,new_dentry);
-	if (rc)
-		return rc;
 	return may_link(dir, old_dentry, MAY_LINK);
 }
 
@@ -2108,11 +2007,6 @@ static void selinux_inode_post_link(stru
 
 static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
 {
-	int rc;
-
-	rc = secondary_ops->inode_unlink(dir, dentry);
-	if (rc)
-		return rc;
 	return may_link(dir, dentry, MAY_UNLINK);
 }
 
@@ -2143,12 +2037,6 @@ static int selinux_inode_rmdir(struct in
 
 static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
 {
-	int rc;
-
-	rc = secondary_ops->inode_mknod(dir, dentry, mode, dev);
-	if (rc)
-		return rc;
-
 	return may_create(dir, dentry, inode_mode_to_security_class(mode));
 }
 
@@ -2176,23 +2064,12 @@ static int selinux_inode_readlink(struct
 
 static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
 {
-	int rc;
-
-	rc = secondary_ops->inode_follow_link(dentry,nameidata);
-	if (rc)
-		return rc;
 	return dentry_has_perm(current, NULL, dentry, FILE__READ);
 }
 
 static int selinux_inode_permission(struct inode *inode, int mask,
 				    struct nameidata *nd)
 {
-	int rc;
-
-	rc = secondary_ops->inode_permission(inode, mask, nd);
-	if (rc)
-		return rc;
-
 	if (!mask) {
 		/* No permission to check.  Existence test. */
 		return 0;
@@ -2204,12 +2081,6 @@ static int selinux_inode_permission(stru
 
 static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
 {
-	int rc;
-
-	rc = secondary_ops->inode_setattr(dentry, iattr);
-	if (rc)
-		return rc;
-
 	if (iattr->ia_valid & ATTR_FORCE)
 		return 0;
 
@@ -2531,12 +2402,6 @@ static int file_map_prot_check(struct fi
 static int selinux_file_mmap(struct file *file, unsigned long reqprot,
 			     unsigned long prot, unsigned long flags)
 {
-	int rc;
-
-	rc = secondary_ops->file_mmap(file, reqprot, prot, flags);
-	if (rc)
-		return rc;
-
 	if (selinux_checkreqprot)
 		prot = reqprot;
 
@@ -2550,10 +2415,6 @@ static int selinux_file_mprotect(struct 
 {
 	int rc;
 
-	rc = secondary_ops->file_mprotect(vma, reqprot, prot);
-	if (rc)
-		return rc;
-
 	if (selinux_checkreqprot)
 		prot = reqprot;
 
@@ -2576,7 +2437,7 @@ static int selinux_file_mprotect(struct 
 		 * check ability to execute the possibly modified content.
 		 * This typically should only occur for text relocations.
 		 */
-		int rc = file_has_perm(current, vma->vm_file, FILE__EXECMOD);
+		rc = file_has_perm(current, vma->vm_file, FILE__EXECMOD);
 		if (rc)
 			return rc;
 	}
@@ -2692,12 +2553,6 @@ static int selinux_file_receive(struct f
 
 static int selinux_task_create(unsigned long clone_flags)
 {
-	int rc;
-
-	rc = secondary_ops->task_create(clone_flags);
-	if (rc)
-		return rc;
-
 	return task_has_perm(current, current, PROCESS__FORK);
 }
 
@@ -2746,11 +2601,6 @@ static int selinux_task_setuid(uid_t id0
 	return 0;
 }
 
-static int selinux_task_post_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
-{
-	return secondary_ops->task_post_setuid(id0,id1,id2,flags);
-}
-
 static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags)
 {
 	/* See the comment for setuid above. */
@@ -2780,24 +2630,12 @@ static int selinux_task_setgroups(struct
 
 static int selinux_task_setnice(struct task_struct *p, int nice)
 {
-	int rc;
-
-	rc = secondary_ops->task_setnice(p, nice);
-	if (rc)
-		return rc;
-
 	return task_has_perm(current,p, PROCESS__SETSCHED);
 }
 
 static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim)
 {
 	struct rlimit *old_rlim = current->signal->rlim + resource;
-	int rc;
-
-	rc = secondary_ops->task_setrlimit(resource, new_rlim);
-	if (rc)
-		return rc;
-
 	/* Control the ability to change the hard limit (whether
 	   lowering or raising it), so that the hard limit can
 	   later be used as a safe reset point for the soft limit
@@ -2821,11 +2659,6 @@ static int selinux_task_getscheduler(str
 static int selinux_task_kill(struct task_struct *p, struct siginfo *info, int sig)
 {
 	u32 perm;
-	int rc;
-
-	rc = secondary_ops->task_kill(p, info, sig);
-	if (rc)
-		return rc;
 
 	if (info && ((unsigned long)info == 1 ||
 	             (unsigned long)info == 2 || SI_FROMKERNEL(info)))
@@ -2864,8 +2697,6 @@ static void selinux_task_reparent_to_ini
 {
   	struct task_security_struct *tsec;
 
-	secondary_ops->task_reparent_to_init(p);
-
 	tsec = security_get_value_type(&p->security, SELINUX_LSM_ID,
 		struct task_security_struct);
 	tsec->osid = tsec->sid;
@@ -3329,10 +3160,6 @@ static int selinux_socket_unix_stream_co
 	struct avc_audit_data ad;
 	int err;
 
-	err = secondary_ops->unix_stream_connect(sock, other, newsk);
-	if (err)
-		return err;
-
 	isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
 		SELINUX_LSM_ID, struct inode_security_struct);
 	other_isec = security_get_value_type(&SOCK_INODE(other)->i_security,
@@ -3716,11 +3543,7 @@ static int selinux_netlink_send(struct s
 {
 	struct task_security_struct *tsec;
 	struct av_decision avd;
-	int err;
-
-	err = secondary_ops->netlink_send(sk, skb);
-	if (err)
-		return err;
+	int err = 0;
 
 	tsec = security_get_value_type(&current->security,
 		SELINUX_LSM_ID, struct task_security_struct);
@@ -3736,13 +3559,6 @@ static int selinux_netlink_send(struct s
 	return err;
 }
 
-static int selinux_netlink_recv(struct sk_buff *skb)
-{
-	if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN))
-		return -EPERM;
-	return 0;
-}
-
 static int ipc_alloc_security(struct task_struct *task,
 			      struct kern_ipc_perm *perm,
 			      u16 sclass)
@@ -4080,11 +3896,6 @@ static int selinux_shm_shmat(struct shmi
 			     char __user *shmaddr, int shmflg)
 {
 	u32 perms;
-	int rc;
-
-	rc = secondary_ops->shm_shmat(shp, shmaddr, shmflg);
-	if (rc)
-		return rc;
 
 	if (shmflg & SHM_RDONLY)
 		perms = SHM__READ;
@@ -4220,32 +4031,12 @@ static int selinux_ipc_permission(struct
 /* module stacking operations */
 static int selinux_register_security (const char *name, struct security_operations *ops)
 {
-	if (secondary_ops != original_ops) {
-		printk(KERN_INFO "%s:  There is already a secondary security "
-		       "module registered.\n", __FUNCTION__);
-		return -EINVAL;
- 	}
-
-	secondary_ops = ops;
-
-	printk(KERN_INFO "%s:  Registering secondary module %s\n",
-	       __FUNCTION__,
-	       name);
-
-	return 0;
+	return -EINVAL;
 }
 
 static int selinux_unregister_security (const char *name, struct security_operations *ops)
 {
-	if (ops != secondary_ops) {
-		printk (KERN_INFO "%s:  trying to unregister a security module "
-		        "that is not registered.\n", __FUNCTION__);
-		return -EINVAL;
-	}
-
-	secondary_ops = original_ops;
-
-	return 0;
+	return -EINVAL;
 }
 
 static void selinux_d_instantiate (struct dentry *dentry, struct inode *inode)
@@ -4410,23 +4201,19 @@ static struct security_operations selinu
 	.ptrace =			selinux_ptrace,
 	.capget =			selinux_capget,
 	.capset_check =			selinux_capset_check,
-	.capset_set =			selinux_capset_set,
 	.sysctl =			selinux_sysctl,
 	.capable =			selinux_capable,
 	.quotactl =			selinux_quotactl,
 	.quota_on =			selinux_quota_on,
 	.syslog =			selinux_syslog,
-	.vm_enough_memory =		selinux_vm_enough_memory,
 
 	.netlink_send =			selinux_netlink_send,
-        .netlink_recv =			selinux_netlink_recv,
 
 	.bprm_alloc_security =		selinux_bprm_alloc_security,
 	.bprm_free_security =		selinux_bprm_free_security,
 	.bprm_apply_creds =		selinux_bprm_apply_creds,
 	.bprm_post_apply_creds =	selinux_bprm_post_apply_creds,
 	.bprm_set_security =		selinux_bprm_set_security,
-	.bprm_check_security =		selinux_bprm_check_security,
 	.bprm_secureexec =		selinux_bprm_secureexec,
 
 	.sb_alloc_security =		selinux_sb_alloc_security,
@@ -4483,7 +4270,6 @@ static struct security_operations selinu
 	.task_alloc_security =		selinux_task_alloc_security,
 	.task_free_security =		selinux_task_free_security,
 	.task_setuid =			selinux_task_setuid,
-	.task_post_setuid =		selinux_task_post_setuid,
 	.task_setgid =			selinux_task_setgid,
 	.task_setpgid =			selinux_task_setpgid,
 	.task_getpgid =			selinux_task_getpgid,
@@ -4555,10 +4341,12 @@ static struct security_operations selinu
 #endif
 };
 
+#define MY_NAME "selinux"
 static __init int selinux_init(void)
 {
 	struct task_security_struct *tsec;
 
+	secondary = 0;
 	if (!selinux_enabled) {
 		printk(KERN_INFO "SELinux:  Disabled at boot.\n");
 		return 0;
@@ -4569,22 +4357,30 @@ static __init int selinux_init(void)
 	/* Set the security state for the initial task. */
 	if (task_alloc_security(current))
 		panic("SELinux:  Failed to initialize initial task.\n");
-	tsec = current->security;
+	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
+		struct task_security_struct);
 	tsec->osid = tsec->sid = SECINITSID_KERNEL;
 
 	avc_init();
 
-	original_ops = secondary_ops = security_ops;
-	if (!secondary_ops)
-		panic ("SELinux: No initial security operations\n");
-	if (register_security (&selinux_ops))
-		panic("SELinux: Unable to register with kernel.\n");
+	if (register_security (&selinux_ops)) {
+		if (mod_reg_security( MY_NAME, &selinux_ops)) {
+			printk(KERN_ERR "%s: Failed to register with primary LSM.\n",
+				__FUNCTION__);
+			panic("SELinux: Unable to register with kernel.\n");
+		} else {
+			printk(KERN_ERR "%s: registered with primary LSM.\n",
+				__FUNCTION__);
+		}
+		secondary = 1;
+	}
 
 	if (selinux_enforcing) {
 		printk(KERN_INFO "SELinux:  Starting in enforcing mode\n");
 	} else {
 		printk(KERN_INFO "SELinux:  Starting in permissive mode\n");
 	}
+
 	return 0;
 }
 
@@ -4694,6 +4490,7 @@ int selinux_disable(void)
 {
 	extern void exit_sel_fs(void);
 	static int selinux_disabled = 0;
+	int ret;
 
 	if (ss_initialized) {
 		/* Not permitted after initial policy load. */
@@ -4709,8 +4506,15 @@ int selinux_disable(void)
 
 	selinux_disabled = 1;
 
-	/* Reset security_ops to the secondary module, dummy or capability. */
-	security_ops = secondary_ops;
+	if (secondary)
+		ret = mod_unreg_security(MY_NAME, &selinux_ops);
+	else
+		ret = unregister_security(&selinux_ops);
+
+	if (ret)
+		printk(KERN_INFO "Failure unregistering selinux.\n");
+	else
+		printk(KERN_INFO "Unregistered selinux.\n");
 
 	/* Unregister netfilter hooks. */
 	selinux_nf_ip_exit();

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [patch 12/15] lsm stacking v0.3: hook completeness verification script
  2005-07-27 18:19 ` [patch 1/15] lsm stacking v0.3: introduce securityfs serue
                     ` (9 preceding siblings ...)
  2005-07-27 18:27   ` [patch 11/15] lsm stacking v0.3: selinux: remove secondary support serue
@ 2005-07-27 18:27   ` serue
  2005-07-27 18:28   ` [patch 13/15] lsm stacking v0.3: seclvl: update for stacking serue
                     ` (2 subsequent siblings)
  13 siblings, 0 replies; 39+ messages in thread
From: serue @ 2005-07-27 18:27 UTC (permalink / raw)
  To: lkml
  Cc: Chris Wright, Stephen Smalley, James Morris, Andrew Morton,
	Michael Halcrow, David Safford, Reiner Sailer, Gerrit Huizenga,
	Emily Ratliff

Add a script to check whether all security_operations hooks are defined
in both dummy_security_ops (through security_fixup_ops) and in stacker_ops.
Also adds a note in security.h to remind developers that all hooks must
be defined in these two modules, and to verify this using the
lsm_verify_hooks.sh script.

Signed-off-by: Serge Hallyn <serue@us.ibm.com>
---
 include/linux/security.h    |    4 ++++
 scripts/lsm_verify_hooks.sh |   44 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+)

Index: linux-2.6.13-rc3/include/linux/security.h
===================================================================
--- linux-2.6.13-rc3.orig/include/linux/security.h	2005-07-25 14:55:20.000000000 -0500
+++ linux-2.6.13-rc3/include/linux/security.h	2005-07-25 14:55:59.000000000 -0500
@@ -125,6 +125,10 @@ struct swap_info_struct;
 /**
  * struct security_operations - main security structure
  *
+ * When adding functions to this structure, please add them to
+ * dummy.c and stacker.c, and run linux/scripts/lsm_verify_hooks.sh
+ * to verify their inclusion in these modules.
+ *
  * Security hooks for program execution operations.
  *
  *
Index: linux-2.6.13-rc3/scripts/lsm_verify_hooks.sh
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.13-rc3/scripts/lsm_verify_hooks.sh	2005-07-25 14:55:59.000000000 -0500
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+# Author: Serge E. Hallyn <serue@us.ibm.com>
+
+# Checks that both the dummy and stacker modules define all the
+# security hooks.
+
+# This probably should be done in perl
+
+# Copyright (C) 2002,2003,2004,2005 Serge E. Hallyn <serue@us.ibm.com>
+# Copyright (C) 2002 David A. Wheeler <dwheeler@dwheeler.com>.
+#  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.
+
+# Grab the relevant pieces of text
+sed -n '/^void security_fixup_ops /,/}/p' dummy.c > dummy.out
+sed -n '/^static struct security_operations/,/}/p' stacker.c > stack.out
+../scripts/Lindent -o tmpsec.h ../include/linux/security.h
+sed -n '/^struct security_operations {/,/}/p' tmpsec.h > sech.out
+rm tmpsec.h
+
+# Get a list of functions in security.h
+cat sech.out | sed -n '/\t[a-z]/p' | sed -e 's/^\t[a-z]* (\*\([^)]*\).*$/\1/' > sech.out
+
+# check dummy.c
+for line in `cat sech.out`; do
+	grep $line dummy.out > /dev/null 2>&1
+	if [ $? -ne 0 ]; then
+		echo "WARNING: $line missing from dummy module!"
+	fi
+done
+
+# check stacker.c
+for line in `cat sech.out`; do
+	grep $line stack.out > /dev/null 2>&1
+	if [ $? -ne 0 ]; then
+		echo "WARNING: $line missing from stacker module!"
+	fi
+done
+
+rm sech.out stack.out dummy.out
+echo "LSM hook verification done."

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [patch 13/15] lsm stacking v0.3: seclvl: update for stacking
  2005-07-27 18:19 ` [patch 1/15] lsm stacking v0.3: introduce securityfs serue
                     ` (10 preceding siblings ...)
  2005-07-27 18:27   ` [patch 12/15] lsm stacking v0.3: hook completeness verification script serue
@ 2005-07-27 18:28   ` serue
  2005-07-27 18:28   ` [patch 14/15] lsm stacking v0.3: fix security_{del,unlink}_value race serue
  2005-07-27 18:28   ` [patch 15/15] lsm stacking v0.3: stacking for digsig serue
  13 siblings, 0 replies; 39+ messages in thread
From: serue @ 2005-07-27 18:28 UTC (permalink / raw)
  To: lkml
  Cc: Chris Wright, Stephen Smalley, James Morris, Andrew Morton,
	Michael Halcrow, David Safford, Reiner Sailer, Gerrit Huizenga,
	Emily Ratliff

Add stacking support to the seclvl module.

Note that seclvl is currently unable to prevent it's own unloading, as
it actually claims to do.

Changelog:
	[Jul 26] Updated seclvl to use security_unlink_value to free
	its data when seclvl is unloaded.

Signed-off-by: Serge Hallyn <serue@us.ibm.com>
---
 seclvl.c |  133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 123 insertions(+), 10 deletions(-)

Index: linux-2.6.13-rc3/security/seclvl.c
===================================================================
--- linux-2.6.13-rc3.orig/security/seclvl.c	2005-07-25 14:40:42.000000000 -0500
+++ linux-2.6.13-rc3/security/seclvl.c	2005-07-25 14:56:37.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/security.h>
+#include <linux/security-stack.h>
 #include <linux/netlink.h>
 #include <linux/fs.h>
 #include <linux/namei.h>
@@ -35,6 +36,7 @@
 #include <linux/sysfs.h>
 
 #define SHA1_DIGEST_SIZE 20
+#define SECLVL_LSM_ID 0xF45
 
 /**
  * Module parameter that defines the initial secure level.
@@ -485,12 +487,46 @@ static int seclvl_settime(struct timespe
 	return 0;
 }
 
+/*
+ * A structure which is stored with the inode when a process
+ * has a unmounted block device open for writing.
+ */
+struct seclvl_i_sec {
+	struct security_list lsm_list;
+	struct task_struct *task;
+	spinlock_t spinlock;
+	struct list_head chain;
+};
+
+static LIST_HEAD(seclvl_ichain);
+static DEFINE_SPINLOCK(seclvl_ichain_lock);
+
+static void seclvl_inode_free(struct inode *inode)
+{
+	struct seclvl_i_sec *isec;
+
+	isec = security_del_value_type(&inode->i_security, SECLVL_LSM_ID,
+				struct seclvl_i_sec);
+	if (isec) {
+		spin_lock(&seclvl_ichain_lock);
+		list_del(&isec->chain);
+		spin_unlock(&seclvl_ichain_lock);
+		if (isec->task == current)
+			isec->task = NULL;
+		kfree(isec);
+	}
+}
+
 /* claim the blockdev to exclude mounters, release on file close */
-static int seclvl_bd_claim(struct inode *inode)
+static int seclvl_bd_claim(struct inode *inode, struct seclvl_i_sec *isec)
 {
 	int holder;
 	struct block_device *bdev = NULL;
 	dev_t dev = inode->i_rdev;
+
+	if (isec->task && isec->task != current)
+		return -EPERM;
+
 	bdev = open_by_devnum(dev, FMODE_WRITE);
 	if (bdev) {
 		if (bd_claim(bdev, &holder)) {
@@ -498,7 +534,7 @@ static int seclvl_bd_claim(struct inode 
 			return -EPERM;
 		}
 		/* claimed, mark it to release on close */
-		inode->i_security = current;
+		isec->task = current;
 	}
 	return 0;
 }
@@ -506,17 +542,60 @@ static int seclvl_bd_claim(struct inode 
 /* release the blockdev if you claimed it */
 static void seclvl_bd_release(struct inode *inode)
 {
-	if (inode && S_ISBLK(inode->i_mode) && inode->i_security == current) {
-		struct block_device *bdev = inode->i_bdev;
-		if (bdev) {
-			bd_release(bdev);
-			blkdev_put(bdev);
-			inode->i_security = NULL;
-		}
+	struct seclvl_i_sec *isec;
+
+	if (inode && S_ISBLK(inode->i_mode)) {
+		isec = security_get_value_type(&inode->i_security,
+				SECLVL_LSM_ID, struct seclvl_i_sec);
+		if (!isec)
+			return;
+		spin_lock(&isec->spinlock);
+		if (isec->task == current) {
+			struct block_device *bdev = inode->i_bdev;
+			if (bdev) {
+				bd_release(bdev);
+				blkdev_put(bdev);
+				isec->task = NULL;
+			}
+ 		}
+		spin_unlock(&isec->spinlock);
 	}
 }
 
 /**
+ * Either returns the existing inode isec, or creates a new
+ * isec, places it on the inode->i_security list, and returns
+ * it.
+ * On error, return NULL.
+ */
+static struct seclvl_i_sec *
+seclvl_inode_get_or_alloc(struct inode *inode)
+{
+	struct seclvl_i_sec *isec;
+
+	isec = security_get_value_type(&inode->i_security,
+			SECLVL_LSM_ID, struct seclvl_i_sec);
+	if (isec)
+		return isec;
+	spin_lock(&seclvl_ichain_lock);
+	isec = security_get_value_type(&inode->i_security,
+			SECLVL_LSM_ID, struct seclvl_i_sec);
+	if (isec)
+		goto out;
+	isec = kmalloc(sizeof(struct seclvl_i_sec), GFP_KERNEL);
+	if (!isec)
+		goto out;
+	spin_lock_init(&isec->spinlock);
+	INIT_LIST_HEAD(&isec->chain);
+	list_add(&isec->chain, &seclvl_ichain);
+	security_add_value_type(&inode->i_security, SECLVL_LSM_ID, isec);
+
+out:
+	spin_unlock(&seclvl_ichain_lock);
+	return isec;
+}
+
+/**
  * Security for writes to block devices is regulated by this seclvl
  * function.  Deny all writes to block devices in seclvl 2.  In
  * seclvl 1, we only deny writes to *mounted* block devices.
@@ -524,6 +603,8 @@ static void seclvl_bd_release(struct ino
 static int
 seclvl_inode_permission(struct inode *inode, int mask, struct nameidata *nd)
 {
+	struct seclvl_i_sec *isec;
+
 	if (current->pid != 1 && S_ISBLK(inode->i_mode) && (mask & MAY_WRITE)) {
 		switch (seclvl) {
 		case 2:
@@ -531,13 +612,19 @@ seclvl_inode_permission(struct inode *in
 				      "denied in secure level [%d]\n", seclvl);
 			return -EPERM;
 		case 1:
-			if (seclvl_bd_claim(inode)) {
+			isec = seclvl_inode_get_or_alloc(inode);
+			if (!isec)
+				return -ENOMEM;
+			spin_lock(&isec->spinlock);
+			if (seclvl_bd_claim(inode, isec)) {
 				seclvl_printk(1, KERN_WARNING,
 					      "Write to mounted block device "
 					      "denied in secure level [%d]\n",
 					      seclvl);
+				spin_unlock(&isec->spinlock);
 				return -EPERM;
 			}
+			spin_unlock(&isec->spinlock);
 		}
 	}
 	return 0;
@@ -596,6 +683,7 @@ static struct security_operations seclvl
 	.capable = seclvl_capable,
 	.inode_permission = seclvl_inode_permission,
 	.inode_setattr = seclvl_inode_setattr,
+	.inode_free_security = seclvl_inode_free,
 	.file_free_security = seclvl_file_free_security,
 	.settime = seclvl_settime,
 	.sb_umount = seclvl_umount,
@@ -720,6 +808,29 @@ static int __init seclvl_init(void)
 	return rc;
 }
 
+/*
+ * free_ichain: Called when seclvl is unloaded to free all the memory
+ * it has attached to inodes.
+ * First we go through the list and remove the objects from the
+ * object chains (ie inode->i_security).  Then we wait an rcu cycle.
+ * Then we can safely delete the object, as any any stacker m->hook()
+ * loop should have moved on to isec->lsm_list.next.
+ */
+static void free_ichain(void)
+{
+	struct seclvl_i_sec *isec, *n;
+
+	list_for_each_entry_safe(isec, n, &seclvl_ichain, chain) {
+		security_unlink_value(&isec->lsm_list.list);
+	}
+
+	synchronize_rcu();
+	list_for_each_entry_safe(isec, n, &seclvl_ichain, chain) {
+		list_del(&isec->chain);
+		kfree(isec);
+	}
+}
+
 /**
  * Remove the seclvl module.
  */
@@ -738,6 +849,8 @@ static void __exit seclvl_exit(void)
 			      "seclvl: Failure unregistering with the "
 			      "kernel\n");
 	}
+
+	free_ichain();
 }
 
 module_init(seclvl_init);

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [patch 14/15] lsm stacking v0.3: fix security_{del,unlink}_value race
  2005-07-27 18:19 ` [patch 1/15] lsm stacking v0.3: introduce securityfs serue
                     ` (11 preceding siblings ...)
  2005-07-27 18:28   ` [patch 13/15] lsm stacking v0.3: seclvl: update for stacking serue
@ 2005-07-27 18:28   ` serue
  2005-07-27 18:28   ` [patch 15/15] lsm stacking v0.3: stacking for digsig serue
  13 siblings, 0 replies; 39+ messages in thread
From: serue @ 2005-07-27 18:28 UTC (permalink / raw)
  To: lkml
  Cc: Chris Wright, Stephen Smalley, James Morris, Andrew Morton,
	Michael Halcrow, David Safford, Reiner Sailer, Gerrit Huizenga,
	Emily Ratliff

The security_unlink_value() hook can race with security_del_value().  This
is because security_del_value() is optimized to assume that it is naturally
serialized by only being called from security_<object>_free().

At the moment we want modules to only call security_unlink_value() while
they are being unloaded, so we try to avoid a spinlock at any other time.
If this is unreasonable, we can simply protect security_del_value() with
the spinlock at all times.  Or, we can try to find another solution.

Signed-off-by: Serge Hallyn <serue@us.ibm.com>
---
 security.c |   18 ++++++++++++++++--
 stacker.c  |    2 ++
 2 files changed, 18 insertions(+), 2 deletions(-)

Index: linux-2.6.13-rc3/security/security.c
===================================================================
--- linux-2.6.13-rc3.orig/security/security.c	2005-07-25 14:50:34.000000000 -0500
+++ linux-2.6.13-rc3/security/security.c	2005-07-25 15:30:35.000000000 -0500
@@ -125,22 +125,36 @@ void security_disown_value(struct hlist_
 	spin_unlock(&stacker_value_spinlock);
 }
 
+int lsm_unloading;
+
 /* No locking needed: only called during object_destroy */
 fastcall struct security_list *
 security_del_value(struct hlist_head *head, int security_id)
 {
 	struct security_list *e;
 	struct hlist_node *tmp;
+	char d = 0;
+
+	if (lsm_unloading) {
+		d = 1;
+		spin_lock(&stacker_value_spinlock);
+	}
 
 	for (tmp = head->first; tmp; tmp = tmp->next) {
 		e = hlist_entry(tmp, struct security_list, list);
 		if (e->security_id == security_id) {
 			hlist_del(&e->list);
-			return e;
+			goto out;
 		}
 	}
 
-	return NULL;
+	e = NULL;
+
+out:
+	if (d)
+		spin_unlock(&stacker_value_spinlock);
+
+	return e;
 }
 
 EXPORT_SYMBOL_GPL(security_get_value);
Index: linux-2.6.13-rc3/security/stacker.c
===================================================================
--- linux-2.6.13-rc3.orig/security/stacker.c	2005-07-25 14:55:27.000000000 -0500
+++ linux-2.6.13-rc3/security/stacker.c	2005-07-25 15:31:17.000000000 -0500
@@ -1267,6 +1267,7 @@ find_lsm_with_namelen(const char *name, 
 	return ret;
 }
 
+extern int lsm_unloading;  /* from security/security.c */
 /*
  * XXX TODO I need an all_modules list again to use here
  */
@@ -1286,6 +1287,7 @@ static int stacker_unregister (const cha
 	}
 	list_del_rcu(&m->all_lsms);
 	call_rcu(&m->m_rcu, stacker_del_module);
+	lsm_unloading = 1;
 
 out:
 	spin_unlock(&stacker_lock);

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [patch 15/15] lsm stacking v0.3: stacking for digsig
  2005-07-27 18:19 ` [patch 1/15] lsm stacking v0.3: introduce securityfs serue
                     ` (12 preceding siblings ...)
  2005-07-27 18:28   ` [patch 14/15] lsm stacking v0.3: fix security_{del,unlink}_value race serue
@ 2005-07-27 18:28   ` serue
  13 siblings, 0 replies; 39+ messages in thread
From: serue @ 2005-07-27 18:28 UTC (permalink / raw)
  To: lkml
  Cc: Chris Wright, Stephen Smalley, James Morris, Andrew Morton,
	Michael Halcrow, David Safford, Reiner Sailer, Gerrit Huizenga,
	Emily Ratliff

Support stacking in digsig.  This patch is on top of the cvs version from
www.sf.net/projects/disec.

	[Jul 16] Update to support dynamic unloading by freeing
		object->security data at unload.

Signed-off-by: Serge Hallyn <serue@us.ibm.com>
--
 digsig.c |  142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 128 insertions(+), 14 deletions(-)

--- digsig/digsig.c	2005-07-06 08:41:38.000000000 -0500
+++ digsig-patched/digsig.c	2005-07-25 16:08:36.000000000 -0500
@@ -33,6 +33,7 @@
 #include <linux/fs.h>
 #include <asm/uaccess.h>
 #include <linux/security.h>
+#include <linux/security-stack.h>
 #include <linux/dcache.h>
 #include <linux/kobject.h>
 #include <linux/mman.h>
@@ -47,6 +48,8 @@
 #include "gnupg/mpi/mpi.h"
 #include "gnupg/cipher/rsa-verify.h"
 
+#define DIGSIG_LSM_ID 0x5AA8
+
 #ifdef DIGSIG_DEBUG
 #define DIGSIG_MODE 0		/*permissive  mode */
 #define DIGSIG_BENCH 1
@@ -55,11 +58,11 @@
 #define DIGSIG_BENCH 0
 #endif
 
-#define get_inode_security(ino) ((unsigned long)(ino->i_security))
-#define set_inode_security(ino,val) (ino->i_security = (void *)val)
-
-#define get_file_security(file) ((unsigned long)(file->f_security))
-#define set_file_security(file,val) (file->f_security = (void *)val)
+struct digsig_ksec {
+	struct security_list lsm_list;
+	struct list_head chain;
+	unsigned count;
+};
 
 unsigned long int total_jiffies = 0;
 
@@ -82,6 +85,73 @@ int dsi_cache_buckets = 128;
 module_param(dsi_cache_buckets, int, 0);
 MODULE_PARM_DESC(dsi_cache_buckets, "Number of cache buckets for signatures validations.\n");
 
+LIST_HEAD(digsig_del_chain);
+DEFINE_SPINLOCK(digsig_chain_lock);
+
+static int get_file_security(struct file *file)
+{
+	struct digsig_ksec *ksec;
+
+	ksec = security_get_value_type(&file->f_security, DIGSIG_LSM_ID,
+				struct digsig_ksec);
+	if (!ksec)
+		return 0;
+	return ksec->count;
+}
+
+static int set_file_security(struct file *file, int v)
+{
+	struct digsig_ksec *ksec;
+
+	ksec = security_get_value_type(&file->f_security, DIGSIG_LSM_ID,
+				struct digsig_ksec);
+	if (!ksec) {
+		ksec = kmalloc(sizeof(struct digsig_ksec), GFP_KERNEL);
+		if (!ksec)
+			return -ENOMEM;
+		INIT_LIST_HEAD(&ksec->chain);
+		spin_lock(&digsig_chain_lock);
+		list_add_rcu(&ksec->chain, &digsig_del_chain);
+		spin_unlock(&digsig_chain_lock);
+		security_add_value_type(&file->f_security, DIGSIG_LSM_ID,
+				 ksec);
+	}
+	ksec->count = v;
+	return 0;
+}
+
+
+static int get_inode_security(struct inode *inode)
+{
+	struct digsig_ksec *ksec;
+
+	ksec = security_get_value_type(&inode->i_security, DIGSIG_LSM_ID,
+				struct digsig_ksec);
+	if (!ksec)
+		return 0;
+	return ksec->count;
+}
+
+static int set_inode_security(struct inode *inode, int v)
+{
+	struct digsig_ksec *ksec;
+
+	ksec = security_get_value_type(&inode->i_security, DIGSIG_LSM_ID,
+				struct digsig_ksec);
+	if (!ksec) {
+		ksec = kmalloc(sizeof(struct digsig_ksec), GFP_KERNEL);
+		if (!ksec)
+			return -ENOMEM;
+		INIT_LIST_HEAD(&ksec->chain);
+		spin_lock(&digsig_chain_lock);
+		list_add(&ksec->chain, &digsig_del_chain);
+		spin_unlock(&digsig_chain_lock);
+		security_add_value_type(&inode->i_security, DIGSIG_LSM_ID,
+				 ksec);
+	}
+	ksec->count = v;
+	return 0;
+}
 
 /******************************************************************************
 Description : 
@@ -342,18 +412,22 @@ static int digsig_deny_write_access(stru
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	unsigned long isec;
+	int err;
 
 	spin_lock(&inode->i_lock);
 	isec = get_inode_security(inode);
 	if (atomic_read(&inode->i_writecount) > 0) {
-		spin_unlock(&inode->i_lock);
-		return -ETXTBSY;
+		err = -ETXTBSY;
+		goto out;
 	}
 	set_inode_security(inode, (isec+1));
-	set_file_security(file, 1);
-	spin_unlock(&inode->i_lock);
+	err = set_file_security(file, 1);
+	if (err)
+		set_inode_security(inode, (isec));
 
-	return 0;
+out:
+	spin_unlock(&inode->i_lock);
+	return err;
 }
 
 /*
@@ -379,9 +453,17 @@ static void digsig_allow_write_access(st
  */
 static void digsig_file_free_security(struct file *file)
 {
-	if (file->f_security) {
-		digsig_allow_write_access(file);
-	}
+	struct digsig_ksec *ksec;
+
+	ksec = security_get_value_type(&file->f_security, DIGSIG_LSM_ID,
+				struct digsig_ksec);
+	if (!ksec)
+		return;
+
+	spin_lock(&digsig_chain_lock);
+	list_del(&ksec->chain);
+	spin_unlock(&digsig_chain_lock);
+	kfree(ksec);
 }
 
 /**
@@ -530,7 +612,7 @@ static inline int is_unprotected_file(st
 			__FUNCTION__, file->f_dentry->d_name.name, exec_time); \
 	}
 	
-static int digsig_file_mmap(struct file * file, unsigned long prot, unsigned long flags)
+static int digsig_file_mmap(struct file * file, unsigned long reqprot, unsigned long prot, unsigned long flags)
 {
 	struct elf64_hdr *elf64_ex;
 	struct elf32_hdr *elf32_ex;
@@ -668,8 +750,20 @@ static int digsig_file_mmap(struct file 
 
 static void digsig_inode_free_security(struct inode *inode)
 {
+	struct digsig_ksec *ksec;
+
 	if (is_cached_signature(inode))
 		remove_signature(inode);
+
+	ksec = security_del_value_type(&inode->i_security, DIGSIG_LSM_ID,
+				struct digsig_ksec);
+	if (!ksec)
+		return;
+
+	spin_lock(&digsig_chain_lock);
+	list_del(&ksec->chain);
+	spin_unlock(&digsig_chain_lock);
+	kfree(ksec);
 }
 
 static struct security_operations digsig_security_ops = {
@@ -715,6 +809,25 @@ out:
 	return ret;
 }
 
+static void digsig_free_secchain(void)
+{
+	struct digsig_ksec *ksec, *n;
+
+	list_for_each_entry_safe(ksec, n, &digsig_del_chain, chain) {
+		printk(KERN_NOTICE "free_ichain unlinking %u, %d, %lu\n",
+			ksec->count, ksec->lsm_list.security_id,
+			(unsigned long)ksec->lsm_list.list.pprev);
+		security_unlink_value(&ksec->lsm_list.list);
+	}
+
+	synchronize_rcu();
+	list_for_each_entry_safe(ksec, n, &digsig_del_chain, chain) {
+		printk(KERN_NOTICE "free_ichain freeing 1\n");
+		list_del(&ksec->chain);
+		kfree(ksec);
+	}
+}
+
 static void __exit digsig_exit_module(void)
 {
 	DSM_PRINT (DEBUG_INIT, "Deinitializing module\n");
@@ -734,6 +847,7 @@ static void __exit digsig_exit_module(vo
 	digsig_cleanup_sysfs();
 	digsig_cleanup_revocation();
 	digsig_cache_cleanup();
+	digsig_free_secchain();
 	mpi_free(digsig_public_key[0]);
 	mpi_free(digsig_public_key[1]);
 }

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [patch 0/15] lsm stacking v0.3: intro
  2005-07-27 18:17 [patch 0/15] lsm stacking v0.3: intro serue
  2005-07-27 18:19 ` [patch 1/15] lsm stacking v0.3: introduce securityfs serue
@ 2005-07-27 19:34 ` James Morris
  2005-07-27 19:37   ` James Morris
  2005-07-27 19:54   ` [patch 0/15] lsm stacking v0.3: intro serue
  2005-07-30  5:07 ` Tony Jones
  2 siblings, 2 replies; 39+ messages in thread
From: James Morris @ 2005-07-27 19:34 UTC (permalink / raw)
  To: serue; +Cc: lkml, Chris Wright, Stephen Smalley, Andrew Morton,
	Michael Halcrow

On Wed, 27 Jul 2005 serue@us.ibm.com wrote:

> if interested in the performance results.  I am certainly interested in
> ways to further speed up security_get_value.

What about having a small static array of security blob pointers for the 
common case (e.g. SELinux + capabilities + perhaps something else), the 
total number of which is compile-time configurable.  Reserve one pointer 
at the end for the hlist.

When a module registers with stacker, if there's room in the array, it 
reserves a slot for the module.  This slot value can be stored by stacker 
in a handle held by the module (along with the stacker ID etc. perhaps).

Calls to security_get_value() etc. can then be very fast and simple for 
the common case, where the security blob is a pointer offset by an index 
in a small array.  The arbitrarily sized hlist would then be a fallback 
with a higher performance hit.


- James
-- 
James Morris
<jmorris@redhat.com>


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [patch 0/15] lsm stacking v0.3: intro
  2005-07-27 19:34 ` [patch 0/15] lsm stacking v0.3: intro James Morris
@ 2005-07-27 19:37   ` James Morris
  2005-08-03 16:45     ` [PATCH] Stacker - single-use static slots serue
  2005-07-27 19:54   ` [patch 0/15] lsm stacking v0.3: intro serue
  1 sibling, 1 reply; 39+ messages in thread
From: James Morris @ 2005-07-27 19:37 UTC (permalink / raw)
  To: serue; +Cc: lkml, Chris Wright, Stephen Smalley, Andrew Morton,
	Michael Halcrow

On Wed, 27 Jul 2005, James Morris wrote:

> Calls to security_get_value() etc. can then be very fast and simple for 
> the common case, where the security blob is a pointer offset by an index 
> in a small array.  The arbitrarily sized hlist would then be a fallback 
> with a higher performance hit.

Also, the static slots could be single-use only, so once a module 
registers for one, it's permanently assigned (even if the module unloads), 
to avoid locking overhead.  Module registration can just be test & set a 
bitmap.


- James
-- 
James Morris
<jmorris@redhat.com>


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [patch 0/15] lsm stacking v0.3: intro
  2005-07-27 19:34 ` [patch 0/15] lsm stacking v0.3: intro James Morris
  2005-07-27 19:37   ` James Morris
@ 2005-07-27 19:54   ` serue
  1 sibling, 0 replies; 39+ messages in thread
From: serue @ 2005-07-27 19:54 UTC (permalink / raw)
  To: James Morris
  Cc: serue, lkml, Chris Wright, Stephen Smalley, Andrew Morton,
	Michael Halcrow

Thanks, James.  I'll give this a shot and send out performance results
this weekend or next week.

thanks,
-serge

Quoting James Morris (jmorris@redhat.com):
> On Wed, 27 Jul 2005 serue@us.ibm.com wrote:
> 
> > if interested in the performance results.  I am certainly interested in
> > ways to further speed up security_get_value.
> 
> What about having a small static array of security blob pointers for the 
> common case (e.g. SELinux + capabilities + perhaps something else), the 
> total number of which is compile-time configurable.  Reserve one pointer 
> at the end for the hlist.
> 
> When a module registers with stacker, if there's room in the array, it 
> reserves a slot for the module.  This slot value can be stored by stacker 
> in a handle held by the module (along with the stacker ID etc. perhaps).
> 
> Calls to security_get_value() etc. can then be very fast and simple for 
> the common case, where the security blob is a pointer offset by an index 
> in a small array.  The arbitrarily sized hlist would then be a fallback 
> with a higher performance hit.
> 
> 
> - James
> -- 
> James Morris
> <jmorris@redhat.com>
> 
> 

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [patch 0/15] lsm stacking v0.3: intro
  2005-07-27 18:17 [patch 0/15] lsm stacking v0.3: intro serue
  2005-07-27 18:19 ` [patch 1/15] lsm stacking v0.3: introduce securityfs serue
  2005-07-27 19:34 ` [patch 0/15] lsm stacking v0.3: intro James Morris
@ 2005-07-30  5:07 ` Tony Jones
  2005-07-30 19:02   ` serge
  2 siblings, 1 reply; 39+ messages in thread
From: Tony Jones @ 2005-07-30  5:07 UTC (permalink / raw)
  To: serue
  Cc: lkml, Chris Wright, Stephen Smalley, James Morris, Andrew Morton,
	Michael Halcrow

On Wed, Jul 27, 2005 at 01:17:32PM -0500, serue@us.ibm.com wrote:

Hi Serge.

A few trivial things I noticed whilst writing some internal documentation
on Stacker.  Nothing deep here, but thought I'd pass them along.

I'll try to actually try out the code next week.

I made these notes as I was going along,  lmk if you need them annotated
to the original patch and I'll go back and redo.

Thanks again

Tony


1) Documentation refers to /security/stacker/list_modules,  code refers to
   "listmodules".  list_modules is more consistent with other file names.

2) symbol_get(ops) still at the end of stacker_register.

3) struct module_entry{
        struct list_head lsm_list;  /* list of active lsms */
        struct list_head all_lsms;  /* list of active lsms */

   fix comments

4) Would it be useful to change the struct elements lsm_list and all_lsms to
   be consistent with their list heads (stacked_modules and all_modules).

5) /*
 * Workarounds for the fact that get and setprocattr are used only by
 * selinux.  (Maybe)
 */

No complaints on selinux getting to avoid the (module), they are intree.
Just a FYI that SubDomain/AppArmor uses these hooks also.

6) stop_responding control file is misnamed, as stacker still continues to work
   it just removes the virtual file system

7) Does the lsm_list really need to be at the top of the struct?  Good style
but not sure it is required (must).

8) security-stack.h
 * If stacker is compiled in, then we use the full functions as
 * defined in security/security.c.  Otherwise we use the #defines
 * here.

I noticed the conditional CONFIG_SECURITY_STACKER code went away, previously
it would look at the value chain head only for the !case. But this comment
still remains.

> Hi,
> 
> The set of patches to follow introduces support for stacking LSMs.  This
> is its third posting to lkml.  I am sending it out in the hopes of
> soliciting more widespread feedback and testing, with the obvious eventual
> goal of mainline adoption.
> 
> Any feedback from people actually using this patch is appreciated.  Even
> better would be posts of (stackable) LSMs for upstream inclusion :)

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [patch 0/15] lsm stacking v0.3: intro
  2005-07-30  5:07 ` Tony Jones
@ 2005-07-30 19:02   ` serge
  2005-07-30 20:18     ` Tony Jones
  0 siblings, 1 reply; 39+ messages in thread
From: serge @ 2005-07-30 19:02 UTC (permalink / raw)
  To: Tony Jones
  Cc: serue, lkml, Chris Wright, Stephen Smalley, James Morris,
	Andrew Morton, Michael Halcrow

Quoting Tony Jones (tonyj@immunix.com):

Thanks, Tony.  I'll address each of these in the next patchset.  Just
two things I wanted to actually converse about:

> 5) /*
>  * Workarounds for the fact that get and setprocattr are used only by
>  * selinux.  (Maybe)
>  */
> 
> No complaints on selinux getting to avoid the (module), they are intree.
> Just a FYI that SubDomain/AppArmor uses these hooks also.

And is it ok with using the "some_data (apparmor)" convention?

The special handling of selinux is intended to be temporary, due to the
large base of installed userspace which hasn't yet been updated.  I
would imagine that at some point that code would go away.

> I noticed the conditional CONFIG_SECURITY_STACKER code went away, previously
> it would look at the value chain head only for the !case. But this comment
> still remains.

Yes, after I added the unlink function, it started to seem that the
special cases for !CONFIG_SECURITY_STACKER wouldn't be any faster than
the stacker versions.  They still might be, but I'll have to think about
it.  If I just ditch those, then I can probably ditch the whole
security-stack.h file, and move those declarations into security.h.
They were just in their own file because Stephen had pointed out that
switching between stacker and non-stacker would cause too much code to
be recompiled.

thanks,
-serge

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [patch 0/15] lsm stacking v0.3: intro
  2005-07-30 19:02   ` serge
@ 2005-07-30 20:18     ` Tony Jones
  2005-07-31  3:22       ` Steve Beattie
  2005-07-31  3:53       ` serge
  0 siblings, 2 replies; 39+ messages in thread
From: Tony Jones @ 2005-07-30 20:18 UTC (permalink / raw)
  To: serge
  Cc: serue, lkml, Chris Wright, Stephen Smalley, James Morris,
	Andrew Morton, Michael Halcrow, steve

Hi Serge

> > 5) /*
> >  * Workarounds for the fact that get and setprocattr are used only by
> >  * selinux.  (Maybe)
> >  */
> > 
> > No complaints on selinux getting to avoid the (module), they are intree.
> > Just a FYI that SubDomain/AppArmor uses these hooks also.
> 
> And is it ok with using the "some_data (apparmor)" convention?

Yes.  Our use of setprocattr is thru a library fn so I just made the change
there.  We'll have to change our user tools (that read /proc/pid/attr/current
but thats fine too).

> The special handling of selinux is intended to be temporary, due to the
> large base of installed userspace which hasn't yet been updated.  I
> would imagine that at some point that code would go away.

I assumed it was due to this. Doesn't inconvenience us any and it it helps 
SELinux it's fine w/ me.


Of more concern is ps -Z (pstools).

We had to have the pstools maintainer extend the set of characters that it
considered valid from the getprocattr.    I forget the details but IIRC he 
wanted to know (for ?documentation?) every character that could be returned 
by our getprocattr hook (which for us is pretty much any character thats 
valid in a pathname -- though IIRC we forgot one).

Anyway, I'm guessing (at least with pstools 3.2.5) that '(' is not one of
the valid characters. IIRC ps gives up when it sees a "non-valid" character.

I wrote a trivial little lsm which just returns 'foobar' for any getprocattr.

# cat /proc/2322/attr/current 
unconstrained (subdomain)
foobar (foobar)

# ps -Z -p 2322
LABEL                             PID TTY          TIME CMD
unconstrained                    2322 ttyS0    00:00:00 bash

Even if ps did return them all, I think it could create a usability problem.  
There was another LSM (forget which) which wanted to return a large blob 
from getprocattr, I recall like a page? in size which obviously caused problems
for ps -Z both in terms of content and especially length.

> > I noticed the conditional CONFIG_SECURITY_STACKER code went away, previously
> > it would look at the value chain head only for the !case. But this comment
> > still remains.
> 
> Yes, after I added the unlink function, it started to seem that the
> special cases for !CONFIG_SECURITY_STACKER wouldn't be any faster than
> the stacker versions.  They still might be, but I'll have to think about
> it.  If I just ditch those, then I can probably ditch the whole

Esp since James' suggestion would impact it. I'd imagine you would always want
array[0] for this case, no?

I was just pointing out the legacy comment. Thats all.

Thanks again

Tony

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [patch 0/15] lsm stacking v0.3: intro
  2005-07-30 20:18     ` Tony Jones
@ 2005-07-31  3:22       ` Steve Beattie
  2005-07-31  3:44         ` serge
  2005-07-31  3:53       ` serge
  1 sibling, 1 reply; 39+ messages in thread
From: Steve Beattie @ 2005-07-31  3:22 UTC (permalink / raw)
  To: Tony Jones
  Cc: serge, serue, lkml, Chris Wright, Stephen Smalley, James Morris,
	Andrew Morton, Michael Halcrow

[-- Attachment #1: Type: text/plain, Size: 1456 bytes --]

On Sat, Jul 30, 2005 at 01:18:52PM -0700, Tony Jones wrote:
> Of more concern is ps -Z (pstools).
> 
> We had to have the pstools maintainer extend the set of characters that it
> considered valid from the getprocattr.    I forget the details but IIRC he 
> wanted to know (for ?documentation?) every character that could be returned 
> by our getprocattr hook (which for us is pretty much any character thats 
> valid in a pathname -- though IIRC we forgot one).
> 
> Anyway, I'm guessing (at least with pstools 3.2.5) that '(' is not one of
> the valid characters. IIRC ps gives up when it sees a "non-valid" character.
> 
> I wrote a trivial little lsm which just returns 'foobar' for any getprocattr.
> 
> # cat /proc/2322/attr/current 
> unconstrained (subdomain)
> foobar (foobar)
> 
> # ps -Z -p 2322
> LABEL                             PID TTY          TIME CMD
> unconstrained                    2322 ttyS0    00:00:00 bash

Actually, no, it is the space preceding the open paren that is invalid;
see this patch for the expanded allowed character set in procps 3.2.5:

  http://cvs.sourceforge.net/viewcvs.py/procps/procps/ps/output.c?r1=1.51&r2=1.52

When I discussed this with Albert Cahalan, he *strongly* objected to
allowing whitespace in security contexts, as he felt it would break
scripts that parsed 'ps -Z' output.

-- 
Steve Beattie
SUSE Labs, Novell Inc. 
<sbeattie@suse.de>
http://NxNW.org/~steve/

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [patch 0/15] lsm stacking v0.3: intro
  2005-07-31  3:22       ` Steve Beattie
@ 2005-07-31  3:44         ` serge
  2005-07-31  4:13           ` Tony Jones
  0 siblings, 1 reply; 39+ messages in thread
From: serge @ 2005-07-31  3:44 UTC (permalink / raw)
  To: Steve Beattie
  Cc: Tony Jones, serue, lkml, Chris Wright, Stephen Smalley,
	James Morris, Andrew Morton, Michael Halcrow

Quoting Steve Beattie (sbeattie@suse.de):
> On Sat, Jul 30, 2005 at 01:18:52PM -0700, Tony Jones wrote:
> > # cat /proc/2322/attr/current 
> > unconstrained (subdomain)
> > foobar (foobar)
> > 
> > # ps -Z -p 2322
> > LABEL                             PID TTY          TIME CMD
> > unconstrained                    2322 ttyS0    00:00:00 bash
> 
> Actually, no, it is the space preceding the open paren that is invalid;
> see this patch for the expanded allowed character set in procps 3.2.5:
> 
>   http://cvs.sourceforge.net/viewcvs.py/procps/procps/ps/output.c?r1=1.51&r2=1.52
> 
> When I discussed this with Albert Cahalan, he *strongly* objected to
> allowing whitespace in security contexts, as he felt it would break
> scripts that parsed 'ps -Z' output.

Right, I thought this was actually a feature :)  This is how ps
continues to show expected output under stacker.  Given naturally limited
space, showing output for multiple modules may not be a good idea.  If
you want more detail, you go to /proc/pid/attr/current...

Clearly this is limiting, but then so is the one line per process you
get with ps - "fixing" that is obviously not acceptable.  Is there
another suggestion for how to handle this, in such a way that ps would
show info for >1 module?  Is there any example where the current
behavior is actually a problem - two modules which it makes sense to
stack, which both need to give output under ps?

thanks,
-serge

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [patch 0/15] lsm stacking v0.3: intro
  2005-07-30 20:18     ` Tony Jones
  2005-07-31  3:22       ` Steve Beattie
@ 2005-07-31  3:53       ` serge
  1 sibling, 0 replies; 39+ messages in thread
From: serge @ 2005-07-31  3:53 UTC (permalink / raw)
  To: Tony Jones
  Cc: serue, lkml, Chris Wright, Stephen Smalley, James Morris,
	Andrew Morton, Michael Halcrow, steve

Quoting Tony Jones (tonyj@suse.de):
> > Yes, after I added the unlink function, it started to seem that the
> > special cases for !CONFIG_SECURITY_STACKER wouldn't be any faster than
> > the stacker versions.  They still might be, but I'll have to think about
> > it.  If I just ditch those, then I can probably ditch the whole
> 
> Esp since James' suggestion would impact it. I'd imagine you would always want
> array[0] for this case, no?

Actually I don't think that's even needed - I just wasn't thinking right
while addressing another bug.

thanks,
-serge

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [patch 0/15] lsm stacking v0.3: intro
  2005-07-31  3:44         ` serge
@ 2005-07-31  4:13           ` Tony Jones
  2005-07-31 13:37             ` serge
  0 siblings, 1 reply; 39+ messages in thread
From: Tony Jones @ 2005-07-31  4:13 UTC (permalink / raw)
  To: serge
  Cc: Steve Beattie, Tony Jones, serue, lkml, Chris Wright,
	Stephen Smalley, James Morris, Andrew Morton, Michael Halcrow

On Sat, Jul 30, 2005 at 10:44:09PM -0500, serge@hallyn.com wrote:
> > When I discussed this with Albert Cahalan, he *strongly* objected to
> > allowing whitespace in security contexts, as he felt it would break
> > scripts that parsed 'ps -Z' output.
> 
> Right, I thought this was actually a feature :)  This is how ps
> continues to show expected output under stacker.  Given naturally limited
> space, showing output for multiple modules may not be a good idea.  If
> you want more detail, you go to /proc/pid/attr/current...

OK. As long as you are aware of it, which it sounds like you are.

Serge, I think it should be documented as a known issue.

> Clearly this is limiting, but then so is the one line per process you
> get with ps - "fixing" that is obviously not acceptable.  Is there

Nothing jumps out at me.

> Is there any example where the current
> behavior is actually a problem - two modules which it makes sense to
> stack, which both need to give output under ps?

I don't know.  Isn't this the big negative against stacker, controlling
the composition?  pstools has clearly cast it's vote :-)

Tony

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [patch 0/15] lsm stacking v0.3: intro
  2005-07-31  4:13           ` Tony Jones
@ 2005-07-31 13:37             ` serge
  0 siblings, 0 replies; 39+ messages in thread
From: serge @ 2005-07-31 13:37 UTC (permalink / raw)
  To: Tony Jones
  Cc: Steve Beattie, Tony Jones, serue, lkml, Chris Wright,
	Stephen Smalley, James Morris, Andrew Morton, Michael Halcrow

Quoting Tony Jones (tonyj@immunix.com):
> OK. As long as you are aware of it, which it sounds like you are.
> 
> Serge, I think it should be documented as a known issue.

Ok.

> > Clearly this is limiting, but then so is the one line per process you
> > get with ps - "fixing" that is obviously not acceptable.  Is there
> 
> Nothing jumps out at me.
> 
> > Is there any example where the current
> > behavior is actually a problem - two modules which it makes sense to
> > stack, which both need to give output under ps?
> 
> I don't know.  Isn't this the big negative against stacker, controlling
> the composition?  pstools has clearly cast it's vote :-)

Well, pstools combined with existing userspace tools.  I think the
older version of stacker outputed comma-delimited output for each
module.  But that requires changes in the selinux userspace tools for
things to work at all.  That doesn't mean it's not the better way to
solve the problem.  So for instance we could output

staff_u:staff_r:serge_t(selinux),jail3(bsdjail)

-serge

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH] Stacker - single-use static slots
  2005-07-27 19:37   ` James Morris
@ 2005-08-03 16:45     ` serue
  2005-08-03 17:57       ` Chris Wright
  2005-08-05 15:55       ` James Morris
  0 siblings, 2 replies; 39+ messages in thread
From: serue @ 2005-08-03 16:45 UTC (permalink / raw)
  To: James Morris; +Cc: lkml, Chris Wright, Stephen Smalley, Andrew Morton

Quoting James Morris (jmorris@redhat.com):
> On Wed, 27 Jul 2005, James Morris wrote:
> 
> > Calls to security_get_value() etc. can then be very fast and simple for 
> > the common case, where the security blob is a pointer offset by an index 
> > in a small array.  The arbitrarily sized hlist would then be a fallback 
> > with a higher performance hit.
> 
> Also, the static slots could be single-use only, so once a module 
> registers for one, it's permanently assigned (even if the module unloads), 
> to avoid locking overhead.  Module registration can just be test & set a 
> bitmap.

Oops, I didn't notice this last part, so module unload does unregister
the slot, but this shouldn't affect performance.  However I may get rid
of it still since the non-stacker mod_reg_security is not protected.
Or, I may just throw in a spinlock, since this is clearly an infrequent
call.

The attached patch implements your idea on top of my previous patchset.
Following is performance data on a 16-way ppc.  dbench and tbench were
run 50 times, kernbench and reaim 10 times each;  results are mean +/-
95% confidence half-interval.  The 'static slot' kernel had a single
static slot for selinux, plus the (unused in this case) shared struct
hlist_head security.

The improvements are very slight, but at least in the case of dbench
they appear to be significant.  I'm particularly surprised by the 
reaim results, as I would have expected some punishment for the extra
memory use.

dbench (throughput, higher is better):
plain stacker:  1450.847800 +/- 12.666275
static slot:    1471.137400 +/- 5.905005

kernbench (time, lower is better):
plain stacker:  52.977000 +/- 0.101730
static slot:    52.976000 +/- 0.129828

tbench (throughput, higher is better):
plain stacker:  140.335360 +/- 2.622280
static slot:    142.455340 +/- 2.957549

reaim (number of jobs vs number of children forked, higher is better)
plain stacker:
1 100542.857000 3296.286475
3 284142.855000 16481.432373
5 480857.144000 26914.062669
7 622200.000000 23074.003061
9 799971.426000 29666.576010
11 949692.861000 27194.361719
13 1065535.715000 53564.650500
15 1147500.000000 0.000000

static slot:
1 100542.857000 3296.286475
3 288514.284000 16148.439818
5 488142.858000 25175.800349
7 612000.000000 0.000000
9 799971.426000 29666.576010
11 949692.861000 27194.361719
13 1093950.001000 49092.813099
15 1147500.000000 0.000000

thank,
-serge

Signed-off-by: Serge Hallyn <serue@us.ibm.com>
--
 fs/inode.c                     |    2 
 include/linux/binfmts.h        |    1 
 include/linux/fs.h             |    4 
 include/linux/ipc.h            |    1 
 include/linux/msg.h            |    1 
 include/linux/sched.h          |    1 
 include/linux/security-stack.h |    2 
 include/linux/security.h       |   74 ++++++--
 include/net/sock.h             |    1 
 ipc/msg.c                      |    2 
 ipc/msgutil.c                  |    2 
 ipc/sem.c                      |    2 
 ipc/shm.c                      |    2 
 kernel/fork.c                  |    2 
 security/Kconfig               |   12 +
 security/cap_stack.c           |    4 
 security/capability.c          |    4 
 security/root_plug.c           |    4 
 security/seclvl.c              |   22 +-
 security/security.c            |   79 +++++++-
 security/selinux/hooks.c       |  375 +++++++++++++++++++++++++++--------------
 security/selinux/selinuxfs.c   |   11 -
 security/stacker.c             |    2 
 23 files changed, 443 insertions(+), 167 deletions(-)

Index: linux-2.6.12/include/linux/security.h
===================================================================
--- linux-2.6.12.orig/include/linux/security.h	2005-08-01 20:00:51.000000000 -0500
+++ linux-2.6.12/include/linux/security.h	2005-08-01 20:23:52.000000000 -0500
@@ -44,24 +44,65 @@ struct security_list {
 };
 
 
+static inline void *__get_value(void *head, int idx)
+{
+	void **p = head + sizeof(struct hlist_head);
+#if 0
+	printk(KERN_NOTICE "__get_value: %s (%d): head %lx p %lx idx %d returning %lx at %lx\n",
+		__FUNCTION__, __LINE__, (long)head, (long)p, idx, (long)p[idx], (long)&p[idx]);
+#endif
+	return p[idx];
+}
+
+static inline void __set_value(void *head, int idx, void *v)
+{
+	void **p = head + sizeof(struct hlist_head);
+	p[idx] = v;
+#if 0
+	printk(KERN_NOTICE "%s (%d): hd %lx, p %lx, idx %d,"
+		"v %lx, p[idx] %lx at %lx\n",
+		__FUNCTION__, __LINE__, (long) (head),
+		(long) p, idx, (long) (v),
+		(long)p[idx], (long)&p[idx]);
+#endif
+}
+
 /*
  * These #defines present more convenient interfaces to
  * LSMs for using the security{g,d,s}et_value functions.
  */
-#define security_get_value_type(head, id, type) ( { \
-	struct security_list *v = security_get_value((head), id); \
-	v ? hlist_entry(v, type, lsm_list) : NULL; } )
-
-#define security_set_value_type(head, id, value) \
-	security_set_value((head), id, &(value)->lsm_list);
-
-#define security_add_value_type(head, id, value) \
-	security_add_value((head), id, &(value)->lsm_list);
-
-#define security_del_value_type(head, id, type) ( { \
-	struct security_list *v; \
-	v = security_del_value((head), id); \
-	v ? hlist_entry(v, type, lsm_list) : NULL; } )
+#define security_get_value_type(head, id, type, idx) (idx>=0) ? \
+		(type *)__get_value((head), idx) \
+	: ({ \
+		struct security_list *v = security_get_value((head), id); \
+		v ? hlist_entry(v, type, lsm_list) : NULL; \
+	})
+
+#define security_set_value_type(head, id, value, idx) \
+	do { \
+		if (idx>=0) { \
+			__set_value((head), idx, (value)); \
+		} else { \
+			security_set_value((head), id, &(value)->lsm_list); \
+		} \
+	} while (0);
+
+#define security_add_value_type(head, id, value, idx) \
+	do { \
+		if (idx>=0) { \
+			__set_value((head), idx, (value)); \
+		} else { \
+			security_add_value((head), id, &(value)->lsm_list); \
+		} \
+	} while (0);
+
+#define security_del_value_type(head, id, type, idx) (idx>=0) ? \
+		(type *)__get_value((head), idx) \
+	: ( { \
+		struct security_list *v; \
+		v = security_del_value((head), id); \
+		v ? hlist_entry(v, type, lsm_list) : NULL; \
+	} )
 
 /* security_disown_value is really only to be used by stacker */
 extern void security_disown_value(struct hlist_head *);
@@ -2022,9 +2063,10 @@ static inline int security_netlink_recv(
 
 /* prototypes */
 extern int security_init	(void);
-extern int register_security	(struct security_operations *ops);
+extern int register_security	(struct security_operations *ops, int *idx);
 extern int unregister_security	(struct security_operations *ops);
-extern int mod_reg_security	(const char *name, struct security_operations *ops);
+extern int mod_reg_security	(const char *name,
+			struct security_operations *ops, int *idx);
 extern int mod_unreg_security	(const char *name, struct security_operations *ops);
 extern struct dentry *securityfs_create_file(const char *name, mode_t mode,
 					     struct dentry *parent, void *data,
Index: linux-2.6.12/security/Kconfig
===================================================================
--- linux-2.6.12.orig/security/Kconfig	2005-08-01 20:00:51.000000000 -0500
+++ linux-2.6.12/security/Kconfig	2005-08-01 20:24:11.000000000 -0500
@@ -112,5 +112,17 @@ config SECURITY_STACKER
 	help
 	  Stack multiple LSMs.
 
+config SECURITY_STACKER_NUMFIELDS
+	int "Number of security fields to reserve"
+	depends on SECURITY_STACKER
+	default 1
+	help
+	  This option reserves extra space in each kernel object
+	  for security information.  This may speed up modules which
+	  make a lot of use of these fields, as these accesses can
+	  be lock-free.  However each kernel object requires one
+	  extra byte for each field reserved her, which can slow
+	  the system down.
+
 endmenu
 
Index: linux-2.6.12/fs/inode.c
===================================================================
--- linux-2.6.12.orig/fs/inode.c	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.12/fs/inode.c	2005-08-01 20:24:25.000000000 -0500
@@ -134,6 +134,8 @@ static struct inode *alloc_inode(struct 
 		inode->i_cdev = NULL;
 		inode->i_rdev = 0;
 		INIT_HLIST_HEAD(&inode->i_security);
+		memset(&inode->i_security_p, 0,
+			CONFIG_SECURITY_STACKER_NUMFIELDS*sizeof(void *));
 		inode->dirtied_when = 0;
 		if (security_inode_alloc(inode)) {
 			if (inode->i_sb->s_op->destroy_inode)
Index: linux-2.6.12/include/linux/binfmts.h
===================================================================
--- linux-2.6.12.orig/include/linux/binfmts.h	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.12/include/linux/binfmts.h	2005-08-01 20:24:41.000000000 -0500
@@ -30,6 +30,7 @@ struct linux_binprm{
 	int e_uid, e_gid;
 	kernel_cap_t cap_inheritable, cap_permitted, cap_effective;
 	struct hlist_head security;
+	void * security_p[CONFIG_SECURITY_STACKER_NUMFIELDS];
 	int argc, envc;
 	char * filename;	/* Name of binary as seen by procps */
 	char * interp;		/* Name of the binary really executed. Most
Index: linux-2.6.12/include/linux/fs.h
===================================================================
--- linux-2.6.12.orig/include/linux/fs.h	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.12/include/linux/fs.h	2005-08-01 20:24:55.000000000 -0500
@@ -486,6 +486,7 @@ struct inode {
 
 	atomic_t		i_writecount;
 	struct hlist_head	i_security;
+	void			*i_security_p[CONFIG_SECURITY_STACKER_NUMFIELDS];
 	union {
 		void		*generic_ip;
 	} u;
@@ -560,6 +561,7 @@ struct fown_struct {
 	int pid;		/* pid or -pgrp where SIGIO should be sent */
 	uid_t uid, euid;	/* uid/euid of process setting the owner */
 	struct hlist_head security;
+	void * security_p[CONFIG_SECURITY_STACKER_NUMFIELDS];
 	int signum;		/* posix.1b rt signal to be delivered on IO */
 };
 
@@ -597,6 +599,7 @@ struct file {
 	size_t			f_maxcount;
 	unsigned long		f_version;
 	struct hlist_head	f_security;
+	void 			*f_security_p[CONFIG_SECURITY_STACKER_NUMFIELDS];
 
 	/* needed for tty driver, and maybe others */
 	void			*private_data;
@@ -786,6 +789,7 @@ struct super_block {
 	int			s_need_sync_fs;
 	atomic_t		s_active;
  	struct hlist_head	s_security;
+	void			*s_security_p[CONFIG_SECURITY_STACKER_NUMFIELDS];
 	struct xattr_handler	**s_xattr;
 
 	struct list_head	s_inodes;	/* all inodes */
Index: linux-2.6.12/include/linux/ipc.h
===================================================================
--- linux-2.6.12.orig/include/linux/ipc.h	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.12/include/linux/ipc.h	2005-08-01 20:25:09.000000000 -0500
@@ -67,6 +67,7 @@ struct kern_ipc_perm
 	mode_t		mode; 
 	unsigned long	seq;
 	struct hlist_head security;
+	void		*security_p[CONFIG_SECURITY_STACKER_NUMFIELDS];
 };
 
 #endif /* __KERNEL__ */
Index: linux-2.6.12/include/linux/msg.h
===================================================================
--- linux-2.6.12.orig/include/linux/msg.h	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.12/include/linux/msg.h	2005-08-01 20:25:28.000000000 -0500
@@ -71,6 +71,7 @@ struct msg_msg {
 	int m_ts;           /* message text size */
 	struct msg_msgseg* next;
 	struct hlist_head security;
+	void * security_p[CONFIG_SECURITY_STACKER_NUMFIELDS];
 	/* the actual message follows immediately */
 };
 
Index: linux-2.6.12/include/linux/sched.h
===================================================================
--- linux-2.6.12.orig/include/linux/sched.h	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.12/include/linux/sched.h	2005-08-01 20:25:56.000000000 -0500
@@ -722,6 +722,7 @@ struct task_struct {
 	sigset_t *notifier_mask;
 	
 	struct hlist_head security;
+	void *security_p[CONFIG_SECURITY_STACKER_NUMFIELDS];
 	struct audit_context *audit_context;
 	seccomp_t seccomp;
 
Index: linux-2.6.12/include/net/sock.h
===================================================================
--- linux-2.6.12.orig/include/net/sock.h	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.12/include/net/sock.h	2005-08-01 20:26:11.000000000 -0500
@@ -241,6 +241,7 @@ struct sock {
 	__u32			sk_sndmsg_off;
 	int			sk_write_pending;
 	struct hlist_head	sk_security;
+	void			*sk_security_p[CONFIG_SECURITY_STACKER_NUMFIELDS];
 	void			(*sk_state_change)(struct sock *sk);
 	void			(*sk_data_ready)(struct sock *sk, int bytes);
 	void			(*sk_write_space)(struct sock *sk);
Index: linux-2.6.12/ipc/msg.c
===================================================================
--- linux-2.6.12.orig/ipc/msg.c	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.12/ipc/msg.c	2005-08-01 20:26:27.000000000 -0500
@@ -100,6 +100,8 @@ static int newque (key_t key, int msgflg
 	msq->q_perm.key = key;
 
 	INIT_HLIST_HEAD(&msq->q_perm.security);
+	memset(&msq->q_perm.security_p, 0,
+			CONFIG_SECURITY_STACKER_NUMFIELDS*sizeof(void *));
 	retval = security_msg_queue_alloc(msq);
 	if (retval) {
 		ipc_rcu_putref(msq);
Index: linux-2.6.12/ipc/msgutil.c
===================================================================
--- linux-2.6.12.orig/ipc/msgutil.c	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.12/ipc/msgutil.c	2005-08-01 20:26:41.000000000 -0500
@@ -42,6 +42,8 @@ struct msg_msg *load_msg(const void __us
 
 	msg->next = NULL;
 	INIT_HLIST_HEAD(&msg->security);
+	memset(&msg->security_p, 0,
+		CONFIG_SECURITY_STACKER_NUMFIELDS*sizeof(void *));
 
 	if (copy_from_user(msg + 1, src, alen)) {
 		err = -EFAULT;
Index: linux-2.6.12/ipc/sem.c
===================================================================
--- linux-2.6.12.orig/ipc/sem.c	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.12/ipc/sem.c	2005-08-01 20:26:57.000000000 -0500
@@ -179,6 +179,8 @@ static int newary (key_t key, int nsems,
 	sma->sem_perm.key = key;
 
 	INIT_HLIST_HEAD(&sma->sem_perm.security);
+	memset(&sma->sem_perm.security_p, 0,
+		CONFIG_SECURITY_STACKER_NUMFIELDS*sizeof(void *));
 	retval = security_sem_alloc(sma);
 	if (retval) {
 		ipc_rcu_putref(sma);
Index: linux-2.6.12/ipc/shm.c
===================================================================
--- linux-2.6.12.orig/ipc/shm.c	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.12/ipc/shm.c	2005-08-01 20:27:10.000000000 -0500
@@ -200,6 +200,8 @@ static int newseg (key_t key, int shmflg
 	shp->mlock_user = NULL;
 
 	INIT_HLIST_HEAD(&shp->shm_perm.security);
+	memset(&shp->shm_perm.security_p, 0,
+		CONFIG_SECURITY_STACKER_NUMFIELDS*sizeof(void *));
 	error = security_shm_alloc(shp);
 	if (error) {
 		ipc_rcu_putref(shp);
Index: linux-2.6.12/kernel/fork.c
===================================================================
--- linux-2.6.12.orig/kernel/fork.c	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.12/kernel/fork.c	2005-08-01 20:27:22.000000000 -0500
@@ -942,6 +942,8 @@ static task_t *copy_process(unsigned lon
 	p->lock_depth = -1;		/* -1 = no lock */
 	do_posix_clock_monotonic_gettime(&p->start_time);
 	INIT_HLIST_HEAD(&p->security);
+	memset(&p->security_p, 0,
+		CONFIG_SECURITY_STACKER_NUMFIELDS*sizeof(void *));
 	p->io_context = NULL;
 	p->io_wait = NULL;
 	p->audit_context = NULL;
Index: linux-2.6.12/security/security.c
===================================================================
--- linux-2.6.12.orig/security/security.c	2005-08-01 20:00:51.000000000 -0500
+++ linux-2.6.12/security/security.c	2005-08-01 20:27:40.000000000 -0500
@@ -20,6 +20,9 @@
 
 #define SECURITY_FRAMEWORK_VERSION	"1.0.0"
 
+static struct security_operations
+	*security_field_owners[CONFIG_SECURITY_STACKER_NUMFIELDS];
+
 fastcall struct security_list *
 security_get_value(struct hlist_head *head, int security_id)
 {
@@ -49,12 +52,12 @@ fastcall void
 security_set_value(struct hlist_head *head, int security_id,
 	struct security_list *obj_node)
 {
-
 	obj_node->security_id = security_id;
 	hlist_add_head(&obj_node->list, head);
 }
 
 static DEFINE_SPINLOCK(stacker_value_spinlock);
+static DEFINE_SPINLOCK(security_field_spinlock);
 
 /*
  * Used outside of security_*_alloc hooks, so we need to
@@ -65,7 +68,6 @@ fastcall void
 security_add_value(struct hlist_head *head, int security_id,
 	struct security_list *obj_node)
 {
-
 	spin_lock(&stacker_value_spinlock);
 	obj_node->security_id = security_id;
 	hlist_add_head_rcu(&obj_node->list, head);
@@ -86,9 +88,13 @@ security_add_value(struct hlist_head *he
  * XXX TODO - switch this to take a type, and deref
  * obj->lsm_list.list here.
  */
-int security_unlink_value(struct hlist_node *n)
+int security_unlink_value(struct hlist_node *n, int idx)
 {
 	int ret = 0;
+
+	if (idx>=0)
+		return 0;
+
 	spin_lock(&stacker_value_spinlock);
 	if (n->pprev == LIST_POISON2) {
 		ret = 1;
@@ -223,7 +229,7 @@ int __init security_init(void)
  * If there is already a security module registered with the kernel,
  * an error will be returned.  Otherwise 0 is returned on success.
  */
-int register_security(struct security_operations *ops)
+int register_security(struct security_operations *ops, int *idx)
 {
 	if (security_ops != &dummy_security_ops)
 		return -EAGAIN;
@@ -234,6 +240,21 @@ int register_security(struct security_op
 		return -EINVAL;
 	}
 
+	spin_lock(&security_field_spinlock);
+	if (idx && *idx) {
+		int i;
+
+		*idx = -1;
+		for (i=0; i<CONFIG_SECURITY_STACKER_NUMFIELDS; i++) {
+			if (security_field_owners[i] == NULL) {
+				security_field_owners[i] = ops;
+				*idx = i;
+				break;
+			}
+		}
+	}
+	spin_unlock(&security_field_spinlock);
+
 	security_ops = ops;
 
 	return 0;
@@ -252,6 +273,8 @@ int register_security(struct security_op
  */
 int unregister_security(struct security_operations *ops)
 {
+	int i;
+
 	if (ops != security_ops) {
 		printk(KERN_INFO "%s: trying to unregister "
 		       "a security_opts structure that is not "
@@ -261,6 +284,15 @@ int unregister_security(struct security_
 
 	security_ops = &dummy_security_ops;
 
+	spin_lock(&security_field_spinlock);
+	for (i=0; i<CONFIG_SECURITY_STACKER_NUMFIELDS; i++) {
+		if (security_field_owners[i] == ops) {
+			security_field_owners[i] = NULL;
+			break;
+		}
+	}
+	spin_unlock(&security_field_spinlock);
+
 	return 0;
 }
 
@@ -276,8 +308,11 @@ int unregister_security(struct security_
  * The return value depends on the currently loaded security module, with 0 as
  * success.
  */
-int mod_reg_security(const char *name, struct security_operations *ops)
+int mod_reg_security(const char *name, struct security_operations *ops,
+			int *idx)
 {
+	int ret = 0;
+
 	if (!ops) {
 		printk(KERN_INFO "%s received NULL security operations",
 						       __FUNCTION__);
@@ -290,7 +325,28 @@ int mod_reg_security(const char *name, s
 		return -EINVAL;
 	}
 
-	return security_ops->register_security(name, ops);
+	ret = security_ops->register_security(name, ops);
+
+	if (ret < 0)
+		goto out;
+
+	spin_lock(&security_field_spinlock);
+	if (idx && *idx) {
+		int i;
+
+		*idx = -1;
+		for (i=0; i<CONFIG_SECURITY_STACKER_NUMFIELDS; i++) {
+			if (security_field_owners[i] == NULL) {
+				security_field_owners[i] = ops;
+				*idx = i;
+				break;
+			}
+		}
+	}
+	spin_unlock(&security_field_spinlock);
+
+out:
+	return ret;
 }
 
 /**
@@ -308,12 +364,23 @@ int mod_reg_security(const char *name, s
  */
 int mod_unreg_security(const char *name, struct security_operations *ops)
 {
+	int i;
+
 	if (ops == security_ops) {
 		printk(KERN_INFO "%s invalid attempt to unregister "
 		       " primary security ops.\n", __FUNCTION__);
 		return -EINVAL;
 	}
 
+	spin_lock(&security_field_spinlock);
+	for (i=0; i<CONFIG_SECURITY_STACKER_NUMFIELDS; i++) {
+		if (security_field_owners[i] == ops) {
+			security_field_owners[i] = NULL;
+			break;
+		}
+	}
+	spin_unlock(&security_field_spinlock);
+
 	return security_ops->unregister_security(name, ops);
 }
 
Index: linux-2.6.12/security/selinux/hooks.c
===================================================================
--- linux-2.6.12.orig/security/selinux/hooks.c	2005-08-01 20:00:51.000000000 -0500
+++ linux-2.6.12/security/selinux/hooks.c	2005-08-01 20:27:56.000000000 -0500
@@ -78,6 +78,8 @@
 #define XATTR_SELINUX_SUFFIX "selinux"
 #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
 
+int selinux_secidx;
+
 extern unsigned int policydb_loaded_version;
 extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
 
@@ -123,7 +125,8 @@ static int task_alloc_security(struct ta
 	memset(tsec, 0, sizeof(struct task_security_struct));
 	tsec->task = task;
 	tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;
-	security_set_value_type(&task->security, SELINUX_LSM_ID, tsec);
+	security_set_value_type(&task->security, SELINUX_LSM_ID, tsec,
+		selinux_secidx);
 
 	return 0;
 }
@@ -133,7 +136,8 @@ static void task_free_security(struct ta
 	struct task_security_struct *tsec;
 	
 	tsec = security_del_value_type(&task->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+			selinux_secidx);
 
 	kfree(tsec);
 }
@@ -144,7 +148,8 @@ static int inode_alloc_security(struct i
 	struct inode_security_struct *isec;
 
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	isec = kmalloc(sizeof(struct inode_security_struct), GFP_KERNEL);
 	if (!isec)
 		return -ENOMEM;
@@ -159,7 +164,8 @@ static int inode_alloc_security(struct i
 		isec->task_sid = tsec->sid;
 	else
 		isec->task_sid = SECINITSID_UNLABELED;
-	security_set_value_type(&inode->i_security, SELINUX_LSM_ID, isec);
+	security_set_value_type(&inode->i_security, SELINUX_LSM_ID, isec,
+		selinux_secidx);
 
 	return 0;
 }
@@ -170,12 +176,14 @@ static void inode_free_security(struct i
 	struct superblock_security_struct *sbsec;
 
 	isec = security_del_value_type(&inode->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+		struct inode_security_struct,
+			selinux_secidx);
 	if (!isec)
 		return;
 
 	sbsec = security_get_value_type(&inode->i_sb->s_security,
-		SELINUX_LSM_ID, struct superblock_security_struct);
+		SELINUX_LSM_ID, struct superblock_security_struct,
+		selinux_secidx);
 
 	spin_lock(&sbsec->isec_lock);
 	if (!list_empty(&isec->list))
@@ -191,7 +199,8 @@ static int file_alloc_security(struct fi
 	struct file_security_struct *fsec;
 
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	fsec = kmalloc(sizeof(struct file_security_struct), GFP_ATOMIC);
 	if (!fsec)
 		return -ENOMEM;
@@ -205,7 +214,8 @@ static int file_alloc_security(struct fi
 		fsec->sid = SECINITSID_UNLABELED;
 		fsec->fown_sid = SECINITSID_UNLABELED;
 	}
-	security_set_value_type(&file->f_security, SELINUX_LSM_ID, fsec);
+	security_set_value_type(&file->f_security, SELINUX_LSM_ID, fsec,
+		selinux_secidx);
 
 	return 0;
 }
@@ -215,7 +225,8 @@ static void file_free_security(struct fi
 	struct file_security_struct *fsec;
 
 	fsec = security_del_value_type(&file->f_security, SELINUX_LSM_ID,
-		struct file_security_struct);
+		struct file_security_struct,
+			selinux_secidx);
 
 	kfree(fsec);
 }
@@ -236,7 +247,8 @@ static int superblock_alloc_security(str
 	sbsec->sb = sb;
 	sbsec->sid = SECINITSID_UNLABELED;
 	sbsec->def_sid = SECINITSID_FILE;
-	security_set_value_type(&sb->s_security, SELINUX_LSM_ID, sbsec);
+	security_set_value_type(&sb->s_security, SELINUX_LSM_ID, sbsec,
+		selinux_secidx);
 
 	return 0;
 }
@@ -246,7 +258,7 @@ static void superblock_free_security(str
 	struct superblock_security_struct *sbsec;
 
 	sbsec = security_del_value_type(&sb->s_security, SELINUX_LSM_ID,
-		struct superblock_security_struct);
+		struct superblock_security_struct, selinux_secidx);
 	if (!sbsec)
 		return;
 
@@ -273,7 +285,8 @@ static int sk_alloc_security(struct sock
 	memset(ssec, 0, sizeof(*ssec));
 	ssec->sk = sk;
 	ssec->peer_sid = SECINITSID_UNLABELED;
-	security_set_value_type(&sk->sk_security, SELINUX_LSM_ID, ssec);
+	security_set_value_type(&sk->sk_security, SELINUX_LSM_ID, ssec,
+		selinux_secidx);
 
 	return 0;
 }
@@ -286,7 +299,7 @@ static void sk_free_security(struct sock
 		return;
 
 	ssec = security_del_value_type(&sk->sk_security, SELINUX_LSM_ID,
-		struct sk_security_struct);
+		struct sk_security_struct, selinux_secidx);
 
 	kfree(ssec);
 }
@@ -338,9 +351,11 @@ static int try_context_mount(struct supe
 	struct superblock_security_struct *sbsec;
 
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	sbsec = security_get_value_type(&sb->s_security, SELINUX_LSM_ID,
-		struct superblock_security_struct);
+		struct superblock_security_struct,
+		selinux_secidx);
 
 	if (!data)
 		goto out;
@@ -512,7 +527,8 @@ static int superblock_doinit(struct supe
 	int rc = 0;
 
 	sbsec = security_get_value_type(&sb->s_security, SELINUX_LSM_ID,
-		struct superblock_security_struct);
+		struct superblock_security_struct,
+		selinux_secidx);
 
 	down(&sbsec->sem);
 	if (sbsec->initialized)
@@ -748,7 +764,8 @@ static int inode_doinit_with_dentry(stru
 	int hold_sem = 0;
 
 	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+		struct inode_security_struct,
+		selinux_secidx);
 
 	if (isec->initialized)
 		goto out;
@@ -759,7 +776,8 @@ static int inode_doinit_with_dentry(stru
 		goto out;
 
 	sbsec = security_get_value_type(&inode->i_sb->s_security,
-		SELINUX_LSM_ID, struct superblock_security_struct);
+		SELINUX_LSM_ID, struct superblock_security_struct,
+		selinux_secidx);
 	if (!sbsec->initialized) {
 		/* Defer initialization until selinux_complete_init,
 		   after the initial policy is loaded and the security
@@ -935,9 +953,11 @@ static int task_has_perm(struct task_str
 	struct task_security_struct *tsec1, *tsec2;
 
 	tsec1 = security_get_value_type(&tsk1->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	tsec2 = security_get_value_type(&tsk2->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	return avc_has_perm(tsec1->sid, tsec2->sid,
 			    SECCLASS_PROCESS, perms, NULL);
 }
@@ -950,7 +970,8 @@ static int task_has_capability(struct ta
 	struct avc_audit_data ad;
 
 	tsec = security_get_value_type(&tsk->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad,CAP);
 	ad.tsk = tsk;
@@ -967,7 +988,8 @@ static int task_has_system(struct task_s
 	struct task_security_struct *tsec;
 
 	tsec = security_get_value_type(&tsk->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 
 	return avc_has_perm(tsec->sid, SECINITSID_KERNEL,
 			    SECCLASS_SYSTEM, perms, NULL);
@@ -986,9 +1008,11 @@ static int inode_has_perm(struct task_st
 	struct avc_audit_data ad;
 
 	tsec = security_get_value_type(&tsk->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+		struct inode_security_struct,
+		selinux_secidx);
 
 	if (!adp) {
 		adp = &ad;
@@ -1036,9 +1060,11 @@ static inline int file_has_perm(struct t
 	int rc;
 
 	tsec = security_get_value_type(&tsk->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	fsec = security_get_value_type(&file->f_security, SELINUX_LSM_ID,
-		struct file_security_struct);
+		struct file_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad, FS);
 	ad.u.fs.mnt = mnt;
@@ -1073,11 +1099,14 @@ static int may_create(struct inode *dir,
 	int rc;
 
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	dsec = security_get_value_type(&dir->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+		struct inode_security_struct,
+		selinux_secidx);
 	sbsec = security_get_value_type(&dir->i_sb->s_security, SELINUX_LSM_ID,
-		struct superblock_security_struct);
+		struct superblock_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad, FS);
 	ad.u.fs.dentry = dentry;
@@ -1123,11 +1152,14 @@ static int may_link(struct inode *dir,
 	int rc;
 
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	dsec = security_get_value_type(&dir->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+		struct inode_security_struct,
+		selinux_secidx);
 	isec = security_get_value_type(&dentry->d_inode->i_security,
-		SELINUX_LSM_ID, struct inode_security_struct);
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad, FS);
 	ad.u.fs.dentry = dentry;
@@ -1170,14 +1202,18 @@ static inline int may_rename(struct inod
 	int rc;
 
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	old_dsec = security_get_value_type(&old_dir->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+		struct inode_security_struct,
+		selinux_secidx);
 	old_isec = security_get_value_type(&old_dentry->d_inode->i_security,
-		SELINUX_LSM_ID, struct inode_security_struct);
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
 	old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
 	new_dsec = security_get_value_type(&new_dir->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+		struct inode_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad, FS);
 
@@ -1206,7 +1242,8 @@ static inline int may_rename(struct inod
 		return rc;
 	if (new_dentry->d_inode) {
 		new_isec = security_get_value_type(&new_dentry->d_inode->i_security,
-			SELINUX_LSM_ID, struct inode_security_struct);
+			SELINUX_LSM_ID, struct inode_security_struct,
+			selinux_secidx);
 		new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
 		rc = avc_has_perm(tsec->sid, new_isec->sid,
 				  new_isec->sclass,
@@ -1228,9 +1265,11 @@ static int superblock_has_perm(struct ta
 	struct superblock_security_struct *sbsec;
 
 	tsec = security_get_value_type(&tsk->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	sbsec = security_get_value_type(&sb->s_security, SELINUX_LSM_ID,
-		struct superblock_security_struct);
+		struct superblock_security_struct,
+		selinux_secidx);
 	return avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
 			    perms, ad);
 }
@@ -1287,9 +1326,11 @@ static int inode_security_set_sid(struct
 	struct superblock_security_struct *sbsec;
 
 	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+		struct inode_security_struct,
+		selinux_secidx);
 	sbsec = security_get_value_type(&inode->i_sb->s_security,
-		SELINUX_LSM_ID, struct superblock_security_struct);
+		SELINUX_LSM_ID, struct superblock_security_struct,
+		selinux_secidx);
 
 	if (!sbsec->initialized) {
 		/* Defer initialization to selinux_complete_init. */
@@ -1319,11 +1360,14 @@ static int post_create(struct inode *dir
 	int rc;
 
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	dsec = security_get_value_type(&dir->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+		struct inode_security_struct,
+		selinux_secidx);
 	sbsec = security_get_value_type(&dir->i_sb->s_security, SELINUX_LSM_ID,
-		struct superblock_security_struct);
+		struct superblock_security_struct,
+		selinux_secidx);
 
 	inode = dentry->d_inode;
 	if (!inode) {
@@ -1395,9 +1439,11 @@ static int selinux_ptrace(struct task_st
 	int rc;
 
 	psec = security_get_value_type(&parent->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	csec = security_get_value_type(&child->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 
 	rc = task_has_perm(parent, child, PROCESS__PTRACE);
 	/* Save the SID of the tracing process for later use in apply_creds. */
@@ -1432,7 +1478,8 @@ static int selinux_sysctl(ctl_table *tab
 	int rc;
 
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 
 	rc = selinux_proc_get_sid(table->de, (op == 001) ?
 	                          SECCLASS_DIR : SECCLASS_FILE, &tsid);
@@ -1537,7 +1584,8 @@ static int selinux_bprm_alloc_security(s
 	bsec->sid = SECINITSID_UNLABELED;
 	bsec->set = 0;
 
-	security_set_value_type(&bprm->security, SELINUX_LSM_ID, bsec);
+	security_set_value_type(&bprm->security, SELINUX_LSM_ID, bsec,
+		selinux_secidx);
 	return 0;
 }
 
@@ -1552,15 +1600,18 @@ static int selinux_bprm_set_security(str
 	int rc;
 
 	bsec = security_get_value_type(&bprm->security, SELINUX_LSM_ID,
-		struct bprm_security_struct);
+		struct bprm_security_struct,
+		selinux_secidx);
 
 	if (bsec->set)
 		return 0;
 
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+		struct inode_security_struct,
+		selinux_secidx);
 
 	/* Default to the current task SID. */
 	bsec->sid = tsec->sid;
@@ -1621,7 +1672,8 @@ static int selinux_bprm_secureexec (stru
 	int atsecure = 0;
 
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	if (tsec->osid != tsec->sid) {
 		/* Enable secure mode for SIDs transitions unless
 		   the noatsecure permission is granted between
@@ -1639,7 +1691,7 @@ static void selinux_bprm_free_security(s
  	struct bprm_security_struct *bsec;
 
  	bsec = security_del_value_type(&bprm->security, SELINUX_LSM_ID,
- 			struct bprm_security_struct);
+ 			struct bprm_security_struct, selinux_secidx);
 	kfree(bsec);
 }
 
@@ -1736,9 +1788,11 @@ static void selinux_bprm_apply_creds(str
 	int rc;
 
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	bsec = security_get_value_type(&bprm->security, SELINUX_LSM_ID,
-		struct bprm_security_struct);
+		struct bprm_security_struct,
+		selinux_secidx);
 	sid = bsec->sid;
 
 	tsec->osid = tsec->sid;
@@ -1782,9 +1836,11 @@ static void selinux_bprm_post_apply_cred
 	int rc, i;
 
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	bsec = security_get_value_type(&bprm->security, SELINUX_LSM_ID,
-		struct bprm_security_struct);
+		struct bprm_security_struct,
+		selinux_secidx);
 
 	if (bsec->unsafe) {
 		force_sig_specific(SIGKILL, current);
@@ -2122,7 +2178,8 @@ static int selinux_inode_setxattr(struct
 	}
 
 	sbsec = security_get_value_type(&inode->i_sb->s_security,
-		SELINUX_LSM_ID, struct superblock_security_struct);
+		SELINUX_LSM_ID, struct superblock_security_struct,
+		selinux_secidx);
 	if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
 		return -EOPNOTSUPP;
 
@@ -2133,9 +2190,11 @@ static int selinux_inode_setxattr(struct
 	ad.u.fs.dentry = dentry;
 
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+		struct inode_security_struct,
+		selinux_secidx);
 	rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass,
 			  FILE__RELABELFROM, &ad);
 	if (rc)
@@ -2171,7 +2230,8 @@ static void selinux_inode_post_setxattr(
 	int rc;
 
 	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+		struct inode_security_struct,
+		selinux_secidx);
 
 	if (strcmp(name, XATTR_NAME_SELINUX)) {
 		/* Not an attribute we recognize, so nothing to do. */
@@ -2195,7 +2255,8 @@ static int selinux_inode_getxattr (struc
 	struct superblock_security_struct *sbsec;
 	
 	sbsec = security_get_value_type(&inode->i_sb->s_security,
-		SELINUX_LSM_ID, struct superblock_security_struct);
+		SELINUX_LSM_ID, struct superblock_security_struct,
+		selinux_secidx);
 
 	if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
 		return -EOPNOTSUPP;
@@ -2243,7 +2304,8 @@ static int selinux_inode_getsecurity(str
 		return -EOPNOTSUPP;
 
 	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+		struct inode_security_struct,
+		selinux_secidx);
 
 	rc = security_sid_to_context(isec->sid, &context, &len);
 	if (rc)
@@ -2273,7 +2335,8 @@ static int selinux_inode_setsecurity(str
 		return -EOPNOTSUPP;
 
 	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+		struct inode_security_struct,
+		selinux_secidx);
 
 	if (!value || !size)
 		return -EACCES;
@@ -2512,9 +2575,11 @@ static int selinux_file_set_fowner(struc
 	struct file_security_struct *fsec;
 
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	fsec = security_get_value_type(&file->f_security, SELINUX_LSM_ID,
-		struct file_security_struct);
+		struct file_security_struct,
+		selinux_secidx);
 	fsec->fown_sid = tsec->sid;
 
 	return 0;
@@ -2532,9 +2597,11 @@ static int selinux_file_send_sigiotask(s
         file = (struct file *)((long)fown - offsetof(struct file,f_owner));
 
 	tsec = security_get_value_type(&tsk->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	fsec = security_get_value_type(&file->f_security, SELINUX_LSM_ID,
-		struct file_security_struct);
+		struct file_security_struct,
+		selinux_secidx);
 
 	if (!signum)
 		perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
@@ -2563,13 +2630,15 @@ static int selinux_task_alloc_security(s
 	int rc;
 
 	tsec1 = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 
 	rc = task_alloc_security(tsk);
 	if (rc)
 		return rc;
 	tsec2 = security_get_value_type(&tsk->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 
 	tsec2->osid = tsec1->osid;
 	tsec2->sid = tsec1->sid;
@@ -2699,7 +2768,8 @@ static void selinux_task_reparent_to_ini
   	struct task_security_struct *tsec;
 
 	tsec = security_get_value_type(&p->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	tsec->osid = tsec->sid;
 	tsec->sid = SECINITSID_KERNEL;
 	return;
@@ -2712,9 +2782,11 @@ static void selinux_task_to_inode(struct
 	struct inode_security_struct *isec;
 
 	tsec = security_get_value_type(&p->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+		struct inode_security_struct,
+		selinux_secidx);
 
 	isec->sid = tsec->sid;
 	isec->initialized = 1;
@@ -2883,9 +2955,11 @@ static int socket_has_perm(struct task_s
 	int err = 0;
 
 	tsec = security_get_value_type(&task->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	isec = security_get_value_type(&SOCK_INODE(sock)->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
+	isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
 
 	if (isec->sid == SECINITSID_KERNEL)
 		goto out;
@@ -2908,7 +2982,8 @@ static int selinux_socket_create(int fam
 		goto out;
 
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	err = avc_has_perm(tsec->sid, tsec->sid,
 			   socket_type_to_security_class(family, type,
 			   protocol), SOCKET__CREATE, NULL);
@@ -2924,10 +2999,12 @@ static void selinux_socket_post_create(s
 	struct task_security_struct *tsec;
 
 	isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
-		SELINUX_LSM_ID, struct inode_security_struct);
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
 
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	isec->sclass = socket_type_to_security_class(family, type, protocol);
 	isec->sid = kern ? SECINITSID_KERNEL : tsec->sid;
 	isec->initialized = 1;
@@ -2966,9 +3043,11 @@ static int selinux_socket_bind(struct so
 		u32 sid, node_perm, addrlen;
 
 		tsec = security_get_value_type(&current->security,
-			SELINUX_LSM_ID, struct task_security_struct);
+			SELINUX_LSM_ID, struct task_security_struct,
+			selinux_secidx);
 		isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
-			SELINUX_LSM_ID, struct inode_security_struct);
+			SELINUX_LSM_ID, struct inode_security_struct,
+			selinux_secidx);
 
 		if (family == PF_INET) {
 			addr4 = (struct sockaddr_in *)address;
@@ -3047,7 +3126,8 @@ static int selinux_socket_connect(struct
 	 * If a TCP socket, check name_connect permission for the port.
 	 */
 	isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
-		SELINUX_LSM_ID, struct inode_security_struct);
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
 	if (isec->sclass == SECCLASS_TCP_SOCKET) {
 		struct sock *sk = sock->sk;
 		struct avc_audit_data ad;
@@ -3102,10 +3182,12 @@ static int selinux_socket_accept(struct 
 		return err;
 
 	newisec = security_get_value_type(&SOCK_INODE(newsock)->i_security,
-		SELINUX_LSM_ID, struct inode_security_struct);
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
 
 	isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
-		SELINUX_LSM_ID, struct inode_security_struct);
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
 	newisec->sclass = isec->sclass;
 	newisec->sid = isec->sid;
 	newisec->initialized = 1;
@@ -3162,9 +3244,11 @@ static int selinux_socket_unix_stream_co
 	int err;
 
 	isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
-		SELINUX_LSM_ID, struct inode_security_struct);
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
 	other_isec = security_get_value_type(&SOCK_INODE(other)->i_security,
-		SELINUX_LSM_ID, struct inode_security_struct);
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad,NET);
 	ad.u.net.sk = other->sk;
@@ -3177,12 +3261,14 @@ static int selinux_socket_unix_stream_co
 
 	/* connecting socket */
 	ssec = security_get_value_type(&sock->sk->sk_security, SELINUX_LSM_ID,
-		struct sk_security_struct);
+		struct sk_security_struct,
+		selinux_secidx);
 	ssec->peer_sid = other_isec->sid;
 	
 	/* server child socket */
 	ssec = security_get_value_type(&newsk->sk_security, SELINUX_LSM_ID,
-		struct sk_security_struct);
+		struct sk_security_struct,
+		selinux_secidx);
 	ssec->peer_sid = isec->sid;
 	
 	return 0;
@@ -3197,9 +3283,11 @@ static int selinux_socket_unix_may_send(
 	int err;
 
 	isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
-		SELINUX_LSM_ID, struct inode_security_struct);
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
 	other_isec = security_get_value_type(&SOCK_INODE(other)->i_security,
-		SELINUX_LSM_ID, struct inode_security_struct);
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad,NET);
 	ad.u.net.sk = other->sk;
@@ -3240,7 +3328,8 @@ static int selinux_socket_sock_rcv_skb(s
  		if (inode) {
  			struct inode_security_struct *isec;
 			isec = security_get_value_type(&inode->i_security,
-				SELINUX_LSM_ID, struct inode_security_struct);
+				SELINUX_LSM_ID, struct inode_security_struct,
+				selinux_secidx);
  			sock_sid = isec->sid;
  			sock_class = isec->sclass;
  		}
@@ -3324,14 +3413,16 @@ static int selinux_socket_getpeersec(str
 	struct inode_security_struct *isec;
 
 	isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
-		SELINUX_LSM_ID, struct inode_security_struct);
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
 	if (isec->sclass != SECCLASS_UNIX_STREAM_SOCKET) {
 		err = -ENOPROTOOPT;
 		goto out;
 	}
 
 	ssec = security_get_value_type(&sock->sk->sk_security, SELINUX_LSM_ID,
-		struct sk_security_struct);
+		struct sk_security_struct,
+		selinux_secidx);
 	
 	err = security_sid_to_context(ssec->peer_sid, &scontext, &scontext_len);
 	if (err)
@@ -3373,7 +3464,8 @@ static int selinux_nlmsg_perm(struct soc
 	struct inode_security_struct *isec;
 	
 	isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
-		SELINUX_LSM_ID, struct inode_security_struct);
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
 	
 	if (skb->len < NLMSG_SPACE(0)) {
 		err = -EINVAL;
@@ -3440,7 +3532,8 @@ static unsigned int selinux_ip_postroute
 		goto out;
 
 	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+		struct inode_security_struct,
+		selinux_secidx);
 	
 	switch (isec->sclass) {
 	case SECCLASS_UDP_SOCKET:
@@ -3547,7 +3640,8 @@ static int selinux_netlink_send(struct s
 	int err = 0;
 
 	tsec = security_get_value_type(&current->security,
-		SELINUX_LSM_ID, struct task_security_struct);
+		SELINUX_LSM_ID, struct task_security_struct,
+		selinux_secidx);
 
 	avd.allowed = 0;
 	avc_has_perm_noaudit(tsec->sid, tsec->sid,
@@ -3568,7 +3662,8 @@ static int ipc_alloc_security(struct tas
 	struct ipc_security_struct *isec;
 
 	tsec = security_get_value_type(&task->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 
 	isec = kmalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
 	if (!isec)
@@ -3582,7 +3677,8 @@ static int ipc_alloc_security(struct tas
 	} else {
 		isec->sid = SECINITSID_UNLABELED;
 	}
-	security_set_value_type(&perm->security, SELINUX_LSM_ID, isec);
+	security_set_value_type(&perm->security, SELINUX_LSM_ID, isec,
+		selinux_secidx);
 
 	return 0;
 }
@@ -3592,7 +3688,7 @@ static void ipc_free_security(struct ker
 	struct ipc_security_struct *isec;
 	
 	isec = security_del_value_type(&perm->security, SELINUX_LSM_ID,
-		struct ipc_security_struct);
+		struct ipc_security_struct, selinux_secidx);
 
 	kfree(isec);
 }
@@ -3608,7 +3704,8 @@ static int msg_msg_alloc_security(struct
 	memset(msec, 0, sizeof(struct msg_security_struct));
 	msec->msg = msg;
 	msec->sid = SECINITSID_UNLABELED;
-	security_set_value_type(&msg->security, SELINUX_LSM_ID, msec);
+	security_set_value_type(&msg->security, SELINUX_LSM_ID, msec,
+		selinux_secidx);
 
 	return 0;
 }
@@ -3618,7 +3715,8 @@ static void msg_msg_free_security(struct
 	struct msg_security_struct *msec;
 	
 	msec = security_del_value_type(&msg->security, SELINUX_LSM_ID,
-		struct msg_security_struct);
+		struct msg_security_struct,
+			selinux_secidx);
 
 	kfree(msec);
 }
@@ -3631,9 +3729,11 @@ static int ipc_has_perm(struct kern_ipc_
 	struct avc_audit_data ad;
 
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	isec = security_get_value_type(&ipc_perms->security, SELINUX_LSM_ID,
-		struct ipc_security_struct);
+		struct ipc_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
 	ad.u.ipc_id = ipc_perms->key;
@@ -3664,9 +3764,11 @@ static int selinux_msg_queue_alloc_secur
 		return rc;
 
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	isec = security_get_value_type(&msq->q_perm.security, SELINUX_LSM_ID,
-		struct ipc_security_struct);
+		struct ipc_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
  	ad.u.ipc_id = msq->q_perm.key;
@@ -3692,9 +3794,11 @@ static int selinux_msg_queue_associate(s
 	struct avc_audit_data ad;
 
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	isec = security_get_value_type(&msq->q_perm.security, SELINUX_LSM_ID,
-		struct ipc_security_struct);
+		struct ipc_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
 	ad.u.ipc_id = msq->q_perm.key;
@@ -3740,11 +3844,14 @@ static int selinux_msg_queue_msgsnd(stru
 	int rc;
 
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	isec = security_get_value_type(&msq->q_perm.security, SELINUX_LSM_ID,
-		struct ipc_security_struct);
+		struct ipc_security_struct,
+		selinux_secidx);
 	msec = security_get_value_type(&msg->security, SELINUX_LSM_ID,
-		struct msg_security_struct);
+		struct msg_security_struct,
+		selinux_secidx);
 
 	/*
 	 * First time through, need to assign label to the message
@@ -3791,11 +3898,14 @@ static int selinux_msg_queue_msgrcv(stru
 	int rc;
 
 	tsec = security_get_value_type(&target->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	isec = security_get_value_type(&msq->q_perm.security, SELINUX_LSM_ID,
-		struct ipc_security_struct);
+		struct ipc_security_struct,
+		selinux_secidx);
 	msec = security_get_value_type(&msg->security, SELINUX_LSM_ID,
-		struct msg_security_struct);
+		struct msg_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
  	ad.u.ipc_id = msq->q_perm.key;
@@ -3821,9 +3931,11 @@ static int selinux_shm_alloc_security(st
 		return rc;
 
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	isec = security_get_value_type(&shp->shm_perm.security, SELINUX_LSM_ID,
-		struct ipc_security_struct);
+		struct ipc_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
  	ad.u.ipc_id = shp->shm_perm.key;
@@ -3849,9 +3961,11 @@ static int selinux_shm_associate(struct 
 	struct avc_audit_data ad;
 
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	isec = security_get_value_type(&shp->shm_perm.security, SELINUX_LSM_ID,
-		struct ipc_security_struct);
+		struct ipc_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
 	ad.u.ipc_id = shp->shm_perm.key;
@@ -3919,9 +4033,11 @@ static int selinux_sem_alloc_security(st
 		return rc;
 
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	isec = security_get_value_type(&sma->sem_perm.security, SELINUX_LSM_ID,
-		struct ipc_security_struct);
+		struct ipc_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
  	ad.u.ipc_id = sma->sem_perm.key;
@@ -3947,9 +4063,11 @@ static int selinux_sem_associate(struct 
 	struct avc_audit_data ad;
 
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	isec = security_get_value_type(&sma->sem_perm.security, SELINUX_LSM_ID,
-		struct ipc_security_struct);
+		struct ipc_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
 	ad.u.ipc_id = sma->sem_perm.key;
@@ -4064,7 +4182,8 @@ static int selinux_getprocattr(struct ta
 		return -ERANGE;
 
 	tsec = security_get_value_type(&p->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 
 	if (!strcmp(name, "current"))
 		sid = tsec->sid;
@@ -4140,7 +4259,8 @@ static int selinux_setprocattr(struct ta
 	   checks and may_create for the file creation checks. The
 	   operation will then fail if the context is not permitted. */
 	tsec = security_get_value_type(&p->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	if (!strcmp(name, "exec"))
 		tsec->exec_sid = sid;
 	else if (!strcmp(name, "fscreate"))
@@ -4359,13 +4479,15 @@ static __init int selinux_init(void)
 	if (task_alloc_security(current))
 		panic("SELinux:  Failed to initialize initial task.\n");
 	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+		struct task_security_struct,
+		selinux_secidx);
 	tsec->osid = tsec->sid = SECINITSID_KERNEL;
 
 	avc_init();
 
-	if (register_security (&selinux_ops)) {
-		if (mod_reg_security( MY_NAME, &selinux_ops)) {
+	selinux_secidx = 1;
+	if (register_security (&selinux_ops, &selinux_secidx)) {
+		if (mod_reg_security( MY_NAME, &selinux_ops, &selinux_secidx)) {
 			printk(KERN_ERR "%s: Failed to register with primary LSM.\n",
 				__FUNCTION__);
 			panic("SELinux: Unable to register with kernel.\n");
@@ -4375,6 +4497,7 @@ static __init int selinux_init(void)
 		}
 		secondary = 1;
 	}
+	printk(KERN_NOTICE "got selinux_secidx %d\n", selinux_secidx);
 
 	if (selinux_enforcing) {
 		printk(KERN_INFO "SELinux:  Starting in enforcing mode\n");
Index: linux-2.6.12/security/selinux/selinuxfs.c
===================================================================
--- linux-2.6.12.orig/security/selinux/selinuxfs.c	2005-08-01 20:00:51.000000000 -0500
+++ linux-2.6.12/security/selinux/selinuxfs.c	2005-08-01 20:28:09.000000000 -0500
@@ -35,6 +35,8 @@
 #include "objsec.h"
 #include "conditional.h"
 
+extern int selinux_secidx;
+
 unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
 
 static int __init checkreqprot_setup(char *str)
@@ -61,7 +63,8 @@ static int task_has_security(struct task
 	struct task_security_struct *tsec;
 
 	tsec = security_get_value_type(&tsk->security, SELINUX_LSM_ID,
-			struct task_security_struct);
+			struct task_security_struct,
+			selinux_secidx);
 	if (!tsec)
 		return -EACCES;
 
@@ -985,7 +988,8 @@ static int sel_make_bools(void)
 			goto err;
 		}
 		isec = security_get_value_type(&inode->i_security,
-				SELINUX_LSM_ID, struct inode_security_struct);
+				SELINUX_LSM_ID, struct inode_security_struct,
+				selinux_secidx);
 		if ((ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid)))
 			goto err;
 		isec->sid = sid;
@@ -1271,7 +1275,8 @@ static int sel_fill_super(struct super_b
 	if (!inode)
 		goto out;
 	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
-			struct inode_security_struct);
+			struct inode_security_struct,
+			selinux_secidx);
 	isec->sid = SECINITSID_DEVNULL;
 	isec->sclass = SECCLASS_CHR_FILE;
 	isec->initialized = 1;
Index: linux-2.6.12/security/seclvl.c
===================================================================
--- linux-2.6.12.orig/security/seclvl.c	2005-08-01 20:00:51.000000000 -0500
+++ linux-2.6.12/security/seclvl.c	2005-08-01 20:28:28.000000000 -0500
@@ -38,6 +38,8 @@
 #define SHA1_DIGEST_SIZE 20
 #define SECLVL_LSM_ID 0xF45
 
+static int seclvl_secidx;
+
 /**
  * Module parameter that defines the initial secure level.
  *
@@ -506,7 +508,7 @@ static void seclvl_inode_free(struct ino
 	struct seclvl_i_sec *isec;
 
 	isec = security_del_value_type(&inode->i_security, SECLVL_LSM_ID,
-				struct seclvl_i_sec);
+				struct seclvl_i_sec, seclvl_secidx);
 	if (isec) {
 		spin_lock(&seclvl_ichain_lock);
 		list_del(&isec->chain);
@@ -546,7 +548,8 @@ static void seclvl_bd_release(struct ino
 
 	if (inode && S_ISBLK(inode->i_mode)) {
 		isec = security_get_value_type(&inode->i_security,
-				SECLVL_LSM_ID, struct seclvl_i_sec);
+				SECLVL_LSM_ID, struct seclvl_i_sec,
+				seclvl_secidx);
 		if (!isec)
 			return;
 		spin_lock(&isec->spinlock);
@@ -574,12 +577,12 @@ seclvl_inode_get_or_alloc(struct inode *
 	struct seclvl_i_sec *isec;
 
 	isec = security_get_value_type(&inode->i_security,
-			SECLVL_LSM_ID, struct seclvl_i_sec);
+			SECLVL_LSM_ID, struct seclvl_i_sec, seclvl_secidx);
 	if (isec)
 		return isec;
 	spin_lock(&seclvl_ichain_lock);
 	isec = security_get_value_type(&inode->i_security,
-			SECLVL_LSM_ID, struct seclvl_i_sec);
+			SECLVL_LSM_ID, struct seclvl_i_sec, seclvl_secidx);
 	if (isec)
 		goto out;
 	isec = kmalloc(sizeof(struct seclvl_i_sec), GFP_KERNEL);
@@ -588,7 +591,8 @@ seclvl_inode_get_or_alloc(struct inode *
 	spin_lock_init(&isec->spinlock);
 	INIT_LIST_HEAD(&isec->chain);
 	list_add(&isec->chain, &seclvl_ichain);
-	security_add_value_type(&inode->i_security, SECLVL_LSM_ID, isec);
+	security_add_value_type(&inode->i_security, SECLVL_LSM_ID, isec,
+				seclvl_secidx);
 
 out:
 	spin_unlock(&seclvl_ichain_lock);
@@ -781,12 +785,13 @@ static int __init seclvl_init(void)
 		goto exit;
 	}
 	/* register ourselves with the security framework */
-	if (register_security(&seclvl_ops)) {
+	seclvl_secidx = 1;  /* yes we want to use a security field */
+	if (register_security(&seclvl_ops, &seclvl_secidx)) {
 		seclvl_printk(0, KERN_ERR,
 			      "seclvl: Failure registering with the "
 			      "kernel.\n");
 		/* try registering with primary module */
-		rc = mod_reg_security(MY_NAME, &seclvl_ops);
+		rc = mod_reg_security(MY_NAME, &seclvl_ops, &seclvl_secidx);
 		if (rc) {
 			seclvl_printk(0, KERN_ERR, "seclvl: Failure "
 				      "registering with primary security "
@@ -795,6 +800,7 @@ static int __init seclvl_init(void)
 		}		/* if primary module registered */
 		secondary = 1;
 	}			/* if we registered ourselves with the security framework */
+	printk(KERN_NOTICE "got seclvl_secidx %d\n", seclvl_secidx);
 	if ((rc = doSysfsRegistrations())) {
 		seclvl_printk(0, KERN_ERR, "Error registering with sysfs\n");
 		goto exit;
@@ -821,7 +827,7 @@ static void free_ichain(void)
 	struct seclvl_i_sec *isec, *n;
 
 	list_for_each_entry_safe(isec, n, &seclvl_ichain, chain) {
-		security_unlink_value(&isec->lsm_list.list);
+		security_unlink_value(&isec->lsm_list.list, seclvl_secidx);
 	}
 
 	synchronize_rcu();
Index: linux-2.6.12/security/capability.c
===================================================================
--- linux-2.6.12.orig/security/capability.c	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.12/security/capability.c	2005-08-01 20:28:42.000000000 -0500
@@ -66,9 +66,9 @@ static int __init capability_init (void)
 		return 0;
 	}
 	/* register ourselves with the security framework */
-	if (register_security (&capability_ops)) {
+	if (register_security (&capability_ops, NULL)) {
 		/* try registering with primary module */
-		if (mod_reg_security (MY_NAME, &capability_ops)) {
+		if (mod_reg_security (MY_NAME, &capability_ops, NULL)) {
 			printk (KERN_INFO "Failure registering capabilities "
 				"with primary security module.\n");
 			return -EINVAL;
Index: linux-2.6.12/security/root_plug.c
===================================================================
--- linux-2.6.12.orig/security/root_plug.c	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.12/security/root_plug.c	2005-08-01 20:28:53.000000000 -0500
@@ -104,11 +104,11 @@ static struct security_operations rootpl
 static int __init rootplug_init (void)
 {
 	/* register ourselves with the security framework */
-	if (register_security (&rootplug_security_ops)) {
+	if (register_security (&rootplug_security_ops, NULL)) {
 		printk (KERN_INFO 
 			"Failure registering Root Plug module with the kernel\n");
 		/* try registering with primary module */
-		if (mod_reg_security (MY_NAME, &rootplug_security_ops)) {
+		if (mod_reg_security (MY_NAME, &rootplug_security_ops, NULL)) {
 			printk (KERN_INFO "Failure registering Root Plug "
 				" module with primary security module.\n");
 			return -EINVAL;
Index: linux-2.6.12/security/cap_stack.c
===================================================================
--- linux-2.6.12.orig/security/cap_stack.c	2005-08-01 20:00:51.000000000 -0500
+++ linux-2.6.12/security/cap_stack.c	2005-08-01 20:33:21.000000000 -0500
@@ -62,9 +62,9 @@ static int __init capability_init (void)
 		return 0;
 	}
 	/* register ourselves with the security framework */
-	if (register_security (&capability_ops)) {
+	if (register_security (&capability_ops, NULL)) {
 		/* try registering with primary module */
-		if (mod_reg_security (MY_NAME, &capability_ops)) {
+		if (mod_reg_security (MY_NAME, &capability_ops, NULL)) {
 			printk (KERN_INFO "Failure registering capabilities "
 				"with primary security module.\n");
 			return -EINVAL;
Index: linux-2.6.12/security/stacker.c
===================================================================
--- linux-2.6.12.orig/security/stacker.c	2005-08-01 20:00:51.000000000 -0500
+++ linux-2.6.12/security/stacker.c	2005-08-01 20:29:42.000000000 -0500
@@ -1629,7 +1629,7 @@ static int __init stacker_init (void)
 	INIT_LIST_HEAD(&default_module.lsm_list);
 	list_add_tail(&default_module.lsm_list, &stacked_modules);
 
-	if (register_security (&stacker_ops)) {
+	if (register_security (&stacker_ops, NULL)) {
 		/*
 		 * stacking stacker is just a stupid idea, so don't ask
 		 * the current module to load us.
Index: linux-2.6.12/include/linux/security-stack.h
===================================================================
--- linux-2.6.12.orig/include/linux/security-stack.h	2005-08-01 20:00:51.000000000 -0500
+++ linux-2.6.12/include/linux/security-stack.h	2005-08-01 20:34:18.000000000 -0500
@@ -19,7 +19,7 @@ extern fastcall struct security_list *se
 extern fastcall struct security_list *security_add_value(
 			struct hlist_head *head,
 			int security_id, struct security_list *obj_node);
-extern int security_unlink_value(struct hlist_node *n);
+extern int security_unlink_value(struct hlist_node *n, int idx);
 extern fastcall struct security_list *security_del_value(
 			struct hlist_head *head,
 			int security_id);

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH] Stacker - single-use static slots
  2005-08-03 16:45     ` [PATCH] Stacker - single-use static slots serue
@ 2005-08-03 17:57       ` Chris Wright
  2005-08-03 19:27         ` serue
  2005-08-05 15:55       ` James Morris
  1 sibling, 1 reply; 39+ messages in thread
From: Chris Wright @ 2005-08-03 17:57 UTC (permalink / raw)
  To: serue; +Cc: James Morris, lkml, Chris Wright, Stephen Smalley, Andrew Morton

* serue@us.ibm.com (serue@us.ibm.com) wrote:
> Index: linux-2.6.12/include/linux/security.h
> ===================================================================
> --- linux-2.6.12.orig/include/linux/security.h	2005-08-01 20:00:51.000000000 -0500
> +++ linux-2.6.12/include/linux/security.h	2005-08-01 20:23:52.000000000 -0500
> @@ -44,24 +44,65 @@ struct security_list {
>  };
>  
>  
> +static inline void *__get_value(void *head, int idx)
> +{
> +	void **p = head + sizeof(struct hlist_head);
> +#if 0
> +	printk(KERN_NOTICE "__get_value: %s (%d): head %lx p %lx idx %d returning %lx at %lx\n",
> +		__FUNCTION__, __LINE__, (long)head, (long)p, idx, (long)p[idx], (long)&p[idx]);
> +#endif
> +	return p[idx];

pr_debug

> +}
> +
> +static inline void __set_value(void *head, int idx, void *v)
> +{
> +	void **p = head + sizeof(struct hlist_head);
> +	p[idx] = v;
> +#if 0
> +	printk(KERN_NOTICE "%s (%d): hd %lx, p %lx, idx %d,"
> +		"v %lx, p[idx] %lx at %lx\n",
> +		__FUNCTION__, __LINE__, (long) (head),
> +		(long) p, idx, (long) (v),
> +		(long)p[idx], (long)&p[idx]);
> +#endif

pr_debug

> Index: linux-2.6.12/security/Kconfig
> ===================================================================
> --- linux-2.6.12.orig/security/Kconfig	2005-08-01 20:00:51.000000000 -0500
> +++ linux-2.6.12/security/Kconfig	2005-08-01 20:24:11.000000000 -0500
> @@ -112,5 +112,17 @@ config SECURITY_STACKER
>  	help
>  	  Stack multiple LSMs.
>  
> +config SECURITY_STACKER_NUMFIELDS
> +	int "Number of security fields to reserve"
> +	depends on SECURITY_STACKER
> +	default 1

Not sure config is worth it, also, James had suggested smth like 3
slots.

>  		INIT_HLIST_HEAD(&inode->i_security);
> +		memset(&inode->i_security_p, 0,
> +			CONFIG_SECURITY_STACKER_NUMFIELDS*sizeof(void *));

This CONFIG... is a bit rough.  Can we use a simple name, and if config
is necessary, assign config to simple name?

>  		inode->dirtied_when = 0;
>  		if (security_inode_alloc(inode)) {
>  			if (inode->i_sb->s_op->destroy_inode)
> Index: linux-2.6.12/include/linux/binfmts.h
> ===================================================================
> --- linux-2.6.12.orig/include/linux/binfmts.h	2005-08-01 20:00:50.000000000 -0500
> +++ linux-2.6.12/include/linux/binfmts.h	2005-08-01 20:24:41.000000000 -0500
> @@ -30,6 +30,7 @@ struct linux_binprm{
>  	int e_uid, e_gid;
>  	kernel_cap_t cap_inheritable, cap_permitted, cap_effective;
>  	struct hlist_head security;
> +	void * security_p[CONFIG_SECURITY_STACKER_NUMFIELDS];
>  	int argc, envc;
>  	char * filename;	/* Name of binary as seen by procps */
>  	char * interp;		/* Name of the binary really executed. Most
> Index: linux-2.6.12/include/linux/fs.h
> ===================================================================
> --- linux-2.6.12.orig/include/linux/fs.h	2005-08-01 20:00:50.000000000 -0500
> +++ linux-2.6.12/include/linux/fs.h	2005-08-01 20:24:55.000000000 -0500
> @@ -486,6 +486,7 @@ struct inode {
>  
>  	atomic_t		i_writecount;
>  	struct hlist_head	i_security;
> +	void			*i_security_p[CONFIG_SECURITY_STACKER_NUMFIELDS];

James had suggested to effectively stash the list in the last slot, so
there's only the array with one reserved slot.

thanks,
-chris

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH] Stacker - single-use static slots
  2005-08-03 17:57       ` Chris Wright
@ 2005-08-03 19:27         ` serue
  2005-08-03 19:45           ` Chris Wright
  0 siblings, 1 reply; 39+ messages in thread
From: serue @ 2005-08-03 19:27 UTC (permalink / raw)
  To: Chris Wright; +Cc: serue, James Morris, lkml, Stephen Smalley, Andrew Morton

Quoting Chris Wright (chrisw@osdl.org):
> * serue@us.ibm.com (serue@us.ibm.com) wrote:
> > +#if 0
> > +	printk(KERN_NOTICE "__get_value: %s (%d): head %lx p %lx idx %d returning %lx at %lx\n",
> > +		__FUNCTION__, __LINE__, (long)head, (long)p, idx, (long)p[idx], (long)&p[idx]);
> > +#endif
> > +	return p[idx];
> 
> pr_debug

Thanks.

> > +config SECURITY_STACKER_NUMFIELDS
> > +	int "Number of security fields to reserve"
> > +	depends on SECURITY_STACKER
> > +	default 1
> 
> Not sure config is worth it, also, James had suggested smth like 3
> slots.

I misread that.  I'd latched onto the "selinux+capability" (again),
which combined would need only one spot.

> >  		INIT_HLIST_HEAD(&inode->i_security);
> > +		memset(&inode->i_security_p, 0,
> > +			CONFIG_SECURITY_STACKER_NUMFIELDS*sizeof(void *));
> 
> This CONFIG... is a bit rough.  Can we use a simple name, and if config
> is necessary, assign config to simple name?

Will do.

> > Index: linux-2.6.12/include/linux/fs.h
> > ===================================================================
> > --- linux-2.6.12.orig/include/linux/fs.h	2005-08-01 20:00:50.000000000 -0500
> > +++ linux-2.6.12/include/linux/fs.h	2005-08-01 20:24:55.000000000 -0500
> > @@ -486,6 +486,7 @@ struct inode {
> >  
> >  	atomic_t		i_writecount;
> >  	struct hlist_head	i_security;
> > +	void			*i_security_p[CONFIG_SECURITY_STACKER_NUMFIELDS];
> 
> James had suggested to effectively stash the list in the last slot, so
> there's only the array with one reserved slot.

Oh, I didn't catch that.  I like it.  Will do.

So you mean 3 slots total including the shared one?

Any comments on the added argument to register_security and
mod_reg_security to request a static slot?  Given the likelyhood of
capability/cap_stack being registered, it seemed worthwhile not to have
it waste a spot, but it is an API change...

thanks,
-serge

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH] Stacker - single-use static slots
  2005-08-03 19:27         ` serue
@ 2005-08-03 19:45           ` Chris Wright
  2005-08-03 20:31             ` serge
  0 siblings, 1 reply; 39+ messages in thread
From: Chris Wright @ 2005-08-03 19:45 UTC (permalink / raw)
  To: serue; +Cc: Chris Wright, James Morris, lkml, Stephen Smalley, Andrew Morton

* serue@us.ibm.com (serue@us.ibm.com) wrote:
> > James had suggested to effectively stash the list in the last slot, so
> > there's only the array with one reserved slot.
> 
> Oh, I didn't catch that.  I like it.  Will do.
> 
> So you mean 3 slots total including the shared one?

Yeah, i.e. common case is $LSM and capabilities.  Stack slot is last
one, and gets put to use only if needed.

> Any comments on the added argument to register_security and
> mod_reg_security to request a static slot?

Why would you not request a static slot?

> +	spin_lock(&security_field_spinlock);
> +	if (idx && *idx) {
> +		int i;
> +
> +		*idx = -1;

So, I guess this means you request one, but who knows which one you'll
get?

> +		for (i=0; i<CONFIG_SECURITY_STACKER_NUMFIELDS; i++) {
> +			if (security_field_owners[i] == NULL) {
> +				security_field_owners[i] = ops;
> +				*idx = i;
> +				break;
> +			}
> +		}
> +	}
> +	spin_unlock(&security_field_spinlock);

> Given the likelyhood of
> capability/cap_stack being registered, it seemed worthwhile not to have
> it waste a spot, but it is an API change...

API change is no big deal.  Seems useful to get index value so you can
do optimized retrieve later.  But, I don't see it useful to request that
way.  Just register, get index, if index == last slot, lookup hits list.

thanks,
-chris

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH] Stacker - single-use static slots
  2005-08-03 19:45           ` Chris Wright
@ 2005-08-03 20:31             ` serge
  0 siblings, 0 replies; 39+ messages in thread
From: serge @ 2005-08-03 20:31 UTC (permalink / raw)
  To: Chris Wright; +Cc: James Morris, lkml, Stephen Smalley, Andrew Morton

Quoting Chris Wright (chrisw@osdl.org):
> * serue@us.ibm.com (serue@us.ibm.com) wrote:
> > > James had suggested to effectively stash the list in the last slot, so
> > > there's only the array with one reserved slot.
> > 
> > Oh, I didn't catch that.  I like it.  Will do.
> > 
> > So you mean 3 slots total including the shared one?
> 
> Yeah, i.e. common case is $LSM and capabilities.  Stack slot is last
> one, and gets put to use only if needed.
> 
> > Any comments on the added argument to register_security and
> > mod_reg_security to request a static slot?
> 
> Why would you not request a static slot?

Capability wouldn't use it, though, so that slot would be wasted.  In my
patch, capability, cap_stack, and root_plug don't ask for a slot.

> > +	spin_lock(&security_field_spinlock);
> > +	if (idx && *idx) {
> > +		int i;
> > +
> > +		*idx = -1;
> 
> So, I guess this means you request one, but who knows which one you'll
> get?

If you get -1 back, you didn't get a static slot.  But you don't have to
care as a module writer, the security_*_value functions will default to
using the shared slot if idx==-1.

> > +		for (i=0; i<CONFIG_SECURITY_STACKER_NUMFIELDS; i++) {
> > +			if (security_field_owners[i] == NULL) {
> > +				security_field_owners[i] = ops;
> > +				*idx = i;

This (idx != -1) means you got a static slot.

Of course this can now switch to idx==num_slots meaning you use the
shared slot.

> > Given the likelyhood of
> > capability/cap_stack being registered, it seemed worthwhile not to have
> > it waste a spot, but it is an API change...
> 
> API change is no big deal.  Seems useful to get index value so you can
> do optimized retrieve later.  But, I don't see it useful to request that
> way.  Just register, get index, if index == last slot, lookup hits list.

If we do switch to all LSMs getting a slot, should we just have the
return value for register_security and mod_reg_security be the slot#, or
-error?

thanks,
-serge

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH] Stacker - single-use static slots
  2005-08-03 16:45     ` [PATCH] Stacker - single-use static slots serue
  2005-08-03 17:57       ` Chris Wright
@ 2005-08-05 15:55       ` James Morris
  2005-08-05 17:27         ` serue
  2005-08-10 14:45         ` serue
  1 sibling, 2 replies; 39+ messages in thread
From: James Morris @ 2005-08-05 15:55 UTC (permalink / raw)
  To: serue; +Cc: lkml, Chris Wright, Stephen Smalley, Andrew Morton

On Wed, 3 Aug 2005 serue@us.ibm.com wrote:

> The attached patch implements your idea on top of my previous patchset.
> Following is performance data on a 16-way ppc.  dbench and tbench were
> run 50 times, kernbench and reaim 10 times each;  results are mean +/-
> 95% confidence half-interval.  The 'static slot' kernel had a single
> static slot for selinux, plus the (unused in this case) shared struct
> hlist_head security.

Can you also compare with no stacker at all (i.e. just SELinux with caps 
as secondary module) ?


- James
-- 
James Morris
<jmorris@redhat.com>


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH] Stacker - single-use static slots
  2005-08-05 15:55       ` James Morris
@ 2005-08-05 17:27         ` serue
  2005-08-05 17:34           ` serue
  2005-08-10 14:45         ` serue
  1 sibling, 1 reply; 39+ messages in thread
From: serue @ 2005-08-05 17:27 UTC (permalink / raw)
  To: James Morris; +Cc: serue, lkml, Chris Wright, Stephen Smalley, Andrew Morton

Quoting James Morris (jmorris@redhat.com):
> On Wed, 3 Aug 2005 serue@us.ibm.com wrote:
> 
> > The attached patch implements your idea on top of my previous patchset.
> > Following is performance data on a 16-way ppc.  dbench and tbench were
> > run 50 times, kernbench and reaim 10 times each;  results are mean +/-
> > 95% confidence half-interval.  The 'static slot' kernel had a single
> > static slot for selinux, plus the (unused in this case) shared struct
> > hlist_head security.
> 
> Can you also compare with no stacker at all (i.e. just SELinux with caps 
> as secondary module) ?

Will do.

I'll try to get a full set of numbers by next week, comparing:

	no stacker
	"original" stacker
	stacker with one shared slot
	stacker with two shared slots

thanks,
-serge

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH] Stacker - single-use static slots
  2005-08-05 17:27         ` serue
@ 2005-08-05 17:34           ` serue
  0 siblings, 0 replies; 39+ messages in thread
From: serue @ 2005-08-05 17:34 UTC (permalink / raw)
  To: serue; +Cc: James Morris, lkml, Chris Wright, Stephen Smalley, Andrew Morton

Quoting serue@us.ibm.com (serue@us.ibm.com):
> Quoting James Morris (jmorris@redhat.com):
> > On Wed, 3 Aug 2005 serue@us.ibm.com wrote:
> > 
> > > The attached patch implements your idea on top of my previous patchset.
> > > Following is performance data on a 16-way ppc.  dbench and tbench were
> > > run 50 times, kernbench and reaim 10 times each;  results are mean +/-
> > > 95% confidence half-interval.  The 'static slot' kernel had a single
> > > static slot for selinux, plus the (unused in this case) shared struct
> > > hlist_head security.
> > 
> > Can you also compare with no stacker at all (i.e. just SELinux with caps 
> > as secondary module) ?
> 
> Will do.
> 
> I'll try to get a full set of numbers by next week, comparing:
> 
> 	no stacker
> 	"original" stacker
> 	stacker with one shared slot
> 	stacker with two shared slots

Obviously, I meant to say stacker with one static slot (and one shared
slot), and stacker with two static slots (and one shared slot)  :)

thanks,
-serge

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH] Stacker - single-use static slots
  2005-08-05 15:55       ` James Morris
  2005-08-05 17:27         ` serue
@ 2005-08-10 14:45         ` serue
  2005-08-11  7:42           ` James Morris
  1 sibling, 1 reply; 39+ messages in thread
From: serue @ 2005-08-10 14:45 UTC (permalink / raw)
  To: James Morris; +Cc: serue, lkml, Chris Wright, Stephen Smalley, Andrew Morton

Quoting James Morris (jmorris@redhat.com):
> On Wed, 3 Aug 2005 serue@us.ibm.com wrote:
> 
> > The attached patch implements your idea on top of my previous patchset.
> > Following is performance data on a 16-way ppc.  dbench and tbench were
> > run 50 times, kernbench and reaim 10 times each;  results are mean +/-
> > 95% confidence half-interval.  The 'static slot' kernel had a single
> > static slot for selinux, plus the (unused in this case) shared struct
> > hlist_head security.
> 
> Can you also compare with no stacker at all (i.e. just SELinux with caps 
> as secondary module) ?

Attached is the patch taking into account Chris' comments.  More of
those annoying cache effects, I assume - 3 slots (the default)
outperforms two slots, even though only one slot is being used.  These
tests were run on a 16-way power4+ system.  I may try to re-run on some
x86 hardware, though each run will probably take 24 hours.

As usual, this reflects 50 runs of dbench and tbench, 10 of reaim and
10 of kernbench, with numbers representing mean +/- 95% confidence
half-interval.  Reaim plots # children vs max # jobs/min.  All tests
were on an ext2fs.

dbench (Throughput, larger is better):
2slots:    1459.680400 +/- 11.841823
3slots:    1460.549600 +/- 9.623773
nostacker: 1484.219200 +/- 11.900471

tbench (Throughput, larger is better):
2slots:    141.181200 +/- 2.982634
3slots:    143.333940 +/- 3.163371
nostacker: 143.884120 +/- 2.260252

kernbench (time, smaller is better):
2slots:    53.064000 +/- 0.150592
3slots:    52.959000 +/- 0.138074
nostacker: 52.618000 +/- 0.164646

reaim (number workers vs max jobs/min, larger is better):
2slots:

1 100542.857000 3296.286475
3 279771.426000 16148.439818
5 459000.002000 25175.800349
7 652800.000000 37679.689215
9 813085.712000 39555.434680
11 937671.432000 36259.148959
13 1093950.001000 49092.813099
15 1109250.000000 44057.652338

3slots:
1 102000.000000 0.000000
3 292885.713000 15105.482283
5 480857.144000 26914.062669
7 663000.000000 38456.671768
9 799971.426000 29666.576010
11 949692.861000 27194.361719
13 1093950.001000 49092.813099
15 1122000.000000 38456.671768

nostacker:
1 108120.000000 7049.224374
3 297257.142000 13185.145899
5 473571.430000 27469.050185
7 693600.000000 30765.337414
9 852428.570000 49444.293350
11 961714.290000 0.000000
13 1065535.715000 53564.650500
15 1147500.000000 0.000000

This patch is on top of the previous set of stacker patches.

Signed-off-by: Serge Hallyn <serue@us.ibm.com>
--
 fs/compat.c                    |    4 
 fs/exec.c                      |    2 
 fs/inode.c                     |    3 
 include/linux/binfmts.h        |    2 
 include/linux/fs.h             |    8 
 include/linux/ipc.h            |    2 
 include/linux/msg.h            |    2 
 include/linux/sched.h          |    2 
 include/linux/security-stack.h |   14 
 include/linux/security.h       |   72 +++-
 include/net/sock.h             |    2 
 ipc/msg.c                      |    3 
 ipc/msgutil.c                  |    3 
 ipc/sem.c                      |    3 
 ipc/shm.c                      |    3 
 kernel/fork.c                  |    3 
 security/Kconfig               |   16 +
 security/cap_stack.c           |    4 
 security/capability.c          |    4 
 security/root_plug.c           |    4 
 security/seclvl.c              |   30 +-
 security/security.c            |  105 ++++++-
 security/selinux/hooks.c       |  607 ++++++++++++++++++++++++-----------------
 security/selinux/selinuxfs.c   |   17 -
 security/stacker.c             |   62 ++--
 25 files changed, 638 insertions(+), 339 deletions(-)

Index: linux-2.6.13-rc4/include/linux/security.h
===================================================================
--- linux-2.6.13-rc4.orig/include/linux/security.h	2005-08-01 20:00:51.000000000 -0500
+++ linux-2.6.13-rc4/include/linux/security.h	2005-08-06 21:29:30.000000000 -0500
@@ -34,6 +34,8 @@
 struct ctl_table;
 struct module;
 
+extern int sec_shared_slot;
+
 /*
  * structure to be embedded at top of each LSM's security
  * objects.
@@ -44,24 +46,61 @@ struct security_list {
 };
 
 
+static inline void *__get_value(void *head, int idx)
+{
+	void **p = head;
+	pr_debug("__get_value: %s (%d): head %lx p %lx idx %d returning %lx at %lx\n",
+		__FUNCTION__, __LINE__, (long)head, (long)p, idx, (long)p[idx], (long)&p[idx]);
+	return p[idx];
+}
+
+static inline void __set_value(void *head, int idx, void *v)
+{
+	void **p = head;
+	p[idx] = v;
+	pr_debug("%s (%d): hd %lx, p %lx, idx %d,"
+		"v %lx, p[idx] %lx at %lx\n",
+		__FUNCTION__, __LINE__, (long) (head),
+		(long) p, idx, (long) (v),
+		(long)p[idx], (long)&p[idx]);
+}
+
 /*
  * These #defines present more convenient interfaces to
  * LSMs for using the security{g,d,s}et_value functions.
  */
-#define security_get_value_type(head, id, type) ( { \
-	struct security_list *v = security_get_value((head), id); \
-	v ? hlist_entry(v, type, lsm_list) : NULL; } )
-
-#define security_set_value_type(head, id, value) \
-	security_set_value((head), id, &(value)->lsm_list);
-
-#define security_add_value_type(head, id, value) \
-	security_add_value((head), id, &(value)->lsm_list);
-
-#define security_del_value_type(head, id, type) ( { \
-	struct security_list *v; \
-	v = security_del_value((head), id); \
-	v ? hlist_entry(v, type, lsm_list) : NULL; } )
+#define security_get_value_type(head, id, type, idx) (idx < sec_shared_slot) ? \
+		(type *)__get_value((head), idx) \
+	: ({ \
+		struct security_list *v = security_get_value((head), id); \
+		v ? hlist_entry(v, type, lsm_list) : NULL; \
+	})
+
+#define security_set_value_type(head, id, value, idx) \
+	do { \
+		if (idx < sec_shared_slot) { \
+			__set_value((head), idx, (value)); \
+		} else { \
+			security_set_value((head), id, &(value)->lsm_list); \
+		} \
+	} while (0);
+
+#define security_add_value_type(head, id, value, idx) \
+	do { \
+		if (idx < sec_shared_slot) { \
+			__set_value((head), idx, (value)); \
+		} else { \
+			security_add_value((head), id, &(value)->lsm_list); \
+		} \
+	} while (0);
+
+#define security_del_value_type(head, id, type, idx) (idx < sec_shared_slot) ? \
+		(type *)__get_value((head), idx) \
+	: ( { \
+		struct security_list *v; \
+		v = security_del_value((head), id); \
+		v ? hlist_entry(v, type, lsm_list) : NULL; \
+	} )
 
 /* security_disown_value is really only to be used by stacker */
 extern void security_disown_value(struct hlist_head *);
@@ -2022,9 +2061,10 @@ static inline int security_netlink_recv(
 
 /* prototypes */
 extern int security_init	(void);
-extern int register_security	(struct security_operations *ops);
+extern int register_security	(struct security_operations *ops, int *idx);
 extern int unregister_security	(struct security_operations *ops);
-extern int mod_reg_security	(const char *name, struct security_operations *ops);
+extern int mod_reg_security	(const char *name,
+			struct security_operations *ops, int *idx);
 extern int mod_unreg_security	(const char *name, struct security_operations *ops);
 extern struct dentry *securityfs_create_file(const char *name, mode_t mode,
 					     struct dentry *parent, void *data,
Index: linux-2.6.13-rc4/security/Kconfig
===================================================================
--- linux-2.6.13-rc4.orig/security/Kconfig	2005-08-01 20:00:51.000000000 -0500
+++ linux-2.6.13-rc4/security/Kconfig	2005-08-05 16:49:51.000000000 -0500
@@ -112,5 +112,21 @@ config SECURITY_STACKER
 	help
 	  Stack multiple LSMs.
 
+config SECURITY_STACKER_NUMFIELDS
+	int "Number of security fields to reserve"
+	depends on SECURITY_STACKER
+	default 3
+	help
+	  This option reserves extra space in each kernel object
+	  for security information.  This may speed up modules which
+	  make a lot of use of these fields, as these accesses can
+	  be lock-free.  However each kernel object requires one
+	  extra byte for each field reserved her, which can slow
+	  the system down.
+
+	  The actual number of static slots will be 1 greater than
+	  this number, and this number must always be at least 1.
+	  That one will be the shared slot for all LSMs to share.
+
 endmenu
 
Index: linux-2.6.13-rc4/fs/inode.c
===================================================================
--- linux-2.6.13-rc4.orig/fs/inode.c	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.13-rc4/fs/inode.c	2005-08-06 01:48:43.000000000 -0500
@@ -133,7 +133,8 @@ static struct inode *alloc_inode(struct 
 		inode->i_bdev = NULL;
 		inode->i_cdev = NULL;
 		inode->i_rdev = 0;
-		INIT_HLIST_HEAD(&inode->i_security);
+		memset(&inode->i_security, 0, (sec_shared_slot)*sizeof(void *));
+		INIT_HLIST_HEAD((struct hlist_head *)&(inode->i_security[sec_shared_slot]));
 		inode->dirtied_when = 0;
 		if (security_inode_alloc(inode)) {
 			if (inode->i_sb->s_op->destroy_inode)
Index: linux-2.6.13-rc4/include/linux/binfmts.h
===================================================================
--- linux-2.6.13-rc4.orig/include/linux/binfmts.h	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.13-rc4/include/linux/binfmts.h	2005-08-05 16:59:15.000000000 -0500
@@ -29,7 +29,7 @@ struct linux_binprm{
 	struct file * file;
 	int e_uid, e_gid;
 	kernel_cap_t cap_inheritable, cap_permitted, cap_effective;
-	struct hlist_head security;
+	void * security[CONFIG_SECURITY_STACKER_NUMFIELDS];
 	int argc, envc;
 	char * filename;	/* Name of binary as seen by procps */
 	char * interp;		/* Name of the binary really executed. Most
Index: linux-2.6.13-rc4/include/linux/fs.h
===================================================================
--- linux-2.6.13-rc4.orig/include/linux/fs.h	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.13-rc4/include/linux/fs.h	2005-08-05 16:59:37.000000000 -0500
@@ -485,7 +485,7 @@ struct inode {
 	unsigned int		i_flags;
 
 	atomic_t		i_writecount;
-	struct hlist_head	i_security;
+	void			*i_security[CONFIG_SECURITY_STACKER_NUMFIELDS];
 	union {
 		void		*generic_ip;
 	} u;
@@ -559,7 +559,7 @@ struct fown_struct {
 	rwlock_t lock;          /* protects pid, uid, euid fields */
 	int pid;		/* pid or -pgrp where SIGIO should be sent */
 	uid_t uid, euid;	/* uid/euid of process setting the owner */
-	struct hlist_head security;
+	void * security[CONFIG_SECURITY_STACKER_NUMFIELDS];
 	int signum;		/* posix.1b rt signal to be delivered on IO */
 };
 
@@ -596,7 +596,7 @@ struct file {
 
 	size_t			f_maxcount;
 	unsigned long		f_version;
-	struct hlist_head	f_security;
+	void 			*f_security[CONFIG_SECURITY_STACKER_NUMFIELDS];
 
 	/* needed for tty driver, and maybe others */
 	void			*private_data;
@@ -785,7 +785,7 @@ struct super_block {
 	int			s_syncing;
 	int			s_need_sync_fs;
 	atomic_t		s_active;
- 	struct hlist_head	s_security;
+	void			*s_security[CONFIG_SECURITY_STACKER_NUMFIELDS];
 	struct xattr_handler	**s_xattr;
 
 	struct list_head	s_inodes;	/* all inodes */
Index: linux-2.6.13-rc4/include/linux/ipc.h
===================================================================
--- linux-2.6.13-rc4.orig/include/linux/ipc.h	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.13-rc4/include/linux/ipc.h	2005-08-05 16:59:43.000000000 -0500
@@ -66,7 +66,7 @@ struct kern_ipc_perm
 	gid_t		cgid;
 	mode_t		mode; 
 	unsigned long	seq;
-	struct hlist_head security;
+	void		*security[CONFIG_SECURITY_STACKER_NUMFIELDS];
 };
 
 #endif /* __KERNEL__ */
Index: linux-2.6.13-rc4/include/linux/msg.h
===================================================================
--- linux-2.6.13-rc4.orig/include/linux/msg.h	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.13-rc4/include/linux/msg.h	2005-08-05 16:59:47.000000000 -0500
@@ -70,7 +70,7 @@ struct msg_msg {
 	long  m_type;          
 	int m_ts;           /* message text size */
 	struct msg_msgseg* next;
-	struct hlist_head security;
+	void * security[CONFIG_SECURITY_STACKER_NUMFIELDS];
 	/* the actual message follows immediately */
 };
 
Index: linux-2.6.13-rc4/include/linux/sched.h
===================================================================
--- linux-2.6.13-rc4.orig/include/linux/sched.h	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.13-rc4/include/linux/sched.h	2005-08-05 16:59:52.000000000 -0500
@@ -721,7 +721,7 @@ struct task_struct {
 	void *notifier_data;
 	sigset_t *notifier_mask;
 	
-	struct hlist_head security;
+	void *security[CONFIG_SECURITY_STACKER_NUMFIELDS];
 	struct audit_context *audit_context;
 	seccomp_t seccomp;
 
Index: linux-2.6.13-rc4/include/net/sock.h
===================================================================
--- linux-2.6.13-rc4.orig/include/net/sock.h	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.13-rc4/include/net/sock.h	2005-08-05 17:00:01.000000000 -0500
@@ -240,7 +240,7 @@ struct sock {
 	struct sk_buff		*sk_send_head;
 	__u32			sk_sndmsg_off;
 	int			sk_write_pending;
-	struct hlist_head	sk_security;
+	void			*sk_security[CONFIG_SECURITY_STACKER_NUMFIELDS];
 	void			(*sk_state_change)(struct sock *sk);
 	void			(*sk_data_ready)(struct sock *sk, int bytes);
 	void			(*sk_write_space)(struct sock *sk);
Index: linux-2.6.13-rc4/ipc/msg.c
===================================================================
--- linux-2.6.13-rc4.orig/ipc/msg.c	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.13-rc4/ipc/msg.c	2005-08-06 01:44:19.000000000 -0500
@@ -99,7 +99,8 @@ static int newque (key_t key, int msgflg
 	msq->q_perm.mode = (msgflg & S_IRWXUGO);
 	msq->q_perm.key = key;
 
-	INIT_HLIST_HEAD(&msq->q_perm.security);
+	memset(&msq->q_perm.security, 0, (sec_shared_slot)*sizeof(void *));
+	INIT_HLIST_HEAD((struct hlist_head *)&(msq->q_perm.security[sec_shared_slot]));
 	retval = security_msg_queue_alloc(msq);
 	if (retval) {
 		ipc_rcu_putref(msq);
Index: linux-2.6.13-rc4/ipc/msgutil.c
===================================================================
--- linux-2.6.13-rc4.orig/ipc/msgutil.c	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.13-rc4/ipc/msgutil.c	2005-08-06 01:44:23.000000000 -0500
@@ -41,7 +41,8 @@ struct msg_msg *load_msg(const void __us
 		return ERR_PTR(-ENOMEM);
 
 	msg->next = NULL;
-	INIT_HLIST_HEAD(&msg->security);
+	memset(&msg->security, 0, (sec_shared_slot)*sizeof(void *));
+	INIT_HLIST_HEAD((struct hlist_head *)&(msg->security[sec_shared_slot]));
 
 	if (copy_from_user(msg + 1, src, alen)) {
 		err = -EFAULT;
Index: linux-2.6.13-rc4/ipc/sem.c
===================================================================
--- linux-2.6.13-rc4.orig/ipc/sem.c	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.13-rc4/ipc/sem.c	2005-08-06 01:44:26.000000000 -0500
@@ -178,7 +178,8 @@ static int newary (key_t key, int nsems,
 	sma->sem_perm.mode = (semflg & S_IRWXUGO);
 	sma->sem_perm.key = key;
 
-	INIT_HLIST_HEAD(&sma->sem_perm.security);
+	memset(&sma->sem_perm.security, 0, (sec_shared_slot)*sizeof(void *));
+	INIT_HLIST_HEAD((struct hlist_head *)&(sma->sem_perm.security[sec_shared_slot]));
 	retval = security_sem_alloc(sma);
 	if (retval) {
 		ipc_rcu_putref(sma);
Index: linux-2.6.13-rc4/ipc/shm.c
===================================================================
--- linux-2.6.13-rc4.orig/ipc/shm.c	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.13-rc4/ipc/shm.c	2005-08-06 01:44:28.000000000 -0500
@@ -199,7 +199,8 @@ static int newseg (key_t key, int shmflg
 	shp->shm_flags = (shmflg & S_IRWXUGO);
 	shp->mlock_user = NULL;
 
-	INIT_HLIST_HEAD(&shp->shm_perm.security);
+	memset(&shp->shm_perm.security, 0, (sec_shared_slot)*sizeof(void *));
+	INIT_HLIST_HEAD((struct hlist_head *)&(shp->shm_perm.security[sec_shared_slot]));
 	error = security_shm_alloc(shp);
 	if (error) {
 		ipc_rcu_putref(shp);
Index: linux-2.6.13-rc4/kernel/fork.c
===================================================================
--- linux-2.6.13-rc4.orig/kernel/fork.c	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.13-rc4/kernel/fork.c	2005-08-06 01:44:30.000000000 -0500
@@ -941,7 +941,8 @@ static task_t *copy_process(unsigned lon
 
 	p->lock_depth = -1;		/* -1 = no lock */
 	do_posix_clock_monotonic_gettime(&p->start_time);
-	INIT_HLIST_HEAD(&p->security);
+	memset(&p->security, 0, (sec_shared_slot)*sizeof(void *));
+	INIT_HLIST_HEAD((struct hlist_head *)&(p->security[sec_shared_slot]));
 	p->io_context = NULL;
 	p->io_wait = NULL;
 	p->audit_context = NULL;
Index: linux-2.6.13-rc4/security/security.c
===================================================================
--- linux-2.6.13-rc4.orig/security/security.c	2005-08-01 20:00:51.000000000 -0500
+++ linux-2.6.13-rc4/security/security.c	2005-08-06 21:33:50.000000000 -0500
@@ -20,12 +20,22 @@
 
 #define SECURITY_FRAMEWORK_VERSION	"1.0.0"
 
+int sec_numslots = CONFIG_SECURITY_STACKER_NUMFIELDS;
+int sec_shared_slot;
+EXPORT_SYMBOL_GPL(sec_shared_slot);
+
+static struct security_operations
+	*security_field_owners[CONFIG_SECURITY_STACKER_NUMFIELDS];
+
 fastcall struct security_list *
-security_get_value(struct hlist_head *head, int security_id)
+security_get_value(void **sec, int security_id)
 {
 	struct security_list *e, *ret = NULL;
+	struct hlist_head *head;
 	struct hlist_node *tmp;
 
+	head = (struct hlist_head *) &(sec[sec_shared_slot]);
+
 	rcu_read_lock();
 	for (tmp = head->first; tmp;
 			 tmp = rcu_dereference(tmp->next)) {
@@ -46,15 +56,18 @@ out:
  * no locking as it is naturally serialized.
  */
 fastcall void
-security_set_value(struct hlist_head *head, int security_id,
+security_set_value(void **sec, int security_id,
 	struct security_list *obj_node)
 {
+	struct hlist_head *head;
 
+	head = (struct hlist_head *) &(sec[sec_shared_slot]);
 	obj_node->security_id = security_id;
 	hlist_add_head(&obj_node->list, head);
 }
 
 static DEFINE_SPINLOCK(stacker_value_spinlock);
+static DEFINE_SPINLOCK(security_field_spinlock);
 
 /*
  * Used outside of security_*_alloc hooks, so we need to
@@ -62,10 +75,12 @@ static DEFINE_SPINLOCK(stacker_value_spi
  * spinlock for now.
  */
 fastcall void
-security_add_value(struct hlist_head *head, int security_id,
+security_add_value(void **sec, int security_id,
 	struct security_list *obj_node)
 {
+	struct hlist_head *head;
 
+	head = (struct hlist_head *) &(sec[sec_shared_slot]);
 	spin_lock(&stacker_value_spinlock);
 	obj_node->security_id = security_id;
 	hlist_add_head_rcu(&obj_node->list, head);
@@ -86,9 +101,13 @@ security_add_value(struct hlist_head *he
  * XXX TODO - switch this to take a type, and deref
  * obj->lsm_list.list here.
  */
-int security_unlink_value(struct hlist_node *n)
+int security_unlink_value(struct hlist_node *n, int idx)
 {
 	int ret = 0;
+
+	if (idx == sec_shared_slot)
+		return 0;
+
 	spin_lock(&stacker_value_spinlock);
 	if (n->pprev == LIST_POISON2) {
 		ret = 1;
@@ -119,9 +138,10 @@ out:
 void security_disown_value(struct hlist_head *h)
 {
 	spin_lock(&stacker_value_spinlock);
-	if (h->first)
+	if (h->first) {
 		h->first->pprev = LIST_POISON2;
-	h->first = NULL;
+		h->first = NULL;
+	}
 	spin_unlock(&stacker_value_spinlock);
 }
 
@@ -129,11 +149,14 @@ int lsm_unloading;
 
 /* No locking needed: only called during object_destroy */
 fastcall struct security_list *
-security_del_value(struct hlist_head *head, int security_id)
+security_del_value(void **sec, int security_id)
 {
 	struct security_list *e;
 	struct hlist_node *tmp;
 	char d = 0;
+	struct hlist_head *head;
+
+	head = (struct hlist_head *) &(sec[sec_shared_slot]);
 
 	if (lsm_unloading) {
 		d = 1;
@@ -205,6 +228,7 @@ int __init security_init(void)
 		return -EIO;
 	}
 
+	sec_shared_slot = sec_numslots - 1;
 	security_ops = &dummy_security_ops;
 	do_security_initcalls();
 
@@ -223,7 +247,7 @@ int __init security_init(void)
  * If there is already a security module registered with the kernel,
  * an error will be returned.  Otherwise 0 is returned on success.
  */
-int register_security(struct security_operations *ops)
+int register_security(struct security_operations *ops, int *idx)
 {
 	if (security_ops != &dummy_security_ops)
 		return -EAGAIN;
@@ -234,6 +258,21 @@ int register_security(struct security_op
 		return -EINVAL;
 	}
 
+	spin_lock(&security_field_spinlock);
+	if (idx && *idx) {
+		int i;
+
+		for (i=0; i<sec_shared_slot; i++) {
+			if (security_field_owners[i] == NULL) {
+				security_field_owners[i] = ops;
+				break;
+			}
+		}
+
+		*idx = i;
+	}
+	spin_unlock(&security_field_spinlock);
+
 	security_ops = ops;
 
 	return 0;
@@ -252,6 +291,8 @@ int register_security(struct security_op
  */
 int unregister_security(struct security_operations *ops)
 {
+	int i;
+
 	if (ops != security_ops) {
 		printk(KERN_INFO "%s: trying to unregister "
 		       "a security_opts structure that is not "
@@ -261,6 +302,15 @@ int unregister_security(struct security_
 
 	security_ops = &dummy_security_ops;
 
+	spin_lock(&security_field_spinlock);
+	for (i=0; i<sec_shared_slot; i++) {
+		if (security_field_owners[i] == ops) {
+			security_field_owners[i] = NULL;
+			break;
+		}
+	}
+	spin_unlock(&security_field_spinlock);
+
 	return 0;
 }
 
@@ -276,8 +326,11 @@ int unregister_security(struct security_
  * The return value depends on the currently loaded security module, with 0 as
  * success.
  */
-int mod_reg_security(const char *name, struct security_operations *ops)
+int mod_reg_security(const char *name, struct security_operations *ops,
+			int *idx)
 {
+	int ret = 0;
+
 	if (!ops) {
 		printk(KERN_INFO "%s received NULL security operations",
 						       __FUNCTION__);
@@ -290,7 +343,28 @@ int mod_reg_security(const char *name, s
 		return -EINVAL;
 	}
 
-	return security_ops->register_security(name, ops);
+	ret = security_ops->register_security(name, ops);
+
+	if (ret < 0)
+		goto out;
+
+	spin_lock(&security_field_spinlock);
+	if (idx && *idx) {
+		int i;
+
+		for (i=0; i<sec_shared_slot; i++) {
+			if (security_field_owners[i] == NULL) {
+				security_field_owners[i] = ops;
+				break;
+			}
+		}
+
+		*idx = i;
+	}
+	spin_unlock(&security_field_spinlock);
+
+out:
+	return ret;
 }
 
 /**
@@ -308,12 +382,23 @@ int mod_reg_security(const char *name, s
  */
 int mod_unreg_security(const char *name, struct security_operations *ops)
 {
+	int i;
+
 	if (ops == security_ops) {
 		printk(KERN_INFO "%s invalid attempt to unregister "
 		       " primary security ops.\n", __FUNCTION__);
 		return -EINVAL;
 	}
 
+	spin_lock(&security_field_spinlock);
+	for (i=0; i<sec_shared_slot; i++) {
+		if (security_field_owners[i] == ops) {
+			security_field_owners[i] = NULL;
+			break;
+		}
+	}
+	spin_unlock(&security_field_spinlock);
+
 	return security_ops->unregister_security(name, ops);
 }
 
Index: linux-2.6.13-rc4/security/selinux/hooks.c
===================================================================
--- linux-2.6.13-rc4.orig/security/selinux/hooks.c	2005-08-01 20:00:51.000000000 -0500
+++ linux-2.6.13-rc4/security/selinux/hooks.c	2005-08-05 22:06:22.000000000 -0500
@@ -78,6 +78,8 @@
 #define XATTR_SELINUX_SUFFIX "selinux"
 #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
 
+int selinux_secidx;
+
 extern unsigned int policydb_loaded_version;
 extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
 
@@ -123,7 +125,8 @@ static int task_alloc_security(struct ta
 	memset(tsec, 0, sizeof(struct task_security_struct));
 	tsec->task = task;
 	tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;
-	security_set_value_type(&task->security, SELINUX_LSM_ID, tsec);
+	security_set_value_type(task->security, SELINUX_LSM_ID, tsec,
+		selinux_secidx);
 
 	return 0;
 }
@@ -132,8 +135,9 @@ static void task_free_security(struct ta
 {
 	struct task_security_struct *tsec;
 	
-	tsec = security_del_value_type(&task->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+	tsec = security_del_value_type(task->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+			selinux_secidx);
 
 	kfree(tsec);
 }
@@ -143,8 +147,9 @@ static int inode_alloc_security(struct i
 	struct task_security_struct *tsec;
 	struct inode_security_struct *isec;
 
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
 	isec = kmalloc(sizeof(struct inode_security_struct), GFP_KERNEL);
 	if (!isec)
 		return -ENOMEM;
@@ -159,7 +164,8 @@ static int inode_alloc_security(struct i
 		isec->task_sid = tsec->sid;
 	else
 		isec->task_sid = SECINITSID_UNLABELED;
-	security_set_value_type(&inode->i_security, SELINUX_LSM_ID, isec);
+	security_set_value_type(inode->i_security, SELINUX_LSM_ID, isec,
+		selinux_secidx);
 
 	return 0;
 }
@@ -169,13 +175,15 @@ static void inode_free_security(struct i
 	struct inode_security_struct *isec;
 	struct superblock_security_struct *sbsec;
 
-	isec = security_del_value_type(&inode->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+	isec = security_del_value_type(inode->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct,
+			selinux_secidx);
 	if (!isec)
 		return;
 
-	sbsec = security_get_value_type(&inode->i_sb->s_security,
-		SELINUX_LSM_ID, struct superblock_security_struct);
+	sbsec = security_get_value_type(inode->i_sb->s_security,
+		SELINUX_LSM_ID, struct superblock_security_struct,
+		selinux_secidx);
 
 	spin_lock(&sbsec->isec_lock);
 	if (!list_empty(&isec->list))
@@ -190,8 +198,9 @@ static int file_alloc_security(struct fi
 	struct task_security_struct *tsec;
 	struct file_security_struct *fsec;
 
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
 	fsec = kmalloc(sizeof(struct file_security_struct), GFP_ATOMIC);
 	if (!fsec)
 		return -ENOMEM;
@@ -205,7 +214,8 @@ static int file_alloc_security(struct fi
 		fsec->sid = SECINITSID_UNLABELED;
 		fsec->fown_sid = SECINITSID_UNLABELED;
 	}
-	security_set_value_type(&file->f_security, SELINUX_LSM_ID, fsec);
+	security_set_value_type(file->f_security, SELINUX_LSM_ID, fsec,
+		selinux_secidx);
 
 	return 0;
 }
@@ -214,8 +224,9 @@ static void file_free_security(struct fi
 {
 	struct file_security_struct *fsec;
 
-	fsec = security_del_value_type(&file->f_security, SELINUX_LSM_ID,
-		struct file_security_struct);
+	fsec = security_del_value_type(file->f_security, SELINUX_LSM_ID,
+		struct file_security_struct,
+			selinux_secidx);
 
 	kfree(fsec);
 }
@@ -236,7 +247,8 @@ static int superblock_alloc_security(str
 	sbsec->sb = sb;
 	sbsec->sid = SECINITSID_UNLABELED;
 	sbsec->def_sid = SECINITSID_FILE;
-	security_set_value_type(&sb->s_security, SELINUX_LSM_ID, sbsec);
+	security_set_value_type(sb->s_security, SELINUX_LSM_ID, sbsec,
+		selinux_secidx);
 
 	return 0;
 }
@@ -245,8 +257,8 @@ static void superblock_free_security(str
 {
 	struct superblock_security_struct *sbsec;
 
-	sbsec = security_del_value_type(&sb->s_security, SELINUX_LSM_ID,
-		struct superblock_security_struct);
+	sbsec = security_del_value_type(sb->s_security, SELINUX_LSM_ID,
+		struct superblock_security_struct, selinux_secidx);
 	if (!sbsec)
 		return;
 
@@ -273,7 +285,8 @@ static int sk_alloc_security(struct sock
 	memset(ssec, 0, sizeof(*ssec));
 	ssec->sk = sk;
 	ssec->peer_sid = SECINITSID_UNLABELED;
-	security_set_value_type(&sk->sk_security, SELINUX_LSM_ID, ssec);
+	security_set_value_type(sk->sk_security, SELINUX_LSM_ID, ssec,
+		selinux_secidx);
 
 	return 0;
 }
@@ -285,8 +298,8 @@ static void sk_free_security(struct sock
 	if (sk->sk_family != PF_UNIX)
 		return;
 
-	ssec = security_del_value_type(&sk->sk_security, SELINUX_LSM_ID,
-		struct sk_security_struct);
+	ssec = security_del_value_type(sk->sk_security, SELINUX_LSM_ID,
+		struct sk_security_struct, selinux_secidx);
 
 	kfree(ssec);
 }
@@ -337,10 +350,12 @@ static int try_context_mount(struct supe
 	struct task_security_struct *tsec;
 	struct superblock_security_struct *sbsec;
 
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	sbsec = security_get_value_type(&sb->s_security, SELINUX_LSM_ID,
-		struct superblock_security_struct);
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	sbsec = security_get_value_type(sb->s_security, SELINUX_LSM_ID,
+		struct superblock_security_struct,
+		selinux_secidx);
 
 	if (!data)
 		goto out;
@@ -511,8 +526,9 @@ static int superblock_doinit(struct supe
 	struct inode *inode = root->d_inode;
 	int rc = 0;
 
-	sbsec = security_get_value_type(&sb->s_security, SELINUX_LSM_ID,
-		struct superblock_security_struct);
+	sbsec = security_get_value_type(sb->s_security, SELINUX_LSM_ID,
+		struct superblock_security_struct,
+		selinux_secidx);
 
 	down(&sbsec->sem);
 	if (sbsec->initialized)
@@ -747,8 +763,9 @@ static int inode_doinit_with_dentry(stru
 	int rc = 0;
 	int hold_sem = 0;
 
-	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+	isec = security_get_value_type(inode->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct,
+		selinux_secidx);
 
 	if (isec->initialized)
 		goto out;
@@ -758,8 +775,9 @@ static int inode_doinit_with_dentry(stru
 	if (isec->initialized)
 		goto out;
 
-	sbsec = security_get_value_type(&inode->i_sb->s_security,
-		SELINUX_LSM_ID, struct superblock_security_struct);
+	sbsec = security_get_value_type(inode->i_sb->s_security,
+		SELINUX_LSM_ID, struct superblock_security_struct,
+		selinux_secidx);
 	if (!sbsec->initialized) {
 		/* Defer initialization until selinux_complete_init,
 		   after the initial policy is loaded and the security
@@ -934,10 +952,12 @@ static int task_has_perm(struct task_str
 {
 	struct task_security_struct *tsec1, *tsec2;
 
-	tsec1 = security_get_value_type(&tsk1->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	tsec2 = security_get_value_type(&tsk2->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+	tsec1 = security_get_value_type(tsk1->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	tsec2 = security_get_value_type(tsk2->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
 	return avc_has_perm(tsec1->sid, tsec2->sid,
 			    SECCLASS_PROCESS, perms, NULL);
 }
@@ -949,8 +969,9 @@ static int task_has_capability(struct ta
 	struct task_security_struct *tsec;
 	struct avc_audit_data ad;
 
-	tsec = security_get_value_type(&tsk->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+	tsec = security_get_value_type(tsk->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad,CAP);
 	ad.tsk = tsk;
@@ -966,8 +987,9 @@ static int task_has_system(struct task_s
 {
 	struct task_security_struct *tsec;
 
-	tsec = security_get_value_type(&tsk->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+	tsec = security_get_value_type(tsk->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
 
 	return avc_has_perm(tsec->sid, SECINITSID_KERNEL,
 			    SECCLASS_SYSTEM, perms, NULL);
@@ -985,10 +1007,12 @@ static int inode_has_perm(struct task_st
 	struct inode_security_struct *isec;
 	struct avc_audit_data ad;
 
-	tsec = security_get_value_type(&tsk->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+	tsec = security_get_value_type(tsk->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	isec = security_get_value_type(inode->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct,
+		selinux_secidx);
 
 	if (!adp) {
 		adp = &ad;
@@ -1035,10 +1059,12 @@ static inline int file_has_perm(struct t
 	struct avc_audit_data ad;
 	int rc;
 
-	tsec = security_get_value_type(&tsk->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	fsec = security_get_value_type(&file->f_security, SELINUX_LSM_ID,
-		struct file_security_struct);
+	tsec = security_get_value_type(tsk->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	fsec = security_get_value_type(file->f_security, SELINUX_LSM_ID,
+		struct file_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad, FS);
 	ad.u.fs.mnt = mnt;
@@ -1072,12 +1098,15 @@ static int may_create(struct inode *dir,
 	struct avc_audit_data ad;
 	int rc;
 
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	dsec = security_get_value_type(&dir->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
-	sbsec = security_get_value_type(&dir->i_sb->s_security, SELINUX_LSM_ID,
-		struct superblock_security_struct);
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	dsec = security_get_value_type(dir->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct,
+		selinux_secidx);
+	sbsec = security_get_value_type(dir->i_sb->s_security, SELINUX_LSM_ID,
+		struct superblock_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad, FS);
 	ad.u.fs.dentry = dentry;
@@ -1122,12 +1151,15 @@ static int may_link(struct inode *dir,
 	u32 av;
 	int rc;
 
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	dsec = security_get_value_type(&dir->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
-	isec = security_get_value_type(&dentry->d_inode->i_security,
-		SELINUX_LSM_ID, struct inode_security_struct);
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	dsec = security_get_value_type(dir->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct,
+		selinux_secidx);
+	isec = security_get_value_type(dentry->d_inode->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad, FS);
 	ad.u.fs.dentry = dentry;
@@ -1169,15 +1201,19 @@ static inline int may_rename(struct inod
 	int old_is_dir, new_is_dir;
 	int rc;
 
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	old_dsec = security_get_value_type(&old_dir->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
-	old_isec = security_get_value_type(&old_dentry->d_inode->i_security,
-		SELINUX_LSM_ID, struct inode_security_struct);
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	old_dsec = security_get_value_type(old_dir->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct,
+		selinux_secidx);
+	old_isec = security_get_value_type(old_dentry->d_inode->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
 	old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
-	new_dsec = security_get_value_type(&new_dir->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+	new_dsec = security_get_value_type(new_dir->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad, FS);
 
@@ -1205,8 +1241,9 @@ static inline int may_rename(struct inod
 	if (rc)
 		return rc;
 	if (new_dentry->d_inode) {
-		new_isec = security_get_value_type(&new_dentry->d_inode->i_security,
-			SELINUX_LSM_ID, struct inode_security_struct);
+		new_isec = security_get_value_type(new_dentry->d_inode->i_security,
+			SELINUX_LSM_ID, struct inode_security_struct,
+			selinux_secidx);
 		new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
 		rc = avc_has_perm(tsec->sid, new_isec->sid,
 				  new_isec->sclass,
@@ -1227,10 +1264,12 @@ static int superblock_has_perm(struct ta
 	struct task_security_struct *tsec;
 	struct superblock_security_struct *sbsec;
 
-	tsec = security_get_value_type(&tsk->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	sbsec = security_get_value_type(&sb->s_security, SELINUX_LSM_ID,
-		struct superblock_security_struct);
+	tsec = security_get_value_type(tsk->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	sbsec = security_get_value_type(sb->s_security, SELINUX_LSM_ID,
+		struct superblock_security_struct,
+		selinux_secidx);
 	return avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
 			    perms, ad);
 }
@@ -1286,10 +1325,12 @@ static int inode_security_set_sid(struct
 	struct inode_security_struct *isec;
 	struct superblock_security_struct *sbsec;
 
-	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
-	sbsec = security_get_value_type(&inode->i_sb->s_security,
-		SELINUX_LSM_ID, struct superblock_security_struct);
+	isec = security_get_value_type(inode->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct,
+		selinux_secidx);
+	sbsec = security_get_value_type(inode->i_sb->s_security,
+		SELINUX_LSM_ID, struct superblock_security_struct,
+		selinux_secidx);
 
 	if (!sbsec->initialized) {
 		/* Defer initialization to selinux_complete_init. */
@@ -1318,12 +1359,15 @@ static int post_create(struct inode *dir
 	unsigned int len;
 	int rc;
 
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	dsec = security_get_value_type(&dir->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
-	sbsec = security_get_value_type(&dir->i_sb->s_security, SELINUX_LSM_ID,
-		struct superblock_security_struct);
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	dsec = security_get_value_type(dir->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct,
+		selinux_secidx);
+	sbsec = security_get_value_type(dir->i_sb->s_security, SELINUX_LSM_ID,
+		struct superblock_security_struct,
+		selinux_secidx);
 
 	inode = dentry->d_inode;
 	if (!inode) {
@@ -1394,10 +1438,12 @@ static int selinux_ptrace(struct task_st
 	struct task_security_struct *csec;
 	int rc;
 
-	psec = security_get_value_type(&parent->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	csec = security_get_value_type(&child->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+	psec = security_get_value_type(parent->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	csec = security_get_value_type(child->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
 
 	rc = task_has_perm(parent, child, PROCESS__PTRACE);
 	/* Save the SID of the tracing process for later use in apply_creds. */
@@ -1431,8 +1477,9 @@ static int selinux_sysctl(ctl_table *tab
 	u32 tsid;
 	int rc;
 
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
 
 	rc = selinux_proc_get_sid(table->de, (op == 001) ?
 	                          SECCLASS_DIR : SECCLASS_FILE, &tsid);
@@ -1537,7 +1584,8 @@ static int selinux_bprm_alloc_security(s
 	bsec->sid = SECINITSID_UNLABELED;
 	bsec->set = 0;
 
-	security_set_value_type(&bprm->security, SELINUX_LSM_ID, bsec);
+	security_set_value_type(bprm->security, SELINUX_LSM_ID, bsec,
+		selinux_secidx);
 	return 0;
 }
 
@@ -1551,16 +1599,19 @@ static int selinux_bprm_set_security(str
 	struct avc_audit_data ad;
 	int rc;
 
-	bsec = security_get_value_type(&bprm->security, SELINUX_LSM_ID,
-		struct bprm_security_struct);
+	bsec = security_get_value_type(bprm->security, SELINUX_LSM_ID,
+		struct bprm_security_struct,
+		selinux_secidx);
 
 	if (bsec->set)
 		return 0;
 
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	isec = security_get_value_type(inode->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct,
+		selinux_secidx);
 
 	/* Default to the current task SID. */
 	bsec->sid = tsec->sid;
@@ -1620,8 +1671,9 @@ static int selinux_bprm_secureexec (stru
 	struct task_security_struct *tsec;
 	int atsecure = 0;
 
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
 	if (tsec->osid != tsec->sid) {
 		/* Enable secure mode for SIDs transitions unless
 		   the noatsecure permission is granted between
@@ -1638,8 +1690,8 @@ static void selinux_bprm_free_security(s
 {
  	struct bprm_security_struct *bsec;
 
- 	bsec = security_del_value_type(&bprm->security, SELINUX_LSM_ID,
- 			struct bprm_security_struct);
+ 	bsec = security_del_value_type(bprm->security, SELINUX_LSM_ID,
+ 			struct bprm_security_struct, selinux_secidx);
 	kfree(bsec);
 }
 
@@ -1735,10 +1787,12 @@ static void selinux_bprm_apply_creds(str
 	u32 sid;
 	int rc;
 
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	bsec = security_get_value_type(&bprm->security, SELINUX_LSM_ID,
-		struct bprm_security_struct);
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	bsec = security_get_value_type(bprm->security, SELINUX_LSM_ID,
+		struct bprm_security_struct,
+		selinux_secidx);
 	sid = bsec->sid;
 
 	tsec->osid = tsec->sid;
@@ -1781,10 +1835,12 @@ static void selinux_bprm_post_apply_cred
 	struct bprm_security_struct *bsec;
 	int rc, i;
 
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	bsec = security_get_value_type(&bprm->security, SELINUX_LSM_ID,
-		struct bprm_security_struct);
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	bsec = security_get_value_type(bprm->security, SELINUX_LSM_ID,
+		struct bprm_security_struct,
+		selinux_secidx);
 
 	if (bsec->unsafe) {
 		force_sig_specific(SIGKILL, current);
@@ -2121,8 +2177,9 @@ static int selinux_inode_setxattr(struct
 		return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
 	}
 
-	sbsec = security_get_value_type(&inode->i_sb->s_security,
-		SELINUX_LSM_ID, struct superblock_security_struct);
+	sbsec = security_get_value_type(inode->i_sb->s_security,
+		SELINUX_LSM_ID, struct superblock_security_struct,
+		selinux_secidx);
 	if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
 		return -EOPNOTSUPP;
 
@@ -2132,10 +2189,12 @@ static int selinux_inode_setxattr(struct
 	AVC_AUDIT_DATA_INIT(&ad,FS);
 	ad.u.fs.dentry = dentry;
 
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	isec = security_get_value_type(inode->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct,
+		selinux_secidx);
 	rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass,
 			  FILE__RELABELFROM, &ad);
 	if (rc)
@@ -2170,8 +2229,9 @@ static void selinux_inode_post_setxattr(
 	u32 newsid;
 	int rc;
 
-	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+	isec = security_get_value_type(inode->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct,
+		selinux_secidx);
 
 	if (strcmp(name, XATTR_NAME_SELINUX)) {
 		/* Not an attribute we recognize, so nothing to do. */
@@ -2194,8 +2254,9 @@ static int selinux_inode_getxattr (struc
 	struct inode *inode = dentry->d_inode;
 	struct superblock_security_struct *sbsec;
 	
-	sbsec = security_get_value_type(&inode->i_sb->s_security,
-		SELINUX_LSM_ID, struct superblock_security_struct);
+	sbsec = security_get_value_type(inode->i_sb->s_security,
+		SELINUX_LSM_ID, struct superblock_security_struct,
+		selinux_secidx);
 
 	if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
 		return -EOPNOTSUPP;
@@ -2242,8 +2303,9 @@ static int selinux_inode_getsecurity(str
 	if (strcmp(name, XATTR_SELINUX_SUFFIX))
 		return -EOPNOTSUPP;
 
-	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+	isec = security_get_value_type(inode->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct,
+		selinux_secidx);
 
 	rc = security_sid_to_context(isec->sid, &context, &len);
 	if (rc)
@@ -2272,8 +2334,9 @@ static int selinux_inode_setsecurity(str
 	if (strcmp(name, XATTR_SELINUX_SUFFIX))
 		return -EOPNOTSUPP;
 
-	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+	isec = security_get_value_type(inode->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct,
+		selinux_secidx);
 
 	if (!value || !size)
 		return -EACCES;
@@ -2511,10 +2574,12 @@ static int selinux_file_set_fowner(struc
 	struct task_security_struct *tsec;
 	struct file_security_struct *fsec;
 
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	fsec = security_get_value_type(&file->f_security, SELINUX_LSM_ID,
-		struct file_security_struct);
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	fsec = security_get_value_type(file->f_security, SELINUX_LSM_ID,
+		struct file_security_struct,
+		selinux_secidx);
 	fsec->fown_sid = tsec->sid;
 
 	return 0;
@@ -2531,10 +2596,12 @@ static int selinux_file_send_sigiotask(s
 	/* struct fown_struct is never outside the context of a struct file */
         file = (struct file *)((long)fown - offsetof(struct file,f_owner));
 
-	tsec = security_get_value_type(&tsk->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	fsec = security_get_value_type(&file->f_security, SELINUX_LSM_ID,
-		struct file_security_struct);
+	tsec = security_get_value_type(tsk->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	fsec = security_get_value_type(file->f_security, SELINUX_LSM_ID,
+		struct file_security_struct,
+		selinux_secidx);
 
 	if (!signum)
 		perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
@@ -2562,14 +2629,16 @@ static int selinux_task_alloc_security(s
 	struct task_security_struct *tsec1, *tsec2;
 	int rc;
 
-	tsec1 = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+	tsec1 = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
 
 	rc = task_alloc_security(tsk);
 	if (rc)
 		return rc;
-	tsec2 = security_get_value_type(&tsk->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+	tsec2 = security_get_value_type(tsk->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
 
 	tsec2->osid = tsec1->osid;
 	tsec2->sid = tsec1->sid;
@@ -2698,8 +2767,9 @@ static void selinux_task_reparent_to_ini
 {
   	struct task_security_struct *tsec;
 
-	tsec = security_get_value_type(&p->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+	tsec = security_get_value_type(p->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
 	tsec->osid = tsec->sid;
 	tsec->sid = SECINITSID_KERNEL;
 	return;
@@ -2711,10 +2781,12 @@ static void selinux_task_to_inode(struct
 	struct task_security_struct *tsec;
 	struct inode_security_struct *isec;
 
-	tsec = security_get_value_type(&p->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+	tsec = security_get_value_type(p->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	isec = security_get_value_type(inode->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct,
+		selinux_secidx);
 
 	isec->sid = tsec->sid;
 	isec->initialized = 1;
@@ -2882,10 +2954,12 @@ static int socket_has_perm(struct task_s
 	struct avc_audit_data ad;
 	int err = 0;
 
-	tsec = security_get_value_type(&task->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	isec = security_get_value_type(&SOCK_INODE(sock)->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+	tsec = security_get_value_type(task->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	isec = security_get_value_type(SOCK_INODE(sock)->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
 
 	if (isec->sid == SECINITSID_KERNEL)
 		goto out;
@@ -2907,8 +2981,9 @@ static int selinux_socket_create(int fam
 	if (kern)
 		goto out;
 
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
 	err = avc_has_perm(tsec->sid, tsec->sid,
 			   socket_type_to_security_class(family, type,
 			   protocol), SOCKET__CREATE, NULL);
@@ -2923,11 +2998,13 @@ static void selinux_socket_post_create(s
 	struct inode_security_struct *isec;
 	struct task_security_struct *tsec;
 
-	isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
-		SELINUX_LSM_ID, struct inode_security_struct);
-
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+	isec = security_get_value_type(SOCK_INODE(sock)->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
+
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
 	isec->sclass = socket_type_to_security_class(family, type, protocol);
 	isec->sid = kern ? SECINITSID_KERNEL : tsec->sid;
 	isec->initialized = 1;
@@ -2965,10 +3042,12 @@ static int selinux_socket_bind(struct so
 		struct sock *sk = sock->sk;
 		u32 sid, node_perm, addrlen;
 
-		tsec = security_get_value_type(&current->security,
-			SELINUX_LSM_ID, struct task_security_struct);
-		isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
-			SELINUX_LSM_ID, struct inode_security_struct);
+		tsec = security_get_value_type(current->security,
+			SELINUX_LSM_ID, struct task_security_struct,
+			selinux_secidx);
+		isec = security_get_value_type(SOCK_INODE(sock)->i_security,
+			SELINUX_LSM_ID, struct inode_security_struct,
+			selinux_secidx);
 
 		if (family == PF_INET) {
 			addr4 = (struct sockaddr_in *)address;
@@ -3046,8 +3125,9 @@ static int selinux_socket_connect(struct
 	/*
 	 * If a TCP socket, check name_connect permission for the port.
 	 */
-	isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
-		SELINUX_LSM_ID, struct inode_security_struct);
+	isec = security_get_value_type(SOCK_INODE(sock)->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
 	if (isec->sclass == SECCLASS_TCP_SOCKET) {
 		struct sock *sk = sock->sk;
 		struct avc_audit_data ad;
@@ -3101,11 +3181,13 @@ static int selinux_socket_accept(struct 
 	if (err)
 		return err;
 
-	newisec = security_get_value_type(&SOCK_INODE(newsock)->i_security,
-		SELINUX_LSM_ID, struct inode_security_struct);
-
-	isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
-		SELINUX_LSM_ID, struct inode_security_struct);
+	newisec = security_get_value_type(SOCK_INODE(newsock)->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
+
+	isec = security_get_value_type(SOCK_INODE(sock)->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
 	newisec->sclass = isec->sclass;
 	newisec->sid = isec->sid;
 	newisec->initialized = 1;
@@ -3161,10 +3243,12 @@ static int selinux_socket_unix_stream_co
 	struct avc_audit_data ad;
 	int err;
 
-	isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
-		SELINUX_LSM_ID, struct inode_security_struct);
-	other_isec = security_get_value_type(&SOCK_INODE(other)->i_security,
-		SELINUX_LSM_ID, struct inode_security_struct);
+	isec = security_get_value_type(SOCK_INODE(sock)->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
+	other_isec = security_get_value_type(SOCK_INODE(other)->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad,NET);
 	ad.u.net.sk = other->sk;
@@ -3176,13 +3260,15 @@ static int selinux_socket_unix_stream_co
 		return err;
 
 	/* connecting socket */
-	ssec = security_get_value_type(&sock->sk->sk_security, SELINUX_LSM_ID,
-		struct sk_security_struct);
+	ssec = security_get_value_type(sock->sk->sk_security, SELINUX_LSM_ID,
+		struct sk_security_struct,
+		selinux_secidx);
 	ssec->peer_sid = other_isec->sid;
 	
 	/* server child socket */
-	ssec = security_get_value_type(&newsk->sk_security, SELINUX_LSM_ID,
-		struct sk_security_struct);
+	ssec = security_get_value_type(newsk->sk_security, SELINUX_LSM_ID,
+		struct sk_security_struct,
+		selinux_secidx);
 	ssec->peer_sid = isec->sid;
 	
 	return 0;
@@ -3196,10 +3282,12 @@ static int selinux_socket_unix_may_send(
 	struct avc_audit_data ad;
 	int err;
 
-	isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
-		SELINUX_LSM_ID, struct inode_security_struct);
-	other_isec = security_get_value_type(&SOCK_INODE(other)->i_security,
-		SELINUX_LSM_ID, struct inode_security_struct);
+	isec = security_get_value_type(SOCK_INODE(sock)->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
+	other_isec = security_get_value_type(SOCK_INODE(other)->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad,NET);
 	ad.u.net.sk = other->sk;
@@ -3239,8 +3327,9 @@ static int selinux_socket_sock_rcv_skb(s
  		inode = SOCK_INODE(sock);
  		if (inode) {
  			struct inode_security_struct *isec;
-			isec = security_get_value_type(&inode->i_security,
-				SELINUX_LSM_ID, struct inode_security_struct);
+			isec = security_get_value_type(inode->i_security,
+				SELINUX_LSM_ID, struct inode_security_struct,
+				selinux_secidx);
  			sock_sid = isec->sid;
  			sock_class = isec->sclass;
  		}
@@ -3323,15 +3412,17 @@ static int selinux_socket_getpeersec(str
 	struct sk_security_struct *ssec;
 	struct inode_security_struct *isec;
 
-	isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
-		SELINUX_LSM_ID, struct inode_security_struct);
+	isec = security_get_value_type(SOCK_INODE(sock)->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
 	if (isec->sclass != SECCLASS_UNIX_STREAM_SOCKET) {
 		err = -ENOPROTOOPT;
 		goto out;
 	}
 
-	ssec = security_get_value_type(&sock->sk->sk_security, SELINUX_LSM_ID,
-		struct sk_security_struct);
+	ssec = security_get_value_type(sock->sk->sk_security, SELINUX_LSM_ID,
+		struct sk_security_struct,
+		selinux_secidx);
 	
 	err = security_sid_to_context(ssec->peer_sid, &scontext, &scontext_len);
 	if (err)
@@ -3372,8 +3463,9 @@ static int selinux_nlmsg_perm(struct soc
 	struct socket *sock = sk->sk_socket;
 	struct inode_security_struct *isec;
 	
-	isec = security_get_value_type(&SOCK_INODE(sock)->i_security,
-		SELINUX_LSM_ID, struct inode_security_struct);
+	isec = security_get_value_type(SOCK_INODE(sock)->i_security,
+		SELINUX_LSM_ID, struct inode_security_struct,
+		selinux_secidx);
 	
 	if (skb->len < NLMSG_SPACE(0)) {
 		err = -EINVAL;
@@ -3439,8 +3531,9 @@ static unsigned int selinux_ip_postroute
 	if (err)
 		goto out;
 
-	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
-		struct inode_security_struct);
+	isec = security_get_value_type(inode->i_security, SELINUX_LSM_ID,
+		struct inode_security_struct,
+		selinux_secidx);
 	
 	switch (isec->sclass) {
 	case SECCLASS_UDP_SOCKET:
@@ -3546,8 +3639,9 @@ static int selinux_netlink_send(struct s
 	struct av_decision avd;
 	int err = 0;
 
-	tsec = security_get_value_type(&current->security,
-		SELINUX_LSM_ID, struct task_security_struct);
+	tsec = security_get_value_type(current->security,
+		SELINUX_LSM_ID, struct task_security_struct,
+		selinux_secidx);
 
 	avd.allowed = 0;
 	avc_has_perm_noaudit(tsec->sid, tsec->sid,
@@ -3567,8 +3661,9 @@ static int ipc_alloc_security(struct tas
 	struct task_security_struct *tsec;
 	struct ipc_security_struct *isec;
 
-	tsec = security_get_value_type(&task->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+	tsec = security_get_value_type(task->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
 
 	isec = kmalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
 	if (!isec)
@@ -3582,7 +3677,8 @@ static int ipc_alloc_security(struct tas
 	} else {
 		isec->sid = SECINITSID_UNLABELED;
 	}
-	security_set_value_type(&perm->security, SELINUX_LSM_ID, isec);
+	security_set_value_type(perm->security, SELINUX_LSM_ID, isec,
+		selinux_secidx);
 
 	return 0;
 }
@@ -3591,8 +3687,8 @@ static void ipc_free_security(struct ker
 {
 	struct ipc_security_struct *isec;
 	
-	isec = security_del_value_type(&perm->security, SELINUX_LSM_ID,
-		struct ipc_security_struct);
+	isec = security_del_value_type(perm->security, SELINUX_LSM_ID,
+		struct ipc_security_struct, selinux_secidx);
 
 	kfree(isec);
 }
@@ -3608,7 +3704,8 @@ static int msg_msg_alloc_security(struct
 	memset(msec, 0, sizeof(struct msg_security_struct));
 	msec->msg = msg;
 	msec->sid = SECINITSID_UNLABELED;
-	security_set_value_type(&msg->security, SELINUX_LSM_ID, msec);
+	security_set_value_type(msg->security, SELINUX_LSM_ID, msec,
+		selinux_secidx);
 
 	return 0;
 }
@@ -3617,8 +3714,9 @@ static void msg_msg_free_security(struct
 {
 	struct msg_security_struct *msec;
 	
-	msec = security_del_value_type(&msg->security, SELINUX_LSM_ID,
-		struct msg_security_struct);
+	msec = security_del_value_type(msg->security, SELINUX_LSM_ID,
+		struct msg_security_struct,
+			selinux_secidx);
 
 	kfree(msec);
 }
@@ -3630,10 +3728,12 @@ static int ipc_has_perm(struct kern_ipc_
 	struct ipc_security_struct *isec;
 	struct avc_audit_data ad;
 
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	isec = security_get_value_type(&ipc_perms->security, SELINUX_LSM_ID,
-		struct ipc_security_struct);
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	isec = security_get_value_type(ipc_perms->security, SELINUX_LSM_ID,
+		struct ipc_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
 	ad.u.ipc_id = ipc_perms->key;
@@ -3663,10 +3763,12 @@ static int selinux_msg_queue_alloc_secur
 	if (rc)
 		return rc;
 
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	isec = security_get_value_type(&msq->q_perm.security, SELINUX_LSM_ID,
-		struct ipc_security_struct);
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	isec = security_get_value_type(msq->q_perm.security, SELINUX_LSM_ID,
+		struct ipc_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
  	ad.u.ipc_id = msq->q_perm.key;
@@ -3691,10 +3793,12 @@ static int selinux_msg_queue_associate(s
 	struct ipc_security_struct *isec;
 	struct avc_audit_data ad;
 
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	isec = security_get_value_type(&msq->q_perm.security, SELINUX_LSM_ID,
-		struct ipc_security_struct);
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	isec = security_get_value_type(msq->q_perm.security, SELINUX_LSM_ID,
+		struct ipc_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
 	ad.u.ipc_id = msq->q_perm.key;
@@ -3739,12 +3843,15 @@ static int selinux_msg_queue_msgsnd(stru
 	struct avc_audit_data ad;
 	int rc;
 
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	isec = security_get_value_type(&msq->q_perm.security, SELINUX_LSM_ID,
-		struct ipc_security_struct);
-	msec = security_get_value_type(&msg->security, SELINUX_LSM_ID,
-		struct msg_security_struct);
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	isec = security_get_value_type(msq->q_perm.security, SELINUX_LSM_ID,
+		struct ipc_security_struct,
+		selinux_secidx);
+	msec = security_get_value_type(msg->security, SELINUX_LSM_ID,
+		struct msg_security_struct,
+		selinux_secidx);
 
 	/*
 	 * First time through, need to assign label to the message
@@ -3790,12 +3897,15 @@ static int selinux_msg_queue_msgrcv(stru
 	struct avc_audit_data ad;
 	int rc;
 
-	tsec = security_get_value_type(&target->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	isec = security_get_value_type(&msq->q_perm.security, SELINUX_LSM_ID,
-		struct ipc_security_struct);
-	msec = security_get_value_type(&msg->security, SELINUX_LSM_ID,
-		struct msg_security_struct);
+	tsec = security_get_value_type(target->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	isec = security_get_value_type(msq->q_perm.security, SELINUX_LSM_ID,
+		struct ipc_security_struct,
+		selinux_secidx);
+	msec = security_get_value_type(msg->security, SELINUX_LSM_ID,
+		struct msg_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
  	ad.u.ipc_id = msq->q_perm.key;
@@ -3820,10 +3930,12 @@ static int selinux_shm_alloc_security(st
 	if (rc)
 		return rc;
 
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	isec = security_get_value_type(&shp->shm_perm.security, SELINUX_LSM_ID,
-		struct ipc_security_struct);
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	isec = security_get_value_type(shp->shm_perm.security, SELINUX_LSM_ID,
+		struct ipc_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
  	ad.u.ipc_id = shp->shm_perm.key;
@@ -3848,10 +3960,12 @@ static int selinux_shm_associate(struct 
 	struct ipc_security_struct *isec;
 	struct avc_audit_data ad;
 
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	isec = security_get_value_type(&shp->shm_perm.security, SELINUX_LSM_ID,
-		struct ipc_security_struct);
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	isec = security_get_value_type(shp->shm_perm.security, SELINUX_LSM_ID,
+		struct ipc_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
 	ad.u.ipc_id = shp->shm_perm.key;
@@ -3918,10 +4032,12 @@ static int selinux_sem_alloc_security(st
 	if (rc)
 		return rc;
 
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	isec = security_get_value_type(&sma->sem_perm.security, SELINUX_LSM_ID,
-		struct ipc_security_struct);
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	isec = security_get_value_type(sma->sem_perm.security, SELINUX_LSM_ID,
+		struct ipc_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
  	ad.u.ipc_id = sma->sem_perm.key;
@@ -3946,10 +4062,12 @@ static int selinux_sem_associate(struct 
 	struct ipc_security_struct *isec;
 	struct avc_audit_data ad;
 
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
-	isec = security_get_value_type(&sma->sem_perm.security, SELINUX_LSM_ID,
-		struct ipc_security_struct);
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
+	isec = security_get_value_type(sma->sem_perm.security, SELINUX_LSM_ID,
+		struct ipc_security_struct,
+		selinux_secidx);
 
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
 	ad.u.ipc_id = sma->sem_perm.key;
@@ -4063,8 +4181,9 @@ static int selinux_getprocattr(struct ta
 	if (!size)
 		return -ERANGE;
 
-	tsec = security_get_value_type(&p->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+	tsec = security_get_value_type(p->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
 
 	if (!strcmp(name, "current"))
 		sid = tsec->sid;
@@ -4139,8 +4258,9 @@ static int selinux_setprocattr(struct ta
 	   operation.  See selinux_bprm_set_security for the execve
 	   checks and may_create for the file creation checks. The
 	   operation will then fail if the context is not permitted. */
-	tsec = security_get_value_type(&p->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+	tsec = security_get_value_type(p->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
 	if (!strcmp(name, "exec"))
 		tsec->exec_sid = sid;
 	else if (!strcmp(name, "fscreate"))
@@ -4358,14 +4478,16 @@ static __init int selinux_init(void)
 	/* Set the security state for the initial task. */
 	if (task_alloc_security(current))
 		panic("SELinux:  Failed to initialize initial task.\n");
-	tsec = security_get_value_type(&current->security, SELINUX_LSM_ID,
-		struct task_security_struct);
+	tsec = security_get_value_type(current->security, SELINUX_LSM_ID,
+		struct task_security_struct,
+		selinux_secidx);
 	tsec->osid = tsec->sid = SECINITSID_KERNEL;
 
 	avc_init();
 
-	if (register_security (&selinux_ops)) {
-		if (mod_reg_security( MY_NAME, &selinux_ops)) {
+	selinux_secidx = 1;
+	if (register_security (&selinux_ops, &selinux_secidx)) {
+		if (mod_reg_security( MY_NAME, &selinux_ops, &selinux_secidx)) {
 			printk(KERN_ERR "%s: Failed to register with primary LSM.\n",
 				__FUNCTION__);
 			panic("SELinux: Unable to register with kernel.\n");
@@ -4375,6 +4497,7 @@ static __init int selinux_init(void)
 		}
 		secondary = 1;
 	}
+	printk(KERN_NOTICE "got selinux_secidx %d\n", selinux_secidx);
 
 	if (selinux_enforcing) {
 		printk(KERN_INFO "SELinux:  Starting in enforcing mode\n");
Index: linux-2.6.13-rc4/security/selinux/selinuxfs.c
===================================================================
--- linux-2.6.13-rc4.orig/security/selinux/selinuxfs.c	2005-08-01 20:00:51.000000000 -0500
+++ linux-2.6.13-rc4/security/selinux/selinuxfs.c	2005-08-05 22:00:36.000000000 -0500
@@ -35,6 +35,8 @@
 #include "objsec.h"
 #include "conditional.h"
 
+extern int selinux_secidx;
+
 unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
 
 static int __init checkreqprot_setup(char *str)
@@ -60,8 +62,9 @@ static int task_has_security(struct task
 {
 	struct task_security_struct *tsec;
 
-	tsec = security_get_value_type(&tsk->security, SELINUX_LSM_ID,
-			struct task_security_struct);
+	tsec = security_get_value_type(tsk->security, SELINUX_LSM_ID,
+			struct task_security_struct,
+			selinux_secidx);
 	if (!tsec)
 		return -EACCES;
 
@@ -984,8 +987,9 @@ static int sel_make_bools(void)
 			ret = -ENAMETOOLONG;
 			goto err;
 		}
-		isec = security_get_value_type(&inode->i_security,
-				SELINUX_LSM_ID, struct inode_security_struct);
+		isec = security_get_value_type(inode->i_security,
+				SELINUX_LSM_ID, struct inode_security_struct,
+				selinux_secidx);
 		if ((ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid)))
 			goto err;
 		isec->sid = sid;
@@ -1270,8 +1274,9 @@ static int sel_fill_super(struct super_b
 	inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO);
 	if (!inode)
 		goto out;
-	isec = security_get_value_type(&inode->i_security, SELINUX_LSM_ID,
-			struct inode_security_struct);
+	isec = security_get_value_type(inode->i_security, SELINUX_LSM_ID,
+			struct inode_security_struct,
+			selinux_secidx);
 	isec->sid = SECINITSID_DEVNULL;
 	isec->sclass = SECCLASS_CHR_FILE;
 	isec->initialized = 1;
Index: linux-2.6.13-rc4/security/seclvl.c
===================================================================
--- linux-2.6.13-rc4.orig/security/seclvl.c	2005-08-01 20:00:51.000000000 -0500
+++ linux-2.6.13-rc4/security/seclvl.c	2005-08-05 22:00:00.000000000 -0500
@@ -38,6 +38,8 @@
 #define SHA1_DIGEST_SIZE 20
 #define SECLVL_LSM_ID 0xF45
 
+static int seclvl_secidx;
+
 /**
  * Module parameter that defines the initial secure level.
  *
@@ -505,8 +507,8 @@ static void seclvl_inode_free(struct ino
 {
 	struct seclvl_i_sec *isec;
 
-	isec = security_del_value_type(&inode->i_security, SECLVL_LSM_ID,
-				struct seclvl_i_sec);
+	isec = security_del_value_type(inode->i_security, SECLVL_LSM_ID,
+				struct seclvl_i_sec, seclvl_secidx);
 	if (isec) {
 		spin_lock(&seclvl_ichain_lock);
 		list_del(&isec->chain);
@@ -545,8 +547,9 @@ static void seclvl_bd_release(struct ino
 	struct seclvl_i_sec *isec;
 
 	if (inode && S_ISBLK(inode->i_mode)) {
-		isec = security_get_value_type(&inode->i_security,
-				SECLVL_LSM_ID, struct seclvl_i_sec);
+		isec = security_get_value_type(inode->i_security,
+				SECLVL_LSM_ID, struct seclvl_i_sec,
+				seclvl_secidx);
 		if (!isec)
 			return;
 		spin_lock(&isec->spinlock);
@@ -573,13 +576,13 @@ seclvl_inode_get_or_alloc(struct inode *
 {
 	struct seclvl_i_sec *isec;
 
-	isec = security_get_value_type(&inode->i_security,
-			SECLVL_LSM_ID, struct seclvl_i_sec);
+	isec = security_get_value_type(inode->i_security,
+			SECLVL_LSM_ID, struct seclvl_i_sec, seclvl_secidx);
 	if (isec)
 		return isec;
 	spin_lock(&seclvl_ichain_lock);
-	isec = security_get_value_type(&inode->i_security,
-			SECLVL_LSM_ID, struct seclvl_i_sec);
+	isec = security_get_value_type(inode->i_security,
+			SECLVL_LSM_ID, struct seclvl_i_sec, seclvl_secidx);
 	if (isec)
 		goto out;
 	isec = kmalloc(sizeof(struct seclvl_i_sec), GFP_KERNEL);
@@ -588,7 +591,8 @@ seclvl_inode_get_or_alloc(struct inode *
 	spin_lock_init(&isec->spinlock);
 	INIT_LIST_HEAD(&isec->chain);
 	list_add(&isec->chain, &seclvl_ichain);
-	security_add_value_type(&inode->i_security, SECLVL_LSM_ID, isec);
+	security_add_value_type(inode->i_security, SECLVL_LSM_ID, isec,
+				seclvl_secidx);
 
 out:
 	spin_unlock(&seclvl_ichain_lock);
@@ -781,12 +785,13 @@ static int __init seclvl_init(void)
 		goto exit;
 	}
 	/* register ourselves with the security framework */
-	if (register_security(&seclvl_ops)) {
+	seclvl_secidx = 1;  /* yes we want to use a security field */
+	if (register_security(&seclvl_ops, &seclvl_secidx)) {
 		seclvl_printk(0, KERN_ERR,
 			      "seclvl: Failure registering with the "
 			      "kernel.\n");
 		/* try registering with primary module */
-		rc = mod_reg_security(MY_NAME, &seclvl_ops);
+		rc = mod_reg_security(MY_NAME, &seclvl_ops, &seclvl_secidx);
 		if (rc) {
 			seclvl_printk(0, KERN_ERR, "seclvl: Failure "
 				      "registering with primary security "
@@ -795,6 +800,7 @@ static int __init seclvl_init(void)
 		}		/* if primary module registered */
 		secondary = 1;
 	}			/* if we registered ourselves with the security framework */
+	printk(KERN_NOTICE "got seclvl_secidx %d\n", seclvl_secidx);
 	if ((rc = doSysfsRegistrations())) {
 		seclvl_printk(0, KERN_ERR, "Error registering with sysfs\n");
 		goto exit;
@@ -821,7 +827,7 @@ static void free_ichain(void)
 	struct seclvl_i_sec *isec, *n;
 
 	list_for_each_entry_safe(isec, n, &seclvl_ichain, chain) {
-		security_unlink_value(&isec->lsm_list.list);
+		security_unlink_value(&isec->lsm_list.list, seclvl_secidx);
 	}
 
 	synchronize_rcu();
Index: linux-2.6.13-rc4/security/capability.c
===================================================================
--- linux-2.6.13-rc4.orig/security/capability.c	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.13-rc4/security/capability.c	2005-08-01 21:02:39.000000000 -0500
@@ -66,9 +66,9 @@ static int __init capability_init (void)
 		return 0;
 	}
 	/* register ourselves with the security framework */
-	if (register_security (&capability_ops)) {
+	if (register_security (&capability_ops, NULL)) {
 		/* try registering with primary module */
-		if (mod_reg_security (MY_NAME, &capability_ops)) {
+		if (mod_reg_security (MY_NAME, &capability_ops, NULL)) {
 			printk (KERN_INFO "Failure registering capabilities "
 				"with primary security module.\n");
 			return -EINVAL;
Index: linux-2.6.13-rc4/security/root_plug.c
===================================================================
--- linux-2.6.13-rc4.orig/security/root_plug.c	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.13-rc4/security/root_plug.c	2005-08-01 21:02:39.000000000 -0500
@@ -104,11 +104,11 @@ static struct security_operations rootpl
 static int __init rootplug_init (void)
 {
 	/* register ourselves with the security framework */
-	if (register_security (&rootplug_security_ops)) {
+	if (register_security (&rootplug_security_ops, NULL)) {
 		printk (KERN_INFO 
 			"Failure registering Root Plug module with the kernel\n");
 		/* try registering with primary module */
-		if (mod_reg_security (MY_NAME, &rootplug_security_ops)) {
+		if (mod_reg_security (MY_NAME, &rootplug_security_ops, NULL)) {
 			printk (KERN_INFO "Failure registering Root Plug "
 				" module with primary security module.\n");
 			return -EINVAL;
Index: linux-2.6.13-rc4/security/cap_stack.c
===================================================================
--- linux-2.6.13-rc4.orig/security/cap_stack.c	2005-08-01 20:00:51.000000000 -0500
+++ linux-2.6.13-rc4/security/cap_stack.c	2005-08-01 21:02:39.000000000 -0500
@@ -62,9 +62,9 @@ static int __init capability_init (void)
 		return 0;
 	}
 	/* register ourselves with the security framework */
-	if (register_security (&capability_ops)) {
+	if (register_security (&capability_ops, NULL)) {
 		/* try registering with primary module */
-		if (mod_reg_security (MY_NAME, &capability_ops)) {
+		if (mod_reg_security (MY_NAME, &capability_ops, NULL)) {
 			printk (KERN_INFO "Failure registering capabilities "
 				"with primary security module.\n");
 			return -EINVAL;
Index: linux-2.6.13-rc4/security/stacker.c
===================================================================
--- linux-2.6.13-rc4.orig/security/stacker.c	2005-08-01 20:00:51.000000000 -0500
+++ linux-2.6.13-rc4/security/stacker.c	2005-08-06 21:28:05.000000000 -0500
@@ -314,9 +314,11 @@ static int stacker_bprm_alloc_security (
 
 static void stacker_bprm_free_security (struct linux_binprm *bprm)
 {
+	struct hlist_head *h;
 	FREE_ALL(bprm_free_security,bprm_free_security(bprm));
-	if (unlikely(!hlist_empty(&bprm->security)))
-		security_disown_value(&bprm->security);
+	h = (struct hlist_head *)&bprm->security[sec_shared_slot];
+	if (unlikely(!hlist_empty(h)))
+		security_disown_value(h);
 }
 
 static void stacker_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
@@ -351,9 +353,11 @@ static int stacker_sb_alloc_security (st
 
 static void stacker_sb_free_security (struct super_block *sb)
 {
+	struct hlist_head *h;
 	FREE_ALL(sb_free_security,sb_free_security(sb));
-	if (unlikely(!hlist_empty(&sb->s_security)))
-		security_disown_value(&sb->s_security);
+	h = (struct hlist_head *)&sb->s_security[sec_shared_slot];
+	if (unlikely(!hlist_empty(h)))
+		security_disown_value(h);
 }
 
 static int stacker_sb_copy_data (struct file_system_type *type,
@@ -432,9 +436,11 @@ static int stacker_inode_alloc_security 
 
 static void stacker_inode_free_security (struct inode *inode)
 {
+	struct hlist_head *h;
 	FREE_ALL(inode_free_security,inode_free_security(inode));
-	if (unlikely(!hlist_empty(&inode->i_security)))
-		security_disown_value(&inode->i_security);
+	h = (struct hlist_head *)&inode->i_security[sec_shared_slot];
+	if (unlikely(!hlist_empty(h)))
+		security_disown_value(h);
 }
 
 static int stacker_inode_create (struct inode *inode, struct dentry *dentry,
@@ -684,9 +690,11 @@ static int stacker_file_alloc_security (
 
 static void stacker_file_free_security (struct file *file)
 {
+	struct hlist_head *h;
 	FREE_ALL(file_free_security,file_free_security(file));
-	if (unlikely(!hlist_empty(&file->f_security)))
-		security_disown_value(&file->f_security);
+	h = (struct hlist_head *)&file->f_security[sec_shared_slot];
+	if (unlikely(!hlist_empty(h)))
+		security_disown_value(h);
 }
 
 static int stacker_file_ioctl (struct file *file, unsigned int command,
@@ -746,9 +754,11 @@ static int stacker_task_alloc_security (
 
 static void stacker_task_free_security (struct task_struct *p)
 {
+	struct hlist_head *h;
 	FREE_ALL(task_free_security,task_free_security(p));
-	if (unlikely(!hlist_empty(&p->security)))
-		security_disown_value(&p->security);
+	h = (struct hlist_head *)&p->security[sec_shared_slot];
+	if (unlikely(!hlist_empty(h)))
+		security_disown_value(h);
 }
 
 static int stacker_task_setuid (uid_t id0, uid_t id1, uid_t id2, int flags)
@@ -945,9 +955,11 @@ static int stacker_sk_alloc_security(str
 
 static void stacker_sk_free_security (struct sock *sk)
 {
+	struct hlist_head *h;
 	FREE_ALL(sk_free_security,sk_free_security(sk));
-	if (unlikely(!hlist_empty(&sk->sk_security)))
-		security_disown_value(&sk->sk_security);
+	h = (struct hlist_head *)&sk->sk_security[sec_shared_slot];
+	if (unlikely(!hlist_empty(h)))
+		security_disown_value(h);
 }
 
 #endif
@@ -964,9 +976,11 @@ static int stacker_msg_msg_alloc_securit
 
 static void stacker_msg_msg_free_security (struct msg_msg *msg)
 {
+	struct hlist_head *h;
 	FREE_ALL(msg_msg_free_security,msg_msg_free_security(msg));
-	if (unlikely(!hlist_empty(&msg->security)))
-		security_disown_value(&msg->security);
+	h = (struct hlist_head *)&msg->security[sec_shared_slot];
+	if (unlikely(!hlist_empty(h)))
+		security_disown_value(h);
 }
 
 static int stacker_msg_queue_alloc_security (struct msg_queue *msq)
@@ -976,9 +990,11 @@ static int stacker_msg_queue_alloc_secur
 
 static void stacker_msg_queue_free_security (struct msg_queue *msq)
 {
+	struct hlist_head *h;
 	FREE_ALL(msg_queue_free_security,msg_queue_free_security(msq));
-	if (unlikely(!hlist_empty(&msq->q_perm.security)))
-		security_disown_value(&msq->q_perm.security);
+	h = (struct hlist_head *)&msq->q_perm.security[sec_shared_slot];
+	if (unlikely(!hlist_empty(h)))
+		security_disown_value(h);
 }
 
 static int stacker_msg_queue_associate (struct msg_queue *msq, int msqflg)
@@ -1011,9 +1027,11 @@ static int stacker_shm_alloc_security (s
 
 static void stacker_shm_free_security (struct shmid_kernel *shp)
 {
+	struct hlist_head *h;
 	FREE_ALL(shm_free_security,shm_free_security(shp));
-	if (unlikely(!hlist_empty(&shp->shm_perm.security)))
-		security_disown_value(&shp->shm_perm.security);
+	h = (struct hlist_head *)&shp->shm_perm.security[sec_shared_slot];
+	if (unlikely(!hlist_empty(h)))
+		security_disown_value(h);
 }
 
 static int stacker_shm_associate (struct shmid_kernel *shp, int shmflg)
@@ -1039,9 +1057,11 @@ static int stacker_sem_alloc_security (s
 
 static void stacker_sem_free_security (struct sem_array *sma)
 {
+	struct hlist_head *h;
 	FREE_ALL(sem_free_security,sem_free_security(sma));
-	if (unlikely(!hlist_empty(&sma->sem_perm.security)))
-		security_disown_value(&sma->sem_perm.security);
+	h = (struct hlist_head *)&sma->sem_perm.security[sec_shared_slot];
+	if (unlikely(!hlist_empty(h)))
+		security_disown_value(h);
 }
 
 static int stacker_sem_associate (struct sem_array *sma, int semflg)
@@ -1629,7 +1649,7 @@ static int __init stacker_init (void)
 	INIT_LIST_HEAD(&default_module.lsm_list);
 	list_add_tail(&default_module.lsm_list, &stacked_modules);
 
-	if (register_security (&stacker_ops)) {
+	if (register_security (&stacker_ops, NULL)) {
 		/*
 		 * stacking stacker is just a stupid idea, so don't ask
 		 * the current module to load us.
Index: linux-2.6.13-rc4/include/linux/security-stack.h
===================================================================
--- linux-2.6.13-rc4.orig/include/linux/security-stack.h	2005-08-01 20:00:51.000000000 -0500
+++ linux-2.6.13-rc4/include/linux/security-stack.h	2005-08-05 22:08:41.000000000 -0500
@@ -10,16 +10,12 @@
  */
 
 extern fastcall struct security_list *security_get_value(
-			struct hlist_head *head,
-			int security_id);
+			void **sec, int security_id);
 
 extern fastcall struct security_list *security_set_value(
-			struct hlist_head *head,
-			int security_id, struct security_list *obj_node);
+			void **sec, int security_id, struct security_list *obj_node);
 extern fastcall struct security_list *security_add_value(
-			struct hlist_head *head,
-			int security_id, struct security_list *obj_node);
-extern int security_unlink_value(struct hlist_node *n);
+			void **sec, int security_id, struct security_list *obj_node);
+extern int security_unlink_value(struct hlist_node *n, int idx);
 extern fastcall struct security_list *security_del_value(
-			struct hlist_head *head,
-			int security_id);
+			void **sec, int security_id);
Index: linux-2.6.13-rc4/fs/compat.c
===================================================================
--- linux-2.6.13-rc4.orig/fs/compat.c	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.13-rc4/fs/compat.c	2005-08-06 01:43:55.000000000 -0500
@@ -51,6 +51,8 @@
 #include <asm/mmu_context.h>
 #include <asm/ioctls.h>
 
+extern int sec_shared_slot;
+
 /*
  * Not all architectures have sys_utime, so implement this in terms
  * of sys_utimes.
@@ -1523,7 +1525,7 @@ int compat_do_execve(char * filename,
 	bprm->file = file;
 	bprm->filename = filename;
 	bprm->interp = filename;
-	INIT_HLIST_HEAD(&bprm->security);
+	INIT_HLIST_HEAD((struct hlist_head *)&(bprm->security[sec_shared_slot]));
 	bprm->mm = mm_alloc();
 	retval = -ENOMEM;
 	if (!bprm->mm)
Index: linux-2.6.13-rc4/fs/exec.c
===================================================================
--- linux-2.6.13-rc4.orig/fs/exec.c	2005-08-01 20:00:50.000000000 -0500
+++ linux-2.6.13-rc4/fs/exec.c	2005-08-06 01:44:02.000000000 -0500
@@ -1166,7 +1166,7 @@ int do_execve(char * filename,
 	bprm->file = file;
 	bprm->filename = filename;
 	bprm->interp = filename;
-	INIT_HLIST_HEAD(&bprm->security);
+	INIT_HLIST_HEAD((struct hlist_head *)&(bprm->security[sec_shared_slot]));
 	bprm->mm = mm_alloc();
 	retval = -ENOMEM;
 	if (!bprm->mm)

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH] Stacker - single-use static slots
  2005-08-10 14:45         ` serue
@ 2005-08-11  7:42           ` James Morris
  2005-08-11 21:22             ` serue
  0 siblings, 1 reply; 39+ messages in thread
From: James Morris @ 2005-08-11  7:42 UTC (permalink / raw)
  To: serue; +Cc: lkml, Chris Wright, Stephen Smalley, Andrew Morton

On Wed, 10 Aug 2005, serue@us.ibm.com wrote:

> those annoying cache effects, I assume - 3 slots (the default)
> outperforms two slots, even though only one slot is being used.  These
> tests were run on a 16-way power4+ system.  I may try to re-run on some
> x86 hardware, though each run will probably take 24 hours.

I've also run some benchmarks, comparing vanilla kernel with the 
two stacker approaches.  Results below.

Results seem to be mixed, sometimes a bit better, sometimes a bit worse.  
The macro benchmarks tend to show better figures for the static slot 
model.

Overall, it seems that SELinux could expect to take a 1-2% performance hit 
with the stacker.

==============================================================================
Performance testing summary using the stacker patches, 11 Aug 2005.

Test system:
  8-way 900Mhz PIII Xeon, 4GB RAM, FC4, current updates.
  
Test data was managed on an ext2 filesystem, using targeted policy.
Kernel version 2.6.13-rc4.

The kernel was configured as follows:

 control
    Standard kernel with SELinux and secondarily stacked capabilities.

 stacker_dynamic
   Stacker with fully dynamic security fields, SELinux + caps.

 stacker_static 
   Stacker with three static slots for security fields, SELinux + caps.


-----------------------------------------------------------------------------
Unixbench
-----------------------------------------------------------------------------

Six iterations.
Larger is better.

1) control

Execl Throughput                                43.0     1159.7      269.7
File Copy 1024 bufsize 2000 maxblocks         3960.0    93041.0      235.0
File Copy 256 bufsize 500 maxblocks           1655.0    44393.0      268.2
File Copy 4096 bufsize 8000 maxblocks         5800.0   129172.0      222.7
Pipe Throughput                              12440.0   217759.8      175.0
Process Creation                               126.0     5687.4      451.4
Shell Scripts (8 concurrent)                     6.0      750.9     1251.5
System Call Overhead                         15000.0   752195.3      501.5
                                                                 =========
     FINAL SCORE                                                     342.1


2) stacker_dynamic

Execl Throughput                                43.0     1163.8      270.7
File Copy 1024 bufsize 2000 maxblocks         3960.0    92321.0      233.1
File Copy 256 bufsize 500 maxblocks           1655.0    44309.0      267.7
File Copy 4096 bufsize 8000 maxblocks         5800.0   128635.0      221.8
Pipe Throughput                              12440.0   211583.8      170.1
Process Creation                               126.0     5657.9      449.0
Shell Scripts (8 concurrent)                     6.0      744.0     1240.0
System Call Overhead                         15000.0   759228.4      506.2
                                                                 =========
     FINAL SCORE                                                     340.2



3) stacker_static

Execl Throughput                                43.0     1159.6      269.7
File Copy 1024 bufsize 2000 maxblocks         3960.0    88455.0      223.4
File Copy 256 bufsize 500 maxblocks           1655.0    40165.0      242.7
File Copy 4096 bufsize 8000 maxblocks         5800.0   125384.0      216.2
Pipe Throughput                              12440.0   208970.6      168.0
Process Creation                               126.0     5712.9      453.4
Shell Scripts (8 concurrent)                     6.0      752.5     1254.2
System Call Overhead                         15000.0   746153.0      497.4
                                                                 =========
     FINAL SCORE                                                     332.7

-----------------------------------------------------------------------------
Apachebench
-----------------------------------------------------------------------------

Local webserver, logging to /dev/null.
100k requests of a 100k file.

---------------------------------------------------------
#clients                 1         2         4         8
---------------------------------------------------------
control         : 15627.93  18715.48  20377.54  21543.10
stacker_dynamic : 15371.80  18049.45  20281.98  21037.24
stacker_static  : 15247.48  18395.96  20579.46  21523.41
---------------------------------------------------------


----------------------------------------------------------------------------
dbench
-----------------------------------------------------------------------------

300s tests incl. 60s of warmup.
Throughput in MB/s.
Larger is better.

-----------------------------------------------------
# procs                 2        4        8       16
-----------------------------------------------------
control         : 200.264  351.135  514.327  483.085
stacker_dynamic : 192.805  336.097  511.713  474.047
stacker_static  : 197.254  333.781  510.713  471.581
-----------------------------------------------------


----------------------------------------------------------------------------
lmbench
-----------------------------------------------------------------------------

Processor, Processes - times in microseconds - smaller is better
------------------------------------------------------------------------------
Host                 OS  Mhz null null      open slct sig  sig  fork exec sh  
                             call  I/O stat clos TCP  inst hndl proc proc proc
--------- ------------- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
control   Linux 2.6.13-  900 0.24 0.85 5.29 6.83 23.6 1.01 3.98 215. 1054 3482
stack_dyn Linux 2.6.13-  900 0.24 0.91 5.72 7.17 23.6 1.01 4.25 211. 1046 3500
stack_sta Linux 2.6.13-  900 0.24 0.89 5.41 6.97 27.3 1.01 4.28 209. 1052 3450

Context switching - times in microseconds - smaller is better
-------------------------------------------------------------------------
Host                 OS  2p/0K 2p/16K 2p/64K 8p/16K 8p/64K 16p/16K 16p/64K
                         ctxsw  ctxsw  ctxsw ctxsw  ctxsw   ctxsw   ctxsw
--------- ------------- ------ ------ ------ ------ ------ ------- -------
control   Linux 2.6.13- 1.7800 5.3700 7.0500   12.0 6.1000 4.42000    11.6
stack_dyn Linux 2.6.13- 2.1100 3.9800 2.0400   10.2   12.5 8.44000    19.6
stack_sta Linux 2.6.13- 1.8800 4.2500 2.1700   10.2   20.5 9.56000    25.1

*Local* Communication latencies in microseconds - smaller is better
---------------------------------------------------------------------
Host                 OS 2p/0K  Pipe AF     UDP  RPC/   TCP  RPC/ TCP
                        ctxsw       UNIX         UDP         TCP conn
--------- ------------- ----- ----- ---- ----- ----- ----- ----- ----
control   Linux 2.6.13- 1.780  52.3 18.2 100.1  83.4 112.1  96.1 177.
stack_dyn Linux 2.6.13- 2.110  30.4 25.3 101.7  83.7 112.8  98.4 180.
stack_sta Linux 2.6.13- 1.880  52.5 20.6 102.6  84.2 112.7  97.1 180.

File & VM system latencies in microseconds - smaller is better
-------------------------------------------------------------------------------
Host                 OS   0K File      10K File     Mmap    Prot   Page   100fd
                        Create Delete Create Delete Latency Fault  Fault  selct
--------- ------------- ------ ------ ------ ------ ------- ----- ------- -----
control   Linux 2.6.13-   42.4   18.1   79.6   33.4  4066.0 0.341 2.73660  20.8
stack_dyn Linux 2.6.13-   44.2   18.5   77.7   34.2  4064.0 0.217 2.73910  18.5
stack_sta Linux 2.6.13-   44.2   18.4   77.6   34.5  4072.0 0.201 2.76820  18.4

*Local* Communication bandwidths in MB/s - bigger is better
-----------------------------------------------------------------------------
Host                OS  Pipe AF    TCP  File   Mmap  Bcopy  Bcopy  Mem   Mem
                             UNIX      reread reread (libc) (hand) read write
--------- ------------- ---- ---- ---- ------ ------ ------ ------ ---- -----
control   Linux 2.6.13- 105. 163. 106.  228.3  256.7  133.4  130.0 256. 201.4
stack_dyn Linux 2.6.13- 207. 295. 170.  228.1  256.7  133.7  130.2 257. 201.1
stack_sta Linux 2.6.13- 107. 162. 106.  227.6  256.6  133.4  130.4 257. 201.6


==============================================================================



^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH] Stacker - single-use static slots
  2005-08-11  7:42           ` James Morris
@ 2005-08-11 21:22             ` serue
  2005-08-11 23:02               ` James Morris
  0 siblings, 1 reply; 39+ messages in thread
From: serue @ 2005-08-11 21:22 UTC (permalink / raw)
  To: James Morris; +Cc: serue, lkml, Chris Wright, Stephen Smalley, Andrew Morton

Quoting James Morris (jmorris@namei.org):
> On Wed, 10 Aug 2005, serue@us.ibm.com wrote:
> 
> > those annoying cache effects, I assume - 3 slots (the default)
> > outperforms two slots, even though only one slot is being used.  These
> > tests were run on a 16-way power4+ system.  I may try to re-run on some
> > x86 hardware, though each run will probably take 24 hours.
> 
> I've also run some benchmarks, comparing vanilla kernel with the 
> two stacker approaches.  Results below.
> 
> Results seem to be mixed, sometimes a bit better, sometimes a bit worse.  
> The macro benchmarks tend to show better figures for the static slot 
> model.
> 
> Overall, it seems that SELinux could expect to take a 1-2% performance hit 
> with the stacker.

Thanks, James.

I guess I should do some profiling runs - I'm surprised there would be
this much of a hit with the static slots.

thanks,
-serge

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH] Stacker - single-use static slots
  2005-08-11 21:22             ` serue
@ 2005-08-11 23:02               ` James Morris
  0 siblings, 0 replies; 39+ messages in thread
From: James Morris @ 2005-08-11 23:02 UTC (permalink / raw)
  To: serue; +Cc: lkml, Chris Wright, Stephen Smalley, Andrew Morton

On Thu, 11 Aug 2005, serue@us.ibm.com wrote:

> I guess I should do some profiling runs - I'm surprised there would be
> this much of a hit with the static slots.

Yes.  It could be some cache effect, where the exact placement of the 
SELinux pointer might be critical, and also vary depending on the hook and 
subclass of SELinux security struct.

- James
-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 39+ messages in thread

end of thread, other threads:[~2005-08-11 23:02 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-07-27 18:17 [patch 0/15] lsm stacking v0.3: intro serue
2005-07-27 18:19 ` [patch 1/15] lsm stacking v0.3: introduce securityfs serue
2005-07-27 18:20   ` [patch 2/15] lsm stacking v0.3: add module * to security_ops serue
2005-07-27 18:21   ` [patch 3/15] lsm stacking v0.3: don't default to dummy_##hook serue
2005-07-27 18:23   ` [patch 4/15] lsm stacking v0.3: swith ->security to hlist serue
2005-07-27 18:24   ` [patch 5/15] lsm stacking v0.3: introduce security_*_value API serue
2005-07-27 18:24   ` [patch 6/15] lsm stacking v0.3: stacker documentation serue
2005-07-27 18:24   ` [patch 7/15] lsm stacking v0.3: actual stacker module serue
2005-07-27 18:25   ` [patch 8/15] lsm stacking v0.3: stackable capabilities lsm serue
2005-07-27 18:26   ` [patch 9/15] lsm stacking v0.3: selinux: update ->security structs serue
2005-07-27 18:26   ` [patch 10/15] lsm stacking v0.3: selinux: use security_*_value API serue
2005-07-27 18:27   ` [patch 11/15] lsm stacking v0.3: selinux: remove secondary support serue
2005-07-27 18:27   ` [patch 12/15] lsm stacking v0.3: hook completeness verification script serue
2005-07-27 18:28   ` [patch 13/15] lsm stacking v0.3: seclvl: update for stacking serue
2005-07-27 18:28   ` [patch 14/15] lsm stacking v0.3: fix security_{del,unlink}_value race serue
2005-07-27 18:28   ` [patch 15/15] lsm stacking v0.3: stacking for digsig serue
2005-07-27 19:34 ` [patch 0/15] lsm stacking v0.3: intro James Morris
2005-07-27 19:37   ` James Morris
2005-08-03 16:45     ` [PATCH] Stacker - single-use static slots serue
2005-08-03 17:57       ` Chris Wright
2005-08-03 19:27         ` serue
2005-08-03 19:45           ` Chris Wright
2005-08-03 20:31             ` serge
2005-08-05 15:55       ` James Morris
2005-08-05 17:27         ` serue
2005-08-05 17:34           ` serue
2005-08-10 14:45         ` serue
2005-08-11  7:42           ` James Morris
2005-08-11 21:22             ` serue
2005-08-11 23:02               ` James Morris
2005-07-27 19:54   ` [patch 0/15] lsm stacking v0.3: intro serue
2005-07-30  5:07 ` Tony Jones
2005-07-30 19:02   ` serge
2005-07-30 20:18     ` Tony Jones
2005-07-31  3:22       ` Steve Beattie
2005-07-31  3:44         ` serge
2005-07-31  4:13           ` Tony Jones
2005-07-31 13:37             ` serge
2005-07-31  3:53       ` serge

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox