diff mbox

[RFC,10/10] LSM: Configuration for major module stacking

Message ID 520f980c-7e51-58fa-e9ce-f59420ef8868@schaufler-ca.com (mailing list archive)
State New, archived
Headers show

Commit Message

Casey Schaufler July 11, 2016, 7:31 p.m. UTC
Subject: [PATCH RFC 10/10] LSM: Configuration for major module stacking

The ability to stack "major" security modules is introduced
with the configuration option CONFIG_SECURITY_STACKING. If this
is enabled any "major" security module can be specified for use
on the stack. If it is not set the CONFIG_DEFAULT_SECURITY value
will identify a module to be used.

The option CONFIG_SECURITY_APPARMOR_STACKED adds the AppArmor module.
The option CONFIG_SECURITY_SELINUX_STACKED adds the SELinux module.
The option CONFIG_SECURITY_SMACK_STACKED adds the Smack module.
The option CONFIG_SECURITY_TOMOYO_STACKED adds the TOMOYO module.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 Documentation/security/LSM.txt      | 10 ++++++++--
 include/linux/lsm_hooks.h           |  2 +-
 security/Kconfig                    | 22 ++++++++++++++++++++++
 security/apparmor/Kconfig           | 13 +++++++++++++
 security/apparmor/include/context.h | 10 ++++++++++
 security/apparmor/lsm.c             | 11 +++++++++--
 security/security.c                 | 26 +++++++++++++++++++++++++-
 security/selinux/Kconfig            | 13 +++++++++++++
 security/selinux/hooks.c            |  8 +++++++-
 security/selinux/include/objsec.h   |  8 ++++++++
 security/smack/Kconfig              | 13 +++++++++++++
 security/smack/smack.h              |  9 +++++++++
 security/smack/smack_lsm.c          |  8 +++++++-
 security/tomoyo/Kconfig             | 13 +++++++++++++
 security/tomoyo/common.h            |  5 +++++
 security/tomoyo/tomoyo.c            |  8 +++++++-
 16 files changed, 170 insertions(+), 9 deletions(-)


--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/Documentation/security/LSM.txt b/Documentation/security/LSM.txt
index af3eb11..2840583 100644
--- a/Documentation/security/LSM.txt
+++ b/Documentation/security/LSM.txt
@@ -18,8 +18,14 @@  in the core functionality of Linux itself.
 
 The Linux capabilities modules will always be included. For more details
 on capabilities, see capabilities(7) in the Linux man-pages project.
-This may be followed by any number of "minor" modules and at most one
-"major" module.
+
+Security modules that do not use the security data blobs maintained
+by the LSM infrastructure are considered "minor" modules. These may be
+included at compile time and stacked explicitly. Security modules that
+use the LSM maintained security blobs are considered "major" modules.
+These may only be stacked if the CONFIG_SECURITY_STACKED configuration
+option is used. If this is chosen all of the security modules selected
+will be used.
 
 A list of the active security modules can be found by reading
 /sys/kernel/security/lsm. This is a comma separated list, and
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 51f40b3..b7bb470 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1891,7 +1891,7 @@  static inline void security_delete_hooks(struct security_hook_list *hooks,
 }
 #endif /* CONFIG_SECURITY_SELINUX_DISABLE */
 
-extern int __init security_module_enable(const char *module);
+extern int __init security_module_enable(const char *module, const int stacked);
 extern void __init capability_add_hooks(void);
 #ifdef CONFIG_SECURITY_YAMA
 extern void __init yama_add_hooks(void);
diff --git a/security/Kconfig b/security/Kconfig
index 9312c78..d83e995 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -31,6 +31,28 @@  config SECURITY
 
 	  If you are unsure how to answer this question, answer N.
 
+config SECURITY_STACKING
+	bool "Security module stacking"
+	depends on SECURITY
+	help
+	  Allows multiple major security modules to be stacked.
+	  Modules are invoked in the order registered with a
+	  "bail on fail" policy, in which the infrastructure
+	  will stop processing once a denial is detected. Not
+	  all modules can be stacked. SELinux and Smack are
+	  known to be incompatible. User space components may
+	  have trouble identifying the security module providing
+	  data in some cases.
+
+	  If you select this option you will have to select which
+	  of the stackable modules you wish to be active. The
+	  "Default security module" will be ignored. The boot line
+	  "security=" option can be used to specify that one of
+	  the modules identifed for stacking should be used instead
+	  of the entire stack.
+
+	  If you are unsure how to answer this question, answer N.
+
 config SECURITY_STACKING_DEBUG
 	bool "Enable debugging of the LSM infrastructure"
 	depends on SECURITY
diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig
index 232469b..c49d5cb 100644
--- a/security/apparmor/Kconfig
+++ b/security/apparmor/Kconfig
@@ -14,6 +14,19 @@  config SECURITY_APPARMOR
 
 	  If you are unsure how to answer this question, answer N.
 
+config SECURITY_APPARMOR_STACKED
+	bool "AppArmor support is enabled by default"
+	depends on SECURITY_APPARMOR && SECURITY_STACKING
+	default n
+	help
+	  This option instructs the system to use the AppArmor checks.
+	  If not selected the module will not be invoked.
+	  Stacked security modules may interact in unexpected ways.
+	  Please be sure your user space code is accomodating of
+	  multiple security modules.
+
+	  If you are unsure how to answer this question, answer N.
+
 config SECURITY_APPARMOR_BOOTPARAM_VALUE
 	int "AppArmor boot parameter default value"
 	depends on SECURITY_APPARMOR
diff --git a/security/apparmor/include/context.h b/security/apparmor/include/context.h
index c140aad..666b975 100644
--- a/security/apparmor/include/context.h
+++ b/security/apparmor/include/context.h
@@ -87,14 +87,24 @@  int aa_set_current_hat(struct aa_profile *profile, u64 token);
 int aa_restore_previous_profile(u64 cookie);
 struct aa_profile *aa_get_task_profile(struct task_struct *task);
 
+extern struct lsm_blob_sizes apparmor_blob_sizes;
+
 static inline struct aa_task_cxt *apparmor_cred(const struct cred *cred)
 {
+#ifdef CONFIG_SECURITY_STACKING
+	return cred->security + apparmor_blob_sizes.lbs_cred;
+#else
 	return cred->security;
+#endif
 }
 
 static inline struct aa_file_cxt *apparmor_file(const struct file *file)
 {
+#ifdef CONFIG_SECURITY_STACKING
+	return file->f_security + apparmor_blob_sizes.lbs_file;
+#else
 	return file->f_security;
+#endif
 }
 
 /**
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 6c21b08..06efb4f 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -847,19 +847,26 @@  static int __init set_init_cxt(void)
 	return 0;
 }
 
+#ifdef CONFIG_SECURITY_APPARMOR_STACKED
+#define STACKED 1
+#else
+#define STACKED 0
+#endif
+
 static int __init apparmor_init(void)
 {
 	static int finish;
 	int error;
 
 	if (!finish) {
-		if (apparmor_enabled && security_module_enable("apparmor"))
+		if (apparmor_enabled &&
+		    security_module_enable("apparmor", STACKED))
 			security_add_blobs(&apparmor_blob_sizes);
 		finish = 1;
 		return 0;
 	}
 
-	if (!apparmor_enabled || !security_module_enable("apparmor")) {
+	if (!apparmor_enabled || !security_module_enable("apparmor", STACKED)) {
 		aa_info_message(
 			"AppArmor disabled by boot time parameter");
 		apparmor_enabled = 0;
diff --git a/security/security.c b/security/security.c
index 88a9b48..513e319 100644
--- a/security/security.c
+++ b/security/security.c
@@ -31,13 +31,18 @@ 
 
 /* Maximum number of letters for an LSM name string */
 #define SECURITY_NAME_MAX	10
+#define MODULE_STACK		"(stacking)"
 
 char *lsm_names;
 static struct lsm_blob_sizes blob_sizes;
 
 /* Boot-time LSM user choice */
 static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
+#ifdef CONFIG_SECURITY_STACKING
+	MODULE_STACK;
+#else
 	CONFIG_DEFAULT_SECURITY;
+#endif
 
 static void __init do_security_initcalls(void)
 {
@@ -113,6 +118,7 @@  static int lsm_append(char *new, char **result)
 /**
  * security_module_enable - Load given security module on boot ?
  * @module: the name of the module
+ * @stacked: indicates that the module wants to be stacked
  *
  * Each LSM must pass this method before registering its own operations
  * to avoid security registration races. This method may also be used
@@ -124,9 +130,27 @@  static int lsm_append(char *new, char **result)
  *	 choose an alternate LSM at boot time.
  * Otherwise, return false.
  */
-int __init security_module_enable(const char *module)
+int __init security_module_enable(const char *module, const int stacked)
 {
+#ifdef CONFIG_SECURITY_STACKING
+	/*
+	 * Module defined on the command line security=XXXX
+	 */
+	if (strcmp(chosen_lsm, MODULE_STACK)) {
+		if (!strcmp(module, chosen_lsm)) {
+			pr_info("Command line sets the %s security module.\n",
+				module);
+			return 1;
+		}
+		return 0;
+	}
+	/*
+	 * Module configured as stacked.
+	 */
+	return stacked;
+#else
 	return !strcmp(module, chosen_lsm);
+#endif
 }
 
 /**
diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
index 8691e92..35a20dd 100644
--- a/security/selinux/Kconfig
+++ b/security/selinux/Kconfig
@@ -8,6 +8,19 @@  config SECURITY_SELINUX
 	  You will also need a policy configuration and a labeled filesystem.
 	  If you are unsure how to answer this question, answer N.
 
+config SECURITY_SELINUX_STACKED
+	bool "NSA SELinux Support is enabled by default"
+	depends on SECURITY_SELINUX && SECURITY_STACKING
+	default n
+	help
+	  This option instructs the system to use the SELinux checks.
+	  If not selected the module will not be invoked.
+	  Stacked security modules may interact in unexpected ways.
+	  Please be sure your user space code is accomodating of
+	  multiple security modules.
+
+	  If you are unsure how to answer this question, answer N.
+
 config SECURITY_SELINUX_BOOTPARAM
 	bool "NSA SELinux boot parameter"
 	depends on SECURITY_SELINUX
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 9d769f3..b6b441d 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -6167,11 +6167,17 @@  static struct security_hook_list selinux_hooks[] = {
 #endif
 };
 
+#ifdef CONFIG_SECURITY_SELINUX_STACKED
+#define STACKED 1
+#else
+#define STACKED 0
+#endif
+
 static __init int selinux_init(void)
 {
 	static int finish;
 
-	if (!security_module_enable("selinux")) {
+	if (!security_module_enable("selinux", STACKED)) {
 		selinux_enabled = 0;
 		return 0;
 	}
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index b39e03b..8ec78d0 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -136,12 +136,20 @@  extern struct lsm_blob_sizes selinux_blob_sizes;
 
 static inline struct task_security_struct *selinux_cred(const struct cred *cred)
 {
+#ifdef CONFIG_SECURITY_STACKING
+	return cred->security + selinux_blob_sizes.lbs_cred;
+#else
 	return cred->security;
+#endif
 }
 
 static inline struct file_security_struct *selinux_file(const struct file *file)
 {
+#ifdef CONFIG_SECURITY_STACKING
+	return file->f_security + selinux_blob_sizes.lbs_file;
+#else
 	return file->f_security;
+#endif
 }
 
 #endif /* _SELINUX_OBJSEC_H_ */
diff --git a/security/smack/Kconfig b/security/smack/Kconfig
index 271adae..362a865 100644
--- a/security/smack/Kconfig
+++ b/security/smack/Kconfig
@@ -12,6 +12,19 @@  config SECURITY_SMACK
 	  of other mandatory security schemes.
 	  If you are unsure how to answer this question, answer N.
 
+config SECURITY_SMACK_STACKED
+	bool "Smack support is enabled by default"
+	depends on SECURITY_SMACK && SECURITY_STACKING
+	default n
+	help
+	  This option instructs the system to use the Smack checks.
+	  If not selected the module will not be invoked.
+	  Stacked security modules may interact in unexpected ways.
+	  Please be sure your user space code is accomodating of
+	  multiple security modules.
+
+	  If you are unsure how to answer this question, answer N.
+
 config SECURITY_SMACK_BRINGUP
 	bool "Reporting on access granted by Smack rules"
 	depends on SECURITY_SMACK
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 0027ccd..29ae112 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -317,6 +317,7 @@  extern struct smack_known *smack_syslog_label;
 extern struct smack_known *smack_unconfined;
 #endif
 extern int smack_ptrace_rule;
+extern struct lsm_blob_sizes smack_blob_sizes;
 
 extern struct smack_known smack_known_floor;
 extern struct smack_known smack_known_hat;
@@ -340,12 +341,20 @@  extern struct hlist_head smack_known_hash[SMACK_HASH_SLOTS];
 
 static inline struct task_smack *smack_cred(const struct cred *cred)
 {
+#ifdef CONFIG_SECURITY_STACKING
+	return cred->security + smack_blob_sizes.lbs_cred;
+#else
 	return cred->security;
+#endif
 }
 
 static inline struct smack_known **smack_file(const struct file *file)
 {
+#ifdef CONFIG_SECURITY_STACKING
+	return file->f_security + smack_blob_sizes.lbs_file;
+#else
 	return file->f_security;
+#endif
 }
 
 /*
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 94aff94..2296b43 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -4720,6 +4720,12 @@  static __init void init_smack_known_list(void)
 	smk_insert_entry(&smack_known_web);
 }
 
+#ifdef CONFIG_SECURITY_SMACK_STACKED
+#define STACKED 1
+#else
+#define STACKED 0
+#endif
+
 /**
  * smack_init - initialize the smack system
  *
@@ -4731,7 +4737,7 @@  static __init int smack_init(void)
 	struct cred *cred = (struct cred *) current->cred;
 	struct task_smack *tsp;
 
-	if (!security_module_enable("smack"))
+	if (!security_module_enable("smack", STACKED))
 		return 0;
 
 	if (!finish) {
diff --git a/security/tomoyo/Kconfig b/security/tomoyo/Kconfig
index 404dce6..746e8c4 100644
--- a/security/tomoyo/Kconfig
+++ b/security/tomoyo/Kconfig
@@ -14,6 +14,19 @@  config SECURITY_TOMOYO
 	  found at <http://tomoyo.sourceforge.jp/>.
 	  If you are unsure how to answer this question, answer N.
 
+config SECURITY_TOMOYO_STACKED
+	bool "TOMOYO support is enabled by default"
+	depends on SECURITY_TOMOYO && SECURITY_STACKING
+	default n
+	help
+	  This option instructs the system to use the TOMOYO checks.
+	  If not selected the module will not be invoked.
+	  Stacked security modules may interact in unexpected ways.
+	  Please be sure your user space code is accomodating of
+	  multiple security modules.
+
+	  If you are unsure how to answer this question, answer N.
+
 config SECURITY_TOMOYO_MAX_ACCEPT_ENTRY
 	int "Default maximal count for learning mode"
 	default 2048
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index cbcfccc..a78b354 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -1085,6 +1085,7 @@  extern struct tomoyo_domain_info tomoyo_kernel_domain;
 extern struct tomoyo_policy_namespace tomoyo_kernel_namespace;
 extern unsigned int tomoyo_memory_quota[TOMOYO_MAX_MEMORY_STAT];
 extern unsigned int tomoyo_memory_used[TOMOYO_MAX_MEMORY_STAT];
+extern struct lsm_blob_sizes tomoyo_blob_sizes;
 
 /********** Inlined functions. **********/
 
@@ -1204,7 +1205,11 @@  static inline void tomoyo_put_group(struct tomoyo_group *group)
  */
 static inline struct tomoyo_domain_info **tomoyo_cred(const struct cred *cred)
 {
+#ifdef CONFIG_SECURITY_STACKING
+	return cred->security + tomoyo_blob_sizes.lbs_cred;
+#else
 	return cred->security;
+#endif
 }
 
 /**
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index 61285fe..a47ed03 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -550,6 +550,12 @@  static struct security_hook_list tomoyo_hooks[] = {
 /* Lock for GC. */
 DEFINE_SRCU(tomoyo_ss);
 
+#ifdef CONFIG_SECURITY_TOMOYO_STACKED
+#define STACKED 1
+#else
+#define STACKED 0
+#endif
+
 /**
  * tomoyo_init - Register TOMOYO Linux as a LSM module.
  *
@@ -561,7 +567,7 @@  static int __init tomoyo_init(void)
 	struct cred *cred = (struct cred *) current_cred();
 	struct tomoyo_domain_info **blob;
 
-	if (!security_module_enable("tomoyo"))
+	if (!security_module_enable("tomoyo", STACKED))
 		return 0;
 
 	if (!finish) {