* [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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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(¤t->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