| From: |
| Serge Hallyn <serue@us.ibm.com> |
| To: |
| Chris Wright <chrisw@osdl.org>,
Stephen Smalley <sds@epoch.ncsc.mil>,
James Morris <jmorris@redhat.com> |
| Subject: |
| [RFC] [Stacking v4 3/3] Cleaned up stacker patch |
| Date: |
| Fri, 03 Dec 2004 12:04:02 -0600 |
| Cc: |
| LSM Mailing List <linux-security-module@wirex.com> |
| Archive-link: |
| Article,
Thread
|
Hi,
Attached is a cleaned up version of stacker.
Changes:
1. uses RCU to protect the list elements.
2. capable() now just uses RETURN_ERROR_IF_ANY_ERROR explicitly.
3. stacker exports lsm_adopt_next_secondary(char *name), which will
delegate stacking of the next loaded LSM to the module identified by
(name).
4. stacker doesn't touch the get/setprocattr functions. There's no
point messing with that unless/until userspace code can handle it, as
there's no clean way to handle all cases otherwise.
5. mod_unreg_security is removed. All modules use unregister_security
() regardless of whether they were loaded using register_security() or
mod_reg_security(). In this way, if capability() was escalated by
selinux from secondary to a primary module, it doesn't end up
unregistering the wrong way.
I attach lmbench results on a 700Mhz 4-way SMP box comparing a stock -
rc2-bk7 kernel with no stacking patches at all (nostack.lmbench), one
with the stacking patches applied (chain-newrcu.lmbench), and one with
roughly the same stacker.c, except rather than protect the list with
rcu, we do not free memory when a LSM is unloaded, so no RCU protection
in CALL_ALL and RETURN_ERROR_IF_ANY_ERROR.
thanks,
-serge
--
=======================================================
Serge Hallyn
Security Software Engineer, IBM Linux Technology Center
serue@us.ibm.com
Index: linux-2.6.9/Documentation/stacker.txt
===================================================================
--- linux-2.6.9.orig/Documentation/stacker.txt 2004-12-02 12:15:35.390617408
-0600
+++ linux-2.6.9/Documentation/stacker.txt 2004-12-01 11:00:48.000000000 -0600
@@ -0,0 +1,54 @@
+------------
+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 it's sysfs interface, located
+under /sys/stacker/. This consists of the following files:
+
+/sys/stacker/next_secondary:
+In some cases, pairs or sets of LSMs may work together in subtle ways.
+For instance, SELinux and the capabilities modules interact such that
+it is better to have SELinux load the capabilities module as its own
+secondary. To accomplish this, you would
+ 1. compile stacker and selinux both into the kernel
+ 2. compile capabilities as a module.
+ 3. During init,
+ echo selinux > /sys/stacker/next_secondary
+ modprobe capability
+
+/sys/stacker/lockdown:
+Once you write to this file, you will no longer be able to load
+LSMs.
+
+/sys/stacker/list_modules:
+Reading this file will show which LSMs are being stacked. Note that
+LSMs which have been loaded as secondaries of stacked modules will
+not be shown. [ This could be done, but seems deceptive - SEH ]
+
+/sys/stacker/stop_responding:
+Unregisters the /sys/stacker directory, so that you can no longer
+interact with stacker.
+
+/sys/stacker/shortcircuit_restrictive:
+Toggle whether to query all security modules for permission to proceed
+with an action, regardless of whether an early module has denied
+permission. By default, all security modules will be queried, as
+they may need to update some state to reflect the attempted action,
+although an error will still be returned.
+
+---------------------------------------------
+Readying an LSM for stacking with other LSMs.
+---------------------------------------------
+
Index: linux-2.6.9/include/linux/security.h
===================================================================
--- linux-2.6.9.orig/include/linux/security.h 2004-12-01 11:00:43.000000000
-0600
+++ linux-2.6.9/include/linux/security.h 2004-12-01 11:00:48.000000000 -0600
@@ -1946,9 +1946,8 @@
/* prototypes */
extern int security_init (void);
extern int register_security (struct security_operations *ops);
-extern int unregister_security (struct security_operations *ops);
+extern int unregister_security (const char *name, 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);
#else /* CONFIG_SECURITY */
Index: linux-2.6.9/security/Kconfig
===================================================================
--- linux-2.6.9.orig/security/Kconfig 2004-12-01 11:00:11.000000000 -0600
+++ linux-2.6.9/security/Kconfig 2004-12-01 11:00:48.000000000 -0600
@@ -86,5 +86,20 @@
source security/selinux/Kconfig
+config SECURITY_STACKER
+ boolean "LSM Stacking"
+ depends on SECURITY
+ help
+ Stack multiple LSMs.
+
+config SECURITY_STACKER_SHORTCIRCUIT
+ int "Short circuit restrictive hooks by default."
+ range 0 1
+ default 1
+ depends on SECURITY_STACKER
+ help
+ If set, then security modules will be queried for a particular
+ restrictive hook only until a module denies permission.
+
endmenu
Index: linux-2.6.9/security/Makefile
===================================================================
--- linux-2.6.9.orig/security/Makefile 2004-12-01 11:00:11.000000000 -0600
+++ linux-2.6.9/security/Makefile 2004-12-01 11:00:48.000000000 -0600
@@ -2,6 +2,7 @@
# Makefile for the kernel security code
#
+obj-$(CONFIG_SECURITY_STACKER) += stacker.o
obj-$(CONFIG_KEYS) += keys/
subdir-$(CONFIG_SECURITY_SELINUX) += selinux
Index: linux-2.6.9/security/capability.c
===================================================================
--- linux-2.6.9.orig/security/capability.c 2004-12-01 11:00:11.000000000 -0600
+++ linux-2.6.9/security/capability.c 2004-12-01 11:00:48.000000000 -0600
@@ -83,15 +83,8 @@
{
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)) {
+ if (unregister_security (MY_NAME, &capability_ops)) {
printk (KERN_INFO
"Failure unregistering capabilities with the kernel\n");
}
Index: linux-2.6.9/security/root_plug.c
===================================================================
--- linux-2.6.9.orig/security/root_plug.c 2004-10-18 16:55:28.000000000 -0500
+++ linux-2.6.9/security/root_plug.c 2004-12-01 11:00:48.000000000 -0600
@@ -121,17 +121,10 @@
static void __exit rootplug_exit (void)
{
/* remove ourselves from the security framework */
- if (secondary) {
- if (mod_unreg_security (MY_NAME, &rootplug_security_ops))
- printk (KERN_INFO "Failure unregistering Root Plug "
- " module with primary module.\n");
- } else {
- if (unregister_security (&rootplug_security_ops)) {
- printk (KERN_INFO "Failure unregistering Root Plug "
- "module with the kernel\n");
- }
- }
- printk (KERN_INFO "Root Plug module removed\n");
+ if (unregister_security(MY_NAME, &rootplug_security_ops))
+ printk (KERN_INFO "Failure unregistering Root Plug\n");
+ else
+ printk (KERN_INFO "Root Plug module removed\n");
}
security_initcall (rootplug_init);
Index: linux-2.6.9/security/seclvl.c
===================================================================
--- linux-2.6.9.orig/security/seclvl.c 2004-12-01 11:00:44.000000000 -0600
+++ linux-2.6.9/security/seclvl.c 2004-12-01 14:06:10.000000000 -0600
@@ -758,13 +758,10 @@
&sysfs_attr_passwd.attr);
}
subsystem_unregister(&seclvl_subsys);
- if (secondary == 1) {
- mod_unreg_security(MY_NAME, &seclvl_ops);
- } else if (unregister_security(&seclvl_ops)) {
- seclvl_printk(0, KERN_INFO,
- "seclvl: Failure unregistering with the "
- "kernel\n");
- }
+ if (unregister_security(MY_NAME, &seclvl_ops))
+ seclvl_printk(0, KERN_INFO, "seclvl: failure unregistering.\n");
+ else
+ seclvl_printk(0, KERN_INFO, "seclvl unregistered.\n");
}
module_init(seclvl_init);
Index: linux-2.6.9/security/security.c
===================================================================
--- linux-2.6.9.orig/security/security.c 2004-12-01 11:00:43.000000000 -0600
+++ linux-2.6.9/security/security.c 2004-12-01 11:00:48.000000000 -0600
@@ -222,20 +222,13 @@
* @ops: a pointer to the struct security_options that is to be registered
*
* This function removes a struct security_operations variable that had
- * previously been registered with a successful call to register_security().
- *
- * If @ops does not match the valued previously passed to register_security()
- * an error is returned. Otherwise the default security options is set to
the
- * the dummy_security_ops structure, and 0 is returned.
+ * previously been registered with a successful call to register_security()
+ * or mod_reg_security().
*/
-int unregister_security(struct security_operations *ops)
+int unregister_security(const char *name, struct security_operations *ops)
{
- if (ops != security_ops) {
- printk(KERN_INFO "%s: trying to unregister "
- "a security_opts structure that is not "
- "registered, failing.\n", __FUNCTION__);
- return -EINVAL;
- }
+ if (ops != security_ops)
+ return security_ops->unregister_security(name, ops);
security_ops = &dummy_security_ops;
@@ -272,30 +265,6 @@
}
/**
- * mod_unreg_security - allows a security module registered with mod_reg_security() to be
unloaded
- * @name: a pointer to a string with the name of the security_options to be
removed
- * @ops: a pointer to the struct security_options that is to be removed
- *
- * This function allows security modules that have been successfully
registered
- * with a call to mod_reg_security() to be unloaded from the system.
- * This calls the currently loaded security module's unregister_security()
call
- * with the @name and @ops variables.
- *
- * The return value depends on the currently loaded security module, with 0
as
- * success.
- */
-int mod_unreg_security(const char *name, struct security_operations *ops)
-{
- if (ops == security_ops) {
- printk(KERN_INFO "%s invalid attempt to unregister "
- " primary security ops.\n", __FUNCTION__);
- return -EINVAL;
- }
-
- return security_ops->unregister_security(name, ops);
-}
-
-/**
* capable - calls the currently loaded security module's capable() function with the specified
capability
* @cap: the requested capability level.
*
@@ -320,6 +289,5 @@
EXPORT_SYMBOL_GPL(register_security);
EXPORT_SYMBOL_GPL(unregister_security);
EXPORT_SYMBOL_GPL(mod_reg_security);
-EXPORT_SYMBOL_GPL(mod_unreg_security);
EXPORT_SYMBOL(capable);
EXPORT_SYMBOL(security_ops);
Index: linux-2.6.9/security/selinux/hooks.c
===================================================================
--- linux-2.6.9.orig/security/selinux/hooks.c 2004-12-01 11:00:45.000000000
-0600
+++ linux-2.6.9/security/selinux/hooks.c 2004-12-01 11:00:48.000000000 -0600
@@ -4648,22 +4648,26 @@
selinux_disabled = 1;
- if (secondary) {
- if (mod_unreg_security(MY_NAME, &selinux_ops))
- printk(KERN_INFO "Failure unregistering selinux.\n");
+ if (unregister_security(MY_NAME, &selinux_ops))
+ printk(KERN_INFO "Failure unregistering selinux.\n");
+ else
+ printk(KERN_INFO "Unregistered selinux.\n");
+
+ if (secondary_ops) {
+ int ret;
+
+ if (secondary) {
+ ret = mod_reg_security(secondary_name, secondary_ops);
+ } else
+ ret = register_security(secondary_ops);
+
+ if (ret)
+ printk(KERN_INFO
+ "Failure re-registering secondary (%s).\n",
+ secondary_name);
else
- printk(KERN_INFO "Unregistered selinux.\n");
- secondary = 0;
- if (secondary_name)
- if (mod_reg_security(secondary_name, secondary_ops))
- printk(KERN_INFO "Failure registering secondary.\n");
- } else {
- if (unregister_security(&selinux_ops))
- printk(KERN_INFO "Failure unregistering selinux.\n");
- else
- printk(KERN_INFO "Unregistered selinux.\n");
- if (secondary_ops)
- register_security(secondary_ops);
+ printk(KERN_INFO "Re-registered secondary (%s).\n",
+ secondary_name);
}
/* Unregister netfilter hooks. */
Index: linux-2.6.9/security/stacker.c
===================================================================
--- linux-2.6.9.orig/security/stacker.c 2004-12-02 12:15:35.390617408 -0600
+++ linux-2.6.9/security/stacker.c 2004-12-03 11:38:52.969215280 -0600
@@ -0,0 +1,1546 @@
+/* "Stacker" Linux security module (LSM).
+ *
+ * version 2004-11-29
+ * Load this module first as the primary LSM module,
+ * and you can then stack (load) multiple additional LSM modules.
+ *
+ * Copyright (C) 2002,2003,2004 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/kobject.h>
+#include <linux/sysfs.h>
+#include <linux/netdevice.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/spinlock.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 stacked lsms */
+ char *module_name;
+ int namelen;
+ struct security_operations module_operations;
+ struct rcu_head m_rcu;
+ atomic_t use;
+};
+static struct list_head stacked_modules; /* list of stacked modules */
+
+static short sysfsfiles_registered;
+static int num_stacked_modules;
+
+static spinlock_t stacker_lock;
+static int short_circuit_restrictive; /* = 0; if 1, short-circuit
restrictive
+ hooks */
+static int forbid_stacker_register; /* = 0; if 1, can't register */
+
+
+/*
+ * Workarounds for the fact that get and setprocattr are used only by
+ * selinux. (Maybe)
+ */
+static struct module_entry *selinux_module;
+static struct module_entry *next_secondary;
+
+/* 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 inline void stacker_free_module(struct module_entry *m)
+{
+ kfree(m->module_name);
+ kfree(m);
+}
+
+/*
+ * Delete a module entry
+ */
+static void stacker_del_module(struct rcu_head *head)
+{
+ struct module_entry *m = container_of(head, struct module_entry,
+ m_rcu);
+ if (atomic_dec_and_test(&m->use))
+ stacker_free_module(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.
+ *
+ * If shortcircuit_restrictive is set, then we return as soon
+ * as an error is returned. Otherwise, we check all modules.
+ * This may be necessary if some modules have to update their
+ * state based on the permission request.
+ */
+
+#define RETURN_ERROR_IF_ANY_ERROR(BASE_FUNC,FUNC_WITH_ARGS) do { \
+ int final_result = 0; \
+ struct module_entry *m; \
+ rcu_read_lock(); \
+ list_for_each_entry_rcu(m, &stacked_modules, lsm_list) { \
+ int result = 0, stop = 0; \
+ atomic_inc(&m->use); \
+ rcu_read_unlock(); \
+ if (m->module_operations.BASE_FUNC) \
+ result = m->module_operations.FUNC_WITH_ARGS; \
+ if (result && !final_result) { \
+ final_result = result; \
+ if (short_circuit_restrictive) \
+ stop = 1; \
+ } \
+ rcu_read_lock(); \
+ if (unlikely(atomic_dec_and_test(&m->use))) \
+ stacker_free_module(m); \
+ if (stop) \
+ break; \
+ } \
+ rcu_read_unlock(); \
+ return final_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(); \
+ list_for_each_entry_rcu(m, &stacked_modules, lsm_list) { \
+ atomic_inc(&m->use); \
+ rcu_read_unlock(); \
+ if (m->module_operations.BASE_FUNC) \
+ m->module_operations.FUNC_WITH_ARGS; \
+ rcu_read_lock(); \
+ if (unlikely(atomic_dec_and_test(&m->use))) \
+ stacker_free_module(m); \
+ } \
+ rcu_read_unlock(); \
+} 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 file *f)
+{
+ RETURN_ERROR_IF_ANY_ERROR(quota_on,quota_on(f));
+}
+
+static int stacker_syslog (int type)
+{
+ RETURN_ERROR_IF_ANY_ERROR(syslog,syslog(type));
+}
+
+static int stacker_vm_enough_memory(long pages)
+{
+ RETURN_ERROR_IF_ANY_ERROR(vm_enough_memory,vm_enough_memory(pages));
+}
+
+static int stacker_netlink_send (struct sock *sk, struct sk_buff *skb)
+{
+ /* NOTE: The dummy module does this:
+ if (current->euid == 0)
+ cap_raise (NETLINK_CB (skb).eff_cap, CAP_NET_ADMIN);
+ else
+ NETLINK_CB (skb).eff_cap = 0;
+ * if this would be a problem with your module, then tell
+ * your administrators what to do. */
+
+ RETURN_ERROR_IF_ANY_ERROR(netlink_send,netlink_send(sk,skb));
+}
+
+
+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)
+{
+ RETURN_ERROR_IF_ANY_ERROR(bprm_alloc_security,bprm_alloc_security(bprm));
+}
+
+static void stacker_bprm_free_security (struct linux_binprm *bprm)
+{
+ CALL_ALL(bprm_free_security,bprm_free_security(bprm));
+}
+
+static void stacker_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
+{
+ CALL_ALL(bprm_apply_creds,bprm_apply_creds(bprm, unsafe));
+}
+
+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)
+{
+ RETURN_ERROR_IF_ANY_ERROR(sb_alloc_security,sb_alloc_security(sb));
+}
+
+static void stacker_sb_free_security (struct super_block *sb)
+{
+ CALL_ALL(sb_free_security,sb_free_security(sb));
+}
+
+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)
+{
+ RETURN_ERROR_IF_ANY_ERROR(inode_alloc_security,inode_alloc_security(inode));
+}
+
+static void stacker_inode_free_security (struct inode *inode)
+{
+ CALL_ALL(inode_free_security,inode_free_security(inode));
+}
+
+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));
+}
+
+static int stacker_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t
size)
+{
+ RETURN_ERROR_IF_ANY_ERROR(inode_getsecurity,inode_getsecurity(inode,name,buffer,size));
+}
+
+static int stacker_inode_setsecurity(struct inode *inode, const char *name, const void *value,
size_t size, int flags)
+{
+ RETURN_ERROR_IF_ANY_ERROR(inode_setsecurity,inode_setsecurity(inode,name,value,size,flags));
+}
+
+static int stacker_inode_listsecurity(struct inode *inode, char *buffer, size_t
buffer_size)
+{
+ RETURN_ERROR_IF_ANY_ERROR(inode_listsecurity,inode_listsecurity(inode,buffer,
buffer_size));
+}
+
+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)
+{
+ RETURN_ERROR_IF_ANY_ERROR(file_alloc_security,file_alloc_security(file));
+}
+
+static void stacker_file_free_security (struct file *file)
+{
+ CALL_ALL(file_free_security,file_free_security(file));
+}
+
+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 prot,
+ unsigned long flags)
+{
+ RETURN_ERROR_IF_ANY_ERROR(file_mmap,file_mmap(file, prot, flags));
+}
+
+static int stacker_file_mprotect (struct vm_area_struct *vma,
+ unsigned long prot)
+{
+ RETURN_ERROR_IF_ANY_ERROR(file_mprotect,file_mprotect(vma,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)
+{
+ RETURN_ERROR_IF_ANY_ERROR(task_alloc_security,task_alloc_security(p));
+}
+
+static void stacker_task_free_security (struct task_struct *p)
+{
+ CALL_ALL(task_free_security,task_free_security(p));
+}
+
+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)
+{
+ RETURN_ERROR_IF_ANY_ERROR(sk_alloc_security,sk_alloc_security(sk,family,priority));
+}
+
+static void stacker_sk_free_security (struct sock *sk)
+{
+ CALL_ALL(sk_free_security,sk_free_security(sk));
+}
+
+#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)
+{
+ RETURN_ERROR_IF_ANY_ERROR(msg_msg_alloc_security,msg_msg_alloc_security(msg));
+}
+
+static void stacker_msg_msg_free_security (struct msg_msg *msg)
+{
+ CALL_ALL(msg_msg_free_security,msg_msg_free_security(msg));
+}
+
+static int stacker_msg_queue_alloc_security (struct msg_queue *msq)
+{
+ RETURN_ERROR_IF_ANY_ERROR(msg_queue_alloc_security,msg_queue_alloc_security(msq));
+}
+
+static void stacker_msg_queue_free_security (struct msg_queue *msq)
+{
+ CALL_ALL(msg_queue_free_security,msg_queue_free_security(msq));
+}
+
+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)
+{
+ RETURN_ERROR_IF_ANY_ERROR(shm_alloc_security,shm_alloc_security(shp));
+}
+
+static void stacker_shm_free_security (struct shmid_kernel *shp)
+{
+ CALL_ALL(shm_free_security,shm_free_security(shp));
+}
+
+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 *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)
+{
+ RETURN_ERROR_IF_ANY_ERROR(sem_alloc_security,sem_alloc_security(sma));
+}
+
+static void stacker_sem_free_security (struct sem_array *sma)
+{
+ CALL_ALL(sem_free_security,sem_free_security(sma));
+}
+
+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));
+}
+
+static int
+stacker_getprocattr(struct task_struct *p, char *name, void *value, size_t
size)
+{
+ if (!selinux_module)
+ return -EINVAL;
+ if (!selinux_module->module_operations.getprocattr)
+ return -EINVAL;
+ return selinux_module->module_operations.getprocattr(p, name, value, size);
+}
+
+static int stacker_setprocattr(struct task_struct *p, char *name, void *value, size_t
size)
+{
+
+ if (!selinux_module)
+ return -EINVAL;
+ if (!selinux_module->module_operations.setprocattr)
+ return -EINVAL;
+ return selinux_module->module_operations.setprocattr(p, name, value, size);
+}
+
+/*
+ * Add the stacked module (as specified by name and ops)
+ * according to the current ordering policy.
+ */
+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 (next_secondary) {
+ ret = next_secondary->module_operations.register_security(name,
+ ops);
+ printk(KERN_INFO "%s: %s loaded %s (returned %d)\n",
+ __FUNCTION__, next_secondary->module_name,
+ name, ret);
+ next_secondary = NULL;
+ goto out;
+ }
+
+ 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;
+
+ atomic_set(&new_module_entry->use, 1);
+ INIT_LIST_HEAD(&new_module_entry->lsm_list);
+ list_add_tail_rcu(&new_module_entry->lsm_list, &stacked_modules);
+ num_stacked_modules++;
+ if (strcmp(name, "selinux") == 0)
+ selinux_module = new_module_entry;
+
+ printk(KERN_INFO "%s: registered %s module\n", __FUNCTION__,
+ new_module_entry->module_name);
+
+out:
+ spin_unlock(&stacker_lock);
+ return ret;
+}
+
+/*
+ * try to get a stacked module to unregister this module.
+ * called with spinlock held.
+ */
+static inline struct module_entry *
+try_all_unregister(const char *name, struct security_operations *ops)
+{
+ struct module_entry *m, *ret = NULL;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(m, &stacked_modules, lsm_list) {
+ atomic_inc(&m->use);
+ rcu_read_unlock();
+ if (!m->module_operations.unregister_security)
+ goto setup_next_iter;
+ if ( !m->module_operations.unregister_security(name, ops))
+ ret = m;
+
+setup_next_iter:
+ rcu_read_lock();
+ if (unlikely(atomic_dec_and_test(&m->use)))
+ stacker_free_module(m);
+ if (ret)
+ break;
+ }
+ rcu_read_unlock();
+
+ return ret;
+}
+
+/*
+ * find_lsm_module_by_name:
+ * Find a module by name. Used by next_secondary_write. 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, &stacked_modules, lsm_list) {
+ atomic_inc(&m->use);
+ rcu_read_unlock();
+ if (m->namelen == len && !strncmp(m->module_name, name, len))
+ ret = m;
+ rcu_read_lock();
+ if (unlikely(atomic_dec_and_test(&m->use)))
+ stacker_free_module(m);
+ if (ret)
+ break;
+ }
+ rcu_read_unlock();
+
+ return ret;
+}
+
+/*
+ * Unregister a registered LSM.
+ * It would be nice if we could veto this, but we can't...
+ */
+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) {
+ m = try_all_unregister(name, ops);
+ if (m) {
+ printk(KERN_NOTICE "%s: %s unregistered %s\n",
+ __FUNCTION__, m->module_name, name);
+ goto out;
+ }
+ }
+
+ if (!m) {
+ printk(KERN_INFO "%s: could not find module %s.\n",
+ __FUNCTION__, name);
+ ret = -ENOENT;
+ goto out;
+ }
+
+ list_del_rcu(&m->lsm_list);
+ num_stacked_modules--;
+
+ if (strcmp(m->module_name, "selinux") == 0)
+ selinux_module = NULL;
+ if (next_secondary == m)
+ next_secondary = NULL;
+ call_rcu(&m->m_rcu, stacker_del_module);
+
+out:
+ spin_unlock(&stacker_lock);
+
+ return ret;
+}
+
+static struct security_operations stacker_ops = {
+ .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,
+ .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_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
+
+};
+
+
+/*
+ * Functions to provide the sysfs interface
+ */
+
+/* A structure to pass into sysfs through kobjects */
+struct stacker_kobj {
+ struct list_head slot_list;
+ struct kobject kobj;
+};
+
+struct stacker_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct stacker_kobj *, char *);
+ ssize_t (*store)(struct stacker_kobj *, const char *, size_t);
+};
+
+/* variables to hold kobject/sysfs data */
+static struct subsystem stacker_subsys;
+
+static void unregister_sysfs_files(void);
+
+static ssize_t stacker_attr_store(struct kobject *kobj,
+ struct attribute *attr, const char *buf, size_t len)
+{
+ struct stacker_kobj *obj = container_of(kobj,
+ struct stacker_kobj, kobj);
+ struct stacker_attribute *attribute = container_of(attr,
+ struct stacker_attribute, attr);
+
+ return attribute->store ? attribute->store(obj, buf, len) : 0;
+}
+
+static ssize_t stacker_attr_show(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ struct stacker_kobj *obj = container_of(kobj,
+ struct stacker_kobj, kobj);
+ struct stacker_attribute *attribute = container_of(attr,
+ struct stacker_attribute, attr);
+
+ return attribute->show ? attribute->show(obj, buf) : 0;
+}
+
+static struct sysfs_ops stacker_sysfs_ops = {
+ .show = stacker_attr_show,
+ .store = stacker_attr_store,
+};
+
+static struct kobj_type stacker_ktype = {
+ .sysfs_ops = &stacker_sysfs_ops
+};
+
+static decl_subsys(stacker, &stacker_ktype, NULL);
+
+/* Set lockdown */
+static ssize_t lockdown_read (struct stacker_kobj *obj, char *buff)
+{
+ ssize_t len;
+
+ if (forbid_stacker_register)
+ len = sprintf(buff, "Locked down\n");
+ else
+ len = sprintf(buff, "Unlocked\n");
+
+ return len;
+}
+
+static ssize_t lockdown_write (struct stacker_kobj *obj, const char *buff, size_t
count)
+{
+ if (count>0)
+ forbid_stacker_register = 1;
+
+ return count;
+}
+
+static struct stacker_attribute stacker_attr_lockdown = {
+ .attr = {.name = "lockdown", .mode = S_IFREG | S_IRUGO | S_IWUSR},
+ .show = lockdown_read,
+ .store = lockdown_write
+};
+
+/* list modules */
+static ssize_t listmodules_read (struct stacker_kobj *obj, char *buff)
+{
+ ssize_t len = 0;
+ struct module_entry *m;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(m, &stacked_modules, lsm_list) {
+ atomic_inc(&m->use);
+ rcu_read_unlock();
+ len += snprintf(buff+len, PAGE_SIZE - len, "%s\n",
+ m->module_name);
+ rcu_read_lock();
+ if (unlikely(atomic_dec_and_test(&m->use)))
+ stacker_free_module(m);
+ }
+ rcu_read_unlock();
+
+ return len;
+}
+
+static struct stacker_attribute stacker_attr_listmodules = {
+ .attr = {.name = "list_modules", .mode = S_IFREG | S_IRUGO | S_IWUSR},
+ .show = listmodules_read,
+};
+
+/* stop responding to sysfs */
+static ssize_t stop_responding_read (struct stacker_kobj *obj, char *buff)
+{
+ ssize_t len;
+
+ len = sprintf(buff, "Obviously not\n");
+
+ return len;
+}
+
+static ssize_t stop_responding_write (struct stacker_kobj *obj, const char *buff, size_t
count)
+{
+ if (count>0) {
+ unregister_sysfs_files();
+ }
+
+ return count;
+}
+
+static struct stacker_attribute stacker_attr_stop_responding = {
+ .attr = {.name = "stop_responding", .mode = S_IFREG | S_IRUGO | S_IWUSR},
+ .show = stop_responding_read,
+ .store = stop_responding_write
+};
+
+/* short-circuit restrictive */
+static ssize_t shortcircuit_restrictive_read (struct stacker_kobj *obj, char
*buff)
+{
+ ssize_t len;
+
+ if (short_circuit_restrictive)
+ len = sprintf(buff, "Restrictive hooks ARE being short-circuited.\n");
+ else
+ len = sprintf(buff, "Restrictive hooks are NOT being short-circuited.\n");
+
+ return len;
+}
+
+static ssize_t shortcircuit_restrictive_write (struct stacker_kobj *obj, const char *buff, size_t
count)
+{
+ int ret = count;
+
+ if (!count)
+ return count;
+
+ if (buff[0]=='0')
+ short_circuit_restrictive = 0;
+ else if (buff[0]=='1')
+ short_circuit_restrictive = 1;
+ else
+ ret = -ENOENT;
+
+ return ret;
+}
+
+static struct stacker_attribute stacker_attr_shortcircuit_restr = {
+ .attr = {.name = "shortcircuit_restrictive", .mode = S_IFREG | S_IRUGO |
S_IWUSR},
+ .show = shortcircuit_restrictive_read,
+ .store = shortcircuit_restrictive_write
+};
+
+static ssize_t next_secondary_read (struct stacker_kobj *obj, char *buff)
+{
+ if (!next_secondary)
+ return 0;
+ return sprintf(buff, next_secondary->module_name);
+}
+
+static ssize_t next_secondary_write (struct stacker_kobj *obj, const char *buff, size_t
count)
+{
+ unsigned long flags;
+ size_t len = count;
+ ssize_t ret = count;
+
+ if (!len)
+ return count;
+ if (buff[len-1] == '\n')
+ len--;
+ spin_lock_irqsave(&stacker_lock, flags);
+ next_secondary = find_lsm_with_namelen(buff, len);
+ if (!next_secondary)
+ ret = -EINVAL;
+ spin_unlock_irqrestore(&stacker_lock, flags);
+
+ return ret;
+}
+
+/*
+ * An EXPORTed function to allow stacked LSMs to directly ask to adopt
+ * the next LSM, without needing to go through userspace
+ */
+int lsm_adopt_next_secondary(char *name)
+{
+ unsigned long flags;
+ size_t len = strnlen(name, MAX_MODULE_NAME_LEN);
+ int ret = 0;
+
+ spin_lock_irqsave(&stacker_lock, flags);
+ next_secondary = find_lsm_with_namelen(name, len);
+ if (!next_secondary)
+ ret = -EINVAL;
+ spin_unlock_irqrestore(&stacker_lock, flags);
+ return ret;
+}
+
+EXPORT_SYMBOL(lsm_adopt_next_secondary);
+
+static struct stacker_attribute stacker_attr_nextsec = {
+ .attr = {.name = "next_secondary", .mode = S_IFREG | S_IRUGO | S_IWUSR},
+ .show = next_secondary_read,
+ .store = next_secondary_write
+};
+
+static void unregister_sysfs_files(void)
+{
+ struct kobject *kobj;
+
+ if (!sysfsfiles_registered)
+ return;
+
+ kobj = &stacker_subsys.kset.kobj;
+ sysfs_remove_file(kobj, &stacker_attr_nextsec.attr);
+ sysfs_remove_file(kobj, &stacker_attr_lockdown.attr);
+ sysfs_remove_file(kobj, &stacker_attr_listmodules.attr);
+ sysfs_remove_file(kobj, &stacker_attr_stop_responding.attr);
+ sysfs_remove_file(kobj, &stacker_attr_shortcircuit_restr.attr);
+
+ sysfsfiles_registered = 0;
+}
+
+static int register_sysfs_files(void)
+{
+ int result;
+
+ result = subsystem_register(&stacker_subsys);
+ if (result) {
+ printk(KERN_WARNING
+ "Error (%d) registering stacker sysfs subsystem\n",
+ result);
+ return result;
+ }
+
+ sysfs_create_file(&stacker_subsys.kset.kobj,
+ &stacker_attr_lockdown.attr);
+ sysfs_create_file(&stacker_subsys.kset.kobj,
+ &stacker_attr_listmodules.attr);
+ sysfs_create_file(&stacker_subsys.kset.kobj,
+ &stacker_attr_stop_responding.attr);
+ sysfs_create_file(&stacker_subsys.kset.kobj,
+ &stacker_attr_shortcircuit_restr.attr);
+ sysfs_create_file(&stacker_subsys.kset.kobj,
+ &stacker_attr_nextsec.attr);
+ sysfsfiles_registered = 1;
+ stacker_dbg("sysfs files registered\n");
+ return 0;
+}
+
+module_init(register_sysfs_files);
+
+/*
+ * Structure sent back to security modules for getting and
+ * setting security blobs
+ */
+
+static int __init stacker_init (void)
+{
+ forbid_stacker_register = 0;
+ short_circuit_restrictive = CONFIG_SECURITY_STACKER_SHORTCIRCUIT;
+ INIT_LIST_HEAD(&stacked_modules);
+ sysfsfiles_registered = 0;
+ num_stacked_modules = 0;
+ spin_lock_init(&stacker_lock);
+
+ 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;
+ }
+ stacker_dbg("LSM stacker initialized\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_sysfs_files();
+ if (unregister_security (MY_NAME, &stacker_ops))
+ printk (KERN_WARNING
+ "Error unregistering LSM stacker.\n");
+ else
+ stacker_dbg("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");
L M B E N C H 2 . 0 S U M M A R Y
------------------------------------
Basic system parameters
----------------------------------------------------
Host OS Description Mhz
--------- ------------- ----------------------- ----
vega.ltc. Linux 2.6.10- i686-pc-linux-gnu 700
vega.ltc. Linux 2.6.10- i686-pc-linux-gnu 700
vega.ltc. Linux 2.6.10- i686-pc-linux-gnu 700
vega.ltc. Linux 2.6.10- i686-pc-linux-gnu 700
Processor, Processes - times in microseconds - smaller is better
----------------------------------------------------------------
Host OS Mhz null null open selct sig sig fork exec sh
call I/O stat clos TCP inst hndl proc proc
proc
--------- ------------- ---- ---- ---- ---- ---- ----- ---- ---- ---- ----
----
vega.ltc. Linux 2.6.10- 700 0.30 1.10 10.8 12.7 37.0 1.45 5.47 250. 1119
3825
vega.ltc. Linux 2.6.10- 700 0.30 1.13 10.9 12.8 38.2 1.43 5.57 249. 1110
3816
vega.ltc. Linux 2.6.10- 700 0.30 1.12 11.0 12.8 38.8 1.44 5.54 249. 1120
3835
vega.ltc. Linux 2.6.10- 700 0.30 1.11 10.9 12.8 36.5 1.43 5.57 249. 1156
3827
MEAN 1.12 10.9 12.8 37.6 1.44 5.54 249 1126
3826
STDEV .01 0.1 .04 0.9 0.01 0.04 .4 18
7
CI (95%)
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
--------- ------------- ----- ------ ------ ------ ------ ------- -------
vega.ltc. Linux 2.6.10- 11.6 15.9 32.3 17.7 33.1 16.7 32.8
vega.ltc. Linux 2.6.10- 11.0 16.1 32.9 16.4 31.3 16.3 33.1
vega.ltc. Linux 2.6.10- 11.6 15.7 32.5 18.6 31.8 16.9 34.0
vega.ltc. Linux 2.6.10- 11.1 15.7 32.5 17.9 32.8 17.2 32.8
MEAN 11.3 15.9 32.6 17.7 32.3 16.8 33.2
STDEV 0.3 0.2 0.2 0.8 0.7 0.3 0.5
CI (95%)
*Local* Communication latencies in microseconds - smaller is better
-------------------------------------------------------------------
Host OS 2p/0K Pipe AF UDP RPC/ TCP RPC/ TCP
ctxsw UNIX UDP TCP conn
--------- ------------- ----- ----- ---- ----- ----- ----- ----- ----
vega.ltc. Linux 2.6.10- 11.6 53.1 61.5 100.1 179.
vega.ltc. Linux 2.6.10- 11.0 46.2 72.9 98.5 178.
vega.ltc. Linux 2.6.10- 11.6 54.9 69.9 128.4 179.
vega.ltc. Linux 2.6.10- 11.1 55.6 68.9 99.2 181.
MEAN 11.3 52.5 68.3 106.6 179
STDEV 0.3 3.7 4.2 12.6 1
CI (95%)
File & VM system latencies in microseconds - smaller is better
--------------------------------------------------------------
Host OS 0K File 10K File Mmap Prot Page
Create Delete Create Delete Latency Fault Fault
--------- ------------- ------ ------ ------ ------ ------- ----- -----
vega.ltc. Linux 2.6.10- 80.5 42.5 209.6 79.6 11.2K 0.220 4.00000
vega.ltc. Linux 2.6.10- 80.6 42.7 210.4 79.9 11.1K 0.269 5.00000
vega.ltc. Linux 2.6.10- 80.9 42.6 208.1 80.1 11.1K 0.200 5.00000
vega.ltc. Linux 2.6.10- 80.6 43.0 208.9 80.0 11.3K 0.230 4.00000
MEAN 80.7 42.7 209.3 79.9 11.2K 0.230 4.5
STDEV 0.2 0.2 0.9 0.2 0.1K 0.025 0.5
CI (95%)
*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
--------- ------------- ---- ---- ---- ------ ------ ------ ------ ---- -----
vega.ltc. Linux 2.6.10- 291. 283. 198. 278.8 331.7 185.9 158.5 328. 202.6
vega.ltc. Linux 2.6.10- 292. 284. 196. 282.2 327.9 185.9 147.0 331. 202.9
vega.ltc. Linux 2.6.10- 294. 282. 197. 282.1 331.4 187.0 146.6 328. 202.8
vega.ltc. Linux 2.6.10- 293. 283. 199. 278.8 328.0 185.8 145.2 328. 204.9
MEAN 293 283 198 280.5 329.8 186.2 149.3 329 203.3
STDEV 1 1 1 1.7 1.8 0.5 5.3 1 0.9
CI (95%)
Memory latencies in nanoseconds - smaller is better
(WARNING - may not be correct, check graphs)
---------------------------------------------------
Host OS Mhz L1 $ L2 $ Main mem Guesses
--------- ------------- ---- ----- ------ -------- -------
vega.ltc. Linux 2.6.10- 700 4.329 13.0 183.3
vega.ltc. Linux 2.6.10- 700 4.284 12.9 181.3
vega.ltc. Linux 2.6.10- 700 4.284 12.9 181.2
vega.ltc. Linux 2.6.10- 700 4.286 12.9 181.3
L M B E N C H 2 . 0 S U M M A R Y
------------------------------------
Basic system parameters
----------------------------------------------------
Host OS Description Mhz
--------- ------------- ----------------------- ----
vega.ltc. Linux 2.6.10- i686-pc-linux-gnu 700
vega.ltc. Linux 2.6.10- i686-pc-linux-gnu 700
vega.ltc. Linux 2.6.10- i686-pc-linux-gnu 700
vega.ltc. Linux 2.6.10- i686-pc-linux-gnu 700
Processor, Processes - times in microseconds - smaller is better
----------------------------------------------------------------
Host OS Mhz null null open selct sig sig fork exec sh
call I/O stat clos TCP inst hndl proc proc
proc
--------- ------------- ---- ---- ---- ---- ---- ----- ---- ---- ---- ----
----
vega.ltc. Linux 2.6.10- 700 0.30 1.97 15.0 18.5 36.6 1.43 6.20 258. 1172
4011
vega.ltc. Linux 2.6.10- 700 0.30 2.02 15.2 18.4 38.0 1.43 6.31 257. 1179
4041
vega.ltc. Linux 2.6.10- 700 0.30 1.99 15.2 18.7 38.2 1.44 6.13 257. 1189
4041
vega.ltc. Linux 2.6.10- 700 0.30 1.99 15.3 18.7 36.4 1.43 6.18 255. 1176
4043
MEAN 1.99 15.2 18.6 37.3 1.43 6.21 257 1179
4034
STDEV 0.02 0.1 0.1 0.8 .004 0.07 1 6
13
CI (95%)
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
--------- ------------- ----- ------ ------ ------ ------ ------- -------
vega.ltc. Linux 2.6.10- 10.1 14.6 31.3 14.9 30.8 16.5 41.8
vega.ltc. Linux 2.6.10- 10.1 14.6 26.1 15.4 33.1 16.0 33.1
vega.ltc. Linux 2.6.10- 10.3 14.6 32.0 15.2 32.9 14.7 32.8
vega.ltc. Linux 2.6.10- 10.4 14.5 31.3 15.0 33.1 15.0 35.2
MEAN 10.2 14.6 30.2 15.1 32.5 15.6 35.7
STDEV 0.1 0.04 2.4 0.2 1.0 0.7 3.6
CI (95%)
*Local* Communication latencies in microseconds - smaller is better
-------------------------------------------------------------------
Host OS 2p/0K Pipe AF UDP RPC/ TCP RPC/ TCP
ctxsw UNIX UDP TCP conn
--------- ------------- ----- ----- ---- ----- ----- ----- ----- ----
vega.ltc. Linux 2.6.10- 10.1 49.8 97.2 104.8 186.
vega.ltc. Linux 2.6.10- 10.1 48.6 86.7 127.8 187.
vega.ltc. Linux 2.6.10- 10.3 48.9 96.3 105.3 189.
vega.ltc. Linux 2.6.10- 10.4 49.7 100. 103.7 187.
MEAN 10.2 49.3 95.1 110.4 187
STDEV 0.1 0.5 5.0 10.1 1
CI (95%)
File & VM system latencies in microseconds - smaller is better
--------------------------------------------------------------
Host OS 0K File 10K File Mmap Prot Page
Create Delete Create Delete Latency Fault Fault
--------- ------------- ------ ------ ------ ------ ------- ----- -----
vega.ltc. Linux 2.6.10- 88.3 46.4 213.9 82.6 12.0K 5.00000
vega.ltc. Linux 2.6.10- 88.9 46.8 214.4 82.9 11.4K 4.00000
vega.ltc. Linux 2.6.10- 89.0 46.7 215.5 82.6 11.1K 4.00000
vega.ltc. Linux 2.6.10- 88.2 46.3 214.5 81.9 11.0K 5.00000
MEAN 88.6 46.6 214.6 82.5 11.4K 4.5
STDEV 0.4 0.2 0.6 0.4 0.4K 0.5
CI (95%)
*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
--------- ------------- ---- ---- ---- ------ ------ ------ ------ ---- -----
vega.ltc. Linux 2.6.10- 292. 283. 200. 277.8 328.0 183.8 145.1 331. 202.8
vega.ltc. Linux 2.6.10- 289. 283. 196. 277.9 331.5 183.7 146.6 331. 202.9
vega.ltc. Linux 2.6.10- 288. 283. 198. 281.5 328.0 185.3 145.2 328. 202.4
vega.ltc. Linux 2.6.10- 288. 282. 196. 277.3 331.5 185.9 145.3 331. 205.4
MEAN 289 283 198 278.6 329.8 184.7 145.6 330 203.4
STDEV 2 .4 2 1.7 1.8 0.9 0.6 1 1.2
CI (95%)
Memory latencies in nanoseconds - smaller is better
(WARNING - may not be correct, check graphs)
---------------------------------------------------
Host OS Mhz L1 $ L2 $ Main mem Guesses
--------- ------------- ---- ----- ------ -------- -------
vega.ltc. Linux 2.6.10- 700 4.329 13.0 184.9
vega.ltc. Linux 2.6.10- 700 4.329 13.0 184.9
vega.ltc. Linux 2.6.10- 700 4.330 13.0 184.8
vega.ltc. Linux 2.6.10- 700 4.329 13.0 182.9
L M B E N C H 2 . 0 S U M M A R Y
------------------------------------
Basic system parameters
----------------------------------------------------
Host OS Description Mhz
--------- ------------- ----------------------- ----
vega.ltc. Linux 2.6.10- i686-pc-linux-gnu 700
vega.ltc. Linux 2.6.10- i686-pc-linux-gnu 700
vega.ltc. Linux 2.6.10- i686-pc-linux-gnu 700
vega.ltc. Linux 2.6.10- i686-pc-linux-gnu 700
Processor, Processes - times in microseconds - smaller is better
----------------------------------------------------------------
Host OS Mhz null null open selct sig sig fork exec sh
call I/O stat clos TCP inst hndl proc proc
proc
--------- ------------- ---- ---- ---- ---- ---- ----- ---- ---- ---- ----
----
vega.ltc. Linux 2.6.10- 700 0.30 1.86 14.4 17.2 36.5 1.43 5.71 260. 1167
4024
vega.ltc. Linux 2.6.10- 700 0.30 1.89 14.7 17.5 40.7 1.45 5.77 259. 1179
3984
vega.ltc. Linux 2.6.10- 700 0.30 1.88 14.6 17.4 41.6 1.43 5.77 258. 1166
4043
vega.ltc. Linux 2.6.10- 700 0.30 1.88 14.4 17.2 36.7 1.45 5.67 260. 1183
4052
MEAN 0.30 1.88 14.5 17.3 38.9 1.44 5.73 259 1174
4026
STDEV 0.01 0.1 0.1 2.3 0.01 0.04 1 7
26
CI (95%)
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
--------- ------------- ----- ------ ------ ------ ------ ------- -------
vega.ltc. Linux 2.6.10- 10.1 14.5 31.6 15.0 32.8 14.9 32.9
vega.ltc. Linux 2.6.10- 10.2 14.6 31.1 14.8 32.8 15.6 32.4
vega.ltc. Linux 2.6.10- 10.0 14.8 31.7 15.2 32.3 14.8 38.3
vega.ltc. Linux 2.6.10- 9.900 14.3 31.4 14.8 32.1 15.8 32.9
MEAN 10.05 14.6 31.5 15.0 32.5 15.3 34.1
STDEV 0.11 0.2 0.2 0.2 0.3 0.4 2.4
CI (95%)
*Local* Communication latencies in microseconds - smaller is better
-------------------------------------------------------------------
Host OS 2p/0K Pipe AF UDP RPC/ TCP RPC/ TCP
ctxsw UNIX UDP TCP conn
--------- ------------- ----- ----- ---- ----- ----- ----- ----- ----
vega.ltc. Linux 2.6.10- 10.1 46.4 55.6 127.2 187.
vega.ltc. Linux 2.6.10- 10.2 49.2 93.3 104.3 188.
vega.ltc. Linux 2.6.10- 10.0 44.2 85.9 129.0 187.
vega.ltc. Linux 2.6.10- 9.900 45.6 97.4 104.6 188.
MEAN 10.05 46.4 83.1 116.3 188
STDEV 0.11 1.8 16.4 11.8 1
CI (95%)
File & VM system latencies in microseconds - smaller is better
--------------------------------------------------------------
Host OS 0K File 10K File Mmap Prot Page
Create Delete Create Delete Latency Fault Fault
--------- ------------- ------ ------ ------ ------ ------- ----- -----
vega.ltc. Linux 2.6.10- 89.9 45.5 215.2 82.3 11.0K 5.00000
vega.ltc. Linux 2.6.10- 90.6 45.9 217.9 81.5 11.1K 4.00000
vega.ltc. Linux 2.6.10- 90.8 45.8 218.4 83.0 10.7K 0.027 4.00000
vega.ltc. Linux 2.6.10- 90.4 45.9 215.7 81.7 10.8K 0.052 4.00000
MEAN 90.4 45.8 216.8 82.1 10.9K 0.040 4.250
STDEV 0.3 0.2 1.4 0.6 0.2K 0.013 0.433
CI (95%)
*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
--------- ------------- ---- ---- ---- ------ ------ ------ ------ ---- -----
vega.ltc. Linux 2.6.10- 289. 281. 233. 281.9 331.6 183.6 145.0 331. 205.3
vega.ltc. Linux 2.6.10- 288. 282. 197. 277.7 327.7 186.0 145.0 331. 202.5
vega.ltc. Linux 2.6.10- 293. 283. 194. 281.6 331.6 183.8 144.0 328. 202.3
vega.ltc. Linux 2.6.10- 291. 282. 195. 281.6 327.8 183.7 145.0 327. 202.4
MEAN 290 282 205 280.7 329.7 184.3 144.8 329 203.1
STDEV 2 1 16 1.7 1.9 1 0.4 2 1.3
CI (95%)
Memory latencies in nanoseconds - smaller is better
(WARNING - may not be correct, check graphs)
---------------------------------------------------
Host OS Mhz L1 $ L2 $ Main mem Guesses
--------- ------------- ---- ----- ------ -------- -------
vega.ltc. Linux 2.6.10- 700 4.285 12.9 182.8
vega.ltc. Linux 2.6.10- 700 4.329 13.0 184.8
vega.ltc. Linux 2.6.10- 700 4.328 13.0 184.8
vega.ltc. Linux 2.6.10- 700 4.284 12.8 182.8