All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] LSM: Drop security_delete_hooks()
@ 2020-01-07 13:31 Ondrej Mosnacek
  2020-01-07 13:31 ` [PATCH 1/2] selinux: treat atomic flags more carefully Ondrej Mosnacek
  2020-01-07 13:31 ` [PATCH 2/2] security,selinux: get rid of security_delete_hooks() Ondrej Mosnacek
  0 siblings, 2 replies; 18+ messages in thread
From: Ondrej Mosnacek @ 2020-01-07 13:31 UTC (permalink / raw)
  To: linux-security-module, James Morris, Serge E. Hallyn
  Cc: Casey Schaufler, selinux, Paul Moore, Stephen Smalley,
	John Johansen, Kees Cook, Micah Morton, Tetsuo Handa

This is a third iteration of the attempt to fix a race condition in
SELinux runtime disable. [1] [2]

This version takes the approach of removing the security_delete_hooks()
function (and CONFIG_SECURITY_WRITABLE_HOOKS) and just returning from
the hooks early when SELinux has been disabled on runtime. Note that the
runtime disable functionality is being deprecated and this is only a
temporary solution.

The first patch is an SMP semantics cleanup in SELinux; the second one
builds on top of it and does the actual conversion.

Tested on Fedora Rawhide by running selinux-testsuite with SELinux
enabled + boot tested with SELINUX=disabled. Also compile-tested with
all LSMs enabled in config.

[1] https://lore.kernel.org/selinux/20191211140833.939845-1-omosnace@redhat.com/T/
[2] https://lore.kernel.org/selinux/20191209075756.123157-1-omosnace@redhat.com/T/

Ondrej Mosnacek (2):
  selinux: treat atomic flags more carefully
  security,selinux: get rid of security_delete_hooks()

 include/linux/lsm_hooks.h           |  31 --
 security/Kconfig                    |   5 -
 security/apparmor/lsm.c             |   6 +-
 security/commoncap.c                |   2 +-
 security/loadpin/loadpin.c          |   2 +-
 security/lockdown/lockdown.c        |   2 +-
 security/security.c                 |   5 +-
 security/selinux/Kconfig            |   6 -
 security/selinux/hooks.c            | 763 ++++++++++++++++++++++++----
 security/selinux/include/security.h |  33 +-
 security/selinux/ss/services.c      |  38 +-
 security/smack/smack_lsm.c          |   4 +-
 security/tomoyo/tomoyo.c            |   6 +-
 security/yama/yama_lsm.c            |   2 +-
 14 files changed, 715 insertions(+), 190 deletions(-)

-- 
2.24.1


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

* [PATCH 1/2] selinux: treat atomic flags more carefully
  2020-01-07 13:31 [PATCH 0/2] LSM: Drop security_delete_hooks() Ondrej Mosnacek
@ 2020-01-07 13:31 ` Ondrej Mosnacek
  2020-01-07 14:45   ` Stephen Smalley
                     ` (3 more replies)
  2020-01-07 13:31 ` [PATCH 2/2] security,selinux: get rid of security_delete_hooks() Ondrej Mosnacek
  1 sibling, 4 replies; 18+ messages in thread
From: Ondrej Mosnacek @ 2020-01-07 13:31 UTC (permalink / raw)
  To: linux-security-module, James Morris, Serge E. Hallyn
  Cc: Casey Schaufler, selinux, Paul Moore, Stephen Smalley,
	John Johansen, Kees Cook, Micah Morton, Tetsuo Handa

The disabled/enforcing/initialized flags are all accessed concurrently
by threads so use the appropriate accessors that ensure atomicity and
document that it is expected.

Use smp_load/acquire...() helpers (with memory barriers) for the
initialized flag, since it gates access to the rest of the state
structures.

Note that the disabled flag is currently not used for anything other
than avoiding double disable, but it will be used for bailing out of
hooks once security_delete_hooks() is removed.

Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
---
 security/selinux/hooks.c            | 21 ++++++++--------
 security/selinux/include/security.h | 33 +++++++++++++++++++++++--
 security/selinux/ss/services.c      | 38 ++++++++++++++---------------
 3 files changed, 61 insertions(+), 31 deletions(-)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 659c4a81e897..47ad4db925cf 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -272,7 +272,7 @@ static int __inode_security_revalidate(struct inode *inode,
 
 	might_sleep_if(may_sleep);
 
-	if (selinux_state.initialized &&
+	if (selinux_initialized(&selinux_state) &&
 	    isec->initialized != LABEL_INITIALIZED) {
 		if (!may_sleep)
 			return -ECHILD;
@@ -659,7 +659,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
 
 	mutex_lock(&sbsec->lock);
 
-	if (!selinux_state.initialized) {
+	if (!selinux_initialized(&selinux_state)) {
 		if (!opts) {
 			/* Defer initialization until selinux_complete_init,
 			   after the initial policy is loaded and the security
@@ -928,7 +928,7 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
 	 * if the parent was able to be mounted it clearly had no special lsm
 	 * mount options.  thus we can safely deal with this superblock later
 	 */
-	if (!selinux_state.initialized)
+	if (!selinux_initialized(&selinux_state))
 		return 0;
 
 	/*
@@ -1103,7 +1103,7 @@ static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
 	if (!(sbsec->flags & SE_SBINITIALIZED))
 		return 0;
 
-	if (!selinux_state.initialized)
+	if (!selinux_initialized(&selinux_state))
 		return 0;
 
 	if (sbsec->flags & FSCONTEXT_MNT) {
@@ -2920,7 +2920,8 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
 		isec->initialized = LABEL_INITIALIZED;
 	}
 
-	if (!selinux_state.initialized || !(sbsec->flags & SBLABEL_MNT))
+	if (!selinux_initialized(&selinux_state) ||
+	    !(sbsec->flags & SBLABEL_MNT))
 		return -EOPNOTSUPP;
 
 	if (name)
@@ -3143,7 +3144,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
 		return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
 	}
 
-	if (!selinux_state.initialized)
+	if (!selinux_initialized(&selinux_state))
 		return (inode_owner_or_capable(inode) ? 0 : -EPERM);
 
 	sbsec = inode->i_sb->s_security;
@@ -3229,7 +3230,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
 		return;
 	}
 
-	if (!selinux_state.initialized) {
+	if (!selinux_initialized(&selinux_state)) {
 		/* If we haven't even been initialized, then we can't validate
 		 * against a policy, so leave the label as invalid. It may
 		 * resolve to a valid label on the next revalidation try if
@@ -7304,17 +7305,17 @@ static void selinux_nf_ip_exit(void)
 #ifdef CONFIG_SECURITY_SELINUX_DISABLE
 int selinux_disable(struct selinux_state *state)
 {
-	if (state->initialized) {
+	if (selinux_initialized(state)) {
 		/* Not permitted after initial policy load. */
 		return -EINVAL;
 	}
 
-	if (state->disabled) {
+	if (selinux_disabled(state)) {
 		/* Only do this once. */
 		return -EINVAL;
 	}
 
-	state->disabled = 1;
+	selinux_mark_disabled(state);
 
 	pr_info("SELinux:  Disabled at runtime.\n");
 
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index ecdd610e6449..a39f9565d80b 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -117,15 +117,27 @@ void selinux_avc_init(struct selinux_avc **avc);
 
 extern struct selinux_state selinux_state;
 
+static inline bool selinux_initialized(const struct selinux_state *state)
+{
+	/* do a synchronized load to avoid race conditions */
+	return smp_load_acquire(&state->initialized);
+}
+
+static inline void selinux_mark_initialized(struct selinux_state *state)
+{
+	/* do a synchronized write to avoid race conditions */
+	smp_store_release(&state->initialized, true);
+}
+
 #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
 static inline bool enforcing_enabled(struct selinux_state *state)
 {
-	return state->enforcing;
+	return READ_ONCE(state->enforcing);
 }
 
 static inline void enforcing_set(struct selinux_state *state, bool value)
 {
-	state->enforcing = value;
+	WRITE_ONCE(state->enforcing, value);
 }
 #else
 static inline bool enforcing_enabled(struct selinux_state *state)
@@ -138,6 +150,23 @@ static inline void enforcing_set(struct selinux_state *state, bool value)
 }
 #endif
 
+#ifdef CONFIG_SECURITY_SELINUX_DISABLE
+static inline bool selinux_disabled(struct selinux_state *state)
+{
+	return READ_ONCE(state->disabled);
+}
+
+static inline void selinux_mark_disabled(struct selinux_state *state)
+{
+	WRITE_ONCE(state->disabled, true);
+}
+#else
+static inline bool selinux_disabled(struct selinux_state *state)
+{
+	return false;
+}
+#endif
+
 static inline bool selinux_policycap_netpeer(void)
 {
 	struct selinux_state *state = &selinux_state;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 55cf42945cba..0e8b94e8e156 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -767,7 +767,7 @@ static int security_compute_validatetrans(struct selinux_state *state,
 	int rc = 0;
 
 
-	if (!state->initialized)
+	if (!selinux_initialized(state))
 		return 0;
 
 	read_lock(&state->ss->policy_rwlock);
@@ -868,7 +868,7 @@ int security_bounded_transition(struct selinux_state *state,
 	int index;
 	int rc;
 
-	if (!state->initialized)
+	if (!selinux_initialized(state))
 		return 0;
 
 	read_lock(&state->ss->policy_rwlock);
@@ -1027,7 +1027,7 @@ void security_compute_xperms_decision(struct selinux_state *state,
 	memset(xpermd->dontaudit->p, 0, sizeof(xpermd->dontaudit->p));
 
 	read_lock(&state->ss->policy_rwlock);
-	if (!state->initialized)
+	if (!selinux_initialized(state))
 		goto allow;
 
 	policydb = &state->ss->policydb;
@@ -1112,7 +1112,7 @@ void security_compute_av(struct selinux_state *state,
 	read_lock(&state->ss->policy_rwlock);
 	avd_init(state, avd);
 	xperms->len = 0;
-	if (!state->initialized)
+	if (!selinux_initialized(state))
 		goto allow;
 
 	policydb = &state->ss->policydb;
@@ -1166,7 +1166,7 @@ void security_compute_av_user(struct selinux_state *state,
 
 	read_lock(&state->ss->policy_rwlock);
 	avd_init(state, avd);
-	if (!state->initialized)
+	if (!selinux_initialized(state))
 		goto allow;
 
 	policydb = &state->ss->policydb;
@@ -1286,7 +1286,7 @@ int security_sidtab_hash_stats(struct selinux_state *state, char *page)
 {
 	int rc;
 
-	if (!state->initialized) {
+	if (!selinux_initialized(state)) {
 		pr_err("SELinux: %s:  called before initial load_policy\n",
 		       __func__);
 		return -EINVAL;
@@ -1320,7 +1320,7 @@ static int security_sid_to_context_core(struct selinux_state *state,
 		*scontext = NULL;
 	*scontext_len  = 0;
 
-	if (!state->initialized) {
+	if (!selinux_initialized(state)) {
 		if (sid <= SECINITSID_NUM) {
 			char *scontextp;
 
@@ -1549,7 +1549,7 @@ static int security_context_to_sid_core(struct selinux_state *state,
 	if (!scontext2)
 		return -ENOMEM;
 
-	if (!state->initialized) {
+	if (!selinux_initialized(state)) {
 		int i;
 
 		for (i = 1; i < SECINITSID_NUM; i++) {
@@ -1736,7 +1736,7 @@ static int security_compute_sid(struct selinux_state *state,
 	int rc = 0;
 	bool sock;
 
-	if (!state->initialized) {
+	if (!selinux_initialized(state)) {
 		switch (orig_tclass) {
 		case SECCLASS_PROCESS: /* kernel value */
 			*out_sid = ssid;
@@ -2198,7 +2198,7 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len)
 		goto out;
 	}
 
-	if (!state->initialized) {
+	if (!selinux_initialized(state)) {
 		rc = policydb_read(policydb, fp);
 		if (rc) {
 			kfree(newsidtab);
@@ -2223,7 +2223,7 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len)
 
 		state->ss->sidtab = newsidtab;
 		security_load_policycaps(state);
-		state->initialized = 1;
+		selinux_mark_initialized(state);
 		seqno = ++state->ss->latest_granting;
 		selinux_complete_init();
 		avc_ss_reset(state->avc, seqno);
@@ -2639,7 +2639,7 @@ int security_get_user_sids(struct selinux_state *state,
 	*sids = NULL;
 	*nel = 0;
 
-	if (!state->initialized)
+	if (!selinux_initialized(state))
 		goto out;
 
 	read_lock(&state->ss->policy_rwlock);
@@ -2875,7 +2875,7 @@ int security_get_bools(struct selinux_state *state,
 	struct policydb *policydb;
 	int i, rc;
 
-	if (!state->initialized) {
+	if (!selinux_initialized(state)) {
 		*len = 0;
 		*names = NULL;
 		*values = NULL;
@@ -3050,7 +3050,7 @@ int security_sid_mls_copy(struct selinux_state *state,
 	int rc;
 
 	rc = 0;
-	if (!state->initialized || !policydb->mls_enabled) {
+	if (!selinux_initialized(state) || !policydb->mls_enabled) {
 		*new_sid = sid;
 		goto out;
 	}
@@ -3217,7 +3217,7 @@ int security_get_classes(struct selinux_state *state,
 	struct policydb *policydb = &state->ss->policydb;
 	int rc;
 
-	if (!state->initialized) {
+	if (!selinux_initialized(state)) {
 		*nclasses = 0;
 		*classes = NULL;
 		return 0;
@@ -3366,7 +3366,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 
 	*rule = NULL;
 
-	if (!state->initialized)
+	if (!selinux_initialized(state))
 		return -EOPNOTSUPP;
 
 	switch (field) {
@@ -3665,7 +3665,7 @@ int security_netlbl_secattr_to_sid(struct selinux_state *state,
 	struct context *ctx;
 	struct context ctx_new;
 
-	if (!state->initialized) {
+	if (!selinux_initialized(state)) {
 		*sid = SECSID_NULL;
 		return 0;
 	}
@@ -3732,7 +3732,7 @@ int security_netlbl_sid_to_secattr(struct selinux_state *state,
 	int rc;
 	struct context *ctx;
 
-	if (!state->initialized)
+	if (!selinux_initialized(state))
 		return 0;
 
 	read_lock(&state->ss->policy_rwlock);
@@ -3771,7 +3771,7 @@ int security_read_policy(struct selinux_state *state,
 	int rc;
 	struct policy_file fp;
 
-	if (!state->initialized)
+	if (!selinux_initialized(state))
 		return -EINVAL;
 
 	*len = security_policydb_len(state);
-- 
2.24.1


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

* [PATCH 2/2] security,selinux: get rid of security_delete_hooks()
  2020-01-07 13:31 [PATCH 0/2] LSM: Drop security_delete_hooks() Ondrej Mosnacek
  2020-01-07 13:31 ` [PATCH 1/2] selinux: treat atomic flags more carefully Ondrej Mosnacek
@ 2020-01-07 13:31 ` Ondrej Mosnacek
  2020-01-07 14:47   ` [PATCH 2/2] security, selinux: " Stephen Smalley
                     ` (3 more replies)
  1 sibling, 4 replies; 18+ messages in thread
From: Ondrej Mosnacek @ 2020-01-07 13:31 UTC (permalink / raw)
  To: linux-security-module, James Morris, Serge E. Hallyn
  Cc: Casey Schaufler, selinux, Paul Moore, Stephen Smalley,
	John Johansen, Kees Cook, Micah Morton, Tetsuo Handa

The only user is SELinux, which is hereby converted to check the
disabled flag in each hook instead of removing the hooks from the list.

The __lsm_ro_after_init macro is now removed and replaced with
__ro_after_init directly.

This fixes a race condition in SELinux runtime disable, which was
introduced with the switch to hook lists in b1d9e6b0646d ("LSM: Switch
to lists of hooks").

Suggested-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
---
 include/linux/lsm_hooks.h    |  31 --
 security/Kconfig             |   5 -
 security/apparmor/lsm.c      |   6 +-
 security/commoncap.c         |   2 +-
 security/loadpin/loadpin.c   |   2 +-
 security/lockdown/lockdown.c |   2 +-
 security/security.c          |   5 +-
 security/selinux/Kconfig     |   6 -
 security/selinux/hooks.c     | 742 ++++++++++++++++++++++++++++++-----
 security/smack/smack_lsm.c   |   4 +-
 security/tomoyo/tomoyo.c     |   6 +-
 security/yama/yama_lsm.c     |   2 +-
 12 files changed, 654 insertions(+), 159 deletions(-)

diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 20d8cf194fb7..5064060ce910 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -27,7 +27,6 @@
 
 #include <linux/security.h>
 #include <linux/init.h>
-#include <linux/rculist.h>
 
 /**
  * union security_list_options - Linux Security Module hook function list
@@ -2145,36 +2144,6 @@ extern struct lsm_info __start_early_lsm_info[], __end_early_lsm_info[];
 		__used __section(.early_lsm_info.init)			\
 		__aligned(sizeof(unsigned long))
 
-#ifdef CONFIG_SECURITY_SELINUX_DISABLE
-/*
- * Assuring the safety of deleting a security module is up to
- * the security module involved. This may entail ordering the
- * module's hook list in a particular way, refusing to disable
- * the module once a policy is loaded or any number of other
- * actions better imagined than described.
- *
- * The name of the configuration option reflects the only module
- * that currently uses the mechanism. Any developer who thinks
- * disabling their module is a good idea needs to be at least as
- * careful as the SELinux team.
- */
-static inline void security_delete_hooks(struct security_hook_list *hooks,
-						int count)
-{
-	int i;
-
-	for (i = 0; i < count; i++)
-		hlist_del_rcu(&hooks[i].list);
-}
-#endif /* CONFIG_SECURITY_SELINUX_DISABLE */
-
-/* Currently required to handle SELinux runtime hook disable. */
-#ifdef CONFIG_SECURITY_WRITABLE_HOOKS
-#define __lsm_ro_after_init
-#else
-#define __lsm_ro_after_init	__ro_after_init
-#endif /* CONFIG_SECURITY_WRITABLE_HOOKS */
-
 extern int lsm_inode_alloc(struct inode *inode);
 
 #endif /* ! __LINUX_LSM_HOOKS_H */
diff --git a/security/Kconfig b/security/Kconfig
index 2a1a2d396228..456764990a13 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -32,11 +32,6 @@ config SECURITY
 
 	  If you are unsure how to answer this question, answer N.
 
-config SECURITY_WRITABLE_HOOKS
-	depends on SECURITY
-	bool
-	default n
-
 config SECURITYFS
 	bool "Enable the securityfs filesystem"
 	help
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index b621ad74f54a..cd83812a440f 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -1158,13 +1158,13 @@ static int apparmor_inet_conn_request(struct sock *sk, struct sk_buff *skb,
 /*
  * The cred blob is a pointer to, not an instance of, an aa_task_ctx.
  */
-struct lsm_blob_sizes apparmor_blob_sizes __lsm_ro_after_init = {
+struct lsm_blob_sizes apparmor_blob_sizes __ro_after_init = {
 	.lbs_cred = sizeof(struct aa_task_ctx *),
 	.lbs_file = sizeof(struct aa_file_ctx),
 	.lbs_task = sizeof(struct aa_task_ctx),
 };
 
-static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
+static struct security_hook_list apparmor_hooks[] __ro_after_init = {
 	LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
 	LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
 	LSM_HOOK_INIT(capget, apparmor_capget),
@@ -1368,7 +1368,7 @@ static const struct kernel_param_ops param_ops_aaintbool = {
 	.get = param_get_aaintbool
 };
 /* Boot time disable flag */
-static int apparmor_enabled __lsm_ro_after_init = 1;
+static int apparmor_enabled __ro_after_init = 1;
 module_param_named(enabled, apparmor_enabled, aaintbool, 0444);
 
 static int __init apparmor_enabled_setup(char *str)
diff --git a/security/commoncap.c b/security/commoncap.c
index f4ee0ae106b2..1471d9a5a9bc 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -1339,7 +1339,7 @@ int cap_mmap_file(struct file *file, unsigned long reqprot,
 
 #ifdef CONFIG_SECURITY
 
-static struct security_hook_list capability_hooks[] __lsm_ro_after_init = {
+static struct security_hook_list capability_hooks[] __ro_after_init = {
 	LSM_HOOK_INIT(capable, cap_capable),
 	LSM_HOOK_INIT(settime, cap_settime),
 	LSM_HOOK_INIT(ptrace_access_check, cap_ptrace_access_check),
diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c
index ee5cb944f4ad..9bbc08bee2c0 100644
--- a/security/loadpin/loadpin.c
+++ b/security/loadpin/loadpin.c
@@ -180,7 +180,7 @@ static int loadpin_load_data(enum kernel_load_data_id id)
 	return loadpin_read_file(NULL, (enum kernel_read_file_id) id);
 }
 
-static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = {
+static struct security_hook_list loadpin_hooks[] __ro_after_init = {
 	LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security),
 	LSM_HOOK_INIT(kernel_read_file, loadpin_read_file),
 	LSM_HOOK_INIT(kernel_load_data, loadpin_load_data),
diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c
index 5a952617a0eb..8071d0f542c8 100644
--- a/security/lockdown/lockdown.c
+++ b/security/lockdown/lockdown.c
@@ -71,7 +71,7 @@ static int lockdown_is_locked_down(enum lockdown_reason what)
 	return 0;
 }
 
-static struct security_hook_list lockdown_hooks[] __lsm_ro_after_init = {
+static struct security_hook_list lockdown_hooks[] __ro_after_init = {
 	LSM_HOOK_INIT(locked_down, lockdown_is_locked_down),
 };
 
diff --git a/security/security.c b/security/security.c
index 2b5473d92416..3138a5d99813 100644
--- a/security/security.c
+++ b/security/security.c
@@ -27,6 +27,7 @@
 #include <linux/backing-dev.h>
 #include <linux/string.h>
 #include <linux/msg.h>
+#include <linux/rculist.h>
 #include <net/flow.h>
 
 #define MAX_LSM_EVM_XATTR	2
@@ -68,14 +69,14 @@ const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {
 	[LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality",
 };
 
-struct security_hook_heads security_hook_heads __lsm_ro_after_init;
+struct security_hook_heads security_hook_heads __ro_after_init;
 static BLOCKING_NOTIFIER_HEAD(blocking_lsm_notifier_chain);
 
 static struct kmem_cache *lsm_file_cache;
 static struct kmem_cache *lsm_inode_cache;
 
 char *lsm_names;
-static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init;
+static struct lsm_blob_sizes blob_sizes __ro_after_init;
 
 /* Boot-time LSM user choice */
 static __initdata const char *chosen_lsm_order;
diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
index 996d35d950f7..caa5711478ad 100644
--- a/security/selinux/Kconfig
+++ b/security/selinux/Kconfig
@@ -26,7 +26,6 @@ config SECURITY_SELINUX_BOOTPARAM
 config SECURITY_SELINUX_DISABLE
 	bool "NSA SELinux runtime disable"
 	depends on SECURITY_SELINUX
-	select SECURITY_WRITABLE_HOOKS
 	default n
 	help
 	  This option enables writing to a selinuxfs node 'disable', which
@@ -37,11 +36,6 @@ config SECURITY_SELINUX_DISABLE
 	  portability across platforms where boot parameters are difficult
 	  to employ.
 
-	  NOTE: selecting this option will disable the '__ro_after_init'
-	  kernel hardening feature for security hooks.   Please consider
-	  using the selinux=0 boot parameter instead of enabling this
-	  option.
-
 	  If you are unsure how to answer this question, answer N.
 
 config SECURITY_SELINUX_DEVELOP
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 47ad4db925cf..9ac2b6b69ff9 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -650,13 +650,15 @@ static int selinux_set_mnt_opts(struct super_block *sb,
 {
 	const struct cred *cred = current_cred();
 	struct superblock_security_struct *sbsec = sb->s_security;
-	struct dentry *root = sbsec->sb->s_root;
 	struct selinux_mnt_opts *opts = mnt_opts;
 	struct inode_security_struct *root_isec;
 	u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
 	u32 defcontext_sid = 0;
 	int rc = 0;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	mutex_lock(&sbsec->lock);
 
 	if (!selinux_initialized(&selinux_state)) {
@@ -693,7 +695,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
 	    && !opts)
 		goto out;
 
-	root_isec = backing_inode_security_novalidate(root);
+	root_isec = backing_inode_security_novalidate(sbsec->sb->s_root);
 
 	/*
 	 * parse the mount options, check if they are valid sids.
@@ -919,10 +921,14 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
 	int rc = 0;
 	const struct superblock_security_struct *oldsbsec = oldsb->s_security;
 	struct superblock_security_struct *newsbsec = newsb->s_security;
+	int set_fscontext, set_context, set_rootcontext;
+
+	if (selinux_disabled(&selinux_state))
+		return 0;
 
-	int set_fscontext =	(oldsbsec->flags & FSCONTEXT_MNT);
-	int set_context =	(oldsbsec->flags & CONTEXT_MNT);
-	int set_rootcontext =	(oldsbsec->flags & ROOTCONTEXT_MNT);
+	set_fscontext =		(oldsbsec->flags & FSCONTEXT_MNT);
+	set_context =		(oldsbsec->flags & CONTEXT_MNT);
+	set_rootcontext =	(oldsbsec->flags & ROOTCONTEXT_MNT);
 
 	/*
 	 * if the parent was able to be mounted it clearly had no special lsm
@@ -1041,6 +1047,9 @@ static int selinux_add_mnt_opt(const char *option, const char *val, int len,
 	int token = Opt_error;
 	int rc, i;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	for (i = 0; i < ARRAY_SIZE(tokens); i++) {
 		if (strcmp(option, tokens[i].name) == 0) {
 			token = tokens[i].opt;
@@ -1100,6 +1109,9 @@ static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
 	struct superblock_security_struct *sbsec = sb->s_security;
 	int rc;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	if (!(sbsec->flags & SE_SBINITIALIZED))
 		return 0;
 
@@ -2044,22 +2056,27 @@ static inline u32 open_file_to_av(struct file *file)
 
 static int selinux_binder_set_context_mgr(struct task_struct *mgr)
 {
-	u32 mysid = current_sid();
-	u32 mgrsid = task_sid(mgr);
+	if (selinux_disabled(&selinux_state))
+		return 0;
 
 	return avc_has_perm(&selinux_state,
-			    mysid, mgrsid, SECCLASS_BINDER,
+			    current_sid(), task_sid(mgr), SECCLASS_BINDER,
 			    BINDER__SET_CONTEXT_MGR, NULL);
 }
 
 static int selinux_binder_transaction(struct task_struct *from,
 				      struct task_struct *to)
 {
-	u32 mysid = current_sid();
-	u32 fromsid = task_sid(from);
-	u32 tosid = task_sid(to);
+	u32 mysid, fromsid, tosid;
 	int rc;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
+	mysid = current_sid();
+	fromsid = task_sid(from);
+	tosid = task_sid(to);
+
 	if (mysid != fromsid) {
 		rc = avc_has_perm(&selinux_state,
 				  mysid, fromsid, SECCLASS_BINDER,
@@ -2076,11 +2093,12 @@ static int selinux_binder_transaction(struct task_struct *from,
 static int selinux_binder_transfer_binder(struct task_struct *from,
 					  struct task_struct *to)
 {
-	u32 fromsid = task_sid(from);
-	u32 tosid = task_sid(to);
+	if (selinux_disabled(&selinux_state))
+		return 0;
 
 	return avc_has_perm(&selinux_state,
-			    fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
+			    task_sid(from), task_sid(to),
+			    SECCLASS_BINDER, BINDER__TRANSFER,
 			    NULL);
 }
 
@@ -2088,13 +2106,18 @@ static int selinux_binder_transfer_file(struct task_struct *from,
 					struct task_struct *to,
 					struct file *file)
 {
-	u32 sid = task_sid(to);
+	u32 sid;
 	struct file_security_struct *fsec = selinux_file(file);
 	struct dentry *dentry = file->f_path.dentry;
 	struct inode_security_struct *isec;
 	struct common_audit_data ad;
 	int rc;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
+	sid = task_sid(to);
+
 	ad.type = LSM_AUDIT_DATA_PATH;
 	ad.u.path = file->f_path;
 
@@ -2126,19 +2149,26 @@ static int selinux_binder_transfer_file(struct task_struct *from,
 static int selinux_ptrace_access_check(struct task_struct *child,
 				     unsigned int mode)
 {
-	u32 sid = current_sid();
-	u32 csid = task_sid(child);
+	u16 cls = SECCLASS_PROCESS;
+	u32 perm = PROCESS__PTRACE;
 
-	if (mode & PTRACE_MODE_READ)
-		return avc_has_perm(&selinux_state,
-				    sid, csid, SECCLASS_FILE, FILE__READ, NULL);
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
+	if (mode & PTRACE_MODE_READ) {
+		cls = SECCLASS_FILE;
+		perm = FILE__READ;
+	}
 
 	return avc_has_perm(&selinux_state,
-			    sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL);
+			    current_sid(), task_sid(child), cls, perm, NULL);
 }
 
 static int selinux_ptrace_traceme(struct task_struct *parent)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return avc_has_perm(&selinux_state,
 			    task_sid(parent), current_sid(), SECCLASS_PROCESS,
 			    PROCESS__PTRACE, NULL);
@@ -2147,6 +2177,9 @@ static int selinux_ptrace_traceme(struct task_struct *parent)
 static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
 			  kernel_cap_t *inheritable, kernel_cap_t *permitted)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return avc_has_perm(&selinux_state,
 			    current_sid(), task_sid(target), SECCLASS_PROCESS,
 			    PROCESS__GETCAP, NULL);
@@ -2157,6 +2190,9 @@ static int selinux_capset(struct cred *new, const struct cred *old,
 			  const kernel_cap_t *inheritable,
 			  const kernel_cap_t *permitted)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return avc_has_perm(&selinux_state,
 			    cred_sid(old), cred_sid(new), SECCLASS_PROCESS,
 			    PROCESS__SETCAP, NULL);
@@ -2175,6 +2211,9 @@ static int selinux_capset(struct cred *new, const struct cred *old,
 static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
 			   int cap, unsigned int opts)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return cred_has_capability(cred, cap, opts, ns == &init_user_ns);
 }
 
@@ -2186,6 +2225,9 @@ static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
 	if (!sb)
 		return 0;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	switch (cmds) {
 	case Q_SYNC:
 	case Q_QUOTAON:
@@ -2210,11 +2252,17 @@ static int selinux_quota_on(struct dentry *dentry)
 {
 	const struct cred *cred = current_cred();
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return dentry_has_perm(cred, dentry, FILE__QUOTAON);
 }
 
 static int selinux_syslog(int type)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	switch (type) {
 	case SYSLOG_ACTION_READ_ALL:	/* Read last kernel messages */
 	case SYSLOG_ACTION_SIZE_BUFFER:	/* Return size of the log buffer */
@@ -2248,6 +2296,9 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
 {
 	int rc, cap_sys_admin = 0;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
 				 CAP_OPT_NOAUDIT, true);
 	if (rc == 0)
@@ -2335,6 +2386,9 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
 	struct inode *inode = file_inode(bprm->file);
 	int rc;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	/* SELinux context only depends on initial program or script and not
 	 * the script interpreter */
 	if (bprm->called_set_creds)
@@ -2505,6 +2559,9 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
 	struct rlimit *rlim, *initrlim;
 	int rc, i;
 
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	new_tsec = selinux_cred(bprm->cred);
 	if (new_tsec->sid == new_tsec->osid)
 		return;
@@ -2552,6 +2609,9 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
 	u32 osid, sid;
 	int rc;
 
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	osid = tsec->osid;
 	sid = tsec->sid;
 
@@ -2592,11 +2652,17 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
 
 static int selinux_sb_alloc_security(struct super_block *sb)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return superblock_alloc_security(sb);
 }
 
 static void selinux_sb_free_security(struct super_block *sb)
 {
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	superblock_free_security(sb);
 }
 
@@ -2622,6 +2688,9 @@ static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts)
 	bool first = true;
 	int rc;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	while (1) {
 		int len = opt_len(from);
 		int token;
@@ -2682,6 +2751,9 @@ static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
 	u32 sid;
 	int rc;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	if (!(sbsec->flags & SE_SBINITIALIZED))
 		return 0;
 
@@ -2732,6 +2804,9 @@ static int selinux_sb_kern_mount(struct super_block *sb)
 	const struct cred *cred = current_cred();
 	struct common_audit_data ad;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	ad.type = LSM_AUDIT_DATA_DENTRY;
 	ad.u.dentry = sb->s_root;
 	return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
@@ -2742,6 +2817,9 @@ static int selinux_sb_statfs(struct dentry *dentry)
 	const struct cred *cred = current_cred();
 	struct common_audit_data ad;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	ad.type = LSM_AUDIT_DATA_DENTRY;
 	ad.u.dentry = dentry->d_sb->s_root;
 	return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
@@ -2755,6 +2833,9 @@ static int selinux_mount(const char *dev_name,
 {
 	const struct cred *cred = current_cred();
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	if (flags & MS_REMOUNT)
 		return superblock_has_perm(cred, path->dentry->d_sb,
 					   FILESYSTEM__REMOUNT, NULL);
@@ -2766,6 +2847,9 @@ static int selinux_umount(struct vfsmount *mnt, int flags)
 {
 	const struct cred *cred = current_cred();
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return superblock_has_perm(cred, mnt->mnt_sb,
 				   FILESYSTEM__UNMOUNT, NULL);
 }
@@ -2776,6 +2860,9 @@ static int selinux_fs_context_dup(struct fs_context *fc,
 	const struct selinux_mnt_opts *src = src_fc->security;
 	struct selinux_mnt_opts *opts;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	if (!src)
 		return 0;
 
@@ -2828,6 +2915,9 @@ static int selinux_fs_context_parse_param(struct fs_context *fc,
 	struct fs_parse_result result;
 	int opt, rc;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	opt = fs_parse(fc, &selinux_fs_parameters, param, &result);
 	if (opt < 0)
 		return opt;
@@ -2844,11 +2934,17 @@ static int selinux_fs_context_parse_param(struct fs_context *fc,
 
 static int selinux_inode_alloc_security(struct inode *inode)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return inode_alloc_security(inode);
 }
 
 static void selinux_inode_free_security(struct inode *inode)
 {
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	inode_free_security(inode);
 }
 
@@ -2859,6 +2955,9 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,
 	u32 newsid;
 	int rc;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	rc = selinux_determine_inode_label(selinux_cred(current_cred()),
 					   d_inode(dentry->d_parent), name,
 					   inode_mode_to_security_class(mode),
@@ -2879,6 +2978,9 @@ static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
 	int rc;
 	struct task_security_struct *tsec;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	rc = selinux_determine_inode_label(selinux_cred(old),
 					   d_inode(dentry->d_parent), name,
 					   inode_mode_to_security_class(mode),
@@ -2902,6 +3004,9 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
 	int rc;
 	char *context;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	sbsec = dir->i_sb->s_security;
 
 	newsid = tsec->create_sid;
@@ -2941,50 +3046,75 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
 
 static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return may_create(dir, dentry, SECCLASS_FILE);
 }
 
 static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return may_link(dir, old_dentry, MAY_LINK);
 }
 
 static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return may_link(dir, dentry, MAY_UNLINK);
 }
 
 static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return may_create(dir, dentry, SECCLASS_LNK_FILE);
 }
 
 static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return may_create(dir, dentry, SECCLASS_DIR);
 }
 
 static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return may_link(dir, dentry, MAY_RMDIR);
 }
 
 static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return may_create(dir, dentry, inode_mode_to_security_class(mode));
 }
 
 static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
 				struct inode *new_inode, struct dentry *new_dentry)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return may_rename(old_inode, old_dentry, new_inode, new_dentry);
 }
 
 static int selinux_inode_readlink(struct dentry *dentry)
 {
-	const struct cred *cred = current_cred();
+	if (selinux_disabled(&selinux_state))
+		return 0;
 
-	return dentry_has_perm(cred, dentry, FILE__READ);
+	return dentry_has_perm(current_cred(), dentry, FILE__READ);
 }
 
 static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
@@ -2995,6 +3125,9 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
 	struct inode_security_struct *isec;
 	u32 sid;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	validate_creds(cred);
 
 	ad.type = LSM_AUDIT_DATA_DENTRY;
@@ -3040,6 +3173,9 @@ static int selinux_inode_permission(struct inode *inode, int mask)
 	int rc, rc2;
 	u32 audited, denied;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	from_access = mask & MAY_ACCESS;
 	mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
 
@@ -3086,6 +3222,9 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
 	unsigned int ia_valid = iattr->ia_valid;
 	__u32 av = FILE__WRITE;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	/* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
 	if (ia_valid & ATTR_FORCE) {
 		ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
@@ -3109,6 +3248,9 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
 
 static int selinux_inode_getattr(const struct path *path)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return path_has_perm(current_cred(), path, FILE__GETATTR);
 }
 
@@ -3131,9 +3273,12 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
 	struct inode_security_struct *isec;
 	struct superblock_security_struct *sbsec;
 	struct common_audit_data ad;
-	u32 newsid, sid = current_sid();
+	u32 newsid, sid;
 	int rc = 0;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	if (strcmp(name, XATTR_NAME_SELINUX)) {
 		rc = cap_inode_setxattr(dentry, name, value, size, flags);
 		if (rc)
@@ -3154,6 +3299,8 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
 	if (!inode_owner_or_capable(inode))
 		return -EPERM;
 
+	sid = current_sid();
+
 	ad.type = LSM_AUDIT_DATA_DENTRY;
 	ad.u.dentry = dentry;
 
@@ -3225,6 +3372,9 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
 	u32 newsid;
 	int rc;
 
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	if (strcmp(name, XATTR_NAME_SELINUX)) {
 		/* Not an attribute we recognize, so nothing to do. */
 		return;
@@ -3260,20 +3410,25 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
 
 static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
 {
-	const struct cred *cred = current_cred();
+	if (selinux_disabled(&selinux_state))
+		return 0;
 
-	return dentry_has_perm(cred, dentry, FILE__GETATTR);
+	return dentry_has_perm(current_cred(), dentry, FILE__GETATTR);
 }
 
 static int selinux_inode_listxattr(struct dentry *dentry)
 {
-	const struct cred *cred = current_cred();
+	if (selinux_disabled(&selinux_state))
+		return 0;
 
-	return dentry_has_perm(cred, dentry, FILE__GETATTR);
+	return dentry_has_perm(current_cred(), dentry, FILE__GETATTR);
 }
 
 static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	if (strcmp(name, XATTR_NAME_SELINUX)) {
 		int rc = cap_inode_removexattr(dentry, name);
 		if (rc)
@@ -3297,6 +3452,9 @@ static int selinux_path_notify(const struct path *path, u64 mask,
 
 	struct common_audit_data ad;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	ad.type = LSM_AUDIT_DATA_PATH;
 	ad.u.path = *path;
 
@@ -3345,6 +3503,9 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void
 	char *context = NULL;
 	struct inode_security_struct *isec;
 
+	if (selinux_disabled(&selinux_state))
+		return -EOPNOTSUPP;
+
 	if (strcmp(name, XATTR_SELINUX_SUFFIX))
 		return -EOPNOTSUPP;
 
@@ -3385,6 +3546,9 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
 	u32 newsid;
 	int rc;
 
+	if (selinux_disabled(&selinux_state))
+		return -EOPNOTSUPP;
+
 	if (strcmp(name, XATTR_SELINUX_SUFFIX))
 		return -EOPNOTSUPP;
 
@@ -3410,6 +3574,10 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
 static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
 {
 	const int len = sizeof(XATTR_NAME_SELINUX);
+
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	if (buffer && len <= buffer_size)
 		memcpy(buffer, XATTR_NAME_SELINUX, len);
 	return len;
@@ -3417,16 +3585,24 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t
 
 static void selinux_inode_getsecid(struct inode *inode, u32 *secid)
 {
-	struct inode_security_struct *isec = inode_security_novalidate(inode);
+	struct inode_security_struct *isec;
+
+	if (selinux_disabled(&selinux_state))
+		return;
+
+	isec = inode_security_novalidate(inode);
 	*secid = isec->sid;
 }
 
 static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
 {
-	u32 sid;
+	struct inode_security_struct *isec;
 	struct task_security_struct *tsec;
 	struct cred *new_creds = *new;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	if (new_creds == NULL) {
 		new_creds = prepare_creds();
 		if (!new_creds)
@@ -3435,14 +3611,17 @@ static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
 
 	tsec = selinux_cred(new_creds);
 	/* Get label from overlay inode and set it in create_sid */
-	selinux_inode_getsecid(d_inode(src), &sid);
-	tsec->create_sid = sid;
+	isec = inode_security_novalidate(d_inode(src));
+	tsec->create_sid = isec->sid;
 	*new = new_creds;
 	return 0;
 }
 
 static int selinux_inode_copy_up_xattr(const char *name)
 {
+	if (selinux_disabled(&selinux_state))
+		return -EOPNOTSUPP;
+
 	/* The copy_up hook above sets the initial context on an inode, but we
 	 * don't then want to overwrite it by blindly copying all the lower
 	 * xattrs up.  Instead, we have to filter out SELinux-related xattrs.
@@ -3466,6 +3645,9 @@ static int selinux_kernfs_init_security(struct kernfs_node *kn_dir,
 	int rc;
 	char *context;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	rc = kernfs_xattr_get(kn_dir, XATTR_NAME_SELINUX, NULL, 0);
 	if (rc == -ENODATA)
 		return 0;
@@ -3537,14 +3719,16 @@ static int selinux_file_permission(struct file *file, int mask)
 	struct inode *inode = file_inode(file);
 	struct file_security_struct *fsec = selinux_file(file);
 	struct inode_security_struct *isec;
-	u32 sid = current_sid();
+
+	if (selinux_disabled(&selinux_state))
+		return 0;
 
 	if (!mask)
 		/* No permission to check.  Existence test. */
 		return 0;
 
 	isec = inode_security(inode);
-	if (sid == fsec->sid && fsec->isid == isec->sid &&
+	if (current_sid() == fsec->sid && fsec->isid == isec->sid &&
 	    fsec->pseqno == avc_policy_seqno(&selinux_state))
 		/* No change since file_open check. */
 		return 0;
@@ -3554,6 +3738,9 @@ static int selinux_file_permission(struct file *file, int mask)
 
 static int selinux_file_alloc_security(struct file *file)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return file_alloc_security(file);
 }
 
@@ -3606,6 +3793,9 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
 	const struct cred *cred = current_cred();
 	int error = 0;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	switch (cmd) {
 	case FIONREAD:
 	/* fall through */
@@ -3692,6 +3882,9 @@ static int selinux_mmap_addr(unsigned long addr)
 {
 	int rc = 0;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
 		u32 sid = current_sid();
 		rc = avc_has_perm(&selinux_state,
@@ -3708,6 +3901,9 @@ static int selinux_mmap_file(struct file *file, unsigned long reqprot,
 	struct common_audit_data ad;
 	int rc;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	if (file) {
 		ad.type = LSM_AUDIT_DATA_FILE;
 		ad.u.file = file;
@@ -3729,7 +3925,12 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
 				 unsigned long prot)
 {
 	const struct cred *cred = current_cred();
-	u32 sid = cred_sid(cred);
+	u32 sid;
+
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
+	sid = cred_sid(cred);
 
 	if (selinux_state.checkreqprot)
 		prot = reqprot;
@@ -3768,9 +3969,10 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
 
 static int selinux_file_lock(struct file *file, unsigned int cmd)
 {
-	const struct cred *cred = current_cred();
+	if (selinux_disabled(&selinux_state))
+		return 0;
 
-	return file_has_perm(cred, file, FILE__LOCK);
+	return file_has_perm(current_cred(), file, FILE__LOCK);
 }
 
 static int selinux_file_fcntl(struct file *file, unsigned int cmd,
@@ -3779,6 +3981,9 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
 	const struct cred *cred = current_cred();
 	int err = 0;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	switch (cmd) {
 	case F_SETFL:
 		if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
@@ -3817,6 +4022,9 @@ static void selinux_file_set_fowner(struct file *file)
 {
 	struct file_security_struct *fsec;
 
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	fsec = selinux_file(file);
 	fsec->fown_sid = current_sid();
 }
@@ -3825,10 +4033,12 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk,
 				       struct fown_struct *fown, int signum)
 {
 	struct file *file;
-	u32 sid = task_sid(tsk);
 	u32 perm;
 	struct file_security_struct *fsec;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	/* struct fown_struct is never outside the context of a struct file */
 	file = container_of(fown, struct file, f_owner);
 
@@ -3840,15 +4050,16 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk,
 		perm = signal_to_av(signum);
 
 	return avc_has_perm(&selinux_state,
-			    fsec->fown_sid, sid,
+			    fsec->fown_sid, task_sid(tsk),
 			    SECCLASS_PROCESS, perm, NULL);
 }
 
 static int selinux_file_receive(struct file *file)
 {
-	const struct cred *cred = current_cred();
+	if (selinux_disabled(&selinux_state))
+		return 0;
 
-	return file_has_perm(cred, file, file_to_av(file));
+	return file_has_perm(current_cred(), file, file_to_av(file));
 }
 
 static int selinux_file_open(struct file *file)
@@ -3856,6 +4067,9 @@ static int selinux_file_open(struct file *file)
 	struct file_security_struct *fsec;
 	struct inode_security_struct *isec;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	fsec = selinux_file(file);
 	isec = inode_security(file_inode(file));
 	/*
@@ -3883,7 +4097,12 @@ static int selinux_file_open(struct file *file)
 static int selinux_task_alloc(struct task_struct *task,
 			      unsigned long clone_flags)
 {
-	u32 sid = current_sid();
+	u32 sid;
+
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
+	sid = current_sid();
 
 	return avc_has_perm(&selinux_state,
 			    sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL);
@@ -3898,6 +4117,9 @@ static int selinux_cred_prepare(struct cred *new, const struct cred *old,
 	const struct task_security_struct *old_tsec = selinux_cred(old);
 	struct task_security_struct *tsec = selinux_cred(new);
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	*tsec = *old_tsec;
 	return 0;
 }
@@ -3910,11 +4132,17 @@ static void selinux_cred_transfer(struct cred *new, const struct cred *old)
 	const struct task_security_struct *old_tsec = selinux_cred(old);
 	struct task_security_struct *tsec = selinux_cred(new);
 
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	*tsec = *old_tsec;
 }
 
 static void selinux_cred_getsecid(const struct cred *c, u32 *secid)
 {
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	*secid = cred_sid(c);
 }
 
@@ -3925,11 +4153,13 @@ static void selinux_cred_getsecid(const struct cred *c, u32 *secid)
 static int selinux_kernel_act_as(struct cred *new, u32 secid)
 {
 	struct task_security_struct *tsec = selinux_cred(new);
-	u32 sid = current_sid();
 	int ret;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	ret = avc_has_perm(&selinux_state,
-			   sid, secid,
+			   current_sid(), secid,
 			   SECCLASS_KERNEL_SERVICE,
 			   KERNEL_SERVICE__USE_AS_OVERRIDE,
 			   NULL);
@@ -3950,11 +4180,13 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
 {
 	struct inode_security_struct *isec = inode_security(inode);
 	struct task_security_struct *tsec = selinux_cred(new);
-	u32 sid = current_sid();
 	int ret;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	ret = avc_has_perm(&selinux_state,
-			   sid, isec->sid,
+			   current_sid(), isec->sid,
 			   SECCLASS_KERNEL_SERVICE,
 			   KERNEL_SERVICE__CREATE_FILES_AS,
 			   NULL);
@@ -3968,6 +4200,9 @@ static int selinux_kernel_module_request(char *kmod_name)
 {
 	struct common_audit_data ad;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	ad.type = LSM_AUDIT_DATA_KMOD;
 	ad.u.kmod_name = kmod_name;
 
@@ -4012,35 +4247,37 @@ static int selinux_kernel_module_from_file(struct file *file)
 static int selinux_kernel_read_file(struct file *file,
 				    enum kernel_read_file_id id)
 {
-	int rc = 0;
+	if (selinux_disabled(&selinux_state))
+		return 0;
 
 	switch (id) {
 	case READING_MODULE:
-		rc = selinux_kernel_module_from_file(file);
-		break;
+		return selinux_kernel_module_from_file(file);
 	default:
 		break;
 	}
-
-	return rc;
+	return 0;
 }
 
 static int selinux_kernel_load_data(enum kernel_load_data_id id)
 {
-	int rc = 0;
+	if (selinux_disabled(&selinux_state))
+		return 0;
 
 	switch (id) {
 	case LOADING_MODULE:
-		rc = selinux_kernel_module_from_file(NULL);
+		return selinux_kernel_module_from_file(NULL);
 	default:
 		break;
 	}
-
-	return rc;
+	return 0;
 }
 
 static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return avc_has_perm(&selinux_state,
 			    current_sid(), task_sid(p), SECCLASS_PROCESS,
 			    PROCESS__SETPGID, NULL);
@@ -4048,6 +4285,9 @@ static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
 
 static int selinux_task_getpgid(struct task_struct *p)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return avc_has_perm(&selinux_state,
 			    current_sid(), task_sid(p), SECCLASS_PROCESS,
 			    PROCESS__GETPGID, NULL);
@@ -4055,6 +4295,9 @@ static int selinux_task_getpgid(struct task_struct *p)
 
 static int selinux_task_getsid(struct task_struct *p)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return avc_has_perm(&selinux_state,
 			    current_sid(), task_sid(p), SECCLASS_PROCESS,
 			    PROCESS__GETSESSION, NULL);
@@ -4062,11 +4305,17 @@ static int selinux_task_getsid(struct task_struct *p)
 
 static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
 {
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	*secid = task_sid(p);
 }
 
 static int selinux_task_setnice(struct task_struct *p, int nice)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return avc_has_perm(&selinux_state,
 			    current_sid(), task_sid(p), SECCLASS_PROCESS,
 			    PROCESS__SETSCHED, NULL);
@@ -4074,6 +4323,9 @@ static int selinux_task_setnice(struct task_struct *p, int nice)
 
 static int selinux_task_setioprio(struct task_struct *p, int ioprio)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return avc_has_perm(&selinux_state,
 			    current_sid(), task_sid(p), SECCLASS_PROCESS,
 			    PROCESS__SETSCHED, NULL);
@@ -4081,6 +4333,9 @@ static int selinux_task_setioprio(struct task_struct *p, int ioprio)
 
 static int selinux_task_getioprio(struct task_struct *p)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return avc_has_perm(&selinux_state,
 			    current_sid(), task_sid(p), SECCLASS_PROCESS,
 			    PROCESS__GETSCHED, NULL);
@@ -4091,6 +4346,9 @@ static int selinux_task_prlimit(const struct cred *cred, const struct cred *tcre
 {
 	u32 av = 0;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	if (!flags)
 		return 0;
 	if (flags & LSM_PRLIMIT_WRITE)
@@ -4107,6 +4365,9 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
 {
 	struct rlimit *old_rlim = p->signal->rlim + resource;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	/* 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
@@ -4121,6 +4382,9 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
 
 static int selinux_task_setscheduler(struct task_struct *p)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return avc_has_perm(&selinux_state,
 			    current_sid(), task_sid(p), SECCLASS_PROCESS,
 			    PROCESS__SETSCHED, NULL);
@@ -4128,6 +4392,9 @@ static int selinux_task_setscheduler(struct task_struct *p)
 
 static int selinux_task_getscheduler(struct task_struct *p)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return avc_has_perm(&selinux_state,
 			    current_sid(), task_sid(p), SECCLASS_PROCESS,
 			    PROCESS__GETSCHED, NULL);
@@ -4135,6 +4402,9 @@ static int selinux_task_getscheduler(struct task_struct *p)
 
 static int selinux_task_movememory(struct task_struct *p)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return avc_has_perm(&selinux_state,
 			    current_sid(), task_sid(p), SECCLASS_PROCESS,
 			    PROCESS__SETSCHED, NULL);
@@ -4146,6 +4416,9 @@ static int selinux_task_kill(struct task_struct *p, struct kernel_siginfo *info,
 	u32 secid;
 	u32 perm;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	if (!sig)
 		perm = PROCESS__SIGNULL; /* null signal; existence test */
 	else
@@ -4162,11 +4435,13 @@ static void selinux_task_to_inode(struct task_struct *p,
 				  struct inode *inode)
 {
 	struct inode_security_struct *isec = selinux_inode(inode);
-	u32 sid = task_sid(p);
+
+	if (selinux_disabled(&selinux_state))
+		return;
 
 	spin_lock(&isec->lock);
 	isec->sclass = inode_mode_to_security_class(inode->i_mode);
-	isec->sid = sid;
+	isec->sid = task_sid(p);
 	isec->initialized = LABEL_INITIALIZED;
 	spin_unlock(&isec->lock);
 }
@@ -4506,6 +4781,9 @@ static int selinux_socket_create(int family, int type,
 	if (kern)
 		return 0;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	secclass = socket_type_to_security_class(family, type, protocol);
 	rc = socket_sockcreate_sid(tsec, secclass, &newsid);
 	if (rc)
@@ -4525,6 +4803,9 @@ static int selinux_socket_post_create(struct socket *sock, int family,
 	u32 sid = SECINITSID_KERNEL;
 	int err = 0;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	if (!kern) {
 		err = socket_sockcreate_sid(tsec, sclass, &sid);
 		if (err)
@@ -4555,6 +4836,9 @@ static int selinux_socket_socketpair(struct socket *socka,
 	struct sk_security_struct *sksec_a = socka->sk->sk_security;
 	struct sk_security_struct *sksec_b = sockb->sk->sk_security;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	sksec_a->peer_sid = sksec_b->sid;
 	sksec_b->peer_sid = sksec_a->sid;
 
@@ -4572,6 +4856,9 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
 	u16 family;
 	int err;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	err = sock_has_perm(sk, SOCKET__BIND);
 	if (err)
 		goto out;
@@ -4796,6 +5083,9 @@ static int selinux_socket_connect(struct socket *sock,
 	int err;
 	struct sock *sk = sock->sk;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	err = selinux_socket_connect_helper(sock, address, addrlen);
 	if (err)
 		return err;
@@ -4805,6 +5095,9 @@ static int selinux_socket_connect(struct socket *sock,
 
 static int selinux_socket_listen(struct socket *sock, int backlog)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return sock_has_perm(sock->sk, SOCKET__LISTEN);
 }
 
@@ -4816,6 +5109,9 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
 	u16 sclass;
 	u32 sid;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	err = sock_has_perm(sock->sk, SOCKET__ACCEPT);
 	if (err)
 		return err;
@@ -4837,22 +5133,34 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
 static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
 				  int size)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return sock_has_perm(sock->sk, SOCKET__WRITE);
 }
 
 static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
 				  int size, int flags)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return sock_has_perm(sock->sk, SOCKET__READ);
 }
 
 static int selinux_socket_getsockname(struct socket *sock)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return sock_has_perm(sock->sk, SOCKET__GETATTR);
 }
 
 static int selinux_socket_getpeername(struct socket *sock)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return sock_has_perm(sock->sk, SOCKET__GETATTR);
 }
 
@@ -4860,6 +5168,9 @@ static int selinux_socket_setsockopt(struct socket *sock, int level, int optname
 {
 	int err;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	err = sock_has_perm(sock->sk, SOCKET__SETOPT);
 	if (err)
 		return err;
@@ -4870,11 +5181,17 @@ static int selinux_socket_setsockopt(struct socket *sock, int level, int optname
 static int selinux_socket_getsockopt(struct socket *sock, int level,
 				     int optname)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return sock_has_perm(sock->sk, SOCKET__GETOPT);
 }
 
 static int selinux_socket_shutdown(struct socket *sock, int how)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return sock_has_perm(sock->sk, SOCKET__SHUTDOWN);
 }
 
@@ -4889,6 +5206,9 @@ static int selinux_socket_unix_stream_connect(struct sock *sock,
 	struct lsm_network_audit net = {0,};
 	int err;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	ad.type = LSM_AUDIT_DATA_NET;
 	ad.u.net = &net;
 	ad.u.net->sk = other;
@@ -4921,6 +5241,9 @@ static int selinux_socket_unix_may_send(struct socket *sock,
 	struct common_audit_data ad;
 	struct lsm_network_audit net = {0,};
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	ad.type = LSM_AUDIT_DATA_NET;
 	ad.u.net = &net;
 	ad.u.net->sk = other->sk;
@@ -4994,13 +5317,15 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
 	int err;
 	struct sk_security_struct *sksec = sk->sk_security;
 	u16 family = sk->sk_family;
-	u32 sk_sid = sksec->sid;
 	struct common_audit_data ad;
 	struct lsm_network_audit net = {0,};
 	char *addrp;
 	u8 secmark_active;
 	u8 peerlbl_active;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	if (family != PF_INET && family != PF_INET6)
 		return 0;
 
@@ -5041,7 +5366,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
 			return err;
 		}
 		err = avc_has_perm(&selinux_state,
-				   sk_sid, peer_sid, SECCLASS_PEER,
+				   sksec->sid, peer_sid, SECCLASS_PEER,
 				   PEER__RECV, &ad);
 		if (err) {
 			selinux_netlbl_err(skb, family, err, 0);
@@ -5051,7 +5376,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
 
 	if (secmark_active) {
 		err = avc_has_perm(&selinux_state,
-				   sk_sid, skb->secmark, SECCLASS_PACKET,
+				   sksec->sid, skb->secmark, SECCLASS_PACKET,
 				   PACKET__RECV, &ad);
 		if (err)
 			return err;
@@ -5069,6 +5394,9 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op
 	struct sk_security_struct *sksec = sock->sk->sk_security;
 	u32 peer_sid = SECSID_NULL;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
 	    sksec->sclass == SECCLASS_TCP_SOCKET ||
 	    sksec->sclass == SECCLASS_SCTP_SOCKET)
@@ -5102,6 +5430,9 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
 	u16 family;
 	struct inode_security_struct *isec;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	if (skb && skb->protocol == htons(ETH_P_IP))
 		family = PF_INET;
 	else if (skb && skb->protocol == htons(ETH_P_IPV6))
@@ -5128,6 +5459,9 @@ static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority
 {
 	struct sk_security_struct *sksec;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	sksec = kzalloc(sizeof(*sksec), priority);
 	if (!sksec)
 		return -ENOMEM;
@@ -5145,6 +5479,9 @@ static void selinux_sk_free_security(struct sock *sk)
 {
 	struct sk_security_struct *sksec = sk->sk_security;
 
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	sk->sk_security = NULL;
 	selinux_netlbl_sk_security_free(sksec);
 	kfree(sksec);
@@ -5155,6 +5492,9 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
 	struct sk_security_struct *sksec = sk->sk_security;
 	struct sk_security_struct *newsksec = newsk->sk_security;
 
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	newsksec->sid = sksec->sid;
 	newsksec->peer_sid = sksec->peer_sid;
 	newsksec->sclass = sksec->sclass;
@@ -5164,6 +5504,9 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
 
 static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
 {
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	if (!sk)
 		*secid = SECINITSID_ANY_SOCKET;
 	else {
@@ -5175,10 +5518,14 @@ static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
 
 static void selinux_sock_graft(struct sock *sk, struct socket *parent)
 {
-	struct inode_security_struct *isec =
-		inode_security_novalidate(SOCK_INODE(parent));
+	struct inode_security_struct *isec;
 	struct sk_security_struct *sksec = sk->sk_security;
 
+	if (selinux_disabled(&selinux_state))
+		return;
+
+	isec = inode_security_novalidate(SOCK_INODE(parent));
+
 	if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
 	    sk->sk_family == PF_UNIX)
 		isec->sid = sksec->sid;
@@ -5200,6 +5547,9 @@ static int selinux_sctp_assoc_request(struct sctp_endpoint *ep,
 	u32 conn_sid;
 	int err = 0;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	if (!selinux_policycap_extsockclass())
 		return 0;
 
@@ -5270,6 +5620,9 @@ static int selinux_sctp_bind_connect(struct sock *sk, int optname,
 	struct sockaddr *addr;
 	struct socket *sock;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	if (!selinux_policycap_extsockclass())
 		return 0;
 
@@ -5346,6 +5699,9 @@ static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk,
 	struct sk_security_struct *sksec = sk->sk_security;
 	struct sk_security_struct *newsksec = newsk->sk_security;
 
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	/* If policy does not support SECCLASS_SCTP_SOCKET then call
 	 * the non-sctp clone version.
 	 */
@@ -5367,6 +5723,9 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
 	u32 connsid;
 	u32 peersid;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	err = selinux_skb_peerlbl_sid(skb, family, &peersid);
 	if (err)
 		return err;
@@ -5384,6 +5743,9 @@ static void selinux_inet_csk_clone(struct sock *newsk,
 {
 	struct sk_security_struct *newsksec = newsk->sk_security;
 
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	newsksec->sid = req->secid;
 	newsksec->peer_sid = req->peer_secid;
 	/* NOTE: Ideally, we should also get the isec->sid for the
@@ -5401,6 +5763,9 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
 	u16 family = sk->sk_family;
 	struct sk_security_struct *sksec = sk->sk_security;
 
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	/* handle mapped IPv4 packets arriving via IPv6 sockets */
 	if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
 		family = PF_INET;
@@ -5413,6 +5778,9 @@ static int selinux_secmark_relabel_packet(u32 sid)
 	const struct task_security_struct *__tsec;
 	u32 tsid;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	__tsec = selinux_cred(current_cred());
 	tsid = __tsec->sid;
 
@@ -5423,17 +5791,26 @@ static int selinux_secmark_relabel_packet(u32 sid)
 
 static void selinux_secmark_refcount_inc(void)
 {
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	atomic_inc(&selinux_secmark_refcount);
 }
 
 static void selinux_secmark_refcount_dec(void)
 {
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	atomic_dec(&selinux_secmark_refcount);
 }
 
 static void selinux_req_classify_flow(const struct request_sock *req,
 				      struct flowi *fl)
 {
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	fl->flowi_secid = req->secid;
 }
 
@@ -5441,6 +5818,9 @@ static int selinux_tun_dev_alloc_security(void **security)
 {
 	struct tun_security_struct *tunsec;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
 	if (!tunsec)
 		return -ENOMEM;
@@ -5452,12 +5832,20 @@ static int selinux_tun_dev_alloc_security(void **security)
 
 static void selinux_tun_dev_free_security(void *security)
 {
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	kfree(security);
 }
 
 static int selinux_tun_dev_create(void)
 {
-	u32 sid = current_sid();
+	u32 sid;
+
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
+	sid = current_sid();
 
 	/* we aren't taking into account the "sockcreate" SID since the socket
 	 * that is being created here is not a socket in the traditional sense,
@@ -5475,6 +5863,9 @@ static int selinux_tun_dev_attach_queue(void *security)
 {
 	struct tun_security_struct *tunsec = security;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return avc_has_perm(&selinux_state,
 			    current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
 			    TUN_SOCKET__ATTACH_QUEUE, NULL);
@@ -5485,6 +5876,9 @@ static int selinux_tun_dev_attach(struct sock *sk, void *security)
 	struct tun_security_struct *tunsec = security;
 	struct sk_security_struct *sksec = sk->sk_security;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	/* we don't currently perform any NetLabel based labeling here and it
 	 * isn't clear that we would want to do so anyway; while we could apply
 	 * labeling without the support of the TUN user the resulting labeled
@@ -5501,8 +5895,13 @@ static int selinux_tun_dev_attach(struct sock *sk, void *security)
 static int selinux_tun_dev_open(void *security)
 {
 	struct tun_security_struct *tunsec = security;
-	u32 sid = current_sid();
 	int err;
+	u32 sid;
+
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
+	sid = current_sid();
 
 	err = avc_has_perm(&selinux_state,
 			   sid, tunsec->sid, SECCLASS_TUN_SOCKET,
@@ -5885,6 +6284,9 @@ static unsigned int selinux_ipv6_postroute(void *priv,
 
 static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return selinux_nlmsg_perm(sk, skb);
 }
 
@@ -5922,6 +6324,9 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
 
 static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return msg_msg_alloc_security(msg);
 }
 
@@ -5930,9 +6335,11 @@ static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
 {
 	struct ipc_security_struct *isec;
 	struct common_audit_data ad;
-	u32 sid = current_sid();
 	int rc;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	isec = selinux_ipc(msq);
 	ipc_init_security(isec, SECCLASS_MSGQ);
 
@@ -5940,7 +6347,7 @@ static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
 	ad.u.ipc_id = msq->key;
 
 	rc = avc_has_perm(&selinux_state,
-			  sid, isec->sid, SECCLASS_MSGQ,
+			  current_sid(), isec->sid, SECCLASS_MSGQ,
 			  MSGQ__CREATE, &ad);
 	return rc;
 }
@@ -5949,7 +6356,9 @@ static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
 {
 	struct ipc_security_struct *isec;
 	struct common_audit_data ad;
-	u32 sid = current_sid();
+
+	if (selinux_disabled(&selinux_state))
+		return 0;
 
 	isec = selinux_ipc(msq);
 
@@ -5957,7 +6366,7 @@ static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
 	ad.u.ipc_id = msq->key;
 
 	return avc_has_perm(&selinux_state,
-			    sid, isec->sid, SECCLASS_MSGQ,
+			    current_sid(), isec->sid, SECCLASS_MSGQ,
 			    MSGQ__ASSOCIATE, &ad);
 }
 
@@ -5966,6 +6375,9 @@ static int selinux_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd)
 	int err;
 	int perms;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	switch (cmd) {
 	case IPC_INFO:
 	case MSG_INFO:
@@ -5997,9 +6409,14 @@ static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *m
 	struct ipc_security_struct *isec;
 	struct msg_security_struct *msec;
 	struct common_audit_data ad;
-	u32 sid = current_sid();
+	u32 sid;
 	int rc;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
+	sid = current_sid();
+
 	isec = selinux_ipc(msq);
 	msec = selinux_msg_msg(msg);
 
@@ -6045,9 +6462,14 @@ static int selinux_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *m
 	struct ipc_security_struct *isec;
 	struct msg_security_struct *msec;
 	struct common_audit_data ad;
-	u32 sid = task_sid(target);
+	u32 sid;
 	int rc;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
+	sid = task_sid(target);
+
 	isec = selinux_ipc(msq);
 	msec = selinux_msg_msg(msg);
 
@@ -6069,9 +6491,11 @@ static int selinux_shm_alloc_security(struct kern_ipc_perm *shp)
 {
 	struct ipc_security_struct *isec;
 	struct common_audit_data ad;
-	u32 sid = current_sid();
 	int rc;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	isec = selinux_ipc(shp);
 	ipc_init_security(isec, SECCLASS_SHM);
 
@@ -6079,8 +6503,8 @@ static int selinux_shm_alloc_security(struct kern_ipc_perm *shp)
 	ad.u.ipc_id = shp->key;
 
 	rc = avc_has_perm(&selinux_state,
-			  sid, isec->sid, SECCLASS_SHM,
-			  SHM__CREATE, &ad);
+			  current_sid(), isec->sid,
+			  SECCLASS_SHM, SHM__CREATE, &ad);
 	return rc;
 }
 
@@ -6088,7 +6512,9 @@ static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg)
 {
 	struct ipc_security_struct *isec;
 	struct common_audit_data ad;
-	u32 sid = current_sid();
+
+	if (selinux_disabled(&selinux_state))
+		return 0;
 
 	isec = selinux_ipc(shp);
 
@@ -6096,8 +6522,8 @@ static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg)
 	ad.u.ipc_id = shp->key;
 
 	return avc_has_perm(&selinux_state,
-			    sid, isec->sid, SECCLASS_SHM,
-			    SHM__ASSOCIATE, &ad);
+			    current_sid(), isec->sid,
+			    SECCLASS_SHM, SHM__ASSOCIATE, &ad);
 }
 
 /* Note, at this point, shp is locked down */
@@ -6106,6 +6532,9 @@ static int selinux_shm_shmctl(struct kern_ipc_perm *shp, int cmd)
 	int perms;
 	int err;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	switch (cmd) {
 	case IPC_INFO:
 	case SHM_INFO:
@@ -6141,6 +6570,9 @@ static int selinux_shm_shmat(struct kern_ipc_perm *shp,
 {
 	u32 perms;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	if (shmflg & SHM_RDONLY)
 		perms = SHM__READ;
 	else
@@ -6154,9 +6586,11 @@ static int selinux_sem_alloc_security(struct kern_ipc_perm *sma)
 {
 	struct ipc_security_struct *isec;
 	struct common_audit_data ad;
-	u32 sid = current_sid();
 	int rc;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	isec = selinux_ipc(sma);
 	ipc_init_security(isec, SECCLASS_SEM);
 
@@ -6164,8 +6598,8 @@ static int selinux_sem_alloc_security(struct kern_ipc_perm *sma)
 	ad.u.ipc_id = sma->key;
 
 	rc = avc_has_perm(&selinux_state,
-			  sid, isec->sid, SECCLASS_SEM,
-			  SEM__CREATE, &ad);
+			  current_sid(), isec->sid,
+			  SECCLASS_SEM, SEM__CREATE, &ad);
 	return rc;
 }
 
@@ -6173,7 +6607,9 @@ static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg)
 {
 	struct ipc_security_struct *isec;
 	struct common_audit_data ad;
-	u32 sid = current_sid();
+
+	if (selinux_disabled(&selinux_state))
+		return 0;
 
 	isec = selinux_ipc(sma);
 
@@ -6181,8 +6617,8 @@ static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg)
 	ad.u.ipc_id = sma->key;
 
 	return avc_has_perm(&selinux_state,
-			    sid, isec->sid, SECCLASS_SEM,
-			    SEM__ASSOCIATE, &ad);
+			    current_sid(), isec->sid,
+			    SECCLASS_SEM, SEM__ASSOCIATE, &ad);
 }
 
 /* Note, at this point, sma is locked down */
@@ -6191,6 +6627,9 @@ static int selinux_sem_semctl(struct kern_ipc_perm *sma, int cmd)
 	int err;
 	u32 perms;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	switch (cmd) {
 	case IPC_INFO:
 	case SEM_INFO:
@@ -6235,6 +6674,9 @@ static int selinux_sem_semop(struct kern_ipc_perm *sma,
 {
 	u32 perms;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	if (alter)
 		perms = SEM__READ | SEM__WRITE;
 	else
@@ -6247,7 +6689,9 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
 {
 	u32 av = 0;
 
-	av = 0;
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	if (flag & S_IRUGO)
 		av |= IPC__UNIX_READ;
 	if (flag & S_IWUGO)
@@ -6261,12 +6705,17 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
 
 static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
 {
-	struct ipc_security_struct *isec = selinux_ipc(ipcp);
-	*secid = isec->sid;
+	if (selinux_disabled(&selinux_state))
+		return;
+
+	*secid = selinux_ipc(ipcp)->sid;
 }
 
 static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
 {
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	if (inode)
 		inode_doinit_with_dentry(inode, dentry);
 }
@@ -6279,6 +6728,9 @@ static int selinux_getprocattr(struct task_struct *p,
 	int error;
 	unsigned len;
 
+	if (selinux_disabled(&selinux_state))
+		return -EINVAL;
+
 	rcu_read_lock();
 	__tsec = selinux_cred(__task_cred(p));
 
@@ -6325,10 +6777,15 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)
 {
 	struct task_security_struct *tsec;
 	struct cred *new;
-	u32 mysid = current_sid(), sid = 0, ptsid;
+	u32 mysid, sid = 0, ptsid;
 	int error;
 	char *str = value;
 
+	if (selinux_disabled(&selinux_state))
+		return -EINVAL;
+
+	mysid = current_sid();
+
 	/*
 	 * Basic control over ability to set these attributes at all.
 	 */
@@ -6466,17 +6923,26 @@ abort_change:
 
 static int selinux_ismaclabel(const char *name)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
 }
 
 static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
 {
+	if (selinux_disabled(&selinux_state))
+		return -EOPNOTSUPP;
+
 	return security_sid_to_context(&selinux_state, secid,
 				       secdata, seclen);
 }
 
 static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return security_context_to_sid(&selinux_state, secdata, seclen,
 				       secid, GFP_KERNEL);
 }
@@ -6490,6 +6956,9 @@ static void selinux_inode_invalidate_secctx(struct inode *inode)
 {
 	struct inode_security_struct *isec = selinux_inode(inode);
 
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	spin_lock(&isec->lock);
 	isec->initialized = LABEL_INVALID;
 	spin_unlock(&isec->lock);
@@ -6511,6 +6980,9 @@ static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen
  */
 static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
 {
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
 }
 
@@ -6532,6 +7004,9 @@ static int selinux_key_alloc(struct key *k, const struct cred *cred,
 	const struct task_security_struct *tsec;
 	struct key_security_struct *ksec;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
 	if (!ksec)
 		return -ENOMEM;
@@ -6550,6 +7025,9 @@ static void selinux_key_free(struct key *k)
 {
 	struct key_security_struct *ksec = k->security;
 
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	k->security = NULL;
 	kfree(ksec);
 }
@@ -6568,6 +7046,9 @@ static int selinux_key_permission(key_ref_t key_ref,
 	if (perm == 0)
 		return 0;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	sid = cred_sid(cred);
 
 	key = key_ref_to_ptr(key_ref);
@@ -6584,6 +7065,9 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)
 	unsigned len;
 	int rc;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	rc = security_sid_to_context(&selinux_state, ksec->sid,
 				     &context, &len);
 	if (!rc)
@@ -6602,6 +7086,9 @@ static int selinux_ib_pkey_access(void *ib_sec, u64 subnet_prefix, u16 pkey_val)
 	struct ib_security_struct *sec = ib_sec;
 	struct lsm_ibpkey_audit ibpkey;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	err = sel_ib_pkey_sid(subnet_prefix, pkey_val, &sid);
 	if (err)
 		return err;
@@ -6625,6 +7112,9 @@ static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name,
 	struct ib_security_struct *sec = ib_sec;
 	struct lsm_ibendport_audit ibendport;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	err = security_ib_endport_sid(&selinux_state, dev_name, port_num,
 				      &sid);
 
@@ -6645,6 +7135,9 @@ static int selinux_ib_alloc_security(void **ib_sec)
 {
 	struct ib_security_struct *sec;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	sec = kzalloc(sizeof(*sec), GFP_KERNEL);
 	if (!sec)
 		return -ENOMEM;
@@ -6656,6 +7149,9 @@ static int selinux_ib_alloc_security(void **ib_sec)
 
 static void selinux_ib_free_security(void *ib_sec)
 {
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	kfree(ib_sec);
 }
 #endif
@@ -6667,6 +7163,9 @@ static int selinux_bpf(int cmd, union bpf_attr *attr,
 	u32 sid = current_sid();
 	int ret;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	switch (cmd) {
 	case BPF_MAP_CREATE:
 		ret = avc_has_perm(&selinux_state,
@@ -6734,23 +7233,27 @@ static int bpf_fd_pass(struct file *file, u32 sid)
 
 static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode)
 {
-	u32 sid = current_sid();
 	struct bpf_security_struct *bpfsec;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	bpfsec = map->security;
 	return avc_has_perm(&selinux_state,
-			    sid, bpfsec->sid, SECCLASS_BPF,
+			    current_sid(), bpfsec->sid, SECCLASS_BPF,
 			    bpf_map_fmode_to_av(fmode), NULL);
 }
 
 static int selinux_bpf_prog(struct bpf_prog *prog)
 {
-	u32 sid = current_sid();
 	struct bpf_security_struct *bpfsec;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	bpfsec = prog->aux->security;
 	return avc_has_perm(&selinux_state,
-			    sid, bpfsec->sid, SECCLASS_BPF,
+			    current_sid(), bpfsec->sid, SECCLASS_BPF,
 			    BPF__PROG_RUN, NULL);
 }
 
@@ -6758,6 +7261,9 @@ static int selinux_bpf_map_alloc(struct bpf_map *map)
 {
 	struct bpf_security_struct *bpfsec;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
 	if (!bpfsec)
 		return -ENOMEM;
@@ -6772,6 +7278,9 @@ static void selinux_bpf_map_free(struct bpf_map *map)
 {
 	struct bpf_security_struct *bpfsec = map->security;
 
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	map->security = NULL;
 	kfree(bpfsec);
 }
@@ -6780,6 +7289,9 @@ static int selinux_bpf_prog_alloc(struct bpf_prog_aux *aux)
 {
 	struct bpf_security_struct *bpfsec;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
 	if (!bpfsec)
 		return -ENOMEM;
@@ -6794,6 +7306,9 @@ static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
 {
 	struct bpf_security_struct *bpfsec = aux->security;
 
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	aux->security = NULL;
 	kfree(bpfsec);
 }
@@ -6802,11 +7317,14 @@ static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
 static int selinux_lockdown(enum lockdown_reason what)
 {
 	struct common_audit_data ad;
-	u32 sid = current_sid();
+	u32 sid;
 	int invalid_reason = (what <= LOCKDOWN_NONE) ||
 			     (what == LOCKDOWN_INTEGRITY_MAX) ||
 			     (what >= LOCKDOWN_CONFIDENTIALITY_MAX);
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	if (WARN(invalid_reason, "Invalid lockdown reason")) {
 		audit_log(audit_context(),
 			  GFP_ATOMIC, AUDIT_SELINUX_ERR,
@@ -6814,6 +7332,8 @@ static int selinux_lockdown(enum lockdown_reason what)
 		return -EINVAL;
 	}
 
+	sid = current_sid();
+
 	ad.type = LSM_AUDIT_DATA_LOCKDOWN;
 	ad.u.reason = what;
 
@@ -6827,7 +7347,7 @@ static int selinux_lockdown(enum lockdown_reason what)
 				    LOCKDOWN__CONFIDENTIALITY, &ad);
 }
 
-struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = {
+struct lsm_blob_sizes selinux_blob_sizes __ro_after_init = {
 	.lbs_cred = sizeof(struct task_security_struct),
 	.lbs_file = sizeof(struct file_security_struct),
 	.lbs_inode = sizeof(struct inode_security_struct),
@@ -6838,7 +7358,12 @@ struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = {
 #ifdef CONFIG_PERF_EVENTS
 static int selinux_perf_event_open(struct perf_event_attr *attr, int type)
 {
-	u32 requested, sid = current_sid();
+	u32 requested, sid;
+
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
+	sid = current_sid();
 
 	if (type == PERF_SECURITY_OPEN)
 		requested = PERF_EVENT__OPEN;
@@ -6859,6 +7384,9 @@ static int selinux_perf_event_alloc(struct perf_event *event)
 {
 	struct perf_event_security_struct *perfsec;
 
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
 	perfsec = kzalloc(sizeof(*perfsec), GFP_KERNEL);
 	if (!perfsec)
 		return -ENOMEM;
@@ -6873,6 +7401,9 @@ static void selinux_perf_event_free(struct perf_event *event)
 {
 	struct perf_event_security_struct *perfsec = event->security;
 
+	if (selinux_disabled(&selinux_state))
+		return;
+
 	event->security = NULL;
 	kfree(perfsec);
 }
@@ -6880,23 +7411,27 @@ static void selinux_perf_event_free(struct perf_event *event)
 static int selinux_perf_event_read(struct perf_event *event)
 {
 	struct perf_event_security_struct *perfsec = event->security;
-	u32 sid = current_sid();
 
-	return avc_has_perm(&selinux_state, sid, perfsec->sid,
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
+	return avc_has_perm(&selinux_state, current_sid(), perfsec->sid,
 			    SECCLASS_PERF_EVENT, PERF_EVENT__READ, NULL);
 }
 
 static int selinux_perf_event_write(struct perf_event *event)
 {
 	struct perf_event_security_struct *perfsec = event->security;
-	u32 sid = current_sid();
 
-	return avc_has_perm(&selinux_state, sid, perfsec->sid,
+	if (selinux_disabled(&selinux_state))
+		return 0;
+
+	return avc_has_perm(&selinux_state, current_sid(), perfsec->sid,
 			    SECCLASS_PERF_EVENT, PERF_EVENT__WRITE, NULL);
 }
 #endif
 
-static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
+static struct security_hook_list selinux_hooks[] __ro_after_init = {
 	LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
 	LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
 	LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
@@ -7315,18 +7850,19 @@ int selinux_disable(struct selinux_state *state)
 		return -EINVAL;
 	}
 
+	/*
+	 * Unregister netfilter hooks (must be done before
+	 * selinux_mark_disabled()).
+	 */
+	selinux_nf_ip_exit();
+
 	selinux_mark_disabled(state);
 
 	pr_info("SELinux:  Disabled at runtime.\n");
 
-	security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
-
 	/* Try to destroy the avc node cache */
 	avc_disable();
 
-	/* Unregister netfilter hooks. */
-	selinux_nf_ip_exit();
-
 	/* Unregister selinuxfs. */
 	exit_sel_fs();
 
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index ecea41ce919b..de50c69846e0 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -4583,7 +4583,7 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode,
 	return 0;
 }
 
-struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
+struct lsm_blob_sizes smack_blob_sizes __ro_after_init = {
 	.lbs_cred = sizeof(struct task_smack),
 	.lbs_file = sizeof(struct smack_known *),
 	.lbs_inode = sizeof(struct inode_smack),
@@ -4591,7 +4591,7 @@ struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
 	.lbs_msg_msg = sizeof(struct smack_known *),
 };
 
-static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
+static struct security_hook_list smack_hooks[] __ro_after_init = {
 	LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check),
 	LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme),
 	LSM_HOOK_INIT(syslog, smack_syslog),
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index 716c92ec941a..9dcdef99d431 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -486,7 +486,7 @@ static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg,
 	return tomoyo_socket_sendmsg_permission(sock, msg, size);
 }
 
-struct lsm_blob_sizes tomoyo_blob_sizes __lsm_ro_after_init = {
+struct lsm_blob_sizes tomoyo_blob_sizes __ro_after_init = {
 	.lbs_task = sizeof(struct tomoyo_task),
 };
 
@@ -533,7 +533,7 @@ static void tomoyo_task_free(struct task_struct *task)
  * tomoyo_security_ops is a "struct security_operations" which is used for
  * registering TOMOYO.
  */
-static struct security_hook_list tomoyo_hooks[] __lsm_ro_after_init = {
+static struct security_hook_list tomoyo_hooks[] __ro_after_init = {
 	LSM_HOOK_INIT(cred_prepare, tomoyo_cred_prepare),
 	LSM_HOOK_INIT(bprm_committed_creds, tomoyo_bprm_committed_creds),
 	LSM_HOOK_INIT(task_alloc, tomoyo_task_alloc),
@@ -569,7 +569,7 @@ static struct security_hook_list tomoyo_hooks[] __lsm_ro_after_init = {
 /* Lock for GC. */
 DEFINE_SRCU(tomoyo_ss);
 
-int tomoyo_enabled __lsm_ro_after_init = 1;
+int tomoyo_enabled __ro_after_init = 1;
 
 /**
  * tomoyo_init - Register TOMOYO Linux as a LSM module.
diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
index 94dc346370b1..c47d4e09bfb4 100644
--- a/security/yama/yama_lsm.c
+++ b/security/yama/yama_lsm.c
@@ -421,7 +421,7 @@ static int yama_ptrace_traceme(struct task_struct *parent)
 	return rc;
 }
 
-static struct security_hook_list yama_hooks[] __lsm_ro_after_init = {
+static struct security_hook_list yama_hooks[] __ro_after_init = {
 	LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check),
 	LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme),
 	LSM_HOOK_INIT(task_prctl, yama_task_prctl),
-- 
2.24.1


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

* Re: [PATCH 1/2] selinux: treat atomic flags more carefully
  2020-01-07 13:31 ` [PATCH 1/2] selinux: treat atomic flags more carefully Ondrej Mosnacek
@ 2020-01-07 14:45   ` Stephen Smalley
  2020-01-07 18:09   ` Kees Cook
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 18+ messages in thread
From: Stephen Smalley @ 2020-01-07 14:45 UTC (permalink / raw)
  To: Ondrej Mosnacek, linux-security-module, James Morris, Serge E. Hallyn
  Cc: Casey Schaufler, selinux, Paul Moore, John Johansen, Kees Cook,
	Micah Morton, Tetsuo Handa

On 1/7/20 8:31 AM, Ondrej Mosnacek wrote:
> The disabled/enforcing/initialized flags are all accessed concurrently
> by threads so use the appropriate accessors that ensure atomicity and
> document that it is expected.
> 
> Use smp_load/acquire...() helpers (with memory barriers) for the
> initialized flag, since it gates access to the rest of the state
> structures.
> 
> Note that the disabled flag is currently not used for anything other
> than avoiding double disable, but it will be used for bailing out of
> hooks once security_delete_hooks() is removed.
> 
> Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>

This looks good to me as a cleanup regardless of whether the 2nd patch 
is merged.  Similar treatment is likely needed for state->checkreqprot 
(although I'd like to obsolete and get rid of that entirely at some 
point), maybe state->policycap[], isec->initialized, and others, but 
that can all be done separately.

Acked-by: Stephen Smalley <sds@tycho.nsa.gov>

> ---
>   security/selinux/hooks.c            | 21 ++++++++--------
>   security/selinux/include/security.h | 33 +++++++++++++++++++++++--
>   security/selinux/ss/services.c      | 38 ++++++++++++++---------------
>   3 files changed, 61 insertions(+), 31 deletions(-)
> 
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 659c4a81e897..47ad4db925cf 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -272,7 +272,7 @@ static int __inode_security_revalidate(struct inode *inode,
>   
>   	might_sleep_if(may_sleep);
>   
> -	if (selinux_state.initialized &&
> +	if (selinux_initialized(&selinux_state) &&
>   	    isec->initialized != LABEL_INITIALIZED) {
>   		if (!may_sleep)
>   			return -ECHILD;
> @@ -659,7 +659,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
>   
>   	mutex_lock(&sbsec->lock);
>   
> -	if (!selinux_state.initialized) {
> +	if (!selinux_initialized(&selinux_state)) {
>   		if (!opts) {
>   			/* Defer initialization until selinux_complete_init,
>   			   after the initial policy is loaded and the security
> @@ -928,7 +928,7 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
>   	 * if the parent was able to be mounted it clearly had no special lsm
>   	 * mount options.  thus we can safely deal with this superblock later
>   	 */
> -	if (!selinux_state.initialized)
> +	if (!selinux_initialized(&selinux_state))
>   		return 0;
>   
>   	/*
> @@ -1103,7 +1103,7 @@ static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
>   	if (!(sbsec->flags & SE_SBINITIALIZED))
>   		return 0;
>   
> -	if (!selinux_state.initialized)
> +	if (!selinux_initialized(&selinux_state))
>   		return 0;
>   
>   	if (sbsec->flags & FSCONTEXT_MNT) {
> @@ -2920,7 +2920,8 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
>   		isec->initialized = LABEL_INITIALIZED;
>   	}
>   
> -	if (!selinux_state.initialized || !(sbsec->flags & SBLABEL_MNT))
> +	if (!selinux_initialized(&selinux_state) ||
> +	    !(sbsec->flags & SBLABEL_MNT))
>   		return -EOPNOTSUPP;
>   
>   	if (name)
> @@ -3143,7 +3144,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
>   		return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
>   	}
>   
> -	if (!selinux_state.initialized)
> +	if (!selinux_initialized(&selinux_state))
>   		return (inode_owner_or_capable(inode) ? 0 : -EPERM);
>   
>   	sbsec = inode->i_sb->s_security;
> @@ -3229,7 +3230,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
>   		return;
>   	}
>   
> -	if (!selinux_state.initialized) {
> +	if (!selinux_initialized(&selinux_state)) {
>   		/* If we haven't even been initialized, then we can't validate
>   		 * against a policy, so leave the label as invalid. It may
>   		 * resolve to a valid label on the next revalidation try if
> @@ -7304,17 +7305,17 @@ static void selinux_nf_ip_exit(void)
>   #ifdef CONFIG_SECURITY_SELINUX_DISABLE
>   int selinux_disable(struct selinux_state *state)
>   {
> -	if (state->initialized) {
> +	if (selinux_initialized(state)) {
>   		/* Not permitted after initial policy load. */
>   		return -EINVAL;
>   	}
>   
> -	if (state->disabled) {
> +	if (selinux_disabled(state)) {
>   		/* Only do this once. */
>   		return -EINVAL;
>   	}
>   
> -	state->disabled = 1;
> +	selinux_mark_disabled(state);
>   
>   	pr_info("SELinux:  Disabled at runtime.\n");
>   
> diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
> index ecdd610e6449..a39f9565d80b 100644
> --- a/security/selinux/include/security.h
> +++ b/security/selinux/include/security.h
> @@ -117,15 +117,27 @@ void selinux_avc_init(struct selinux_avc **avc);
>   
>   extern struct selinux_state selinux_state;
>   
> +static inline bool selinux_initialized(const struct selinux_state *state)
> +{
> +	/* do a synchronized load to avoid race conditions */
> +	return smp_load_acquire(&state->initialized);
> +}
> +
> +static inline void selinux_mark_initialized(struct selinux_state *state)
> +{
> +	/* do a synchronized write to avoid race conditions */
> +	smp_store_release(&state->initialized, true);
> +}
> +
>   #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
>   static inline bool enforcing_enabled(struct selinux_state *state)
>   {
> -	return state->enforcing;
> +	return READ_ONCE(state->enforcing);
>   }
>   
>   static inline void enforcing_set(struct selinux_state *state, bool value)
>   {
> -	state->enforcing = value;
> +	WRITE_ONCE(state->enforcing, value);
>   }
>   #else
>   static inline bool enforcing_enabled(struct selinux_state *state)
> @@ -138,6 +150,23 @@ static inline void enforcing_set(struct selinux_state *state, bool value)
>   }
>   #endif
>   
> +#ifdef CONFIG_SECURITY_SELINUX_DISABLE
> +static inline bool selinux_disabled(struct selinux_state *state)
> +{
> +	return READ_ONCE(state->disabled);
> +}
> +
> +static inline void selinux_mark_disabled(struct selinux_state *state)
> +{
> +	WRITE_ONCE(state->disabled, true);
> +}
> +#else
> +static inline bool selinux_disabled(struct selinux_state *state)
> +{
> +	return false;
> +}
> +#endif
> +
>   static inline bool selinux_policycap_netpeer(void)
>   {
>   	struct selinux_state *state = &selinux_state;
> diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
> index 55cf42945cba..0e8b94e8e156 100644
> --- a/security/selinux/ss/services.c
> +++ b/security/selinux/ss/services.c
> @@ -767,7 +767,7 @@ static int security_compute_validatetrans(struct selinux_state *state,
>   	int rc = 0;
>   
>   
> -	if (!state->initialized)
> +	if (!selinux_initialized(state))
>   		return 0;
>   
>   	read_lock(&state->ss->policy_rwlock);
> @@ -868,7 +868,7 @@ int security_bounded_transition(struct selinux_state *state,
>   	int index;
>   	int rc;
>   
> -	if (!state->initialized)
> +	if (!selinux_initialized(state))
>   		return 0;
>   
>   	read_lock(&state->ss->policy_rwlock);
> @@ -1027,7 +1027,7 @@ void security_compute_xperms_decision(struct selinux_state *state,
>   	memset(xpermd->dontaudit->p, 0, sizeof(xpermd->dontaudit->p));
>   
>   	read_lock(&state->ss->policy_rwlock);
> -	if (!state->initialized)
> +	if (!selinux_initialized(state))
>   		goto allow;
>   
>   	policydb = &state->ss->policydb;
> @@ -1112,7 +1112,7 @@ void security_compute_av(struct selinux_state *state,
>   	read_lock(&state->ss->policy_rwlock);
>   	avd_init(state, avd);
>   	xperms->len = 0;
> -	if (!state->initialized)
> +	if (!selinux_initialized(state))
>   		goto allow;
>   
>   	policydb = &state->ss->policydb;
> @@ -1166,7 +1166,7 @@ void security_compute_av_user(struct selinux_state *state,
>   
>   	read_lock(&state->ss->policy_rwlock);
>   	avd_init(state, avd);
> -	if (!state->initialized)
> +	if (!selinux_initialized(state))
>   		goto allow;
>   
>   	policydb = &state->ss->policydb;
> @@ -1286,7 +1286,7 @@ int security_sidtab_hash_stats(struct selinux_state *state, char *page)
>   {
>   	int rc;
>   
> -	if (!state->initialized) {
> +	if (!selinux_initialized(state)) {
>   		pr_err("SELinux: %s:  called before initial load_policy\n",
>   		       __func__);
>   		return -EINVAL;
> @@ -1320,7 +1320,7 @@ static int security_sid_to_context_core(struct selinux_state *state,
>   		*scontext = NULL;
>   	*scontext_len  = 0;
>   
> -	if (!state->initialized) {
> +	if (!selinux_initialized(state)) {
>   		if (sid <= SECINITSID_NUM) {
>   			char *scontextp;
>   
> @@ -1549,7 +1549,7 @@ static int security_context_to_sid_core(struct selinux_state *state,
>   	if (!scontext2)
>   		return -ENOMEM;
>   
> -	if (!state->initialized) {
> +	if (!selinux_initialized(state)) {
>   		int i;
>   
>   		for (i = 1; i < SECINITSID_NUM; i++) {
> @@ -1736,7 +1736,7 @@ static int security_compute_sid(struct selinux_state *state,
>   	int rc = 0;
>   	bool sock;
>   
> -	if (!state->initialized) {
> +	if (!selinux_initialized(state)) {
>   		switch (orig_tclass) {
>   		case SECCLASS_PROCESS: /* kernel value */
>   			*out_sid = ssid;
> @@ -2198,7 +2198,7 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len)
>   		goto out;
>   	}
>   
> -	if (!state->initialized) {
> +	if (!selinux_initialized(state)) {
>   		rc = policydb_read(policydb, fp);
>   		if (rc) {
>   			kfree(newsidtab);
> @@ -2223,7 +2223,7 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len)
>   
>   		state->ss->sidtab = newsidtab;
>   		security_load_policycaps(state);
> -		state->initialized = 1;
> +		selinux_mark_initialized(state);
>   		seqno = ++state->ss->latest_granting;
>   		selinux_complete_init();
>   		avc_ss_reset(state->avc, seqno);
> @@ -2639,7 +2639,7 @@ int security_get_user_sids(struct selinux_state *state,
>   	*sids = NULL;
>   	*nel = 0;
>   
> -	if (!state->initialized)
> +	if (!selinux_initialized(state))
>   		goto out;
>   
>   	read_lock(&state->ss->policy_rwlock);
> @@ -2875,7 +2875,7 @@ int security_get_bools(struct selinux_state *state,
>   	struct policydb *policydb;
>   	int i, rc;
>   
> -	if (!state->initialized) {
> +	if (!selinux_initialized(state)) {
>   		*len = 0;
>   		*names = NULL;
>   		*values = NULL;
> @@ -3050,7 +3050,7 @@ int security_sid_mls_copy(struct selinux_state *state,
>   	int rc;
>   
>   	rc = 0;
> -	if (!state->initialized || !policydb->mls_enabled) {
> +	if (!selinux_initialized(state) || !policydb->mls_enabled) {
>   		*new_sid = sid;
>   		goto out;
>   	}
> @@ -3217,7 +3217,7 @@ int security_get_classes(struct selinux_state *state,
>   	struct policydb *policydb = &state->ss->policydb;
>   	int rc;
>   
> -	if (!state->initialized) {
> +	if (!selinux_initialized(state)) {
>   		*nclasses = 0;
>   		*classes = NULL;
>   		return 0;
> @@ -3366,7 +3366,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
>   
>   	*rule = NULL;
>   
> -	if (!state->initialized)
> +	if (!selinux_initialized(state))
>   		return -EOPNOTSUPP;
>   
>   	switch (field) {
> @@ -3665,7 +3665,7 @@ int security_netlbl_secattr_to_sid(struct selinux_state *state,
>   	struct context *ctx;
>   	struct context ctx_new;
>   
> -	if (!state->initialized) {
> +	if (!selinux_initialized(state)) {
>   		*sid = SECSID_NULL;
>   		return 0;
>   	}
> @@ -3732,7 +3732,7 @@ int security_netlbl_sid_to_secattr(struct selinux_state *state,
>   	int rc;
>   	struct context *ctx;
>   
> -	if (!state->initialized)
> +	if (!selinux_initialized(state))
>   		return 0;
>   
>   	read_lock(&state->ss->policy_rwlock);
> @@ -3771,7 +3771,7 @@ int security_read_policy(struct selinux_state *state,
>   	int rc;
>   	struct policy_file fp;
>   
> -	if (!state->initialized)
> +	if (!selinux_initialized(state))
>   		return -EINVAL;
>   
>   	*len = security_policydb_len(state);
> 


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

* Re: [PATCH 2/2] security, selinux: get rid of security_delete_hooks()
  2020-01-07 13:31 ` [PATCH 2/2] security,selinux: get rid of security_delete_hooks() Ondrej Mosnacek
@ 2020-01-07 14:47   ` Stephen Smalley
  2020-01-08  5:31     ` Paul Moore
  2020-01-07 16:46   ` [PATCH 2/2] security,selinux: " Casey Schaufler
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 18+ messages in thread
From: Stephen Smalley @ 2020-01-07 14:47 UTC (permalink / raw)
  To: Ondrej Mosnacek, linux-security-module, James Morris, Serge E. Hallyn
  Cc: Casey Schaufler, selinux, Paul Moore, John Johansen, Kees Cook,
	Micah Morton, Tetsuo Handa

On 1/7/20 8:31 AM, Ondrej Mosnacek wrote:
> The only user is SELinux, which is hereby converted to check the
> disabled flag in each hook instead of removing the hooks from the list.
> 
> The __lsm_ro_after_init macro is now removed and replaced with
> __ro_after_init directly.
> 
> This fixes a race condition in SELinux runtime disable, which was
> introduced with the switch to hook lists in b1d9e6b0646d ("LSM: Switch
> to lists of hooks").

Not opposed (naturally, since I suggested it) but my impression from the 
earlier thread was that Paul preferred the less invasive approach of 
your original patch (just reordering the hooks) as a short term fix with 
an eye toward full removal of disable support in the not-too-distant future.

> 
> Suggested-by: Stephen Smalley <sds@tycho.nsa.gov>
> Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
> ---
>   include/linux/lsm_hooks.h    |  31 --
>   security/Kconfig             |   5 -
>   security/apparmor/lsm.c      |   6 +-
>   security/commoncap.c         |   2 +-
>   security/loadpin/loadpin.c   |   2 +-
>   security/lockdown/lockdown.c |   2 +-
>   security/security.c          |   5 +-
>   security/selinux/Kconfig     |   6 -
>   security/selinux/hooks.c     | 742 ++++++++++++++++++++++++++++++-----
>   security/smack/smack_lsm.c   |   4 +-
>   security/tomoyo/tomoyo.c     |   6 +-
>   security/yama/yama_lsm.c     |   2 +-
>   12 files changed, 654 insertions(+), 159 deletions(-)
> 
> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
> index 20d8cf194fb7..5064060ce910 100644
> --- a/include/linux/lsm_hooks.h
> +++ b/include/linux/lsm_hooks.h
> @@ -27,7 +27,6 @@
>   
>   #include <linux/security.h>
>   #include <linux/init.h>
> -#include <linux/rculist.h>
>   
>   /**
>    * union security_list_options - Linux Security Module hook function list
> @@ -2145,36 +2144,6 @@ extern struct lsm_info __start_early_lsm_info[], __end_early_lsm_info[];
>   		__used __section(.early_lsm_info.init)			\
>   		__aligned(sizeof(unsigned long))
>   
> -#ifdef CONFIG_SECURITY_SELINUX_DISABLE
> -/*
> - * Assuring the safety of deleting a security module is up to
> - * the security module involved. This may entail ordering the
> - * module's hook list in a particular way, refusing to disable
> - * the module once a policy is loaded or any number of other
> - * actions better imagined than described.
> - *
> - * The name of the configuration option reflects the only module
> - * that currently uses the mechanism. Any developer who thinks
> - * disabling their module is a good idea needs to be at least as
> - * careful as the SELinux team.
> - */
> -static inline void security_delete_hooks(struct security_hook_list *hooks,
> -						int count)
> -{
> -	int i;
> -
> -	for (i = 0; i < count; i++)
> -		hlist_del_rcu(&hooks[i].list);
> -}
> -#endif /* CONFIG_SECURITY_SELINUX_DISABLE */
> -
> -/* Currently required to handle SELinux runtime hook disable. */
> -#ifdef CONFIG_SECURITY_WRITABLE_HOOKS
> -#define __lsm_ro_after_init
> -#else
> -#define __lsm_ro_after_init	__ro_after_init
> -#endif /* CONFIG_SECURITY_WRITABLE_HOOKS */
> -
>   extern int lsm_inode_alloc(struct inode *inode);
>   
>   #endif /* ! __LINUX_LSM_HOOKS_H */
> diff --git a/security/Kconfig b/security/Kconfig
> index 2a1a2d396228..456764990a13 100644
> --- a/security/Kconfig
> +++ b/security/Kconfig
> @@ -32,11 +32,6 @@ config SECURITY
>   
>   	  If you are unsure how to answer this question, answer N.
>   
> -config SECURITY_WRITABLE_HOOKS
> -	depends on SECURITY
> -	bool
> -	default n
> -
>   config SECURITYFS
>   	bool "Enable the securityfs filesystem"
>   	help
> diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
> index b621ad74f54a..cd83812a440f 100644
> --- a/security/apparmor/lsm.c
> +++ b/security/apparmor/lsm.c
> @@ -1158,13 +1158,13 @@ static int apparmor_inet_conn_request(struct sock *sk, struct sk_buff *skb,
>   /*
>    * The cred blob is a pointer to, not an instance of, an aa_task_ctx.
>    */
> -struct lsm_blob_sizes apparmor_blob_sizes __lsm_ro_after_init = {
> +struct lsm_blob_sizes apparmor_blob_sizes __ro_after_init = {
>   	.lbs_cred = sizeof(struct aa_task_ctx *),
>   	.lbs_file = sizeof(struct aa_file_ctx),
>   	.lbs_task = sizeof(struct aa_task_ctx),
>   };
>   
> -static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
> +static struct security_hook_list apparmor_hooks[] __ro_after_init = {
>   	LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
>   	LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
>   	LSM_HOOK_INIT(capget, apparmor_capget),
> @@ -1368,7 +1368,7 @@ static const struct kernel_param_ops param_ops_aaintbool = {
>   	.get = param_get_aaintbool
>   };
>   /* Boot time disable flag */
> -static int apparmor_enabled __lsm_ro_after_init = 1;
> +static int apparmor_enabled __ro_after_init = 1;
>   module_param_named(enabled, apparmor_enabled, aaintbool, 0444);
>   
>   static int __init apparmor_enabled_setup(char *str)
> diff --git a/security/commoncap.c b/security/commoncap.c
> index f4ee0ae106b2..1471d9a5a9bc 100644
> --- a/security/commoncap.c
> +++ b/security/commoncap.c
> @@ -1339,7 +1339,7 @@ int cap_mmap_file(struct file *file, unsigned long reqprot,
>   
>   #ifdef CONFIG_SECURITY
>   
> -static struct security_hook_list capability_hooks[] __lsm_ro_after_init = {
> +static struct security_hook_list capability_hooks[] __ro_after_init = {
>   	LSM_HOOK_INIT(capable, cap_capable),
>   	LSM_HOOK_INIT(settime, cap_settime),
>   	LSM_HOOK_INIT(ptrace_access_check, cap_ptrace_access_check),
> diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c
> index ee5cb944f4ad..9bbc08bee2c0 100644
> --- a/security/loadpin/loadpin.c
> +++ b/security/loadpin/loadpin.c
> @@ -180,7 +180,7 @@ static int loadpin_load_data(enum kernel_load_data_id id)
>   	return loadpin_read_file(NULL, (enum kernel_read_file_id) id);
>   }
>   
> -static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = {
> +static struct security_hook_list loadpin_hooks[] __ro_after_init = {
>   	LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security),
>   	LSM_HOOK_INIT(kernel_read_file, loadpin_read_file),
>   	LSM_HOOK_INIT(kernel_load_data, loadpin_load_data),
> diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c
> index 5a952617a0eb..8071d0f542c8 100644
> --- a/security/lockdown/lockdown.c
> +++ b/security/lockdown/lockdown.c
> @@ -71,7 +71,7 @@ static int lockdown_is_locked_down(enum lockdown_reason what)
>   	return 0;
>   }
>   
> -static struct security_hook_list lockdown_hooks[] __lsm_ro_after_init = {
> +static struct security_hook_list lockdown_hooks[] __ro_after_init = {
>   	LSM_HOOK_INIT(locked_down, lockdown_is_locked_down),
>   };
>   
> diff --git a/security/security.c b/security/security.c
> index 2b5473d92416..3138a5d99813 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -27,6 +27,7 @@
>   #include <linux/backing-dev.h>
>   #include <linux/string.h>
>   #include <linux/msg.h>
> +#include <linux/rculist.h>
>   #include <net/flow.h>
>   
>   #define MAX_LSM_EVM_XATTR	2
> @@ -68,14 +69,14 @@ const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {
>   	[LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality",
>   };
>   
> -struct security_hook_heads security_hook_heads __lsm_ro_after_init;
> +struct security_hook_heads security_hook_heads __ro_after_init;
>   static BLOCKING_NOTIFIER_HEAD(blocking_lsm_notifier_chain);
>   
>   static struct kmem_cache *lsm_file_cache;
>   static struct kmem_cache *lsm_inode_cache;
>   
>   char *lsm_names;
> -static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init;
> +static struct lsm_blob_sizes blob_sizes __ro_after_init;
>   
>   /* Boot-time LSM user choice */
>   static __initdata const char *chosen_lsm_order;
> diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
> index 996d35d950f7..caa5711478ad 100644
> --- a/security/selinux/Kconfig
> +++ b/security/selinux/Kconfig
> @@ -26,7 +26,6 @@ config SECURITY_SELINUX_BOOTPARAM
>   config SECURITY_SELINUX_DISABLE
>   	bool "NSA SELinux runtime disable"
>   	depends on SECURITY_SELINUX
> -	select SECURITY_WRITABLE_HOOKS
>   	default n
>   	help
>   	  This option enables writing to a selinuxfs node 'disable', which
> @@ -37,11 +36,6 @@ config SECURITY_SELINUX_DISABLE
>   	  portability across platforms where boot parameters are difficult
>   	  to employ.
>   
> -	  NOTE: selecting this option will disable the '__ro_after_init'
> -	  kernel hardening feature for security hooks.   Please consider
> -	  using the selinux=0 boot parameter instead of enabling this
> -	  option.
> -
>   	  If you are unsure how to answer this question, answer N.
>   
>   config SECURITY_SELINUX_DEVELOP
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 47ad4db925cf..9ac2b6b69ff9 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -650,13 +650,15 @@ static int selinux_set_mnt_opts(struct super_block *sb,
>   {
>   	const struct cred *cred = current_cred();
>   	struct superblock_security_struct *sbsec = sb->s_security;
> -	struct dentry *root = sbsec->sb->s_root;
>   	struct selinux_mnt_opts *opts = mnt_opts;
>   	struct inode_security_struct *root_isec;
>   	u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
>   	u32 defcontext_sid = 0;
>   	int rc = 0;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	mutex_lock(&sbsec->lock);
>   
>   	if (!selinux_initialized(&selinux_state)) {
> @@ -693,7 +695,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
>   	    && !opts)
>   		goto out;
>   
> -	root_isec = backing_inode_security_novalidate(root);
> +	root_isec = backing_inode_security_novalidate(sbsec->sb->s_root);
>   
>   	/*
>   	 * parse the mount options, check if they are valid sids.
> @@ -919,10 +921,14 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
>   	int rc = 0;
>   	const struct superblock_security_struct *oldsbsec = oldsb->s_security;
>   	struct superblock_security_struct *newsbsec = newsb->s_security;
> +	int set_fscontext, set_context, set_rootcontext;
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>   
> -	int set_fscontext =	(oldsbsec->flags & FSCONTEXT_MNT);
> -	int set_context =	(oldsbsec->flags & CONTEXT_MNT);
> -	int set_rootcontext =	(oldsbsec->flags & ROOTCONTEXT_MNT);
> +	set_fscontext =		(oldsbsec->flags & FSCONTEXT_MNT);
> +	set_context =		(oldsbsec->flags & CONTEXT_MNT);
> +	set_rootcontext =	(oldsbsec->flags & ROOTCONTEXT_MNT);
>   
>   	/*
>   	 * if the parent was able to be mounted it clearly had no special lsm
> @@ -1041,6 +1047,9 @@ static int selinux_add_mnt_opt(const char *option, const char *val, int len,
>   	int token = Opt_error;
>   	int rc, i;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	for (i = 0; i < ARRAY_SIZE(tokens); i++) {
>   		if (strcmp(option, tokens[i].name) == 0) {
>   			token = tokens[i].opt;
> @@ -1100,6 +1109,9 @@ static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
>   	struct superblock_security_struct *sbsec = sb->s_security;
>   	int rc;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	if (!(sbsec->flags & SE_SBINITIALIZED))
>   		return 0;
>   
> @@ -2044,22 +2056,27 @@ static inline u32 open_file_to_av(struct file *file)
>   
>   static int selinux_binder_set_context_mgr(struct task_struct *mgr)
>   {
> -	u32 mysid = current_sid();
> -	u32 mgrsid = task_sid(mgr);
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>   
>   	return avc_has_perm(&selinux_state,
> -			    mysid, mgrsid, SECCLASS_BINDER,
> +			    current_sid(), task_sid(mgr), SECCLASS_BINDER,
>   			    BINDER__SET_CONTEXT_MGR, NULL);
>   }
>   
>   static int selinux_binder_transaction(struct task_struct *from,
>   				      struct task_struct *to)
>   {
> -	u32 mysid = current_sid();
> -	u32 fromsid = task_sid(from);
> -	u32 tosid = task_sid(to);
> +	u32 mysid, fromsid, tosid;
>   	int rc;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	mysid = current_sid();
> +	fromsid = task_sid(from);
> +	tosid = task_sid(to);
> +
>   	if (mysid != fromsid) {
>   		rc = avc_has_perm(&selinux_state,
>   				  mysid, fromsid, SECCLASS_BINDER,
> @@ -2076,11 +2093,12 @@ static int selinux_binder_transaction(struct task_struct *from,
>   static int selinux_binder_transfer_binder(struct task_struct *from,
>   					  struct task_struct *to)
>   {
> -	u32 fromsid = task_sid(from);
> -	u32 tosid = task_sid(to);
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>   
>   	return avc_has_perm(&selinux_state,
> -			    fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
> +			    task_sid(from), task_sid(to),
> +			    SECCLASS_BINDER, BINDER__TRANSFER,
>   			    NULL);
>   }
>   
> @@ -2088,13 +2106,18 @@ static int selinux_binder_transfer_file(struct task_struct *from,
>   					struct task_struct *to,
>   					struct file *file)
>   {
> -	u32 sid = task_sid(to);
> +	u32 sid;
>   	struct file_security_struct *fsec = selinux_file(file);
>   	struct dentry *dentry = file->f_path.dentry;
>   	struct inode_security_struct *isec;
>   	struct common_audit_data ad;
>   	int rc;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	sid = task_sid(to);
> +
>   	ad.type = LSM_AUDIT_DATA_PATH;
>   	ad.u.path = file->f_path;
>   
> @@ -2126,19 +2149,26 @@ static int selinux_binder_transfer_file(struct task_struct *from,
>   static int selinux_ptrace_access_check(struct task_struct *child,
>   				     unsigned int mode)
>   {
> -	u32 sid = current_sid();
> -	u32 csid = task_sid(child);
> +	u16 cls = SECCLASS_PROCESS;
> +	u32 perm = PROCESS__PTRACE;
>   
> -	if (mode & PTRACE_MODE_READ)
> -		return avc_has_perm(&selinux_state,
> -				    sid, csid, SECCLASS_FILE, FILE__READ, NULL);
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	if (mode & PTRACE_MODE_READ) {
> +		cls = SECCLASS_FILE;
> +		perm = FILE__READ;
> +	}
>   
>   	return avc_has_perm(&selinux_state,
> -			    sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL);
> +			    current_sid(), task_sid(child), cls, perm, NULL);
>   }
>   
>   static int selinux_ptrace_traceme(struct task_struct *parent)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return avc_has_perm(&selinux_state,
>   			    task_sid(parent), current_sid(), SECCLASS_PROCESS,
>   			    PROCESS__PTRACE, NULL);
> @@ -2147,6 +2177,9 @@ static int selinux_ptrace_traceme(struct task_struct *parent)
>   static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
>   			  kernel_cap_t *inheritable, kernel_cap_t *permitted)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return avc_has_perm(&selinux_state,
>   			    current_sid(), task_sid(target), SECCLASS_PROCESS,
>   			    PROCESS__GETCAP, NULL);
> @@ -2157,6 +2190,9 @@ static int selinux_capset(struct cred *new, const struct cred *old,
>   			  const kernel_cap_t *inheritable,
>   			  const kernel_cap_t *permitted)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return avc_has_perm(&selinux_state,
>   			    cred_sid(old), cred_sid(new), SECCLASS_PROCESS,
>   			    PROCESS__SETCAP, NULL);
> @@ -2175,6 +2211,9 @@ static int selinux_capset(struct cred *new, const struct cred *old,
>   static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
>   			   int cap, unsigned int opts)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return cred_has_capability(cred, cap, opts, ns == &init_user_ns);
>   }
>   
> @@ -2186,6 +2225,9 @@ static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
>   	if (!sb)
>   		return 0;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	switch (cmds) {
>   	case Q_SYNC:
>   	case Q_QUOTAON:
> @@ -2210,11 +2252,17 @@ static int selinux_quota_on(struct dentry *dentry)
>   {
>   	const struct cred *cred = current_cred();
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return dentry_has_perm(cred, dentry, FILE__QUOTAON);
>   }
>   
>   static int selinux_syslog(int type)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	switch (type) {
>   	case SYSLOG_ACTION_READ_ALL:	/* Read last kernel messages */
>   	case SYSLOG_ACTION_SIZE_BUFFER:	/* Return size of the log buffer */
> @@ -2248,6 +2296,9 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
>   {
>   	int rc, cap_sys_admin = 0;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
>   				 CAP_OPT_NOAUDIT, true);
>   	if (rc == 0)
> @@ -2335,6 +2386,9 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
>   	struct inode *inode = file_inode(bprm->file);
>   	int rc;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	/* SELinux context only depends on initial program or script and not
>   	 * the script interpreter */
>   	if (bprm->called_set_creds)
> @@ -2505,6 +2559,9 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
>   	struct rlimit *rlim, *initrlim;
>   	int rc, i;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	new_tsec = selinux_cred(bprm->cred);
>   	if (new_tsec->sid == new_tsec->osid)
>   		return;
> @@ -2552,6 +2609,9 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
>   	u32 osid, sid;
>   	int rc;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	osid = tsec->osid;
>   	sid = tsec->sid;
>   
> @@ -2592,11 +2652,17 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
>   
>   static int selinux_sb_alloc_security(struct super_block *sb)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return superblock_alloc_security(sb);
>   }
>   
>   static void selinux_sb_free_security(struct super_block *sb)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	superblock_free_security(sb);
>   }
>   
> @@ -2622,6 +2688,9 @@ static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts)
>   	bool first = true;
>   	int rc;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	while (1) {
>   		int len = opt_len(from);
>   		int token;
> @@ -2682,6 +2751,9 @@ static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
>   	u32 sid;
>   	int rc;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	if (!(sbsec->flags & SE_SBINITIALIZED))
>   		return 0;
>   
> @@ -2732,6 +2804,9 @@ static int selinux_sb_kern_mount(struct super_block *sb)
>   	const struct cred *cred = current_cred();
>   	struct common_audit_data ad;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	ad.type = LSM_AUDIT_DATA_DENTRY;
>   	ad.u.dentry = sb->s_root;
>   	return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
> @@ -2742,6 +2817,9 @@ static int selinux_sb_statfs(struct dentry *dentry)
>   	const struct cred *cred = current_cred();
>   	struct common_audit_data ad;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	ad.type = LSM_AUDIT_DATA_DENTRY;
>   	ad.u.dentry = dentry->d_sb->s_root;
>   	return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
> @@ -2755,6 +2833,9 @@ static int selinux_mount(const char *dev_name,
>   {
>   	const struct cred *cred = current_cred();
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	if (flags & MS_REMOUNT)
>   		return superblock_has_perm(cred, path->dentry->d_sb,
>   					   FILESYSTEM__REMOUNT, NULL);
> @@ -2766,6 +2847,9 @@ static int selinux_umount(struct vfsmount *mnt, int flags)
>   {
>   	const struct cred *cred = current_cred();
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return superblock_has_perm(cred, mnt->mnt_sb,
>   				   FILESYSTEM__UNMOUNT, NULL);
>   }
> @@ -2776,6 +2860,9 @@ static int selinux_fs_context_dup(struct fs_context *fc,
>   	const struct selinux_mnt_opts *src = src_fc->security;
>   	struct selinux_mnt_opts *opts;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	if (!src)
>   		return 0;
>   
> @@ -2828,6 +2915,9 @@ static int selinux_fs_context_parse_param(struct fs_context *fc,
>   	struct fs_parse_result result;
>   	int opt, rc;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	opt = fs_parse(fc, &selinux_fs_parameters, param, &result);
>   	if (opt < 0)
>   		return opt;
> @@ -2844,11 +2934,17 @@ static int selinux_fs_context_parse_param(struct fs_context *fc,
>   
>   static int selinux_inode_alloc_security(struct inode *inode)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return inode_alloc_security(inode);
>   }
>   
>   static void selinux_inode_free_security(struct inode *inode)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	inode_free_security(inode);
>   }
>   
> @@ -2859,6 +2955,9 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,
>   	u32 newsid;
>   	int rc;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	rc = selinux_determine_inode_label(selinux_cred(current_cred()),
>   					   d_inode(dentry->d_parent), name,
>   					   inode_mode_to_security_class(mode),
> @@ -2879,6 +2978,9 @@ static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
>   	int rc;
>   	struct task_security_struct *tsec;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	rc = selinux_determine_inode_label(selinux_cred(old),
>   					   d_inode(dentry->d_parent), name,
>   					   inode_mode_to_security_class(mode),
> @@ -2902,6 +3004,9 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
>   	int rc;
>   	char *context;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	sbsec = dir->i_sb->s_security;
>   
>   	newsid = tsec->create_sid;
> @@ -2941,50 +3046,75 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
>   
>   static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return may_create(dir, dentry, SECCLASS_FILE);
>   }
>   
>   static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return may_link(dir, old_dentry, MAY_LINK);
>   }
>   
>   static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return may_link(dir, dentry, MAY_UNLINK);
>   }
>   
>   static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return may_create(dir, dentry, SECCLASS_LNK_FILE);
>   }
>   
>   static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return may_create(dir, dentry, SECCLASS_DIR);
>   }
>   
>   static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return may_link(dir, dentry, MAY_RMDIR);
>   }
>   
>   static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return may_create(dir, dentry, inode_mode_to_security_class(mode));
>   }
>   
>   static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
>   				struct inode *new_inode, struct dentry *new_dentry)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return may_rename(old_inode, old_dentry, new_inode, new_dentry);
>   }
>   
>   static int selinux_inode_readlink(struct dentry *dentry)
>   {
> -	const struct cred *cred = current_cred();
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>   
> -	return dentry_has_perm(cred, dentry, FILE__READ);
> +	return dentry_has_perm(current_cred(), dentry, FILE__READ);
>   }
>   
>   static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
> @@ -2995,6 +3125,9 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
>   	struct inode_security_struct *isec;
>   	u32 sid;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	validate_creds(cred);
>   
>   	ad.type = LSM_AUDIT_DATA_DENTRY;
> @@ -3040,6 +3173,9 @@ static int selinux_inode_permission(struct inode *inode, int mask)
>   	int rc, rc2;
>   	u32 audited, denied;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	from_access = mask & MAY_ACCESS;
>   	mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
>   
> @@ -3086,6 +3222,9 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
>   	unsigned int ia_valid = iattr->ia_valid;
>   	__u32 av = FILE__WRITE;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	/* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
>   	if (ia_valid & ATTR_FORCE) {
>   		ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
> @@ -3109,6 +3248,9 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
>   
>   static int selinux_inode_getattr(const struct path *path)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return path_has_perm(current_cred(), path, FILE__GETATTR);
>   }
>   
> @@ -3131,9 +3273,12 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
>   	struct inode_security_struct *isec;
>   	struct superblock_security_struct *sbsec;
>   	struct common_audit_data ad;
> -	u32 newsid, sid = current_sid();
> +	u32 newsid, sid;
>   	int rc = 0;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	if (strcmp(name, XATTR_NAME_SELINUX)) {
>   		rc = cap_inode_setxattr(dentry, name, value, size, flags);
>   		if (rc)
> @@ -3154,6 +3299,8 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
>   	if (!inode_owner_or_capable(inode))
>   		return -EPERM;
>   
> +	sid = current_sid();
> +
>   	ad.type = LSM_AUDIT_DATA_DENTRY;
>   	ad.u.dentry = dentry;
>   
> @@ -3225,6 +3372,9 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
>   	u32 newsid;
>   	int rc;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	if (strcmp(name, XATTR_NAME_SELINUX)) {
>   		/* Not an attribute we recognize, so nothing to do. */
>   		return;
> @@ -3260,20 +3410,25 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
>   
>   static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
>   {
> -	const struct cred *cred = current_cred();
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>   
> -	return dentry_has_perm(cred, dentry, FILE__GETATTR);
> +	return dentry_has_perm(current_cred(), dentry, FILE__GETATTR);
>   }
>   
>   static int selinux_inode_listxattr(struct dentry *dentry)
>   {
> -	const struct cred *cred = current_cred();
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>   
> -	return dentry_has_perm(cred, dentry, FILE__GETATTR);
> +	return dentry_has_perm(current_cred(), dentry, FILE__GETATTR);
>   }
>   
>   static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	if (strcmp(name, XATTR_NAME_SELINUX)) {
>   		int rc = cap_inode_removexattr(dentry, name);
>   		if (rc)
> @@ -3297,6 +3452,9 @@ static int selinux_path_notify(const struct path *path, u64 mask,
>   
>   	struct common_audit_data ad;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	ad.type = LSM_AUDIT_DATA_PATH;
>   	ad.u.path = *path;
>   
> @@ -3345,6 +3503,9 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void
>   	char *context = NULL;
>   	struct inode_security_struct *isec;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return -EOPNOTSUPP;
> +
>   	if (strcmp(name, XATTR_SELINUX_SUFFIX))
>   		return -EOPNOTSUPP;
>   
> @@ -3385,6 +3546,9 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
>   	u32 newsid;
>   	int rc;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return -EOPNOTSUPP;
> +
>   	if (strcmp(name, XATTR_SELINUX_SUFFIX))
>   		return -EOPNOTSUPP;
>   
> @@ -3410,6 +3574,10 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
>   static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
>   {
>   	const int len = sizeof(XATTR_NAME_SELINUX);
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	if (buffer && len <= buffer_size)
>   		memcpy(buffer, XATTR_NAME_SELINUX, len);
>   	return len;
> @@ -3417,16 +3585,24 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t
>   
>   static void selinux_inode_getsecid(struct inode *inode, u32 *secid)
>   {
> -	struct inode_security_struct *isec = inode_security_novalidate(inode);
> +	struct inode_security_struct *isec;
> +
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
> +	isec = inode_security_novalidate(inode);
>   	*secid = isec->sid;
>   }
>   
>   static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
>   {
> -	u32 sid;
> +	struct inode_security_struct *isec;
>   	struct task_security_struct *tsec;
>   	struct cred *new_creds = *new;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	if (new_creds == NULL) {
>   		new_creds = prepare_creds();
>   		if (!new_creds)
> @@ -3435,14 +3611,17 @@ static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
>   
>   	tsec = selinux_cred(new_creds);
>   	/* Get label from overlay inode and set it in create_sid */
> -	selinux_inode_getsecid(d_inode(src), &sid);
> -	tsec->create_sid = sid;
> +	isec = inode_security_novalidate(d_inode(src));
> +	tsec->create_sid = isec->sid;
>   	*new = new_creds;
>   	return 0;
>   }
>   
>   static int selinux_inode_copy_up_xattr(const char *name)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return -EOPNOTSUPP;
> +
>   	/* The copy_up hook above sets the initial context on an inode, but we
>   	 * don't then want to overwrite it by blindly copying all the lower
>   	 * xattrs up.  Instead, we have to filter out SELinux-related xattrs.
> @@ -3466,6 +3645,9 @@ static int selinux_kernfs_init_security(struct kernfs_node *kn_dir,
>   	int rc;
>   	char *context;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	rc = kernfs_xattr_get(kn_dir, XATTR_NAME_SELINUX, NULL, 0);
>   	if (rc == -ENODATA)
>   		return 0;
> @@ -3537,14 +3719,16 @@ static int selinux_file_permission(struct file *file, int mask)
>   	struct inode *inode = file_inode(file);
>   	struct file_security_struct *fsec = selinux_file(file);
>   	struct inode_security_struct *isec;
> -	u32 sid = current_sid();
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>   
>   	if (!mask)
>   		/* No permission to check.  Existence test. */
>   		return 0;
>   
>   	isec = inode_security(inode);
> -	if (sid == fsec->sid && fsec->isid == isec->sid &&
> +	if (current_sid() == fsec->sid && fsec->isid == isec->sid &&
>   	    fsec->pseqno == avc_policy_seqno(&selinux_state))
>   		/* No change since file_open check. */
>   		return 0;
> @@ -3554,6 +3738,9 @@ static int selinux_file_permission(struct file *file, int mask)
>   
>   static int selinux_file_alloc_security(struct file *file)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return file_alloc_security(file);
>   }
>   
> @@ -3606,6 +3793,9 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
>   	const struct cred *cred = current_cred();
>   	int error = 0;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	switch (cmd) {
>   	case FIONREAD:
>   	/* fall through */
> @@ -3692,6 +3882,9 @@ static int selinux_mmap_addr(unsigned long addr)
>   {
>   	int rc = 0;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
>   		u32 sid = current_sid();
>   		rc = avc_has_perm(&selinux_state,
> @@ -3708,6 +3901,9 @@ static int selinux_mmap_file(struct file *file, unsigned long reqprot,
>   	struct common_audit_data ad;
>   	int rc;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	if (file) {
>   		ad.type = LSM_AUDIT_DATA_FILE;
>   		ad.u.file = file;
> @@ -3729,7 +3925,12 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
>   				 unsigned long prot)
>   {
>   	const struct cred *cred = current_cred();
> -	u32 sid = cred_sid(cred);
> +	u32 sid;
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	sid = cred_sid(cred);
>   
>   	if (selinux_state.checkreqprot)
>   		prot = reqprot;
> @@ -3768,9 +3969,10 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
>   
>   static int selinux_file_lock(struct file *file, unsigned int cmd)
>   {
> -	const struct cred *cred = current_cred();
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>   
> -	return file_has_perm(cred, file, FILE__LOCK);
> +	return file_has_perm(current_cred(), file, FILE__LOCK);
>   }
>   
>   static int selinux_file_fcntl(struct file *file, unsigned int cmd,
> @@ -3779,6 +3981,9 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
>   	const struct cred *cred = current_cred();
>   	int err = 0;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	switch (cmd) {
>   	case F_SETFL:
>   		if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
> @@ -3817,6 +4022,9 @@ static void selinux_file_set_fowner(struct file *file)
>   {
>   	struct file_security_struct *fsec;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	fsec = selinux_file(file);
>   	fsec->fown_sid = current_sid();
>   }
> @@ -3825,10 +4033,12 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk,
>   				       struct fown_struct *fown, int signum)
>   {
>   	struct file *file;
> -	u32 sid = task_sid(tsk);
>   	u32 perm;
>   	struct file_security_struct *fsec;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	/* struct fown_struct is never outside the context of a struct file */
>   	file = container_of(fown, struct file, f_owner);
>   
> @@ -3840,15 +4050,16 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk,
>   		perm = signal_to_av(signum);
>   
>   	return avc_has_perm(&selinux_state,
> -			    fsec->fown_sid, sid,
> +			    fsec->fown_sid, task_sid(tsk),
>   			    SECCLASS_PROCESS, perm, NULL);
>   }
>   
>   static int selinux_file_receive(struct file *file)
>   {
> -	const struct cred *cred = current_cred();
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>   
> -	return file_has_perm(cred, file, file_to_av(file));
> +	return file_has_perm(current_cred(), file, file_to_av(file));
>   }
>   
>   static int selinux_file_open(struct file *file)
> @@ -3856,6 +4067,9 @@ static int selinux_file_open(struct file *file)
>   	struct file_security_struct *fsec;
>   	struct inode_security_struct *isec;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	fsec = selinux_file(file);
>   	isec = inode_security(file_inode(file));
>   	/*
> @@ -3883,7 +4097,12 @@ static int selinux_file_open(struct file *file)
>   static int selinux_task_alloc(struct task_struct *task,
>   			      unsigned long clone_flags)
>   {
> -	u32 sid = current_sid();
> +	u32 sid;
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	sid = current_sid();
>   
>   	return avc_has_perm(&selinux_state,
>   			    sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL);
> @@ -3898,6 +4117,9 @@ static int selinux_cred_prepare(struct cred *new, const struct cred *old,
>   	const struct task_security_struct *old_tsec = selinux_cred(old);
>   	struct task_security_struct *tsec = selinux_cred(new);
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	*tsec = *old_tsec;
>   	return 0;
>   }
> @@ -3910,11 +4132,17 @@ static void selinux_cred_transfer(struct cred *new, const struct cred *old)
>   	const struct task_security_struct *old_tsec = selinux_cred(old);
>   	struct task_security_struct *tsec = selinux_cred(new);
>   
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	*tsec = *old_tsec;
>   }
>   
>   static void selinux_cred_getsecid(const struct cred *c, u32 *secid)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	*secid = cred_sid(c);
>   }
>   
> @@ -3925,11 +4153,13 @@ static void selinux_cred_getsecid(const struct cred *c, u32 *secid)
>   static int selinux_kernel_act_as(struct cred *new, u32 secid)
>   {
>   	struct task_security_struct *tsec = selinux_cred(new);
> -	u32 sid = current_sid();
>   	int ret;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	ret = avc_has_perm(&selinux_state,
> -			   sid, secid,
> +			   current_sid(), secid,
>   			   SECCLASS_KERNEL_SERVICE,
>   			   KERNEL_SERVICE__USE_AS_OVERRIDE,
>   			   NULL);
> @@ -3950,11 +4180,13 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
>   {
>   	struct inode_security_struct *isec = inode_security(inode);
>   	struct task_security_struct *tsec = selinux_cred(new);
> -	u32 sid = current_sid();
>   	int ret;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	ret = avc_has_perm(&selinux_state,
> -			   sid, isec->sid,
> +			   current_sid(), isec->sid,
>   			   SECCLASS_KERNEL_SERVICE,
>   			   KERNEL_SERVICE__CREATE_FILES_AS,
>   			   NULL);
> @@ -3968,6 +4200,9 @@ static int selinux_kernel_module_request(char *kmod_name)
>   {
>   	struct common_audit_data ad;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	ad.type = LSM_AUDIT_DATA_KMOD;
>   	ad.u.kmod_name = kmod_name;
>   
> @@ -4012,35 +4247,37 @@ static int selinux_kernel_module_from_file(struct file *file)
>   static int selinux_kernel_read_file(struct file *file,
>   				    enum kernel_read_file_id id)
>   {
> -	int rc = 0;
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>   
>   	switch (id) {
>   	case READING_MODULE:
> -		rc = selinux_kernel_module_from_file(file);
> -		break;
> +		return selinux_kernel_module_from_file(file);
>   	default:
>   		break;
>   	}
> -
> -	return rc;
> +	return 0;
>   }
>   
>   static int selinux_kernel_load_data(enum kernel_load_data_id id)
>   {
> -	int rc = 0;
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>   
>   	switch (id) {
>   	case LOADING_MODULE:
> -		rc = selinux_kernel_module_from_file(NULL);
> +		return selinux_kernel_module_from_file(NULL);
>   	default:
>   		break;
>   	}
> -
> -	return rc;
> +	return 0;
>   }
>   
>   static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return avc_has_perm(&selinux_state,
>   			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>   			    PROCESS__SETPGID, NULL);
> @@ -4048,6 +4285,9 @@ static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
>   
>   static int selinux_task_getpgid(struct task_struct *p)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return avc_has_perm(&selinux_state,
>   			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>   			    PROCESS__GETPGID, NULL);
> @@ -4055,6 +4295,9 @@ static int selinux_task_getpgid(struct task_struct *p)
>   
>   static int selinux_task_getsid(struct task_struct *p)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return avc_has_perm(&selinux_state,
>   			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>   			    PROCESS__GETSESSION, NULL);
> @@ -4062,11 +4305,17 @@ static int selinux_task_getsid(struct task_struct *p)
>   
>   static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	*secid = task_sid(p);
>   }
>   
>   static int selinux_task_setnice(struct task_struct *p, int nice)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return avc_has_perm(&selinux_state,
>   			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>   			    PROCESS__SETSCHED, NULL);
> @@ -4074,6 +4323,9 @@ static int selinux_task_setnice(struct task_struct *p, int nice)
>   
>   static int selinux_task_setioprio(struct task_struct *p, int ioprio)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return avc_has_perm(&selinux_state,
>   			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>   			    PROCESS__SETSCHED, NULL);
> @@ -4081,6 +4333,9 @@ static int selinux_task_setioprio(struct task_struct *p, int ioprio)
>   
>   static int selinux_task_getioprio(struct task_struct *p)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return avc_has_perm(&selinux_state,
>   			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>   			    PROCESS__GETSCHED, NULL);
> @@ -4091,6 +4346,9 @@ static int selinux_task_prlimit(const struct cred *cred, const struct cred *tcre
>   {
>   	u32 av = 0;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	if (!flags)
>   		return 0;
>   	if (flags & LSM_PRLIMIT_WRITE)
> @@ -4107,6 +4365,9 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
>   {
>   	struct rlimit *old_rlim = p->signal->rlim + resource;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	/* 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
> @@ -4121,6 +4382,9 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
>   
>   static int selinux_task_setscheduler(struct task_struct *p)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return avc_has_perm(&selinux_state,
>   			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>   			    PROCESS__SETSCHED, NULL);
> @@ -4128,6 +4392,9 @@ static int selinux_task_setscheduler(struct task_struct *p)
>   
>   static int selinux_task_getscheduler(struct task_struct *p)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return avc_has_perm(&selinux_state,
>   			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>   			    PROCESS__GETSCHED, NULL);
> @@ -4135,6 +4402,9 @@ static int selinux_task_getscheduler(struct task_struct *p)
>   
>   static int selinux_task_movememory(struct task_struct *p)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return avc_has_perm(&selinux_state,
>   			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>   			    PROCESS__SETSCHED, NULL);
> @@ -4146,6 +4416,9 @@ static int selinux_task_kill(struct task_struct *p, struct kernel_siginfo *info,
>   	u32 secid;
>   	u32 perm;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	if (!sig)
>   		perm = PROCESS__SIGNULL; /* null signal; existence test */
>   	else
> @@ -4162,11 +4435,13 @@ static void selinux_task_to_inode(struct task_struct *p,
>   				  struct inode *inode)
>   {
>   	struct inode_security_struct *isec = selinux_inode(inode);
> -	u32 sid = task_sid(p);
> +
> +	if (selinux_disabled(&selinux_state))
> +		return;
>   
>   	spin_lock(&isec->lock);
>   	isec->sclass = inode_mode_to_security_class(inode->i_mode);
> -	isec->sid = sid;
> +	isec->sid = task_sid(p);
>   	isec->initialized = LABEL_INITIALIZED;
>   	spin_unlock(&isec->lock);
>   }
> @@ -4506,6 +4781,9 @@ static int selinux_socket_create(int family, int type,
>   	if (kern)
>   		return 0;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	secclass = socket_type_to_security_class(family, type, protocol);
>   	rc = socket_sockcreate_sid(tsec, secclass, &newsid);
>   	if (rc)
> @@ -4525,6 +4803,9 @@ static int selinux_socket_post_create(struct socket *sock, int family,
>   	u32 sid = SECINITSID_KERNEL;
>   	int err = 0;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	if (!kern) {
>   		err = socket_sockcreate_sid(tsec, sclass, &sid);
>   		if (err)
> @@ -4555,6 +4836,9 @@ static int selinux_socket_socketpair(struct socket *socka,
>   	struct sk_security_struct *sksec_a = socka->sk->sk_security;
>   	struct sk_security_struct *sksec_b = sockb->sk->sk_security;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	sksec_a->peer_sid = sksec_b->sid;
>   	sksec_b->peer_sid = sksec_a->sid;
>   
> @@ -4572,6 +4856,9 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
>   	u16 family;
>   	int err;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	err = sock_has_perm(sk, SOCKET__BIND);
>   	if (err)
>   		goto out;
> @@ -4796,6 +5083,9 @@ static int selinux_socket_connect(struct socket *sock,
>   	int err;
>   	struct sock *sk = sock->sk;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	err = selinux_socket_connect_helper(sock, address, addrlen);
>   	if (err)
>   		return err;
> @@ -4805,6 +5095,9 @@ static int selinux_socket_connect(struct socket *sock,
>   
>   static int selinux_socket_listen(struct socket *sock, int backlog)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return sock_has_perm(sock->sk, SOCKET__LISTEN);
>   }
>   
> @@ -4816,6 +5109,9 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
>   	u16 sclass;
>   	u32 sid;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	err = sock_has_perm(sock->sk, SOCKET__ACCEPT);
>   	if (err)
>   		return err;
> @@ -4837,22 +5133,34 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
>   static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
>   				  int size)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return sock_has_perm(sock->sk, SOCKET__WRITE);
>   }
>   
>   static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
>   				  int size, int flags)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return sock_has_perm(sock->sk, SOCKET__READ);
>   }
>   
>   static int selinux_socket_getsockname(struct socket *sock)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return sock_has_perm(sock->sk, SOCKET__GETATTR);
>   }
>   
>   static int selinux_socket_getpeername(struct socket *sock)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return sock_has_perm(sock->sk, SOCKET__GETATTR);
>   }
>   
> @@ -4860,6 +5168,9 @@ static int selinux_socket_setsockopt(struct socket *sock, int level, int optname
>   {
>   	int err;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	err = sock_has_perm(sock->sk, SOCKET__SETOPT);
>   	if (err)
>   		return err;
> @@ -4870,11 +5181,17 @@ static int selinux_socket_setsockopt(struct socket *sock, int level, int optname
>   static int selinux_socket_getsockopt(struct socket *sock, int level,
>   				     int optname)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return sock_has_perm(sock->sk, SOCKET__GETOPT);
>   }
>   
>   static int selinux_socket_shutdown(struct socket *sock, int how)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return sock_has_perm(sock->sk, SOCKET__SHUTDOWN);
>   }
>   
> @@ -4889,6 +5206,9 @@ static int selinux_socket_unix_stream_connect(struct sock *sock,
>   	struct lsm_network_audit net = {0,};
>   	int err;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	ad.type = LSM_AUDIT_DATA_NET;
>   	ad.u.net = &net;
>   	ad.u.net->sk = other;
> @@ -4921,6 +5241,9 @@ static int selinux_socket_unix_may_send(struct socket *sock,
>   	struct common_audit_data ad;
>   	struct lsm_network_audit net = {0,};
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	ad.type = LSM_AUDIT_DATA_NET;
>   	ad.u.net = &net;
>   	ad.u.net->sk = other->sk;
> @@ -4994,13 +5317,15 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
>   	int err;
>   	struct sk_security_struct *sksec = sk->sk_security;
>   	u16 family = sk->sk_family;
> -	u32 sk_sid = sksec->sid;
>   	struct common_audit_data ad;
>   	struct lsm_network_audit net = {0,};
>   	char *addrp;
>   	u8 secmark_active;
>   	u8 peerlbl_active;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	if (family != PF_INET && family != PF_INET6)
>   		return 0;
>   
> @@ -5041,7 +5366,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
>   			return err;
>   		}
>   		err = avc_has_perm(&selinux_state,
> -				   sk_sid, peer_sid, SECCLASS_PEER,
> +				   sksec->sid, peer_sid, SECCLASS_PEER,
>   				   PEER__RECV, &ad);
>   		if (err) {
>   			selinux_netlbl_err(skb, family, err, 0);
> @@ -5051,7 +5376,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
>   
>   	if (secmark_active) {
>   		err = avc_has_perm(&selinux_state,
> -				   sk_sid, skb->secmark, SECCLASS_PACKET,
> +				   sksec->sid, skb->secmark, SECCLASS_PACKET,
>   				   PACKET__RECV, &ad);
>   		if (err)
>   			return err;
> @@ -5069,6 +5394,9 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op
>   	struct sk_security_struct *sksec = sock->sk->sk_security;
>   	u32 peer_sid = SECSID_NULL;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
>   	    sksec->sclass == SECCLASS_TCP_SOCKET ||
>   	    sksec->sclass == SECCLASS_SCTP_SOCKET)
> @@ -5102,6 +5430,9 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
>   	u16 family;
>   	struct inode_security_struct *isec;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	if (skb && skb->protocol == htons(ETH_P_IP))
>   		family = PF_INET;
>   	else if (skb && skb->protocol == htons(ETH_P_IPV6))
> @@ -5128,6 +5459,9 @@ static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority
>   {
>   	struct sk_security_struct *sksec;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	sksec = kzalloc(sizeof(*sksec), priority);
>   	if (!sksec)
>   		return -ENOMEM;
> @@ -5145,6 +5479,9 @@ static void selinux_sk_free_security(struct sock *sk)
>   {
>   	struct sk_security_struct *sksec = sk->sk_security;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	sk->sk_security = NULL;
>   	selinux_netlbl_sk_security_free(sksec);
>   	kfree(sksec);
> @@ -5155,6 +5492,9 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
>   	struct sk_security_struct *sksec = sk->sk_security;
>   	struct sk_security_struct *newsksec = newsk->sk_security;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	newsksec->sid = sksec->sid;
>   	newsksec->peer_sid = sksec->peer_sid;
>   	newsksec->sclass = sksec->sclass;
> @@ -5164,6 +5504,9 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
>   
>   static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	if (!sk)
>   		*secid = SECINITSID_ANY_SOCKET;
>   	else {
> @@ -5175,10 +5518,14 @@ static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
>   
>   static void selinux_sock_graft(struct sock *sk, struct socket *parent)
>   {
> -	struct inode_security_struct *isec =
> -		inode_security_novalidate(SOCK_INODE(parent));
> +	struct inode_security_struct *isec;
>   	struct sk_security_struct *sksec = sk->sk_security;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
> +	isec = inode_security_novalidate(SOCK_INODE(parent));
> +
>   	if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
>   	    sk->sk_family == PF_UNIX)
>   		isec->sid = sksec->sid;
> @@ -5200,6 +5547,9 @@ static int selinux_sctp_assoc_request(struct sctp_endpoint *ep,
>   	u32 conn_sid;
>   	int err = 0;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	if (!selinux_policycap_extsockclass())
>   		return 0;
>   
> @@ -5270,6 +5620,9 @@ static int selinux_sctp_bind_connect(struct sock *sk, int optname,
>   	struct sockaddr *addr;
>   	struct socket *sock;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	if (!selinux_policycap_extsockclass())
>   		return 0;
>   
> @@ -5346,6 +5699,9 @@ static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk,
>   	struct sk_security_struct *sksec = sk->sk_security;
>   	struct sk_security_struct *newsksec = newsk->sk_security;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	/* If policy does not support SECCLASS_SCTP_SOCKET then call
>   	 * the non-sctp clone version.
>   	 */
> @@ -5367,6 +5723,9 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
>   	u32 connsid;
>   	u32 peersid;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	err = selinux_skb_peerlbl_sid(skb, family, &peersid);
>   	if (err)
>   		return err;
> @@ -5384,6 +5743,9 @@ static void selinux_inet_csk_clone(struct sock *newsk,
>   {
>   	struct sk_security_struct *newsksec = newsk->sk_security;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	newsksec->sid = req->secid;
>   	newsksec->peer_sid = req->peer_secid;
>   	/* NOTE: Ideally, we should also get the isec->sid for the
> @@ -5401,6 +5763,9 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
>   	u16 family = sk->sk_family;
>   	struct sk_security_struct *sksec = sk->sk_security;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	/* handle mapped IPv4 packets arriving via IPv6 sockets */
>   	if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
>   		family = PF_INET;
> @@ -5413,6 +5778,9 @@ static int selinux_secmark_relabel_packet(u32 sid)
>   	const struct task_security_struct *__tsec;
>   	u32 tsid;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	__tsec = selinux_cred(current_cred());
>   	tsid = __tsec->sid;
>   
> @@ -5423,17 +5791,26 @@ static int selinux_secmark_relabel_packet(u32 sid)
>   
>   static void selinux_secmark_refcount_inc(void)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	atomic_inc(&selinux_secmark_refcount);
>   }
>   
>   static void selinux_secmark_refcount_dec(void)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	atomic_dec(&selinux_secmark_refcount);
>   }
>   
>   static void selinux_req_classify_flow(const struct request_sock *req,
>   				      struct flowi *fl)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	fl->flowi_secid = req->secid;
>   }
>   
> @@ -5441,6 +5818,9 @@ static int selinux_tun_dev_alloc_security(void **security)
>   {
>   	struct tun_security_struct *tunsec;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
>   	if (!tunsec)
>   		return -ENOMEM;
> @@ -5452,12 +5832,20 @@ static int selinux_tun_dev_alloc_security(void **security)
>   
>   static void selinux_tun_dev_free_security(void *security)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	kfree(security);
>   }
>   
>   static int selinux_tun_dev_create(void)
>   {
> -	u32 sid = current_sid();
> +	u32 sid;
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	sid = current_sid();
>   
>   	/* we aren't taking into account the "sockcreate" SID since the socket
>   	 * that is being created here is not a socket in the traditional sense,
> @@ -5475,6 +5863,9 @@ static int selinux_tun_dev_attach_queue(void *security)
>   {
>   	struct tun_security_struct *tunsec = security;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return avc_has_perm(&selinux_state,
>   			    current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
>   			    TUN_SOCKET__ATTACH_QUEUE, NULL);
> @@ -5485,6 +5876,9 @@ static int selinux_tun_dev_attach(struct sock *sk, void *security)
>   	struct tun_security_struct *tunsec = security;
>   	struct sk_security_struct *sksec = sk->sk_security;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	/* we don't currently perform any NetLabel based labeling here and it
>   	 * isn't clear that we would want to do so anyway; while we could apply
>   	 * labeling without the support of the TUN user the resulting labeled
> @@ -5501,8 +5895,13 @@ static int selinux_tun_dev_attach(struct sock *sk, void *security)
>   static int selinux_tun_dev_open(void *security)
>   {
>   	struct tun_security_struct *tunsec = security;
> -	u32 sid = current_sid();
>   	int err;
> +	u32 sid;
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	sid = current_sid();
>   
>   	err = avc_has_perm(&selinux_state,
>   			   sid, tunsec->sid, SECCLASS_TUN_SOCKET,
> @@ -5885,6 +6284,9 @@ static unsigned int selinux_ipv6_postroute(void *priv,
>   
>   static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return selinux_nlmsg_perm(sk, skb);
>   }
>   
> @@ -5922,6 +6324,9 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
>   
>   static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return msg_msg_alloc_security(msg);
>   }
>   
> @@ -5930,9 +6335,11 @@ static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
>   {
>   	struct ipc_security_struct *isec;
>   	struct common_audit_data ad;
> -	u32 sid = current_sid();
>   	int rc;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	isec = selinux_ipc(msq);
>   	ipc_init_security(isec, SECCLASS_MSGQ);
>   
> @@ -5940,7 +6347,7 @@ static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
>   	ad.u.ipc_id = msq->key;
>   
>   	rc = avc_has_perm(&selinux_state,
> -			  sid, isec->sid, SECCLASS_MSGQ,
> +			  current_sid(), isec->sid, SECCLASS_MSGQ,
>   			  MSGQ__CREATE, &ad);
>   	return rc;
>   }
> @@ -5949,7 +6356,9 @@ static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
>   {
>   	struct ipc_security_struct *isec;
>   	struct common_audit_data ad;
> -	u32 sid = current_sid();
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>   
>   	isec = selinux_ipc(msq);
>   
> @@ -5957,7 +6366,7 @@ static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
>   	ad.u.ipc_id = msq->key;
>   
>   	return avc_has_perm(&selinux_state,
> -			    sid, isec->sid, SECCLASS_MSGQ,
> +			    current_sid(), isec->sid, SECCLASS_MSGQ,
>   			    MSGQ__ASSOCIATE, &ad);
>   }
>   
> @@ -5966,6 +6375,9 @@ static int selinux_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd)
>   	int err;
>   	int perms;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	switch (cmd) {
>   	case IPC_INFO:
>   	case MSG_INFO:
> @@ -5997,9 +6409,14 @@ static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *m
>   	struct ipc_security_struct *isec;
>   	struct msg_security_struct *msec;
>   	struct common_audit_data ad;
> -	u32 sid = current_sid();
> +	u32 sid;
>   	int rc;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	sid = current_sid();
> +
>   	isec = selinux_ipc(msq);
>   	msec = selinux_msg_msg(msg);
>   
> @@ -6045,9 +6462,14 @@ static int selinux_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *m
>   	struct ipc_security_struct *isec;
>   	struct msg_security_struct *msec;
>   	struct common_audit_data ad;
> -	u32 sid = task_sid(target);
> +	u32 sid;
>   	int rc;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	sid = task_sid(target);
> +
>   	isec = selinux_ipc(msq);
>   	msec = selinux_msg_msg(msg);
>   
> @@ -6069,9 +6491,11 @@ static int selinux_shm_alloc_security(struct kern_ipc_perm *shp)
>   {
>   	struct ipc_security_struct *isec;
>   	struct common_audit_data ad;
> -	u32 sid = current_sid();
>   	int rc;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	isec = selinux_ipc(shp);
>   	ipc_init_security(isec, SECCLASS_SHM);
>   
> @@ -6079,8 +6503,8 @@ static int selinux_shm_alloc_security(struct kern_ipc_perm *shp)
>   	ad.u.ipc_id = shp->key;
>   
>   	rc = avc_has_perm(&selinux_state,
> -			  sid, isec->sid, SECCLASS_SHM,
> -			  SHM__CREATE, &ad);
> +			  current_sid(), isec->sid,
> +			  SECCLASS_SHM, SHM__CREATE, &ad);
>   	return rc;
>   }
>   
> @@ -6088,7 +6512,9 @@ static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg)
>   {
>   	struct ipc_security_struct *isec;
>   	struct common_audit_data ad;
> -	u32 sid = current_sid();
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>   
>   	isec = selinux_ipc(shp);
>   
> @@ -6096,8 +6522,8 @@ static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg)
>   	ad.u.ipc_id = shp->key;
>   
>   	return avc_has_perm(&selinux_state,
> -			    sid, isec->sid, SECCLASS_SHM,
> -			    SHM__ASSOCIATE, &ad);
> +			    current_sid(), isec->sid,
> +			    SECCLASS_SHM, SHM__ASSOCIATE, &ad);
>   }
>   
>   /* Note, at this point, shp is locked down */
> @@ -6106,6 +6532,9 @@ static int selinux_shm_shmctl(struct kern_ipc_perm *shp, int cmd)
>   	int perms;
>   	int err;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	switch (cmd) {
>   	case IPC_INFO:
>   	case SHM_INFO:
> @@ -6141,6 +6570,9 @@ static int selinux_shm_shmat(struct kern_ipc_perm *shp,
>   {
>   	u32 perms;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	if (shmflg & SHM_RDONLY)
>   		perms = SHM__READ;
>   	else
> @@ -6154,9 +6586,11 @@ static int selinux_sem_alloc_security(struct kern_ipc_perm *sma)
>   {
>   	struct ipc_security_struct *isec;
>   	struct common_audit_data ad;
> -	u32 sid = current_sid();
>   	int rc;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	isec = selinux_ipc(sma);
>   	ipc_init_security(isec, SECCLASS_SEM);
>   
> @@ -6164,8 +6598,8 @@ static int selinux_sem_alloc_security(struct kern_ipc_perm *sma)
>   	ad.u.ipc_id = sma->key;
>   
>   	rc = avc_has_perm(&selinux_state,
> -			  sid, isec->sid, SECCLASS_SEM,
> -			  SEM__CREATE, &ad);
> +			  current_sid(), isec->sid,
> +			  SECCLASS_SEM, SEM__CREATE, &ad);
>   	return rc;
>   }
>   
> @@ -6173,7 +6607,9 @@ static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg)
>   {
>   	struct ipc_security_struct *isec;
>   	struct common_audit_data ad;
> -	u32 sid = current_sid();
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>   
>   	isec = selinux_ipc(sma);
>   
> @@ -6181,8 +6617,8 @@ static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg)
>   	ad.u.ipc_id = sma->key;
>   
>   	return avc_has_perm(&selinux_state,
> -			    sid, isec->sid, SECCLASS_SEM,
> -			    SEM__ASSOCIATE, &ad);
> +			    current_sid(), isec->sid,
> +			    SECCLASS_SEM, SEM__ASSOCIATE, &ad);
>   }
>   
>   /* Note, at this point, sma is locked down */
> @@ -6191,6 +6627,9 @@ static int selinux_sem_semctl(struct kern_ipc_perm *sma, int cmd)
>   	int err;
>   	u32 perms;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	switch (cmd) {
>   	case IPC_INFO:
>   	case SEM_INFO:
> @@ -6235,6 +6674,9 @@ static int selinux_sem_semop(struct kern_ipc_perm *sma,
>   {
>   	u32 perms;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	if (alter)
>   		perms = SEM__READ | SEM__WRITE;
>   	else
> @@ -6247,7 +6689,9 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
>   {
>   	u32 av = 0;
>   
> -	av = 0;
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	if (flag & S_IRUGO)
>   		av |= IPC__UNIX_READ;
>   	if (flag & S_IWUGO)
> @@ -6261,12 +6705,17 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
>   
>   static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
>   {
> -	struct ipc_security_struct *isec = selinux_ipc(ipcp);
> -	*secid = isec->sid;
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
> +	*secid = selinux_ipc(ipcp)->sid;
>   }
>   
>   static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	if (inode)
>   		inode_doinit_with_dentry(inode, dentry);
>   }
> @@ -6279,6 +6728,9 @@ static int selinux_getprocattr(struct task_struct *p,
>   	int error;
>   	unsigned len;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return -EINVAL;
> +
>   	rcu_read_lock();
>   	__tsec = selinux_cred(__task_cred(p));
>   
> @@ -6325,10 +6777,15 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)
>   {
>   	struct task_security_struct *tsec;
>   	struct cred *new;
> -	u32 mysid = current_sid(), sid = 0, ptsid;
> +	u32 mysid, sid = 0, ptsid;
>   	int error;
>   	char *str = value;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return -EINVAL;
> +
> +	mysid = current_sid();
> +
>   	/*
>   	 * Basic control over ability to set these attributes at all.
>   	 */
> @@ -6466,17 +6923,26 @@ abort_change:
>   
>   static int selinux_ismaclabel(const char *name)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
>   }
>   
>   static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return -EOPNOTSUPP;
> +
>   	return security_sid_to_context(&selinux_state, secid,
>   				       secdata, seclen);
>   }
>   
>   static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return security_context_to_sid(&selinux_state, secdata, seclen,
>   				       secid, GFP_KERNEL);
>   }
> @@ -6490,6 +6956,9 @@ static void selinux_inode_invalidate_secctx(struct inode *inode)
>   {
>   	struct inode_security_struct *isec = selinux_inode(inode);
>   
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	spin_lock(&isec->lock);
>   	isec->initialized = LABEL_INVALID;
>   	spin_unlock(&isec->lock);
> @@ -6511,6 +6980,9 @@ static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen
>    */
>   static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
>   }
>   
> @@ -6532,6 +7004,9 @@ static int selinux_key_alloc(struct key *k, const struct cred *cred,
>   	const struct task_security_struct *tsec;
>   	struct key_security_struct *ksec;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
>   	if (!ksec)
>   		return -ENOMEM;
> @@ -6550,6 +7025,9 @@ static void selinux_key_free(struct key *k)
>   {
>   	struct key_security_struct *ksec = k->security;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	k->security = NULL;
>   	kfree(ksec);
>   }
> @@ -6568,6 +7046,9 @@ static int selinux_key_permission(key_ref_t key_ref,
>   	if (perm == 0)
>   		return 0;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	sid = cred_sid(cred);
>   
>   	key = key_ref_to_ptr(key_ref);
> @@ -6584,6 +7065,9 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)
>   	unsigned len;
>   	int rc;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	rc = security_sid_to_context(&selinux_state, ksec->sid,
>   				     &context, &len);
>   	if (!rc)
> @@ -6602,6 +7086,9 @@ static int selinux_ib_pkey_access(void *ib_sec, u64 subnet_prefix, u16 pkey_val)
>   	struct ib_security_struct *sec = ib_sec;
>   	struct lsm_ibpkey_audit ibpkey;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	err = sel_ib_pkey_sid(subnet_prefix, pkey_val, &sid);
>   	if (err)
>   		return err;
> @@ -6625,6 +7112,9 @@ static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name,
>   	struct ib_security_struct *sec = ib_sec;
>   	struct lsm_ibendport_audit ibendport;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	err = security_ib_endport_sid(&selinux_state, dev_name, port_num,
>   				      &sid);
>   
> @@ -6645,6 +7135,9 @@ static int selinux_ib_alloc_security(void **ib_sec)
>   {
>   	struct ib_security_struct *sec;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	sec = kzalloc(sizeof(*sec), GFP_KERNEL);
>   	if (!sec)
>   		return -ENOMEM;
> @@ -6656,6 +7149,9 @@ static int selinux_ib_alloc_security(void **ib_sec)
>   
>   static void selinux_ib_free_security(void *ib_sec)
>   {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	kfree(ib_sec);
>   }
>   #endif
> @@ -6667,6 +7163,9 @@ static int selinux_bpf(int cmd, union bpf_attr *attr,
>   	u32 sid = current_sid();
>   	int ret;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	switch (cmd) {
>   	case BPF_MAP_CREATE:
>   		ret = avc_has_perm(&selinux_state,
> @@ -6734,23 +7233,27 @@ static int bpf_fd_pass(struct file *file, u32 sid)
>   
>   static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode)
>   {
> -	u32 sid = current_sid();
>   	struct bpf_security_struct *bpfsec;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	bpfsec = map->security;
>   	return avc_has_perm(&selinux_state,
> -			    sid, bpfsec->sid, SECCLASS_BPF,
> +			    current_sid(), bpfsec->sid, SECCLASS_BPF,
>   			    bpf_map_fmode_to_av(fmode), NULL);
>   }
>   
>   static int selinux_bpf_prog(struct bpf_prog *prog)
>   {
> -	u32 sid = current_sid();
>   	struct bpf_security_struct *bpfsec;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	bpfsec = prog->aux->security;
>   	return avc_has_perm(&selinux_state,
> -			    sid, bpfsec->sid, SECCLASS_BPF,
> +			    current_sid(), bpfsec->sid, SECCLASS_BPF,
>   			    BPF__PROG_RUN, NULL);
>   }
>   
> @@ -6758,6 +7261,9 @@ static int selinux_bpf_map_alloc(struct bpf_map *map)
>   {
>   	struct bpf_security_struct *bpfsec;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
>   	if (!bpfsec)
>   		return -ENOMEM;
> @@ -6772,6 +7278,9 @@ static void selinux_bpf_map_free(struct bpf_map *map)
>   {
>   	struct bpf_security_struct *bpfsec = map->security;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	map->security = NULL;
>   	kfree(bpfsec);
>   }
> @@ -6780,6 +7289,9 @@ static int selinux_bpf_prog_alloc(struct bpf_prog_aux *aux)
>   {
>   	struct bpf_security_struct *bpfsec;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
>   	if (!bpfsec)
>   		return -ENOMEM;
> @@ -6794,6 +7306,9 @@ static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
>   {
>   	struct bpf_security_struct *bpfsec = aux->security;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	aux->security = NULL;
>   	kfree(bpfsec);
>   }
> @@ -6802,11 +7317,14 @@ static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
>   static int selinux_lockdown(enum lockdown_reason what)
>   {
>   	struct common_audit_data ad;
> -	u32 sid = current_sid();
> +	u32 sid;
>   	int invalid_reason = (what <= LOCKDOWN_NONE) ||
>   			     (what == LOCKDOWN_INTEGRITY_MAX) ||
>   			     (what >= LOCKDOWN_CONFIDENTIALITY_MAX);
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	if (WARN(invalid_reason, "Invalid lockdown reason")) {
>   		audit_log(audit_context(),
>   			  GFP_ATOMIC, AUDIT_SELINUX_ERR,
> @@ -6814,6 +7332,8 @@ static int selinux_lockdown(enum lockdown_reason what)
>   		return -EINVAL;
>   	}
>   
> +	sid = current_sid();
> +
>   	ad.type = LSM_AUDIT_DATA_LOCKDOWN;
>   	ad.u.reason = what;
>   
> @@ -6827,7 +7347,7 @@ static int selinux_lockdown(enum lockdown_reason what)
>   				    LOCKDOWN__CONFIDENTIALITY, &ad);
>   }
>   
> -struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = {
> +struct lsm_blob_sizes selinux_blob_sizes __ro_after_init = {
>   	.lbs_cred = sizeof(struct task_security_struct),
>   	.lbs_file = sizeof(struct file_security_struct),
>   	.lbs_inode = sizeof(struct inode_security_struct),
> @@ -6838,7 +7358,12 @@ struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = {
>   #ifdef CONFIG_PERF_EVENTS
>   static int selinux_perf_event_open(struct perf_event_attr *attr, int type)
>   {
> -	u32 requested, sid = current_sid();
> +	u32 requested, sid;
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	sid = current_sid();
>   
>   	if (type == PERF_SECURITY_OPEN)
>   		requested = PERF_EVENT__OPEN;
> @@ -6859,6 +7384,9 @@ static int selinux_perf_event_alloc(struct perf_event *event)
>   {
>   	struct perf_event_security_struct *perfsec;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>   	perfsec = kzalloc(sizeof(*perfsec), GFP_KERNEL);
>   	if (!perfsec)
>   		return -ENOMEM;
> @@ -6873,6 +7401,9 @@ static void selinux_perf_event_free(struct perf_event *event)
>   {
>   	struct perf_event_security_struct *perfsec = event->security;
>   
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>   	event->security = NULL;
>   	kfree(perfsec);
>   }
> @@ -6880,23 +7411,27 @@ static void selinux_perf_event_free(struct perf_event *event)
>   static int selinux_perf_event_read(struct perf_event *event)
>   {
>   	struct perf_event_security_struct *perfsec = event->security;
> -	u32 sid = current_sid();
>   
> -	return avc_has_perm(&selinux_state, sid, perfsec->sid,
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	return avc_has_perm(&selinux_state, current_sid(), perfsec->sid,
>   			    SECCLASS_PERF_EVENT, PERF_EVENT__READ, NULL);
>   }
>   
>   static int selinux_perf_event_write(struct perf_event *event)
>   {
>   	struct perf_event_security_struct *perfsec = event->security;
> -	u32 sid = current_sid();
>   
> -	return avc_has_perm(&selinux_state, sid, perfsec->sid,
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	return avc_has_perm(&selinux_state, current_sid(), perfsec->sid,
>   			    SECCLASS_PERF_EVENT, PERF_EVENT__WRITE, NULL);
>   }
>   #endif
>   
> -static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
> +static struct security_hook_list selinux_hooks[] __ro_after_init = {
>   	LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
>   	LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
>   	LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
> @@ -7315,18 +7850,19 @@ int selinux_disable(struct selinux_state *state)
>   		return -EINVAL;
>   	}
>   
> +	/*
> +	 * Unregister netfilter hooks (must be done before
> +	 * selinux_mark_disabled()).
> +	 */
> +	selinux_nf_ip_exit();
> +
>   	selinux_mark_disabled(state);
>   
>   	pr_info("SELinux:  Disabled at runtime.\n");
>   
> -	security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
> -
>   	/* Try to destroy the avc node cache */
>   	avc_disable();
>   
> -	/* Unregister netfilter hooks. */
> -	selinux_nf_ip_exit();
> -
>   	/* Unregister selinuxfs. */
>   	exit_sel_fs();
>   
> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> index ecea41ce919b..de50c69846e0 100644
> --- a/security/smack/smack_lsm.c
> +++ b/security/smack/smack_lsm.c
> @@ -4583,7 +4583,7 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode,
>   	return 0;
>   }
>   
> -struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
> +struct lsm_blob_sizes smack_blob_sizes __ro_after_init = {
>   	.lbs_cred = sizeof(struct task_smack),
>   	.lbs_file = sizeof(struct smack_known *),
>   	.lbs_inode = sizeof(struct inode_smack),
> @@ -4591,7 +4591,7 @@ struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
>   	.lbs_msg_msg = sizeof(struct smack_known *),
>   };
>   
> -static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
> +static struct security_hook_list smack_hooks[] __ro_after_init = {
>   	LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check),
>   	LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme),
>   	LSM_HOOK_INIT(syslog, smack_syslog),
> diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
> index 716c92ec941a..9dcdef99d431 100644
> --- a/security/tomoyo/tomoyo.c
> +++ b/security/tomoyo/tomoyo.c
> @@ -486,7 +486,7 @@ static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg,
>   	return tomoyo_socket_sendmsg_permission(sock, msg, size);
>   }
>   
> -struct lsm_blob_sizes tomoyo_blob_sizes __lsm_ro_after_init = {
> +struct lsm_blob_sizes tomoyo_blob_sizes __ro_after_init = {
>   	.lbs_task = sizeof(struct tomoyo_task),
>   };
>   
> @@ -533,7 +533,7 @@ static void tomoyo_task_free(struct task_struct *task)
>    * tomoyo_security_ops is a "struct security_operations" which is used for
>    * registering TOMOYO.
>    */
> -static struct security_hook_list tomoyo_hooks[] __lsm_ro_after_init = {
> +static struct security_hook_list tomoyo_hooks[] __ro_after_init = {
>   	LSM_HOOK_INIT(cred_prepare, tomoyo_cred_prepare),
>   	LSM_HOOK_INIT(bprm_committed_creds, tomoyo_bprm_committed_creds),
>   	LSM_HOOK_INIT(task_alloc, tomoyo_task_alloc),
> @@ -569,7 +569,7 @@ static struct security_hook_list tomoyo_hooks[] __lsm_ro_after_init = {
>   /* Lock for GC. */
>   DEFINE_SRCU(tomoyo_ss);
>   
> -int tomoyo_enabled __lsm_ro_after_init = 1;
> +int tomoyo_enabled __ro_after_init = 1;
>   
>   /**
>    * tomoyo_init - Register TOMOYO Linux as a LSM module.
> diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
> index 94dc346370b1..c47d4e09bfb4 100644
> --- a/security/yama/yama_lsm.c
> +++ b/security/yama/yama_lsm.c
> @@ -421,7 +421,7 @@ static int yama_ptrace_traceme(struct task_struct *parent)
>   	return rc;
>   }
>   
> -static struct security_hook_list yama_hooks[] __lsm_ro_after_init = {
> +static struct security_hook_list yama_hooks[] __ro_after_init = {
>   	LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check),
>   	LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme),
>   	LSM_HOOK_INIT(task_prctl, yama_task_prctl),
> 


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

* Re: [PATCH 2/2] security,selinux: get rid of security_delete_hooks()
  2020-01-07 13:31 ` [PATCH 2/2] security,selinux: get rid of security_delete_hooks() Ondrej Mosnacek
  2020-01-07 14:47   ` [PATCH 2/2] security, selinux: " Stephen Smalley
@ 2020-01-07 16:46   ` Casey Schaufler
  2020-01-07 18:10   ` Kees Cook
  2020-01-07 19:59   ` James Morris
  3 siblings, 0 replies; 18+ messages in thread
From: Casey Schaufler @ 2020-01-07 16:46 UTC (permalink / raw)
  To: Ondrej Mosnacek, linux-security-module, James Morris, Serge E. Hallyn
  Cc: selinux, Paul Moore, Stephen Smalley, John Johansen, Kees Cook,
	Micah Morton, Tetsuo Handa, Casey Schaufler

On 1/7/2020 5:31 AM, Ondrej Mosnacek wrote:
> The only user is SELinux, which is hereby converted to check the
> disabled flag in each hook instead of removing the hooks from the list.
>
> The __lsm_ro_after_init macro is now removed and replaced with
> __ro_after_init directly.
>
> This fixes a race condition in SELinux runtime disable, which was
> introduced with the switch to hook lists in b1d9e6b0646d ("LSM: Switch
> to lists of hooks").
>
> Suggested-by: Stephen Smalley <sds@tycho.nsa.gov>
> Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>

I don't see any problems with this solution from a global
LSM or Smack specific perspective. I would leave any judgement
of its impact on SELinux to the maintainers thereof.
To the extent it matters, then

Acked-by: Casey Schaufler <casey@schaufler-ca.com>

> ---
>  include/linux/lsm_hooks.h    |  31 --
>  security/Kconfig             |   5 -
>  security/apparmor/lsm.c      |   6 +-
>  security/commoncap.c         |   2 +-
>  security/loadpin/loadpin.c   |   2 +-
>  security/lockdown/lockdown.c |   2 +-
>  security/security.c          |   5 +-
>  security/selinux/Kconfig     |   6 -
>  security/selinux/hooks.c     | 742 ++++++++++++++++++++++++++++++-----
>  security/smack/smack_lsm.c   |   4 +-
>  security/tomoyo/tomoyo.c     |   6 +-
>  security/yama/yama_lsm.c     |   2 +-
>  12 files changed, 654 insertions(+), 159 deletions(-)
>
> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
> index 20d8cf194fb7..5064060ce910 100644
> --- a/include/linux/lsm_hooks.h
> +++ b/include/linux/lsm_hooks.h
> @@ -27,7 +27,6 @@
>  
>  #include <linux/security.h>
>  #include <linux/init.h>
> -#include <linux/rculist.h>
>  
>  /**
>   * union security_list_options - Linux Security Module hook function list
> @@ -2145,36 +2144,6 @@ extern struct lsm_info __start_early_lsm_info[], __end_early_lsm_info[];
>  		__used __section(.early_lsm_info.init)			\
>  		__aligned(sizeof(unsigned long))
>  
> -#ifdef CONFIG_SECURITY_SELINUX_DISABLE
> -/*
> - * Assuring the safety of deleting a security module is up to
> - * the security module involved. This may entail ordering the
> - * module's hook list in a particular way, refusing to disable
> - * the module once a policy is loaded or any number of other
> - * actions better imagined than described.
> - *
> - * The name of the configuration option reflects the only module
> - * that currently uses the mechanism. Any developer who thinks
> - * disabling their module is a good idea needs to be at least as
> - * careful as the SELinux team.
> - */
> -static inline void security_delete_hooks(struct security_hook_list *hooks,
> -						int count)
> -{
> -	int i;
> -
> -	for (i = 0; i < count; i++)
> -		hlist_del_rcu(&hooks[i].list);
> -}
> -#endif /* CONFIG_SECURITY_SELINUX_DISABLE */
> -
> -/* Currently required to handle SELinux runtime hook disable. */
> -#ifdef CONFIG_SECURITY_WRITABLE_HOOKS
> -#define __lsm_ro_after_init
> -#else
> -#define __lsm_ro_after_init	__ro_after_init
> -#endif /* CONFIG_SECURITY_WRITABLE_HOOKS */
> -
>  extern int lsm_inode_alloc(struct inode *inode);
>  
>  #endif /* ! __LINUX_LSM_HOOKS_H */
> diff --git a/security/Kconfig b/security/Kconfig
> index 2a1a2d396228..456764990a13 100644
> --- a/security/Kconfig
> +++ b/security/Kconfig
> @@ -32,11 +32,6 @@ config SECURITY
>  
>  	  If you are unsure how to answer this question, answer N.
>  
> -config SECURITY_WRITABLE_HOOKS
> -	depends on SECURITY
> -	bool
> -	default n
> -
>  config SECURITYFS
>  	bool "Enable the securityfs filesystem"
>  	help
> diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
> index b621ad74f54a..cd83812a440f 100644
> --- a/security/apparmor/lsm.c
> +++ b/security/apparmor/lsm.c
> @@ -1158,13 +1158,13 @@ static int apparmor_inet_conn_request(struct sock *sk, struct sk_buff *skb,
>  /*
>   * The cred blob is a pointer to, not an instance of, an aa_task_ctx.
>   */
> -struct lsm_blob_sizes apparmor_blob_sizes __lsm_ro_after_init = {
> +struct lsm_blob_sizes apparmor_blob_sizes __ro_after_init = {
>  	.lbs_cred = sizeof(struct aa_task_ctx *),
>  	.lbs_file = sizeof(struct aa_file_ctx),
>  	.lbs_task = sizeof(struct aa_task_ctx),
>  };
>  
> -static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
> +static struct security_hook_list apparmor_hooks[] __ro_after_init = {
>  	LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
>  	LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
>  	LSM_HOOK_INIT(capget, apparmor_capget),
> @@ -1368,7 +1368,7 @@ static const struct kernel_param_ops param_ops_aaintbool = {
>  	.get = param_get_aaintbool
>  };
>  /* Boot time disable flag */
> -static int apparmor_enabled __lsm_ro_after_init = 1;
> +static int apparmor_enabled __ro_after_init = 1;
>  module_param_named(enabled, apparmor_enabled, aaintbool, 0444);
>  
>  static int __init apparmor_enabled_setup(char *str)
> diff --git a/security/commoncap.c b/security/commoncap.c
> index f4ee0ae106b2..1471d9a5a9bc 100644
> --- a/security/commoncap.c
> +++ b/security/commoncap.c
> @@ -1339,7 +1339,7 @@ int cap_mmap_file(struct file *file, unsigned long reqprot,
>  
>  #ifdef CONFIG_SECURITY
>  
> -static struct security_hook_list capability_hooks[] __lsm_ro_after_init = {
> +static struct security_hook_list capability_hooks[] __ro_after_init = {
>  	LSM_HOOK_INIT(capable, cap_capable),
>  	LSM_HOOK_INIT(settime, cap_settime),
>  	LSM_HOOK_INIT(ptrace_access_check, cap_ptrace_access_check),
> diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c
> index ee5cb944f4ad..9bbc08bee2c0 100644
> --- a/security/loadpin/loadpin.c
> +++ b/security/loadpin/loadpin.c
> @@ -180,7 +180,7 @@ static int loadpin_load_data(enum kernel_load_data_id id)
>  	return loadpin_read_file(NULL, (enum kernel_read_file_id) id);
>  }
>  
> -static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = {
> +static struct security_hook_list loadpin_hooks[] __ro_after_init = {
>  	LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security),
>  	LSM_HOOK_INIT(kernel_read_file, loadpin_read_file),
>  	LSM_HOOK_INIT(kernel_load_data, loadpin_load_data),
> diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c
> index 5a952617a0eb..8071d0f542c8 100644
> --- a/security/lockdown/lockdown.c
> +++ b/security/lockdown/lockdown.c
> @@ -71,7 +71,7 @@ static int lockdown_is_locked_down(enum lockdown_reason what)
>  	return 0;
>  }
>  
> -static struct security_hook_list lockdown_hooks[] __lsm_ro_after_init = {
> +static struct security_hook_list lockdown_hooks[] __ro_after_init = {
>  	LSM_HOOK_INIT(locked_down, lockdown_is_locked_down),
>  };
>  
> diff --git a/security/security.c b/security/security.c
> index 2b5473d92416..3138a5d99813 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -27,6 +27,7 @@
>  #include <linux/backing-dev.h>
>  #include <linux/string.h>
>  #include <linux/msg.h>
> +#include <linux/rculist.h>
>  #include <net/flow.h>
>  
>  #define MAX_LSM_EVM_XATTR	2
> @@ -68,14 +69,14 @@ const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {
>  	[LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality",
>  };
>  
> -struct security_hook_heads security_hook_heads __lsm_ro_after_init;
> +struct security_hook_heads security_hook_heads __ro_after_init;
>  static BLOCKING_NOTIFIER_HEAD(blocking_lsm_notifier_chain);
>  
>  static struct kmem_cache *lsm_file_cache;
>  static struct kmem_cache *lsm_inode_cache;
>  
>  char *lsm_names;
> -static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init;
> +static struct lsm_blob_sizes blob_sizes __ro_after_init;
>  
>  /* Boot-time LSM user choice */
>  static __initdata const char *chosen_lsm_order;
> diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
> index 996d35d950f7..caa5711478ad 100644
> --- a/security/selinux/Kconfig
> +++ b/security/selinux/Kconfig
> @@ -26,7 +26,6 @@ config SECURITY_SELINUX_BOOTPARAM
>  config SECURITY_SELINUX_DISABLE
>  	bool "NSA SELinux runtime disable"
>  	depends on SECURITY_SELINUX
> -	select SECURITY_WRITABLE_HOOKS
>  	default n
>  	help
>  	  This option enables writing to a selinuxfs node 'disable', which
> @@ -37,11 +36,6 @@ config SECURITY_SELINUX_DISABLE
>  	  portability across platforms where boot parameters are difficult
>  	  to employ.
>  
> -	  NOTE: selecting this option will disable the '__ro_after_init'
> -	  kernel hardening feature for security hooks.   Please consider
> -	  using the selinux=0 boot parameter instead of enabling this
> -	  option.
> -
>  	  If you are unsure how to answer this question, answer N.
>  
>  config SECURITY_SELINUX_DEVELOP
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 47ad4db925cf..9ac2b6b69ff9 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -650,13 +650,15 @@ static int selinux_set_mnt_opts(struct super_block *sb,
>  {
>  	const struct cred *cred = current_cred();
>  	struct superblock_security_struct *sbsec = sb->s_security;
> -	struct dentry *root = sbsec->sb->s_root;
>  	struct selinux_mnt_opts *opts = mnt_opts;
>  	struct inode_security_struct *root_isec;
>  	u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
>  	u32 defcontext_sid = 0;
>  	int rc = 0;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	mutex_lock(&sbsec->lock);
>  
>  	if (!selinux_initialized(&selinux_state)) {
> @@ -693,7 +695,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
>  	    && !opts)
>  		goto out;
>  
> -	root_isec = backing_inode_security_novalidate(root);
> +	root_isec = backing_inode_security_novalidate(sbsec->sb->s_root);
>  
>  	/*
>  	 * parse the mount options, check if they are valid sids.
> @@ -919,10 +921,14 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
>  	int rc = 0;
>  	const struct superblock_security_struct *oldsbsec = oldsb->s_security;
>  	struct superblock_security_struct *newsbsec = newsb->s_security;
> +	int set_fscontext, set_context, set_rootcontext;
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
> -	int set_fscontext =	(oldsbsec->flags & FSCONTEXT_MNT);
> -	int set_context =	(oldsbsec->flags & CONTEXT_MNT);
> -	int set_rootcontext =	(oldsbsec->flags & ROOTCONTEXT_MNT);
> +	set_fscontext =		(oldsbsec->flags & FSCONTEXT_MNT);
> +	set_context =		(oldsbsec->flags & CONTEXT_MNT);
> +	set_rootcontext =	(oldsbsec->flags & ROOTCONTEXT_MNT);
>  
>  	/*
>  	 * if the parent was able to be mounted it clearly had no special lsm
> @@ -1041,6 +1047,9 @@ static int selinux_add_mnt_opt(const char *option, const char *val, int len,
>  	int token = Opt_error;
>  	int rc, i;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	for (i = 0; i < ARRAY_SIZE(tokens); i++) {
>  		if (strcmp(option, tokens[i].name) == 0) {
>  			token = tokens[i].opt;
> @@ -1100,6 +1109,9 @@ static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
>  	struct superblock_security_struct *sbsec = sb->s_security;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (!(sbsec->flags & SE_SBINITIALIZED))
>  		return 0;
>  
> @@ -2044,22 +2056,27 @@ static inline u32 open_file_to_av(struct file *file)
>  
>  static int selinux_binder_set_context_mgr(struct task_struct *mgr)
>  {
> -	u32 mysid = current_sid();
> -	u32 mgrsid = task_sid(mgr);
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
>  	return avc_has_perm(&selinux_state,
> -			    mysid, mgrsid, SECCLASS_BINDER,
> +			    current_sid(), task_sid(mgr), SECCLASS_BINDER,
>  			    BINDER__SET_CONTEXT_MGR, NULL);
>  }
>  
>  static int selinux_binder_transaction(struct task_struct *from,
>  				      struct task_struct *to)
>  {
> -	u32 mysid = current_sid();
> -	u32 fromsid = task_sid(from);
> -	u32 tosid = task_sid(to);
> +	u32 mysid, fromsid, tosid;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	mysid = current_sid();
> +	fromsid = task_sid(from);
> +	tosid = task_sid(to);
> +
>  	if (mysid != fromsid) {
>  		rc = avc_has_perm(&selinux_state,
>  				  mysid, fromsid, SECCLASS_BINDER,
> @@ -2076,11 +2093,12 @@ static int selinux_binder_transaction(struct task_struct *from,
>  static int selinux_binder_transfer_binder(struct task_struct *from,
>  					  struct task_struct *to)
>  {
> -	u32 fromsid = task_sid(from);
> -	u32 tosid = task_sid(to);
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
>  	return avc_has_perm(&selinux_state,
> -			    fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
> +			    task_sid(from), task_sid(to),
> +			    SECCLASS_BINDER, BINDER__TRANSFER,
>  			    NULL);
>  }
>  
> @@ -2088,13 +2106,18 @@ static int selinux_binder_transfer_file(struct task_struct *from,
>  					struct task_struct *to,
>  					struct file *file)
>  {
> -	u32 sid = task_sid(to);
> +	u32 sid;
>  	struct file_security_struct *fsec = selinux_file(file);
>  	struct dentry *dentry = file->f_path.dentry;
>  	struct inode_security_struct *isec;
>  	struct common_audit_data ad;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	sid = task_sid(to);
> +
>  	ad.type = LSM_AUDIT_DATA_PATH;
>  	ad.u.path = file->f_path;
>  
> @@ -2126,19 +2149,26 @@ static int selinux_binder_transfer_file(struct task_struct *from,
>  static int selinux_ptrace_access_check(struct task_struct *child,
>  				     unsigned int mode)
>  {
> -	u32 sid = current_sid();
> -	u32 csid = task_sid(child);
> +	u16 cls = SECCLASS_PROCESS;
> +	u32 perm = PROCESS__PTRACE;
>  
> -	if (mode & PTRACE_MODE_READ)
> -		return avc_has_perm(&selinux_state,
> -				    sid, csid, SECCLASS_FILE, FILE__READ, NULL);
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	if (mode & PTRACE_MODE_READ) {
> +		cls = SECCLASS_FILE;
> +		perm = FILE__READ;
> +	}
>  
>  	return avc_has_perm(&selinux_state,
> -			    sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL);
> +			    current_sid(), task_sid(child), cls, perm, NULL);
>  }
>  
>  static int selinux_ptrace_traceme(struct task_struct *parent)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    task_sid(parent), current_sid(), SECCLASS_PROCESS,
>  			    PROCESS__PTRACE, NULL);
> @@ -2147,6 +2177,9 @@ static int selinux_ptrace_traceme(struct task_struct *parent)
>  static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
>  			  kernel_cap_t *inheritable, kernel_cap_t *permitted)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    current_sid(), task_sid(target), SECCLASS_PROCESS,
>  			    PROCESS__GETCAP, NULL);
> @@ -2157,6 +2190,9 @@ static int selinux_capset(struct cred *new, const struct cred *old,
>  			  const kernel_cap_t *inheritable,
>  			  const kernel_cap_t *permitted)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    cred_sid(old), cred_sid(new), SECCLASS_PROCESS,
>  			    PROCESS__SETCAP, NULL);
> @@ -2175,6 +2211,9 @@ static int selinux_capset(struct cred *new, const struct cred *old,
>  static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
>  			   int cap, unsigned int opts)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return cred_has_capability(cred, cap, opts, ns == &init_user_ns);
>  }
>  
> @@ -2186,6 +2225,9 @@ static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
>  	if (!sb)
>  		return 0;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	switch (cmds) {
>  	case Q_SYNC:
>  	case Q_QUOTAON:
> @@ -2210,11 +2252,17 @@ static int selinux_quota_on(struct dentry *dentry)
>  {
>  	const struct cred *cred = current_cred();
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return dentry_has_perm(cred, dentry, FILE__QUOTAON);
>  }
>  
>  static int selinux_syslog(int type)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	switch (type) {
>  	case SYSLOG_ACTION_READ_ALL:	/* Read last kernel messages */
>  	case SYSLOG_ACTION_SIZE_BUFFER:	/* Return size of the log buffer */
> @@ -2248,6 +2296,9 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
>  {
>  	int rc, cap_sys_admin = 0;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
>  				 CAP_OPT_NOAUDIT, true);
>  	if (rc == 0)
> @@ -2335,6 +2386,9 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
>  	struct inode *inode = file_inode(bprm->file);
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	/* SELinux context only depends on initial program or script and not
>  	 * the script interpreter */
>  	if (bprm->called_set_creds)
> @@ -2505,6 +2559,9 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
>  	struct rlimit *rlim, *initrlim;
>  	int rc, i;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	new_tsec = selinux_cred(bprm->cred);
>  	if (new_tsec->sid == new_tsec->osid)
>  		return;
> @@ -2552,6 +2609,9 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
>  	u32 osid, sid;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	osid = tsec->osid;
>  	sid = tsec->sid;
>  
> @@ -2592,11 +2652,17 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
>  
>  static int selinux_sb_alloc_security(struct super_block *sb)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return superblock_alloc_security(sb);
>  }
>  
>  static void selinux_sb_free_security(struct super_block *sb)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	superblock_free_security(sb);
>  }
>  
> @@ -2622,6 +2688,9 @@ static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts)
>  	bool first = true;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	while (1) {
>  		int len = opt_len(from);
>  		int token;
> @@ -2682,6 +2751,9 @@ static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
>  	u32 sid;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (!(sbsec->flags & SE_SBINITIALIZED))
>  		return 0;
>  
> @@ -2732,6 +2804,9 @@ static int selinux_sb_kern_mount(struct super_block *sb)
>  	const struct cred *cred = current_cred();
>  	struct common_audit_data ad;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	ad.type = LSM_AUDIT_DATA_DENTRY;
>  	ad.u.dentry = sb->s_root;
>  	return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
> @@ -2742,6 +2817,9 @@ static int selinux_sb_statfs(struct dentry *dentry)
>  	const struct cred *cred = current_cred();
>  	struct common_audit_data ad;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	ad.type = LSM_AUDIT_DATA_DENTRY;
>  	ad.u.dentry = dentry->d_sb->s_root;
>  	return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
> @@ -2755,6 +2833,9 @@ static int selinux_mount(const char *dev_name,
>  {
>  	const struct cred *cred = current_cred();
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (flags & MS_REMOUNT)
>  		return superblock_has_perm(cred, path->dentry->d_sb,
>  					   FILESYSTEM__REMOUNT, NULL);
> @@ -2766,6 +2847,9 @@ static int selinux_umount(struct vfsmount *mnt, int flags)
>  {
>  	const struct cred *cred = current_cred();
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return superblock_has_perm(cred, mnt->mnt_sb,
>  				   FILESYSTEM__UNMOUNT, NULL);
>  }
> @@ -2776,6 +2860,9 @@ static int selinux_fs_context_dup(struct fs_context *fc,
>  	const struct selinux_mnt_opts *src = src_fc->security;
>  	struct selinux_mnt_opts *opts;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (!src)
>  		return 0;
>  
> @@ -2828,6 +2915,9 @@ static int selinux_fs_context_parse_param(struct fs_context *fc,
>  	struct fs_parse_result result;
>  	int opt, rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	opt = fs_parse(fc, &selinux_fs_parameters, param, &result);
>  	if (opt < 0)
>  		return opt;
> @@ -2844,11 +2934,17 @@ static int selinux_fs_context_parse_param(struct fs_context *fc,
>  
>  static int selinux_inode_alloc_security(struct inode *inode)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return inode_alloc_security(inode);
>  }
>  
>  static void selinux_inode_free_security(struct inode *inode)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	inode_free_security(inode);
>  }
>  
> @@ -2859,6 +2955,9 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,
>  	u32 newsid;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	rc = selinux_determine_inode_label(selinux_cred(current_cred()),
>  					   d_inode(dentry->d_parent), name,
>  					   inode_mode_to_security_class(mode),
> @@ -2879,6 +2978,9 @@ static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
>  	int rc;
>  	struct task_security_struct *tsec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	rc = selinux_determine_inode_label(selinux_cred(old),
>  					   d_inode(dentry->d_parent), name,
>  					   inode_mode_to_security_class(mode),
> @@ -2902,6 +3004,9 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
>  	int rc;
>  	char *context;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	sbsec = dir->i_sb->s_security;
>  
>  	newsid = tsec->create_sid;
> @@ -2941,50 +3046,75 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
>  
>  static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return may_create(dir, dentry, SECCLASS_FILE);
>  }
>  
>  static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return may_link(dir, old_dentry, MAY_LINK);
>  }
>  
>  static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return may_link(dir, dentry, MAY_UNLINK);
>  }
>  
>  static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return may_create(dir, dentry, SECCLASS_LNK_FILE);
>  }
>  
>  static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return may_create(dir, dentry, SECCLASS_DIR);
>  }
>  
>  static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return may_link(dir, dentry, MAY_RMDIR);
>  }
>  
>  static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return may_create(dir, dentry, inode_mode_to_security_class(mode));
>  }
>  
>  static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
>  				struct inode *new_inode, struct dentry *new_dentry)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return may_rename(old_inode, old_dentry, new_inode, new_dentry);
>  }
>  
>  static int selinux_inode_readlink(struct dentry *dentry)
>  {
> -	const struct cred *cred = current_cred();
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
> -	return dentry_has_perm(cred, dentry, FILE__READ);
> +	return dentry_has_perm(current_cred(), dentry, FILE__READ);
>  }
>  
>  static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
> @@ -2995,6 +3125,9 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
>  	struct inode_security_struct *isec;
>  	u32 sid;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	validate_creds(cred);
>  
>  	ad.type = LSM_AUDIT_DATA_DENTRY;
> @@ -3040,6 +3173,9 @@ static int selinux_inode_permission(struct inode *inode, int mask)
>  	int rc, rc2;
>  	u32 audited, denied;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	from_access = mask & MAY_ACCESS;
>  	mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
>  
> @@ -3086,6 +3222,9 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
>  	unsigned int ia_valid = iattr->ia_valid;
>  	__u32 av = FILE__WRITE;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	/* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
>  	if (ia_valid & ATTR_FORCE) {
>  		ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
> @@ -3109,6 +3248,9 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
>  
>  static int selinux_inode_getattr(const struct path *path)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return path_has_perm(current_cred(), path, FILE__GETATTR);
>  }
>  
> @@ -3131,9 +3273,12 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
>  	struct inode_security_struct *isec;
>  	struct superblock_security_struct *sbsec;
>  	struct common_audit_data ad;
> -	u32 newsid, sid = current_sid();
> +	u32 newsid, sid;
>  	int rc = 0;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (strcmp(name, XATTR_NAME_SELINUX)) {
>  		rc = cap_inode_setxattr(dentry, name, value, size, flags);
>  		if (rc)
> @@ -3154,6 +3299,8 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
>  	if (!inode_owner_or_capable(inode))
>  		return -EPERM;
>  
> +	sid = current_sid();
> +
>  	ad.type = LSM_AUDIT_DATA_DENTRY;
>  	ad.u.dentry = dentry;
>  
> @@ -3225,6 +3372,9 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
>  	u32 newsid;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	if (strcmp(name, XATTR_NAME_SELINUX)) {
>  		/* Not an attribute we recognize, so nothing to do. */
>  		return;
> @@ -3260,20 +3410,25 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
>  
>  static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
>  {
> -	const struct cred *cred = current_cred();
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
> -	return dentry_has_perm(cred, dentry, FILE__GETATTR);
> +	return dentry_has_perm(current_cred(), dentry, FILE__GETATTR);
>  }
>  
>  static int selinux_inode_listxattr(struct dentry *dentry)
>  {
> -	const struct cred *cred = current_cred();
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
> -	return dentry_has_perm(cred, dentry, FILE__GETATTR);
> +	return dentry_has_perm(current_cred(), dentry, FILE__GETATTR);
>  }
>  
>  static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (strcmp(name, XATTR_NAME_SELINUX)) {
>  		int rc = cap_inode_removexattr(dentry, name);
>  		if (rc)
> @@ -3297,6 +3452,9 @@ static int selinux_path_notify(const struct path *path, u64 mask,
>  
>  	struct common_audit_data ad;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	ad.type = LSM_AUDIT_DATA_PATH;
>  	ad.u.path = *path;
>  
> @@ -3345,6 +3503,9 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void
>  	char *context = NULL;
>  	struct inode_security_struct *isec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return -EOPNOTSUPP;
> +
>  	if (strcmp(name, XATTR_SELINUX_SUFFIX))
>  		return -EOPNOTSUPP;
>  
> @@ -3385,6 +3546,9 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
>  	u32 newsid;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return -EOPNOTSUPP;
> +
>  	if (strcmp(name, XATTR_SELINUX_SUFFIX))
>  		return -EOPNOTSUPP;
>  
> @@ -3410,6 +3574,10 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
>  static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
>  {
>  	const int len = sizeof(XATTR_NAME_SELINUX);
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (buffer && len <= buffer_size)
>  		memcpy(buffer, XATTR_NAME_SELINUX, len);
>  	return len;
> @@ -3417,16 +3585,24 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t
>  
>  static void selinux_inode_getsecid(struct inode *inode, u32 *secid)
>  {
> -	struct inode_security_struct *isec = inode_security_novalidate(inode);
> +	struct inode_security_struct *isec;
> +
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
> +	isec = inode_security_novalidate(inode);
>  	*secid = isec->sid;
>  }
>  
>  static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
>  {
> -	u32 sid;
> +	struct inode_security_struct *isec;
>  	struct task_security_struct *tsec;
>  	struct cred *new_creds = *new;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (new_creds == NULL) {
>  		new_creds = prepare_creds();
>  		if (!new_creds)
> @@ -3435,14 +3611,17 @@ static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
>  
>  	tsec = selinux_cred(new_creds);
>  	/* Get label from overlay inode and set it in create_sid */
> -	selinux_inode_getsecid(d_inode(src), &sid);
> -	tsec->create_sid = sid;
> +	isec = inode_security_novalidate(d_inode(src));
> +	tsec->create_sid = isec->sid;
>  	*new = new_creds;
>  	return 0;
>  }
>  
>  static int selinux_inode_copy_up_xattr(const char *name)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return -EOPNOTSUPP;
> +
>  	/* The copy_up hook above sets the initial context on an inode, but we
>  	 * don't then want to overwrite it by blindly copying all the lower
>  	 * xattrs up.  Instead, we have to filter out SELinux-related xattrs.
> @@ -3466,6 +3645,9 @@ static int selinux_kernfs_init_security(struct kernfs_node *kn_dir,
>  	int rc;
>  	char *context;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	rc = kernfs_xattr_get(kn_dir, XATTR_NAME_SELINUX, NULL, 0);
>  	if (rc == -ENODATA)
>  		return 0;
> @@ -3537,14 +3719,16 @@ static int selinux_file_permission(struct file *file, int mask)
>  	struct inode *inode = file_inode(file);
>  	struct file_security_struct *fsec = selinux_file(file);
>  	struct inode_security_struct *isec;
> -	u32 sid = current_sid();
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
>  	if (!mask)
>  		/* No permission to check.  Existence test. */
>  		return 0;
>  
>  	isec = inode_security(inode);
> -	if (sid == fsec->sid && fsec->isid == isec->sid &&
> +	if (current_sid() == fsec->sid && fsec->isid == isec->sid &&
>  	    fsec->pseqno == avc_policy_seqno(&selinux_state))
>  		/* No change since file_open check. */
>  		return 0;
> @@ -3554,6 +3738,9 @@ static int selinux_file_permission(struct file *file, int mask)
>  
>  static int selinux_file_alloc_security(struct file *file)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return file_alloc_security(file);
>  }
>  
> @@ -3606,6 +3793,9 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
>  	const struct cred *cred = current_cred();
>  	int error = 0;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	switch (cmd) {
>  	case FIONREAD:
>  	/* fall through */
> @@ -3692,6 +3882,9 @@ static int selinux_mmap_addr(unsigned long addr)
>  {
>  	int rc = 0;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
>  		u32 sid = current_sid();
>  		rc = avc_has_perm(&selinux_state,
> @@ -3708,6 +3901,9 @@ static int selinux_mmap_file(struct file *file, unsigned long reqprot,
>  	struct common_audit_data ad;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (file) {
>  		ad.type = LSM_AUDIT_DATA_FILE;
>  		ad.u.file = file;
> @@ -3729,7 +3925,12 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
>  				 unsigned long prot)
>  {
>  	const struct cred *cred = current_cred();
> -	u32 sid = cred_sid(cred);
> +	u32 sid;
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	sid = cred_sid(cred);
>  
>  	if (selinux_state.checkreqprot)
>  		prot = reqprot;
> @@ -3768,9 +3969,10 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
>  
>  static int selinux_file_lock(struct file *file, unsigned int cmd)
>  {
> -	const struct cred *cred = current_cred();
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
> -	return file_has_perm(cred, file, FILE__LOCK);
> +	return file_has_perm(current_cred(), file, FILE__LOCK);
>  }
>  
>  static int selinux_file_fcntl(struct file *file, unsigned int cmd,
> @@ -3779,6 +3981,9 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
>  	const struct cred *cred = current_cred();
>  	int err = 0;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	switch (cmd) {
>  	case F_SETFL:
>  		if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
> @@ -3817,6 +4022,9 @@ static void selinux_file_set_fowner(struct file *file)
>  {
>  	struct file_security_struct *fsec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	fsec = selinux_file(file);
>  	fsec->fown_sid = current_sid();
>  }
> @@ -3825,10 +4033,12 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk,
>  				       struct fown_struct *fown, int signum)
>  {
>  	struct file *file;
> -	u32 sid = task_sid(tsk);
>  	u32 perm;
>  	struct file_security_struct *fsec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	/* struct fown_struct is never outside the context of a struct file */
>  	file = container_of(fown, struct file, f_owner);
>  
> @@ -3840,15 +4050,16 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk,
>  		perm = signal_to_av(signum);
>  
>  	return avc_has_perm(&selinux_state,
> -			    fsec->fown_sid, sid,
> +			    fsec->fown_sid, task_sid(tsk),
>  			    SECCLASS_PROCESS, perm, NULL);
>  }
>  
>  static int selinux_file_receive(struct file *file)
>  {
> -	const struct cred *cred = current_cred();
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
> -	return file_has_perm(cred, file, file_to_av(file));
> +	return file_has_perm(current_cred(), file, file_to_av(file));
>  }
>  
>  static int selinux_file_open(struct file *file)
> @@ -3856,6 +4067,9 @@ static int selinux_file_open(struct file *file)
>  	struct file_security_struct *fsec;
>  	struct inode_security_struct *isec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	fsec = selinux_file(file);
>  	isec = inode_security(file_inode(file));
>  	/*
> @@ -3883,7 +4097,12 @@ static int selinux_file_open(struct file *file)
>  static int selinux_task_alloc(struct task_struct *task,
>  			      unsigned long clone_flags)
>  {
> -	u32 sid = current_sid();
> +	u32 sid;
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	sid = current_sid();
>  
>  	return avc_has_perm(&selinux_state,
>  			    sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL);
> @@ -3898,6 +4117,9 @@ static int selinux_cred_prepare(struct cred *new, const struct cred *old,
>  	const struct task_security_struct *old_tsec = selinux_cred(old);
>  	struct task_security_struct *tsec = selinux_cred(new);
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	*tsec = *old_tsec;
>  	return 0;
>  }
> @@ -3910,11 +4132,17 @@ static void selinux_cred_transfer(struct cred *new, const struct cred *old)
>  	const struct task_security_struct *old_tsec = selinux_cred(old);
>  	struct task_security_struct *tsec = selinux_cred(new);
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	*tsec = *old_tsec;
>  }
>  
>  static void selinux_cred_getsecid(const struct cred *c, u32 *secid)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	*secid = cred_sid(c);
>  }
>  
> @@ -3925,11 +4153,13 @@ static void selinux_cred_getsecid(const struct cred *c, u32 *secid)
>  static int selinux_kernel_act_as(struct cred *new, u32 secid)
>  {
>  	struct task_security_struct *tsec = selinux_cred(new);
> -	u32 sid = current_sid();
>  	int ret;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	ret = avc_has_perm(&selinux_state,
> -			   sid, secid,
> +			   current_sid(), secid,
>  			   SECCLASS_KERNEL_SERVICE,
>  			   KERNEL_SERVICE__USE_AS_OVERRIDE,
>  			   NULL);
> @@ -3950,11 +4180,13 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
>  {
>  	struct inode_security_struct *isec = inode_security(inode);
>  	struct task_security_struct *tsec = selinux_cred(new);
> -	u32 sid = current_sid();
>  	int ret;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	ret = avc_has_perm(&selinux_state,
> -			   sid, isec->sid,
> +			   current_sid(), isec->sid,
>  			   SECCLASS_KERNEL_SERVICE,
>  			   KERNEL_SERVICE__CREATE_FILES_AS,
>  			   NULL);
> @@ -3968,6 +4200,9 @@ static int selinux_kernel_module_request(char *kmod_name)
>  {
>  	struct common_audit_data ad;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	ad.type = LSM_AUDIT_DATA_KMOD;
>  	ad.u.kmod_name = kmod_name;
>  
> @@ -4012,35 +4247,37 @@ static int selinux_kernel_module_from_file(struct file *file)
>  static int selinux_kernel_read_file(struct file *file,
>  				    enum kernel_read_file_id id)
>  {
> -	int rc = 0;
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
>  	switch (id) {
>  	case READING_MODULE:
> -		rc = selinux_kernel_module_from_file(file);
> -		break;
> +		return selinux_kernel_module_from_file(file);
>  	default:
>  		break;
>  	}
> -
> -	return rc;
> +	return 0;
>  }
>  
>  static int selinux_kernel_load_data(enum kernel_load_data_id id)
>  {
> -	int rc = 0;
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
>  	switch (id) {
>  	case LOADING_MODULE:
> -		rc = selinux_kernel_module_from_file(NULL);
> +		return selinux_kernel_module_from_file(NULL);
>  	default:
>  		break;
>  	}
> -
> -	return rc;
> +	return 0;
>  }
>  
>  static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>  			    PROCESS__SETPGID, NULL);
> @@ -4048,6 +4285,9 @@ static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
>  
>  static int selinux_task_getpgid(struct task_struct *p)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>  			    PROCESS__GETPGID, NULL);
> @@ -4055,6 +4295,9 @@ static int selinux_task_getpgid(struct task_struct *p)
>  
>  static int selinux_task_getsid(struct task_struct *p)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>  			    PROCESS__GETSESSION, NULL);
> @@ -4062,11 +4305,17 @@ static int selinux_task_getsid(struct task_struct *p)
>  
>  static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	*secid = task_sid(p);
>  }
>  
>  static int selinux_task_setnice(struct task_struct *p, int nice)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>  			    PROCESS__SETSCHED, NULL);
> @@ -4074,6 +4323,9 @@ static int selinux_task_setnice(struct task_struct *p, int nice)
>  
>  static int selinux_task_setioprio(struct task_struct *p, int ioprio)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>  			    PROCESS__SETSCHED, NULL);
> @@ -4081,6 +4333,9 @@ static int selinux_task_setioprio(struct task_struct *p, int ioprio)
>  
>  static int selinux_task_getioprio(struct task_struct *p)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>  			    PROCESS__GETSCHED, NULL);
> @@ -4091,6 +4346,9 @@ static int selinux_task_prlimit(const struct cred *cred, const struct cred *tcre
>  {
>  	u32 av = 0;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (!flags)
>  		return 0;
>  	if (flags & LSM_PRLIMIT_WRITE)
> @@ -4107,6 +4365,9 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
>  {
>  	struct rlimit *old_rlim = p->signal->rlim + resource;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	/* 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
> @@ -4121,6 +4382,9 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
>  
>  static int selinux_task_setscheduler(struct task_struct *p)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>  			    PROCESS__SETSCHED, NULL);
> @@ -4128,6 +4392,9 @@ static int selinux_task_setscheduler(struct task_struct *p)
>  
>  static int selinux_task_getscheduler(struct task_struct *p)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>  			    PROCESS__GETSCHED, NULL);
> @@ -4135,6 +4402,9 @@ static int selinux_task_getscheduler(struct task_struct *p)
>  
>  static int selinux_task_movememory(struct task_struct *p)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>  			    PROCESS__SETSCHED, NULL);
> @@ -4146,6 +4416,9 @@ static int selinux_task_kill(struct task_struct *p, struct kernel_siginfo *info,
>  	u32 secid;
>  	u32 perm;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (!sig)
>  		perm = PROCESS__SIGNULL; /* null signal; existence test */
>  	else
> @@ -4162,11 +4435,13 @@ static void selinux_task_to_inode(struct task_struct *p,
>  				  struct inode *inode)
>  {
>  	struct inode_security_struct *isec = selinux_inode(inode);
> -	u32 sid = task_sid(p);
> +
> +	if (selinux_disabled(&selinux_state))
> +		return;
>  
>  	spin_lock(&isec->lock);
>  	isec->sclass = inode_mode_to_security_class(inode->i_mode);
> -	isec->sid = sid;
> +	isec->sid = task_sid(p);
>  	isec->initialized = LABEL_INITIALIZED;
>  	spin_unlock(&isec->lock);
>  }
> @@ -4506,6 +4781,9 @@ static int selinux_socket_create(int family, int type,
>  	if (kern)
>  		return 0;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	secclass = socket_type_to_security_class(family, type, protocol);
>  	rc = socket_sockcreate_sid(tsec, secclass, &newsid);
>  	if (rc)
> @@ -4525,6 +4803,9 @@ static int selinux_socket_post_create(struct socket *sock, int family,
>  	u32 sid = SECINITSID_KERNEL;
>  	int err = 0;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (!kern) {
>  		err = socket_sockcreate_sid(tsec, sclass, &sid);
>  		if (err)
> @@ -4555,6 +4836,9 @@ static int selinux_socket_socketpair(struct socket *socka,
>  	struct sk_security_struct *sksec_a = socka->sk->sk_security;
>  	struct sk_security_struct *sksec_b = sockb->sk->sk_security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	sksec_a->peer_sid = sksec_b->sid;
>  	sksec_b->peer_sid = sksec_a->sid;
>  
> @@ -4572,6 +4856,9 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
>  	u16 family;
>  	int err;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	err = sock_has_perm(sk, SOCKET__BIND);
>  	if (err)
>  		goto out;
> @@ -4796,6 +5083,9 @@ static int selinux_socket_connect(struct socket *sock,
>  	int err;
>  	struct sock *sk = sock->sk;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	err = selinux_socket_connect_helper(sock, address, addrlen);
>  	if (err)
>  		return err;
> @@ -4805,6 +5095,9 @@ static int selinux_socket_connect(struct socket *sock,
>  
>  static int selinux_socket_listen(struct socket *sock, int backlog)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return sock_has_perm(sock->sk, SOCKET__LISTEN);
>  }
>  
> @@ -4816,6 +5109,9 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
>  	u16 sclass;
>  	u32 sid;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	err = sock_has_perm(sock->sk, SOCKET__ACCEPT);
>  	if (err)
>  		return err;
> @@ -4837,22 +5133,34 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
>  static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
>  				  int size)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return sock_has_perm(sock->sk, SOCKET__WRITE);
>  }
>  
>  static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
>  				  int size, int flags)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return sock_has_perm(sock->sk, SOCKET__READ);
>  }
>  
>  static int selinux_socket_getsockname(struct socket *sock)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return sock_has_perm(sock->sk, SOCKET__GETATTR);
>  }
>  
>  static int selinux_socket_getpeername(struct socket *sock)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return sock_has_perm(sock->sk, SOCKET__GETATTR);
>  }
>  
> @@ -4860,6 +5168,9 @@ static int selinux_socket_setsockopt(struct socket *sock, int level, int optname
>  {
>  	int err;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	err = sock_has_perm(sock->sk, SOCKET__SETOPT);
>  	if (err)
>  		return err;
> @@ -4870,11 +5181,17 @@ static int selinux_socket_setsockopt(struct socket *sock, int level, int optname
>  static int selinux_socket_getsockopt(struct socket *sock, int level,
>  				     int optname)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return sock_has_perm(sock->sk, SOCKET__GETOPT);
>  }
>  
>  static int selinux_socket_shutdown(struct socket *sock, int how)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return sock_has_perm(sock->sk, SOCKET__SHUTDOWN);
>  }
>  
> @@ -4889,6 +5206,9 @@ static int selinux_socket_unix_stream_connect(struct sock *sock,
>  	struct lsm_network_audit net = {0,};
>  	int err;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	ad.type = LSM_AUDIT_DATA_NET;
>  	ad.u.net = &net;
>  	ad.u.net->sk = other;
> @@ -4921,6 +5241,9 @@ static int selinux_socket_unix_may_send(struct socket *sock,
>  	struct common_audit_data ad;
>  	struct lsm_network_audit net = {0,};
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	ad.type = LSM_AUDIT_DATA_NET;
>  	ad.u.net = &net;
>  	ad.u.net->sk = other->sk;
> @@ -4994,13 +5317,15 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
>  	int err;
>  	struct sk_security_struct *sksec = sk->sk_security;
>  	u16 family = sk->sk_family;
> -	u32 sk_sid = sksec->sid;
>  	struct common_audit_data ad;
>  	struct lsm_network_audit net = {0,};
>  	char *addrp;
>  	u8 secmark_active;
>  	u8 peerlbl_active;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (family != PF_INET && family != PF_INET6)
>  		return 0;
>  
> @@ -5041,7 +5366,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
>  			return err;
>  		}
>  		err = avc_has_perm(&selinux_state,
> -				   sk_sid, peer_sid, SECCLASS_PEER,
> +				   sksec->sid, peer_sid, SECCLASS_PEER,
>  				   PEER__RECV, &ad);
>  		if (err) {
>  			selinux_netlbl_err(skb, family, err, 0);
> @@ -5051,7 +5376,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
>  
>  	if (secmark_active) {
>  		err = avc_has_perm(&selinux_state,
> -				   sk_sid, skb->secmark, SECCLASS_PACKET,
> +				   sksec->sid, skb->secmark, SECCLASS_PACKET,
>  				   PACKET__RECV, &ad);
>  		if (err)
>  			return err;
> @@ -5069,6 +5394,9 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op
>  	struct sk_security_struct *sksec = sock->sk->sk_security;
>  	u32 peer_sid = SECSID_NULL;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
>  	    sksec->sclass == SECCLASS_TCP_SOCKET ||
>  	    sksec->sclass == SECCLASS_SCTP_SOCKET)
> @@ -5102,6 +5430,9 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
>  	u16 family;
>  	struct inode_security_struct *isec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (skb && skb->protocol == htons(ETH_P_IP))
>  		family = PF_INET;
>  	else if (skb && skb->protocol == htons(ETH_P_IPV6))
> @@ -5128,6 +5459,9 @@ static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority
>  {
>  	struct sk_security_struct *sksec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	sksec = kzalloc(sizeof(*sksec), priority);
>  	if (!sksec)
>  		return -ENOMEM;
> @@ -5145,6 +5479,9 @@ static void selinux_sk_free_security(struct sock *sk)
>  {
>  	struct sk_security_struct *sksec = sk->sk_security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	sk->sk_security = NULL;
>  	selinux_netlbl_sk_security_free(sksec);
>  	kfree(sksec);
> @@ -5155,6 +5492,9 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
>  	struct sk_security_struct *sksec = sk->sk_security;
>  	struct sk_security_struct *newsksec = newsk->sk_security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	newsksec->sid = sksec->sid;
>  	newsksec->peer_sid = sksec->peer_sid;
>  	newsksec->sclass = sksec->sclass;
> @@ -5164,6 +5504,9 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
>  
>  static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	if (!sk)
>  		*secid = SECINITSID_ANY_SOCKET;
>  	else {
> @@ -5175,10 +5518,14 @@ static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
>  
>  static void selinux_sock_graft(struct sock *sk, struct socket *parent)
>  {
> -	struct inode_security_struct *isec =
> -		inode_security_novalidate(SOCK_INODE(parent));
> +	struct inode_security_struct *isec;
>  	struct sk_security_struct *sksec = sk->sk_security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
> +	isec = inode_security_novalidate(SOCK_INODE(parent));
> +
>  	if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
>  	    sk->sk_family == PF_UNIX)
>  		isec->sid = sksec->sid;
> @@ -5200,6 +5547,9 @@ static int selinux_sctp_assoc_request(struct sctp_endpoint *ep,
>  	u32 conn_sid;
>  	int err = 0;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (!selinux_policycap_extsockclass())
>  		return 0;
>  
> @@ -5270,6 +5620,9 @@ static int selinux_sctp_bind_connect(struct sock *sk, int optname,
>  	struct sockaddr *addr;
>  	struct socket *sock;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (!selinux_policycap_extsockclass())
>  		return 0;
>  
> @@ -5346,6 +5699,9 @@ static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk,
>  	struct sk_security_struct *sksec = sk->sk_security;
>  	struct sk_security_struct *newsksec = newsk->sk_security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	/* If policy does not support SECCLASS_SCTP_SOCKET then call
>  	 * the non-sctp clone version.
>  	 */
> @@ -5367,6 +5723,9 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
>  	u32 connsid;
>  	u32 peersid;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	err = selinux_skb_peerlbl_sid(skb, family, &peersid);
>  	if (err)
>  		return err;
> @@ -5384,6 +5743,9 @@ static void selinux_inet_csk_clone(struct sock *newsk,
>  {
>  	struct sk_security_struct *newsksec = newsk->sk_security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	newsksec->sid = req->secid;
>  	newsksec->peer_sid = req->peer_secid;
>  	/* NOTE: Ideally, we should also get the isec->sid for the
> @@ -5401,6 +5763,9 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
>  	u16 family = sk->sk_family;
>  	struct sk_security_struct *sksec = sk->sk_security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	/* handle mapped IPv4 packets arriving via IPv6 sockets */
>  	if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
>  		family = PF_INET;
> @@ -5413,6 +5778,9 @@ static int selinux_secmark_relabel_packet(u32 sid)
>  	const struct task_security_struct *__tsec;
>  	u32 tsid;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	__tsec = selinux_cred(current_cred());
>  	tsid = __tsec->sid;
>  
> @@ -5423,17 +5791,26 @@ static int selinux_secmark_relabel_packet(u32 sid)
>  
>  static void selinux_secmark_refcount_inc(void)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	atomic_inc(&selinux_secmark_refcount);
>  }
>  
>  static void selinux_secmark_refcount_dec(void)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	atomic_dec(&selinux_secmark_refcount);
>  }
>  
>  static void selinux_req_classify_flow(const struct request_sock *req,
>  				      struct flowi *fl)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	fl->flowi_secid = req->secid;
>  }
>  
> @@ -5441,6 +5818,9 @@ static int selinux_tun_dev_alloc_security(void **security)
>  {
>  	struct tun_security_struct *tunsec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
>  	if (!tunsec)
>  		return -ENOMEM;
> @@ -5452,12 +5832,20 @@ static int selinux_tun_dev_alloc_security(void **security)
>  
>  static void selinux_tun_dev_free_security(void *security)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	kfree(security);
>  }
>  
>  static int selinux_tun_dev_create(void)
>  {
> -	u32 sid = current_sid();
> +	u32 sid;
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	sid = current_sid();
>  
>  	/* we aren't taking into account the "sockcreate" SID since the socket
>  	 * that is being created here is not a socket in the traditional sense,
> @@ -5475,6 +5863,9 @@ static int selinux_tun_dev_attach_queue(void *security)
>  {
>  	struct tun_security_struct *tunsec = security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
>  			    TUN_SOCKET__ATTACH_QUEUE, NULL);
> @@ -5485,6 +5876,9 @@ static int selinux_tun_dev_attach(struct sock *sk, void *security)
>  	struct tun_security_struct *tunsec = security;
>  	struct sk_security_struct *sksec = sk->sk_security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	/* we don't currently perform any NetLabel based labeling here and it
>  	 * isn't clear that we would want to do so anyway; while we could apply
>  	 * labeling without the support of the TUN user the resulting labeled
> @@ -5501,8 +5895,13 @@ static int selinux_tun_dev_attach(struct sock *sk, void *security)
>  static int selinux_tun_dev_open(void *security)
>  {
>  	struct tun_security_struct *tunsec = security;
> -	u32 sid = current_sid();
>  	int err;
> +	u32 sid;
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	sid = current_sid();
>  
>  	err = avc_has_perm(&selinux_state,
>  			   sid, tunsec->sid, SECCLASS_TUN_SOCKET,
> @@ -5885,6 +6284,9 @@ static unsigned int selinux_ipv6_postroute(void *priv,
>  
>  static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return selinux_nlmsg_perm(sk, skb);
>  }
>  
> @@ -5922,6 +6324,9 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
>  
>  static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return msg_msg_alloc_security(msg);
>  }
>  
> @@ -5930,9 +6335,11 @@ static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
>  {
>  	struct ipc_security_struct *isec;
>  	struct common_audit_data ad;
> -	u32 sid = current_sid();
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	isec = selinux_ipc(msq);
>  	ipc_init_security(isec, SECCLASS_MSGQ);
>  
> @@ -5940,7 +6347,7 @@ static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
>  	ad.u.ipc_id = msq->key;
>  
>  	rc = avc_has_perm(&selinux_state,
> -			  sid, isec->sid, SECCLASS_MSGQ,
> +			  current_sid(), isec->sid, SECCLASS_MSGQ,
>  			  MSGQ__CREATE, &ad);
>  	return rc;
>  }
> @@ -5949,7 +6356,9 @@ static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
>  {
>  	struct ipc_security_struct *isec;
>  	struct common_audit_data ad;
> -	u32 sid = current_sid();
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
>  	isec = selinux_ipc(msq);
>  
> @@ -5957,7 +6366,7 @@ static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
>  	ad.u.ipc_id = msq->key;
>  
>  	return avc_has_perm(&selinux_state,
> -			    sid, isec->sid, SECCLASS_MSGQ,
> +			    current_sid(), isec->sid, SECCLASS_MSGQ,
>  			    MSGQ__ASSOCIATE, &ad);
>  }
>  
> @@ -5966,6 +6375,9 @@ static int selinux_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd)
>  	int err;
>  	int perms;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	switch (cmd) {
>  	case IPC_INFO:
>  	case MSG_INFO:
> @@ -5997,9 +6409,14 @@ static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *m
>  	struct ipc_security_struct *isec;
>  	struct msg_security_struct *msec;
>  	struct common_audit_data ad;
> -	u32 sid = current_sid();
> +	u32 sid;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	sid = current_sid();
> +
>  	isec = selinux_ipc(msq);
>  	msec = selinux_msg_msg(msg);
>  
> @@ -6045,9 +6462,14 @@ static int selinux_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *m
>  	struct ipc_security_struct *isec;
>  	struct msg_security_struct *msec;
>  	struct common_audit_data ad;
> -	u32 sid = task_sid(target);
> +	u32 sid;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	sid = task_sid(target);
> +
>  	isec = selinux_ipc(msq);
>  	msec = selinux_msg_msg(msg);
>  
> @@ -6069,9 +6491,11 @@ static int selinux_shm_alloc_security(struct kern_ipc_perm *shp)
>  {
>  	struct ipc_security_struct *isec;
>  	struct common_audit_data ad;
> -	u32 sid = current_sid();
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	isec = selinux_ipc(shp);
>  	ipc_init_security(isec, SECCLASS_SHM);
>  
> @@ -6079,8 +6503,8 @@ static int selinux_shm_alloc_security(struct kern_ipc_perm *shp)
>  	ad.u.ipc_id = shp->key;
>  
>  	rc = avc_has_perm(&selinux_state,
> -			  sid, isec->sid, SECCLASS_SHM,
> -			  SHM__CREATE, &ad);
> +			  current_sid(), isec->sid,
> +			  SECCLASS_SHM, SHM__CREATE, &ad);
>  	return rc;
>  }
>  
> @@ -6088,7 +6512,9 @@ static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg)
>  {
>  	struct ipc_security_struct *isec;
>  	struct common_audit_data ad;
> -	u32 sid = current_sid();
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
>  	isec = selinux_ipc(shp);
>  
> @@ -6096,8 +6522,8 @@ static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg)
>  	ad.u.ipc_id = shp->key;
>  
>  	return avc_has_perm(&selinux_state,
> -			    sid, isec->sid, SECCLASS_SHM,
> -			    SHM__ASSOCIATE, &ad);
> +			    current_sid(), isec->sid,
> +			    SECCLASS_SHM, SHM__ASSOCIATE, &ad);
>  }
>  
>  /* Note, at this point, shp is locked down */
> @@ -6106,6 +6532,9 @@ static int selinux_shm_shmctl(struct kern_ipc_perm *shp, int cmd)
>  	int perms;
>  	int err;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	switch (cmd) {
>  	case IPC_INFO:
>  	case SHM_INFO:
> @@ -6141,6 +6570,9 @@ static int selinux_shm_shmat(struct kern_ipc_perm *shp,
>  {
>  	u32 perms;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (shmflg & SHM_RDONLY)
>  		perms = SHM__READ;
>  	else
> @@ -6154,9 +6586,11 @@ static int selinux_sem_alloc_security(struct kern_ipc_perm *sma)
>  {
>  	struct ipc_security_struct *isec;
>  	struct common_audit_data ad;
> -	u32 sid = current_sid();
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	isec = selinux_ipc(sma);
>  	ipc_init_security(isec, SECCLASS_SEM);
>  
> @@ -6164,8 +6598,8 @@ static int selinux_sem_alloc_security(struct kern_ipc_perm *sma)
>  	ad.u.ipc_id = sma->key;
>  
>  	rc = avc_has_perm(&selinux_state,
> -			  sid, isec->sid, SECCLASS_SEM,
> -			  SEM__CREATE, &ad);
> +			  current_sid(), isec->sid,
> +			  SECCLASS_SEM, SEM__CREATE, &ad);
>  	return rc;
>  }
>  
> @@ -6173,7 +6607,9 @@ static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg)
>  {
>  	struct ipc_security_struct *isec;
>  	struct common_audit_data ad;
> -	u32 sid = current_sid();
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
>  	isec = selinux_ipc(sma);
>  
> @@ -6181,8 +6617,8 @@ static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg)
>  	ad.u.ipc_id = sma->key;
>  
>  	return avc_has_perm(&selinux_state,
> -			    sid, isec->sid, SECCLASS_SEM,
> -			    SEM__ASSOCIATE, &ad);
> +			    current_sid(), isec->sid,
> +			    SECCLASS_SEM, SEM__ASSOCIATE, &ad);
>  }
>  
>  /* Note, at this point, sma is locked down */
> @@ -6191,6 +6627,9 @@ static int selinux_sem_semctl(struct kern_ipc_perm *sma, int cmd)
>  	int err;
>  	u32 perms;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	switch (cmd) {
>  	case IPC_INFO:
>  	case SEM_INFO:
> @@ -6235,6 +6674,9 @@ static int selinux_sem_semop(struct kern_ipc_perm *sma,
>  {
>  	u32 perms;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (alter)
>  		perms = SEM__READ | SEM__WRITE;
>  	else
> @@ -6247,7 +6689,9 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
>  {
>  	u32 av = 0;
>  
> -	av = 0;
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (flag & S_IRUGO)
>  		av |= IPC__UNIX_READ;
>  	if (flag & S_IWUGO)
> @@ -6261,12 +6705,17 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
>  
>  static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
>  {
> -	struct ipc_security_struct *isec = selinux_ipc(ipcp);
> -	*secid = isec->sid;
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
> +	*secid = selinux_ipc(ipcp)->sid;
>  }
>  
>  static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	if (inode)
>  		inode_doinit_with_dentry(inode, dentry);
>  }
> @@ -6279,6 +6728,9 @@ static int selinux_getprocattr(struct task_struct *p,
>  	int error;
>  	unsigned len;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return -EINVAL;
> +
>  	rcu_read_lock();
>  	__tsec = selinux_cred(__task_cred(p));
>  
> @@ -6325,10 +6777,15 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)
>  {
>  	struct task_security_struct *tsec;
>  	struct cred *new;
> -	u32 mysid = current_sid(), sid = 0, ptsid;
> +	u32 mysid, sid = 0, ptsid;
>  	int error;
>  	char *str = value;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return -EINVAL;
> +
> +	mysid = current_sid();
> +
>  	/*
>  	 * Basic control over ability to set these attributes at all.
>  	 */
> @@ -6466,17 +6923,26 @@ abort_change:
>  
>  static int selinux_ismaclabel(const char *name)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
>  }
>  
>  static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return -EOPNOTSUPP;
> +
>  	return security_sid_to_context(&selinux_state, secid,
>  				       secdata, seclen);
>  }
>  
>  static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return security_context_to_sid(&selinux_state, secdata, seclen,
>  				       secid, GFP_KERNEL);
>  }
> @@ -6490,6 +6956,9 @@ static void selinux_inode_invalidate_secctx(struct inode *inode)
>  {
>  	struct inode_security_struct *isec = selinux_inode(inode);
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	spin_lock(&isec->lock);
>  	isec->initialized = LABEL_INVALID;
>  	spin_unlock(&isec->lock);
> @@ -6511,6 +6980,9 @@ static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen
>   */
>  static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
>  }
>  
> @@ -6532,6 +7004,9 @@ static int selinux_key_alloc(struct key *k, const struct cred *cred,
>  	const struct task_security_struct *tsec;
>  	struct key_security_struct *ksec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
>  	if (!ksec)
>  		return -ENOMEM;
> @@ -6550,6 +7025,9 @@ static void selinux_key_free(struct key *k)
>  {
>  	struct key_security_struct *ksec = k->security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	k->security = NULL;
>  	kfree(ksec);
>  }
> @@ -6568,6 +7046,9 @@ static int selinux_key_permission(key_ref_t key_ref,
>  	if (perm == 0)
>  		return 0;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	sid = cred_sid(cred);
>  
>  	key = key_ref_to_ptr(key_ref);
> @@ -6584,6 +7065,9 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)
>  	unsigned len;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	rc = security_sid_to_context(&selinux_state, ksec->sid,
>  				     &context, &len);
>  	if (!rc)
> @@ -6602,6 +7086,9 @@ static int selinux_ib_pkey_access(void *ib_sec, u64 subnet_prefix, u16 pkey_val)
>  	struct ib_security_struct *sec = ib_sec;
>  	struct lsm_ibpkey_audit ibpkey;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	err = sel_ib_pkey_sid(subnet_prefix, pkey_val, &sid);
>  	if (err)
>  		return err;
> @@ -6625,6 +7112,9 @@ static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name,
>  	struct ib_security_struct *sec = ib_sec;
>  	struct lsm_ibendport_audit ibendport;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	err = security_ib_endport_sid(&selinux_state, dev_name, port_num,
>  				      &sid);
>  
> @@ -6645,6 +7135,9 @@ static int selinux_ib_alloc_security(void **ib_sec)
>  {
>  	struct ib_security_struct *sec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	sec = kzalloc(sizeof(*sec), GFP_KERNEL);
>  	if (!sec)
>  		return -ENOMEM;
> @@ -6656,6 +7149,9 @@ static int selinux_ib_alloc_security(void **ib_sec)
>  
>  static void selinux_ib_free_security(void *ib_sec)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	kfree(ib_sec);
>  }
>  #endif
> @@ -6667,6 +7163,9 @@ static int selinux_bpf(int cmd, union bpf_attr *attr,
>  	u32 sid = current_sid();
>  	int ret;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	switch (cmd) {
>  	case BPF_MAP_CREATE:
>  		ret = avc_has_perm(&selinux_state,
> @@ -6734,23 +7233,27 @@ static int bpf_fd_pass(struct file *file, u32 sid)
>  
>  static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode)
>  {
> -	u32 sid = current_sid();
>  	struct bpf_security_struct *bpfsec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	bpfsec = map->security;
>  	return avc_has_perm(&selinux_state,
> -			    sid, bpfsec->sid, SECCLASS_BPF,
> +			    current_sid(), bpfsec->sid, SECCLASS_BPF,
>  			    bpf_map_fmode_to_av(fmode), NULL);
>  }
>  
>  static int selinux_bpf_prog(struct bpf_prog *prog)
>  {
> -	u32 sid = current_sid();
>  	struct bpf_security_struct *bpfsec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	bpfsec = prog->aux->security;
>  	return avc_has_perm(&selinux_state,
> -			    sid, bpfsec->sid, SECCLASS_BPF,
> +			    current_sid(), bpfsec->sid, SECCLASS_BPF,
>  			    BPF__PROG_RUN, NULL);
>  }
>  
> @@ -6758,6 +7261,9 @@ static int selinux_bpf_map_alloc(struct bpf_map *map)
>  {
>  	struct bpf_security_struct *bpfsec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
>  	if (!bpfsec)
>  		return -ENOMEM;
> @@ -6772,6 +7278,9 @@ static void selinux_bpf_map_free(struct bpf_map *map)
>  {
>  	struct bpf_security_struct *bpfsec = map->security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	map->security = NULL;
>  	kfree(bpfsec);
>  }
> @@ -6780,6 +7289,9 @@ static int selinux_bpf_prog_alloc(struct bpf_prog_aux *aux)
>  {
>  	struct bpf_security_struct *bpfsec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
>  	if (!bpfsec)
>  		return -ENOMEM;
> @@ -6794,6 +7306,9 @@ static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
>  {
>  	struct bpf_security_struct *bpfsec = aux->security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	aux->security = NULL;
>  	kfree(bpfsec);
>  }
> @@ -6802,11 +7317,14 @@ static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
>  static int selinux_lockdown(enum lockdown_reason what)
>  {
>  	struct common_audit_data ad;
> -	u32 sid = current_sid();
> +	u32 sid;
>  	int invalid_reason = (what <= LOCKDOWN_NONE) ||
>  			     (what == LOCKDOWN_INTEGRITY_MAX) ||
>  			     (what >= LOCKDOWN_CONFIDENTIALITY_MAX);
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (WARN(invalid_reason, "Invalid lockdown reason")) {
>  		audit_log(audit_context(),
>  			  GFP_ATOMIC, AUDIT_SELINUX_ERR,
> @@ -6814,6 +7332,8 @@ static int selinux_lockdown(enum lockdown_reason what)
>  		return -EINVAL;
>  	}
>  
> +	sid = current_sid();
> +
>  	ad.type = LSM_AUDIT_DATA_LOCKDOWN;
>  	ad.u.reason = what;
>  
> @@ -6827,7 +7347,7 @@ static int selinux_lockdown(enum lockdown_reason what)
>  				    LOCKDOWN__CONFIDENTIALITY, &ad);
>  }
>  
> -struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = {
> +struct lsm_blob_sizes selinux_blob_sizes __ro_after_init = {
>  	.lbs_cred = sizeof(struct task_security_struct),
>  	.lbs_file = sizeof(struct file_security_struct),
>  	.lbs_inode = sizeof(struct inode_security_struct),
> @@ -6838,7 +7358,12 @@ struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = {
>  #ifdef CONFIG_PERF_EVENTS
>  static int selinux_perf_event_open(struct perf_event_attr *attr, int type)
>  {
> -	u32 requested, sid = current_sid();
> +	u32 requested, sid;
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	sid = current_sid();
>  
>  	if (type == PERF_SECURITY_OPEN)
>  		requested = PERF_EVENT__OPEN;
> @@ -6859,6 +7384,9 @@ static int selinux_perf_event_alloc(struct perf_event *event)
>  {
>  	struct perf_event_security_struct *perfsec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	perfsec = kzalloc(sizeof(*perfsec), GFP_KERNEL);
>  	if (!perfsec)
>  		return -ENOMEM;
> @@ -6873,6 +7401,9 @@ static void selinux_perf_event_free(struct perf_event *event)
>  {
>  	struct perf_event_security_struct *perfsec = event->security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	event->security = NULL;
>  	kfree(perfsec);
>  }
> @@ -6880,23 +7411,27 @@ static void selinux_perf_event_free(struct perf_event *event)
>  static int selinux_perf_event_read(struct perf_event *event)
>  {
>  	struct perf_event_security_struct *perfsec = event->security;
> -	u32 sid = current_sid();
>  
> -	return avc_has_perm(&selinux_state, sid, perfsec->sid,
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	return avc_has_perm(&selinux_state, current_sid(), perfsec->sid,
>  			    SECCLASS_PERF_EVENT, PERF_EVENT__READ, NULL);
>  }
>  
>  static int selinux_perf_event_write(struct perf_event *event)
>  {
>  	struct perf_event_security_struct *perfsec = event->security;
> -	u32 sid = current_sid();
>  
> -	return avc_has_perm(&selinux_state, sid, perfsec->sid,
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	return avc_has_perm(&selinux_state, current_sid(), perfsec->sid,
>  			    SECCLASS_PERF_EVENT, PERF_EVENT__WRITE, NULL);
>  }
>  #endif
>  
> -static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
> +static struct security_hook_list selinux_hooks[] __ro_after_init = {
>  	LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
>  	LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
>  	LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
> @@ -7315,18 +7850,19 @@ int selinux_disable(struct selinux_state *state)
>  		return -EINVAL;
>  	}
>  
> +	/*
> +	 * Unregister netfilter hooks (must be done before
> +	 * selinux_mark_disabled()).
> +	 */
> +	selinux_nf_ip_exit();
> +
>  	selinux_mark_disabled(state);
>  
>  	pr_info("SELinux:  Disabled at runtime.\n");
>  
> -	security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
> -
>  	/* Try to destroy the avc node cache */
>  	avc_disable();
>  
> -	/* Unregister netfilter hooks. */
> -	selinux_nf_ip_exit();
> -
>  	/* Unregister selinuxfs. */
>  	exit_sel_fs();
>  
> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> index ecea41ce919b..de50c69846e0 100644
> --- a/security/smack/smack_lsm.c
> +++ b/security/smack/smack_lsm.c
> @@ -4583,7 +4583,7 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode,
>  	return 0;
>  }
>  
> -struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
> +struct lsm_blob_sizes smack_blob_sizes __ro_after_init = {
>  	.lbs_cred = sizeof(struct task_smack),
>  	.lbs_file = sizeof(struct smack_known *),
>  	.lbs_inode = sizeof(struct inode_smack),
> @@ -4591,7 +4591,7 @@ struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
>  	.lbs_msg_msg = sizeof(struct smack_known *),
>  };
>  
> -static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
> +static struct security_hook_list smack_hooks[] __ro_after_init = {
>  	LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check),
>  	LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme),
>  	LSM_HOOK_INIT(syslog, smack_syslog),
> diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
> index 716c92ec941a..9dcdef99d431 100644
> --- a/security/tomoyo/tomoyo.c
> +++ b/security/tomoyo/tomoyo.c
> @@ -486,7 +486,7 @@ static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg,
>  	return tomoyo_socket_sendmsg_permission(sock, msg, size);
>  }
>  
> -struct lsm_blob_sizes tomoyo_blob_sizes __lsm_ro_after_init = {
> +struct lsm_blob_sizes tomoyo_blob_sizes __ro_after_init = {
>  	.lbs_task = sizeof(struct tomoyo_task),
>  };
>  
> @@ -533,7 +533,7 @@ static void tomoyo_task_free(struct task_struct *task)
>   * tomoyo_security_ops is a "struct security_operations" which is used for
>   * registering TOMOYO.
>   */
> -static struct security_hook_list tomoyo_hooks[] __lsm_ro_after_init = {
> +static struct security_hook_list tomoyo_hooks[] __ro_after_init = {
>  	LSM_HOOK_INIT(cred_prepare, tomoyo_cred_prepare),
>  	LSM_HOOK_INIT(bprm_committed_creds, tomoyo_bprm_committed_creds),
>  	LSM_HOOK_INIT(task_alloc, tomoyo_task_alloc),
> @@ -569,7 +569,7 @@ static struct security_hook_list tomoyo_hooks[] __lsm_ro_after_init = {
>  /* Lock for GC. */
>  DEFINE_SRCU(tomoyo_ss);
>  
> -int tomoyo_enabled __lsm_ro_after_init = 1;
> +int tomoyo_enabled __ro_after_init = 1;
>  
>  /**
>   * tomoyo_init - Register TOMOYO Linux as a LSM module.
> diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
> index 94dc346370b1..c47d4e09bfb4 100644
> --- a/security/yama/yama_lsm.c
> +++ b/security/yama/yama_lsm.c
> @@ -421,7 +421,7 @@ static int yama_ptrace_traceme(struct task_struct *parent)
>  	return rc;
>  }
>  
> -static struct security_hook_list yama_hooks[] __lsm_ro_after_init = {
> +static struct security_hook_list yama_hooks[] __ro_after_init = {
>  	LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check),
>  	LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme),
>  	LSM_HOOK_INIT(task_prctl, yama_task_prctl),


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

* Re: [PATCH 1/2] selinux: treat atomic flags more carefully
  2020-01-07 13:31 ` [PATCH 1/2] selinux: treat atomic flags more carefully Ondrej Mosnacek
  2020-01-07 14:45   ` Stephen Smalley
@ 2020-01-07 18:09   ` Kees Cook
  2020-01-07 19:45   ` James Morris
  2020-01-10 20:21   ` Paul Moore
  3 siblings, 0 replies; 18+ messages in thread
From: Kees Cook @ 2020-01-07 18:09 UTC (permalink / raw)
  To: Ondrej Mosnacek
  Cc: linux-security-module, James Morris, Serge E. Hallyn,
	Casey Schaufler, selinux, Paul Moore, Stephen Smalley,
	John Johansen, Micah Morton, Tetsuo Handa

On Tue, Jan 07, 2020 at 02:31:53PM +0100, Ondrej Mosnacek wrote:
> The disabled/enforcing/initialized flags are all accessed concurrently
> by threads so use the appropriate accessors that ensure atomicity and
> document that it is expected.
> 
> Use smp_load/acquire...() helpers (with memory barriers) for the
> initialized flag, since it gates access to the rest of the state
> structures.
> 
> Note that the disabled flag is currently not used for anything other
> than avoiding double disable, but it will be used for bailing out of
> hooks once security_delete_hooks() is removed.
> 
> Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>

Reviewed-by: Kees Cook <keescook@chromium.org>

-Kees

> ---
>  security/selinux/hooks.c            | 21 ++++++++--------
>  security/selinux/include/security.h | 33 +++++++++++++++++++++++--
>  security/selinux/ss/services.c      | 38 ++++++++++++++---------------
>  3 files changed, 61 insertions(+), 31 deletions(-)
> 
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 659c4a81e897..47ad4db925cf 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -272,7 +272,7 @@ static int __inode_security_revalidate(struct inode *inode,
>  
>  	might_sleep_if(may_sleep);
>  
> -	if (selinux_state.initialized &&
> +	if (selinux_initialized(&selinux_state) &&
>  	    isec->initialized != LABEL_INITIALIZED) {
>  		if (!may_sleep)
>  			return -ECHILD;
> @@ -659,7 +659,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
>  
>  	mutex_lock(&sbsec->lock);
>  
> -	if (!selinux_state.initialized) {
> +	if (!selinux_initialized(&selinux_state)) {
>  		if (!opts) {
>  			/* Defer initialization until selinux_complete_init,
>  			   after the initial policy is loaded and the security
> @@ -928,7 +928,7 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
>  	 * if the parent was able to be mounted it clearly had no special lsm
>  	 * mount options.  thus we can safely deal with this superblock later
>  	 */
> -	if (!selinux_state.initialized)
> +	if (!selinux_initialized(&selinux_state))
>  		return 0;
>  
>  	/*
> @@ -1103,7 +1103,7 @@ static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
>  	if (!(sbsec->flags & SE_SBINITIALIZED))
>  		return 0;
>  
> -	if (!selinux_state.initialized)
> +	if (!selinux_initialized(&selinux_state))
>  		return 0;
>  
>  	if (sbsec->flags & FSCONTEXT_MNT) {
> @@ -2920,7 +2920,8 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
>  		isec->initialized = LABEL_INITIALIZED;
>  	}
>  
> -	if (!selinux_state.initialized || !(sbsec->flags & SBLABEL_MNT))
> +	if (!selinux_initialized(&selinux_state) ||
> +	    !(sbsec->flags & SBLABEL_MNT))
>  		return -EOPNOTSUPP;
>  
>  	if (name)
> @@ -3143,7 +3144,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
>  		return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
>  	}
>  
> -	if (!selinux_state.initialized)
> +	if (!selinux_initialized(&selinux_state))
>  		return (inode_owner_or_capable(inode) ? 0 : -EPERM);
>  
>  	sbsec = inode->i_sb->s_security;
> @@ -3229,7 +3230,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
>  		return;
>  	}
>  
> -	if (!selinux_state.initialized) {
> +	if (!selinux_initialized(&selinux_state)) {
>  		/* If we haven't even been initialized, then we can't validate
>  		 * against a policy, so leave the label as invalid. It may
>  		 * resolve to a valid label on the next revalidation try if
> @@ -7304,17 +7305,17 @@ static void selinux_nf_ip_exit(void)
>  #ifdef CONFIG_SECURITY_SELINUX_DISABLE
>  int selinux_disable(struct selinux_state *state)
>  {
> -	if (state->initialized) {
> +	if (selinux_initialized(state)) {
>  		/* Not permitted after initial policy load. */
>  		return -EINVAL;
>  	}
>  
> -	if (state->disabled) {
> +	if (selinux_disabled(state)) {
>  		/* Only do this once. */
>  		return -EINVAL;
>  	}
>  
> -	state->disabled = 1;
> +	selinux_mark_disabled(state);
>  
>  	pr_info("SELinux:  Disabled at runtime.\n");
>  
> diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
> index ecdd610e6449..a39f9565d80b 100644
> --- a/security/selinux/include/security.h
> +++ b/security/selinux/include/security.h
> @@ -117,15 +117,27 @@ void selinux_avc_init(struct selinux_avc **avc);
>  
>  extern struct selinux_state selinux_state;
>  
> +static inline bool selinux_initialized(const struct selinux_state *state)
> +{
> +	/* do a synchronized load to avoid race conditions */
> +	return smp_load_acquire(&state->initialized);
> +}
> +
> +static inline void selinux_mark_initialized(struct selinux_state *state)
> +{
> +	/* do a synchronized write to avoid race conditions */
> +	smp_store_release(&state->initialized, true);
> +}
> +
>  #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
>  static inline bool enforcing_enabled(struct selinux_state *state)
>  {
> -	return state->enforcing;
> +	return READ_ONCE(state->enforcing);
>  }
>  
>  static inline void enforcing_set(struct selinux_state *state, bool value)
>  {
> -	state->enforcing = value;
> +	WRITE_ONCE(state->enforcing, value);
>  }
>  #else
>  static inline bool enforcing_enabled(struct selinux_state *state)
> @@ -138,6 +150,23 @@ static inline void enforcing_set(struct selinux_state *state, bool value)
>  }
>  #endif
>  
> +#ifdef CONFIG_SECURITY_SELINUX_DISABLE
> +static inline bool selinux_disabled(struct selinux_state *state)
> +{
> +	return READ_ONCE(state->disabled);
> +}
> +
> +static inline void selinux_mark_disabled(struct selinux_state *state)
> +{
> +	WRITE_ONCE(state->disabled, true);
> +}
> +#else
> +static inline bool selinux_disabled(struct selinux_state *state)
> +{
> +	return false;
> +}
> +#endif
> +
>  static inline bool selinux_policycap_netpeer(void)
>  {
>  	struct selinux_state *state = &selinux_state;
> diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
> index 55cf42945cba..0e8b94e8e156 100644
> --- a/security/selinux/ss/services.c
> +++ b/security/selinux/ss/services.c
> @@ -767,7 +767,7 @@ static int security_compute_validatetrans(struct selinux_state *state,
>  	int rc = 0;
>  
>  
> -	if (!state->initialized)
> +	if (!selinux_initialized(state))
>  		return 0;
>  
>  	read_lock(&state->ss->policy_rwlock);
> @@ -868,7 +868,7 @@ int security_bounded_transition(struct selinux_state *state,
>  	int index;
>  	int rc;
>  
> -	if (!state->initialized)
> +	if (!selinux_initialized(state))
>  		return 0;
>  
>  	read_lock(&state->ss->policy_rwlock);
> @@ -1027,7 +1027,7 @@ void security_compute_xperms_decision(struct selinux_state *state,
>  	memset(xpermd->dontaudit->p, 0, sizeof(xpermd->dontaudit->p));
>  
>  	read_lock(&state->ss->policy_rwlock);
> -	if (!state->initialized)
> +	if (!selinux_initialized(state))
>  		goto allow;
>  
>  	policydb = &state->ss->policydb;
> @@ -1112,7 +1112,7 @@ void security_compute_av(struct selinux_state *state,
>  	read_lock(&state->ss->policy_rwlock);
>  	avd_init(state, avd);
>  	xperms->len = 0;
> -	if (!state->initialized)
> +	if (!selinux_initialized(state))
>  		goto allow;
>  
>  	policydb = &state->ss->policydb;
> @@ -1166,7 +1166,7 @@ void security_compute_av_user(struct selinux_state *state,
>  
>  	read_lock(&state->ss->policy_rwlock);
>  	avd_init(state, avd);
> -	if (!state->initialized)
> +	if (!selinux_initialized(state))
>  		goto allow;
>  
>  	policydb = &state->ss->policydb;
> @@ -1286,7 +1286,7 @@ int security_sidtab_hash_stats(struct selinux_state *state, char *page)
>  {
>  	int rc;
>  
> -	if (!state->initialized) {
> +	if (!selinux_initialized(state)) {
>  		pr_err("SELinux: %s:  called before initial load_policy\n",
>  		       __func__);
>  		return -EINVAL;
> @@ -1320,7 +1320,7 @@ static int security_sid_to_context_core(struct selinux_state *state,
>  		*scontext = NULL;
>  	*scontext_len  = 0;
>  
> -	if (!state->initialized) {
> +	if (!selinux_initialized(state)) {
>  		if (sid <= SECINITSID_NUM) {
>  			char *scontextp;
>  
> @@ -1549,7 +1549,7 @@ static int security_context_to_sid_core(struct selinux_state *state,
>  	if (!scontext2)
>  		return -ENOMEM;
>  
> -	if (!state->initialized) {
> +	if (!selinux_initialized(state)) {
>  		int i;
>  
>  		for (i = 1; i < SECINITSID_NUM; i++) {
> @@ -1736,7 +1736,7 @@ static int security_compute_sid(struct selinux_state *state,
>  	int rc = 0;
>  	bool sock;
>  
> -	if (!state->initialized) {
> +	if (!selinux_initialized(state)) {
>  		switch (orig_tclass) {
>  		case SECCLASS_PROCESS: /* kernel value */
>  			*out_sid = ssid;
> @@ -2198,7 +2198,7 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len)
>  		goto out;
>  	}
>  
> -	if (!state->initialized) {
> +	if (!selinux_initialized(state)) {
>  		rc = policydb_read(policydb, fp);
>  		if (rc) {
>  			kfree(newsidtab);
> @@ -2223,7 +2223,7 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len)
>  
>  		state->ss->sidtab = newsidtab;
>  		security_load_policycaps(state);
> -		state->initialized = 1;
> +		selinux_mark_initialized(state);
>  		seqno = ++state->ss->latest_granting;
>  		selinux_complete_init();
>  		avc_ss_reset(state->avc, seqno);
> @@ -2639,7 +2639,7 @@ int security_get_user_sids(struct selinux_state *state,
>  	*sids = NULL;
>  	*nel = 0;
>  
> -	if (!state->initialized)
> +	if (!selinux_initialized(state))
>  		goto out;
>  
>  	read_lock(&state->ss->policy_rwlock);
> @@ -2875,7 +2875,7 @@ int security_get_bools(struct selinux_state *state,
>  	struct policydb *policydb;
>  	int i, rc;
>  
> -	if (!state->initialized) {
> +	if (!selinux_initialized(state)) {
>  		*len = 0;
>  		*names = NULL;
>  		*values = NULL;
> @@ -3050,7 +3050,7 @@ int security_sid_mls_copy(struct selinux_state *state,
>  	int rc;
>  
>  	rc = 0;
> -	if (!state->initialized || !policydb->mls_enabled) {
> +	if (!selinux_initialized(state) || !policydb->mls_enabled) {
>  		*new_sid = sid;
>  		goto out;
>  	}
> @@ -3217,7 +3217,7 @@ int security_get_classes(struct selinux_state *state,
>  	struct policydb *policydb = &state->ss->policydb;
>  	int rc;
>  
> -	if (!state->initialized) {
> +	if (!selinux_initialized(state)) {
>  		*nclasses = 0;
>  		*classes = NULL;
>  		return 0;
> @@ -3366,7 +3366,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
>  
>  	*rule = NULL;
>  
> -	if (!state->initialized)
> +	if (!selinux_initialized(state))
>  		return -EOPNOTSUPP;
>  
>  	switch (field) {
> @@ -3665,7 +3665,7 @@ int security_netlbl_secattr_to_sid(struct selinux_state *state,
>  	struct context *ctx;
>  	struct context ctx_new;
>  
> -	if (!state->initialized) {
> +	if (!selinux_initialized(state)) {
>  		*sid = SECSID_NULL;
>  		return 0;
>  	}
> @@ -3732,7 +3732,7 @@ int security_netlbl_sid_to_secattr(struct selinux_state *state,
>  	int rc;
>  	struct context *ctx;
>  
> -	if (!state->initialized)
> +	if (!selinux_initialized(state))
>  		return 0;
>  
>  	read_lock(&state->ss->policy_rwlock);
> @@ -3771,7 +3771,7 @@ int security_read_policy(struct selinux_state *state,
>  	int rc;
>  	struct policy_file fp;
>  
> -	if (!state->initialized)
> +	if (!selinux_initialized(state))
>  		return -EINVAL;
>  
>  	*len = security_policydb_len(state);
> -- 
> 2.24.1
> 

-- 
Kees Cook

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

* Re: [PATCH 2/2] security,selinux: get rid of security_delete_hooks()
  2020-01-07 13:31 ` [PATCH 2/2] security,selinux: get rid of security_delete_hooks() Ondrej Mosnacek
  2020-01-07 14:47   ` [PATCH 2/2] security, selinux: " Stephen Smalley
  2020-01-07 16:46   ` [PATCH 2/2] security,selinux: " Casey Schaufler
@ 2020-01-07 18:10   ` Kees Cook
  2020-01-07 19:59   ` James Morris
  3 siblings, 0 replies; 18+ messages in thread
From: Kees Cook @ 2020-01-07 18:10 UTC (permalink / raw)
  To: Ondrej Mosnacek
  Cc: linux-security-module, James Morris, Serge E. Hallyn,
	Casey Schaufler, selinux, Paul Moore, Stephen Smalley,
	John Johansen, Micah Morton, Tetsuo Handa

On Tue, Jan 07, 2020 at 02:31:54PM +0100, Ondrej Mosnacek wrote:
> The only user is SELinux, which is hereby converted to check the
> disabled flag in each hook instead of removing the hooks from the list.
> 
> The __lsm_ro_after_init macro is now removed and replaced with
> __ro_after_init directly.
> 
> This fixes a race condition in SELinux runtime disable, which was
> introduced with the switch to hook lists in b1d9e6b0646d ("LSM: Switch
> to lists of hooks").
> 
> Suggested-by: Stephen Smalley <sds@tycho.nsa.gov>
> Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>

I'm a fan of removing the __lsm_ro_after_init special-case, so from
that regard:

Reviewed-by: Kees Cook <keescook@chromium.org>

-Kees

> ---
>  include/linux/lsm_hooks.h    |  31 --
>  security/Kconfig             |   5 -
>  security/apparmor/lsm.c      |   6 +-
>  security/commoncap.c         |   2 +-
>  security/loadpin/loadpin.c   |   2 +-
>  security/lockdown/lockdown.c |   2 +-
>  security/security.c          |   5 +-
>  security/selinux/Kconfig     |   6 -
>  security/selinux/hooks.c     | 742 ++++++++++++++++++++++++++++++-----
>  security/smack/smack_lsm.c   |   4 +-
>  security/tomoyo/tomoyo.c     |   6 +-
>  security/yama/yama_lsm.c     |   2 +-
>  12 files changed, 654 insertions(+), 159 deletions(-)
> 
> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
> index 20d8cf194fb7..5064060ce910 100644
> --- a/include/linux/lsm_hooks.h
> +++ b/include/linux/lsm_hooks.h
> @@ -27,7 +27,6 @@
>  
>  #include <linux/security.h>
>  #include <linux/init.h>
> -#include <linux/rculist.h>
>  
>  /**
>   * union security_list_options - Linux Security Module hook function list
> @@ -2145,36 +2144,6 @@ extern struct lsm_info __start_early_lsm_info[], __end_early_lsm_info[];
>  		__used __section(.early_lsm_info.init)			\
>  		__aligned(sizeof(unsigned long))
>  
> -#ifdef CONFIG_SECURITY_SELINUX_DISABLE
> -/*
> - * Assuring the safety of deleting a security module is up to
> - * the security module involved. This may entail ordering the
> - * module's hook list in a particular way, refusing to disable
> - * the module once a policy is loaded or any number of other
> - * actions better imagined than described.
> - *
> - * The name of the configuration option reflects the only module
> - * that currently uses the mechanism. Any developer who thinks
> - * disabling their module is a good idea needs to be at least as
> - * careful as the SELinux team.
> - */
> -static inline void security_delete_hooks(struct security_hook_list *hooks,
> -						int count)
> -{
> -	int i;
> -
> -	for (i = 0; i < count; i++)
> -		hlist_del_rcu(&hooks[i].list);
> -}
> -#endif /* CONFIG_SECURITY_SELINUX_DISABLE */
> -
> -/* Currently required to handle SELinux runtime hook disable. */
> -#ifdef CONFIG_SECURITY_WRITABLE_HOOKS
> -#define __lsm_ro_after_init
> -#else
> -#define __lsm_ro_after_init	__ro_after_init
> -#endif /* CONFIG_SECURITY_WRITABLE_HOOKS */
> -
>  extern int lsm_inode_alloc(struct inode *inode);
>  
>  #endif /* ! __LINUX_LSM_HOOKS_H */
> diff --git a/security/Kconfig b/security/Kconfig
> index 2a1a2d396228..456764990a13 100644
> --- a/security/Kconfig
> +++ b/security/Kconfig
> @@ -32,11 +32,6 @@ config SECURITY
>  
>  	  If you are unsure how to answer this question, answer N.
>  
> -config SECURITY_WRITABLE_HOOKS
> -	depends on SECURITY
> -	bool
> -	default n
> -
>  config SECURITYFS
>  	bool "Enable the securityfs filesystem"
>  	help
> diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
> index b621ad74f54a..cd83812a440f 100644
> --- a/security/apparmor/lsm.c
> +++ b/security/apparmor/lsm.c
> @@ -1158,13 +1158,13 @@ static int apparmor_inet_conn_request(struct sock *sk, struct sk_buff *skb,
>  /*
>   * The cred blob is a pointer to, not an instance of, an aa_task_ctx.
>   */
> -struct lsm_blob_sizes apparmor_blob_sizes __lsm_ro_after_init = {
> +struct lsm_blob_sizes apparmor_blob_sizes __ro_after_init = {
>  	.lbs_cred = sizeof(struct aa_task_ctx *),
>  	.lbs_file = sizeof(struct aa_file_ctx),
>  	.lbs_task = sizeof(struct aa_task_ctx),
>  };
>  
> -static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
> +static struct security_hook_list apparmor_hooks[] __ro_after_init = {
>  	LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
>  	LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
>  	LSM_HOOK_INIT(capget, apparmor_capget),
> @@ -1368,7 +1368,7 @@ static const struct kernel_param_ops param_ops_aaintbool = {
>  	.get = param_get_aaintbool
>  };
>  /* Boot time disable flag */
> -static int apparmor_enabled __lsm_ro_after_init = 1;
> +static int apparmor_enabled __ro_after_init = 1;
>  module_param_named(enabled, apparmor_enabled, aaintbool, 0444);
>  
>  static int __init apparmor_enabled_setup(char *str)
> diff --git a/security/commoncap.c b/security/commoncap.c
> index f4ee0ae106b2..1471d9a5a9bc 100644
> --- a/security/commoncap.c
> +++ b/security/commoncap.c
> @@ -1339,7 +1339,7 @@ int cap_mmap_file(struct file *file, unsigned long reqprot,
>  
>  #ifdef CONFIG_SECURITY
>  
> -static struct security_hook_list capability_hooks[] __lsm_ro_after_init = {
> +static struct security_hook_list capability_hooks[] __ro_after_init = {
>  	LSM_HOOK_INIT(capable, cap_capable),
>  	LSM_HOOK_INIT(settime, cap_settime),
>  	LSM_HOOK_INIT(ptrace_access_check, cap_ptrace_access_check),
> diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c
> index ee5cb944f4ad..9bbc08bee2c0 100644
> --- a/security/loadpin/loadpin.c
> +++ b/security/loadpin/loadpin.c
> @@ -180,7 +180,7 @@ static int loadpin_load_data(enum kernel_load_data_id id)
>  	return loadpin_read_file(NULL, (enum kernel_read_file_id) id);
>  }
>  
> -static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = {
> +static struct security_hook_list loadpin_hooks[] __ro_after_init = {
>  	LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security),
>  	LSM_HOOK_INIT(kernel_read_file, loadpin_read_file),
>  	LSM_HOOK_INIT(kernel_load_data, loadpin_load_data),
> diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c
> index 5a952617a0eb..8071d0f542c8 100644
> --- a/security/lockdown/lockdown.c
> +++ b/security/lockdown/lockdown.c
> @@ -71,7 +71,7 @@ static int lockdown_is_locked_down(enum lockdown_reason what)
>  	return 0;
>  }
>  
> -static struct security_hook_list lockdown_hooks[] __lsm_ro_after_init = {
> +static struct security_hook_list lockdown_hooks[] __ro_after_init = {
>  	LSM_HOOK_INIT(locked_down, lockdown_is_locked_down),
>  };
>  
> diff --git a/security/security.c b/security/security.c
> index 2b5473d92416..3138a5d99813 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -27,6 +27,7 @@
>  #include <linux/backing-dev.h>
>  #include <linux/string.h>
>  #include <linux/msg.h>
> +#include <linux/rculist.h>
>  #include <net/flow.h>
>  
>  #define MAX_LSM_EVM_XATTR	2
> @@ -68,14 +69,14 @@ const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {
>  	[LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality",
>  };
>  
> -struct security_hook_heads security_hook_heads __lsm_ro_after_init;
> +struct security_hook_heads security_hook_heads __ro_after_init;
>  static BLOCKING_NOTIFIER_HEAD(blocking_lsm_notifier_chain);
>  
>  static struct kmem_cache *lsm_file_cache;
>  static struct kmem_cache *lsm_inode_cache;
>  
>  char *lsm_names;
> -static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init;
> +static struct lsm_blob_sizes blob_sizes __ro_after_init;
>  
>  /* Boot-time LSM user choice */
>  static __initdata const char *chosen_lsm_order;
> diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
> index 996d35d950f7..caa5711478ad 100644
> --- a/security/selinux/Kconfig
> +++ b/security/selinux/Kconfig
> @@ -26,7 +26,6 @@ config SECURITY_SELINUX_BOOTPARAM
>  config SECURITY_SELINUX_DISABLE
>  	bool "NSA SELinux runtime disable"
>  	depends on SECURITY_SELINUX
> -	select SECURITY_WRITABLE_HOOKS
>  	default n
>  	help
>  	  This option enables writing to a selinuxfs node 'disable', which
> @@ -37,11 +36,6 @@ config SECURITY_SELINUX_DISABLE
>  	  portability across platforms where boot parameters are difficult
>  	  to employ.
>  
> -	  NOTE: selecting this option will disable the '__ro_after_init'
> -	  kernel hardening feature for security hooks.   Please consider
> -	  using the selinux=0 boot parameter instead of enabling this
> -	  option.
> -
>  	  If you are unsure how to answer this question, answer N.
>  
>  config SECURITY_SELINUX_DEVELOP
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 47ad4db925cf..9ac2b6b69ff9 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -650,13 +650,15 @@ static int selinux_set_mnt_opts(struct super_block *sb,
>  {
>  	const struct cred *cred = current_cred();
>  	struct superblock_security_struct *sbsec = sb->s_security;
> -	struct dentry *root = sbsec->sb->s_root;
>  	struct selinux_mnt_opts *opts = mnt_opts;
>  	struct inode_security_struct *root_isec;
>  	u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
>  	u32 defcontext_sid = 0;
>  	int rc = 0;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	mutex_lock(&sbsec->lock);
>  
>  	if (!selinux_initialized(&selinux_state)) {
> @@ -693,7 +695,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
>  	    && !opts)
>  		goto out;
>  
> -	root_isec = backing_inode_security_novalidate(root);
> +	root_isec = backing_inode_security_novalidate(sbsec->sb->s_root);
>  
>  	/*
>  	 * parse the mount options, check if they are valid sids.
> @@ -919,10 +921,14 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
>  	int rc = 0;
>  	const struct superblock_security_struct *oldsbsec = oldsb->s_security;
>  	struct superblock_security_struct *newsbsec = newsb->s_security;
> +	int set_fscontext, set_context, set_rootcontext;
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
> -	int set_fscontext =	(oldsbsec->flags & FSCONTEXT_MNT);
> -	int set_context =	(oldsbsec->flags & CONTEXT_MNT);
> -	int set_rootcontext =	(oldsbsec->flags & ROOTCONTEXT_MNT);
> +	set_fscontext =		(oldsbsec->flags & FSCONTEXT_MNT);
> +	set_context =		(oldsbsec->flags & CONTEXT_MNT);
> +	set_rootcontext =	(oldsbsec->flags & ROOTCONTEXT_MNT);
>  
>  	/*
>  	 * if the parent was able to be mounted it clearly had no special lsm
> @@ -1041,6 +1047,9 @@ static int selinux_add_mnt_opt(const char *option, const char *val, int len,
>  	int token = Opt_error;
>  	int rc, i;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	for (i = 0; i < ARRAY_SIZE(tokens); i++) {
>  		if (strcmp(option, tokens[i].name) == 0) {
>  			token = tokens[i].opt;
> @@ -1100,6 +1109,9 @@ static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
>  	struct superblock_security_struct *sbsec = sb->s_security;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (!(sbsec->flags & SE_SBINITIALIZED))
>  		return 0;
>  
> @@ -2044,22 +2056,27 @@ static inline u32 open_file_to_av(struct file *file)
>  
>  static int selinux_binder_set_context_mgr(struct task_struct *mgr)
>  {
> -	u32 mysid = current_sid();
> -	u32 mgrsid = task_sid(mgr);
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
>  	return avc_has_perm(&selinux_state,
> -			    mysid, mgrsid, SECCLASS_BINDER,
> +			    current_sid(), task_sid(mgr), SECCLASS_BINDER,
>  			    BINDER__SET_CONTEXT_MGR, NULL);
>  }
>  
>  static int selinux_binder_transaction(struct task_struct *from,
>  				      struct task_struct *to)
>  {
> -	u32 mysid = current_sid();
> -	u32 fromsid = task_sid(from);
> -	u32 tosid = task_sid(to);
> +	u32 mysid, fromsid, tosid;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	mysid = current_sid();
> +	fromsid = task_sid(from);
> +	tosid = task_sid(to);
> +
>  	if (mysid != fromsid) {
>  		rc = avc_has_perm(&selinux_state,
>  				  mysid, fromsid, SECCLASS_BINDER,
> @@ -2076,11 +2093,12 @@ static int selinux_binder_transaction(struct task_struct *from,
>  static int selinux_binder_transfer_binder(struct task_struct *from,
>  					  struct task_struct *to)
>  {
> -	u32 fromsid = task_sid(from);
> -	u32 tosid = task_sid(to);
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
>  	return avc_has_perm(&selinux_state,
> -			    fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
> +			    task_sid(from), task_sid(to),
> +			    SECCLASS_BINDER, BINDER__TRANSFER,
>  			    NULL);
>  }
>  
> @@ -2088,13 +2106,18 @@ static int selinux_binder_transfer_file(struct task_struct *from,
>  					struct task_struct *to,
>  					struct file *file)
>  {
> -	u32 sid = task_sid(to);
> +	u32 sid;
>  	struct file_security_struct *fsec = selinux_file(file);
>  	struct dentry *dentry = file->f_path.dentry;
>  	struct inode_security_struct *isec;
>  	struct common_audit_data ad;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	sid = task_sid(to);
> +
>  	ad.type = LSM_AUDIT_DATA_PATH;
>  	ad.u.path = file->f_path;
>  
> @@ -2126,19 +2149,26 @@ static int selinux_binder_transfer_file(struct task_struct *from,
>  static int selinux_ptrace_access_check(struct task_struct *child,
>  				     unsigned int mode)
>  {
> -	u32 sid = current_sid();
> -	u32 csid = task_sid(child);
> +	u16 cls = SECCLASS_PROCESS;
> +	u32 perm = PROCESS__PTRACE;
>  
> -	if (mode & PTRACE_MODE_READ)
> -		return avc_has_perm(&selinux_state,
> -				    sid, csid, SECCLASS_FILE, FILE__READ, NULL);
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	if (mode & PTRACE_MODE_READ) {
> +		cls = SECCLASS_FILE;
> +		perm = FILE__READ;
> +	}
>  
>  	return avc_has_perm(&selinux_state,
> -			    sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL);
> +			    current_sid(), task_sid(child), cls, perm, NULL);
>  }
>  
>  static int selinux_ptrace_traceme(struct task_struct *parent)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    task_sid(parent), current_sid(), SECCLASS_PROCESS,
>  			    PROCESS__PTRACE, NULL);
> @@ -2147,6 +2177,9 @@ static int selinux_ptrace_traceme(struct task_struct *parent)
>  static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
>  			  kernel_cap_t *inheritable, kernel_cap_t *permitted)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    current_sid(), task_sid(target), SECCLASS_PROCESS,
>  			    PROCESS__GETCAP, NULL);
> @@ -2157,6 +2190,9 @@ static int selinux_capset(struct cred *new, const struct cred *old,
>  			  const kernel_cap_t *inheritable,
>  			  const kernel_cap_t *permitted)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    cred_sid(old), cred_sid(new), SECCLASS_PROCESS,
>  			    PROCESS__SETCAP, NULL);
> @@ -2175,6 +2211,9 @@ static int selinux_capset(struct cred *new, const struct cred *old,
>  static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
>  			   int cap, unsigned int opts)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return cred_has_capability(cred, cap, opts, ns == &init_user_ns);
>  }
>  
> @@ -2186,6 +2225,9 @@ static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
>  	if (!sb)
>  		return 0;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	switch (cmds) {
>  	case Q_SYNC:
>  	case Q_QUOTAON:
> @@ -2210,11 +2252,17 @@ static int selinux_quota_on(struct dentry *dentry)
>  {
>  	const struct cred *cred = current_cred();
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return dentry_has_perm(cred, dentry, FILE__QUOTAON);
>  }
>  
>  static int selinux_syslog(int type)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	switch (type) {
>  	case SYSLOG_ACTION_READ_ALL:	/* Read last kernel messages */
>  	case SYSLOG_ACTION_SIZE_BUFFER:	/* Return size of the log buffer */
> @@ -2248,6 +2296,9 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
>  {
>  	int rc, cap_sys_admin = 0;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
>  				 CAP_OPT_NOAUDIT, true);
>  	if (rc == 0)
> @@ -2335,6 +2386,9 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
>  	struct inode *inode = file_inode(bprm->file);
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	/* SELinux context only depends on initial program or script and not
>  	 * the script interpreter */
>  	if (bprm->called_set_creds)
> @@ -2505,6 +2559,9 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
>  	struct rlimit *rlim, *initrlim;
>  	int rc, i;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	new_tsec = selinux_cred(bprm->cred);
>  	if (new_tsec->sid == new_tsec->osid)
>  		return;
> @@ -2552,6 +2609,9 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
>  	u32 osid, sid;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	osid = tsec->osid;
>  	sid = tsec->sid;
>  
> @@ -2592,11 +2652,17 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
>  
>  static int selinux_sb_alloc_security(struct super_block *sb)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return superblock_alloc_security(sb);
>  }
>  
>  static void selinux_sb_free_security(struct super_block *sb)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	superblock_free_security(sb);
>  }
>  
> @@ -2622,6 +2688,9 @@ static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts)
>  	bool first = true;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	while (1) {
>  		int len = opt_len(from);
>  		int token;
> @@ -2682,6 +2751,9 @@ static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
>  	u32 sid;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (!(sbsec->flags & SE_SBINITIALIZED))
>  		return 0;
>  
> @@ -2732,6 +2804,9 @@ static int selinux_sb_kern_mount(struct super_block *sb)
>  	const struct cred *cred = current_cred();
>  	struct common_audit_data ad;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	ad.type = LSM_AUDIT_DATA_DENTRY;
>  	ad.u.dentry = sb->s_root;
>  	return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
> @@ -2742,6 +2817,9 @@ static int selinux_sb_statfs(struct dentry *dentry)
>  	const struct cred *cred = current_cred();
>  	struct common_audit_data ad;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	ad.type = LSM_AUDIT_DATA_DENTRY;
>  	ad.u.dentry = dentry->d_sb->s_root;
>  	return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
> @@ -2755,6 +2833,9 @@ static int selinux_mount(const char *dev_name,
>  {
>  	const struct cred *cred = current_cred();
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (flags & MS_REMOUNT)
>  		return superblock_has_perm(cred, path->dentry->d_sb,
>  					   FILESYSTEM__REMOUNT, NULL);
> @@ -2766,6 +2847,9 @@ static int selinux_umount(struct vfsmount *mnt, int flags)
>  {
>  	const struct cred *cred = current_cred();
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return superblock_has_perm(cred, mnt->mnt_sb,
>  				   FILESYSTEM__UNMOUNT, NULL);
>  }
> @@ -2776,6 +2860,9 @@ static int selinux_fs_context_dup(struct fs_context *fc,
>  	const struct selinux_mnt_opts *src = src_fc->security;
>  	struct selinux_mnt_opts *opts;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (!src)
>  		return 0;
>  
> @@ -2828,6 +2915,9 @@ static int selinux_fs_context_parse_param(struct fs_context *fc,
>  	struct fs_parse_result result;
>  	int opt, rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	opt = fs_parse(fc, &selinux_fs_parameters, param, &result);
>  	if (opt < 0)
>  		return opt;
> @@ -2844,11 +2934,17 @@ static int selinux_fs_context_parse_param(struct fs_context *fc,
>  
>  static int selinux_inode_alloc_security(struct inode *inode)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return inode_alloc_security(inode);
>  }
>  
>  static void selinux_inode_free_security(struct inode *inode)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	inode_free_security(inode);
>  }
>  
> @@ -2859,6 +2955,9 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,
>  	u32 newsid;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	rc = selinux_determine_inode_label(selinux_cred(current_cred()),
>  					   d_inode(dentry->d_parent), name,
>  					   inode_mode_to_security_class(mode),
> @@ -2879,6 +2978,9 @@ static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
>  	int rc;
>  	struct task_security_struct *tsec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	rc = selinux_determine_inode_label(selinux_cred(old),
>  					   d_inode(dentry->d_parent), name,
>  					   inode_mode_to_security_class(mode),
> @@ -2902,6 +3004,9 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
>  	int rc;
>  	char *context;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	sbsec = dir->i_sb->s_security;
>  
>  	newsid = tsec->create_sid;
> @@ -2941,50 +3046,75 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
>  
>  static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return may_create(dir, dentry, SECCLASS_FILE);
>  }
>  
>  static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return may_link(dir, old_dentry, MAY_LINK);
>  }
>  
>  static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return may_link(dir, dentry, MAY_UNLINK);
>  }
>  
>  static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return may_create(dir, dentry, SECCLASS_LNK_FILE);
>  }
>  
>  static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return may_create(dir, dentry, SECCLASS_DIR);
>  }
>  
>  static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return may_link(dir, dentry, MAY_RMDIR);
>  }
>  
>  static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return may_create(dir, dentry, inode_mode_to_security_class(mode));
>  }
>  
>  static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
>  				struct inode *new_inode, struct dentry *new_dentry)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return may_rename(old_inode, old_dentry, new_inode, new_dentry);
>  }
>  
>  static int selinux_inode_readlink(struct dentry *dentry)
>  {
> -	const struct cred *cred = current_cred();
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
> -	return dentry_has_perm(cred, dentry, FILE__READ);
> +	return dentry_has_perm(current_cred(), dentry, FILE__READ);
>  }
>  
>  static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
> @@ -2995,6 +3125,9 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
>  	struct inode_security_struct *isec;
>  	u32 sid;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	validate_creds(cred);
>  
>  	ad.type = LSM_AUDIT_DATA_DENTRY;
> @@ -3040,6 +3173,9 @@ static int selinux_inode_permission(struct inode *inode, int mask)
>  	int rc, rc2;
>  	u32 audited, denied;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	from_access = mask & MAY_ACCESS;
>  	mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
>  
> @@ -3086,6 +3222,9 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
>  	unsigned int ia_valid = iattr->ia_valid;
>  	__u32 av = FILE__WRITE;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	/* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
>  	if (ia_valid & ATTR_FORCE) {
>  		ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
> @@ -3109,6 +3248,9 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
>  
>  static int selinux_inode_getattr(const struct path *path)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return path_has_perm(current_cred(), path, FILE__GETATTR);
>  }
>  
> @@ -3131,9 +3273,12 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
>  	struct inode_security_struct *isec;
>  	struct superblock_security_struct *sbsec;
>  	struct common_audit_data ad;
> -	u32 newsid, sid = current_sid();
> +	u32 newsid, sid;
>  	int rc = 0;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (strcmp(name, XATTR_NAME_SELINUX)) {
>  		rc = cap_inode_setxattr(dentry, name, value, size, flags);
>  		if (rc)
> @@ -3154,6 +3299,8 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
>  	if (!inode_owner_or_capable(inode))
>  		return -EPERM;
>  
> +	sid = current_sid();
> +
>  	ad.type = LSM_AUDIT_DATA_DENTRY;
>  	ad.u.dentry = dentry;
>  
> @@ -3225,6 +3372,9 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
>  	u32 newsid;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	if (strcmp(name, XATTR_NAME_SELINUX)) {
>  		/* Not an attribute we recognize, so nothing to do. */
>  		return;
> @@ -3260,20 +3410,25 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
>  
>  static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
>  {
> -	const struct cred *cred = current_cred();
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
> -	return dentry_has_perm(cred, dentry, FILE__GETATTR);
> +	return dentry_has_perm(current_cred(), dentry, FILE__GETATTR);
>  }
>  
>  static int selinux_inode_listxattr(struct dentry *dentry)
>  {
> -	const struct cred *cred = current_cred();
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
> -	return dentry_has_perm(cred, dentry, FILE__GETATTR);
> +	return dentry_has_perm(current_cred(), dentry, FILE__GETATTR);
>  }
>  
>  static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (strcmp(name, XATTR_NAME_SELINUX)) {
>  		int rc = cap_inode_removexattr(dentry, name);
>  		if (rc)
> @@ -3297,6 +3452,9 @@ static int selinux_path_notify(const struct path *path, u64 mask,
>  
>  	struct common_audit_data ad;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	ad.type = LSM_AUDIT_DATA_PATH;
>  	ad.u.path = *path;
>  
> @@ -3345,6 +3503,9 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void
>  	char *context = NULL;
>  	struct inode_security_struct *isec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return -EOPNOTSUPP;
> +
>  	if (strcmp(name, XATTR_SELINUX_SUFFIX))
>  		return -EOPNOTSUPP;
>  
> @@ -3385,6 +3546,9 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
>  	u32 newsid;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return -EOPNOTSUPP;
> +
>  	if (strcmp(name, XATTR_SELINUX_SUFFIX))
>  		return -EOPNOTSUPP;
>  
> @@ -3410,6 +3574,10 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
>  static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
>  {
>  	const int len = sizeof(XATTR_NAME_SELINUX);
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (buffer && len <= buffer_size)
>  		memcpy(buffer, XATTR_NAME_SELINUX, len);
>  	return len;
> @@ -3417,16 +3585,24 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t
>  
>  static void selinux_inode_getsecid(struct inode *inode, u32 *secid)
>  {
> -	struct inode_security_struct *isec = inode_security_novalidate(inode);
> +	struct inode_security_struct *isec;
> +
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
> +	isec = inode_security_novalidate(inode);
>  	*secid = isec->sid;
>  }
>  
>  static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
>  {
> -	u32 sid;
> +	struct inode_security_struct *isec;
>  	struct task_security_struct *tsec;
>  	struct cred *new_creds = *new;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (new_creds == NULL) {
>  		new_creds = prepare_creds();
>  		if (!new_creds)
> @@ -3435,14 +3611,17 @@ static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
>  
>  	tsec = selinux_cred(new_creds);
>  	/* Get label from overlay inode and set it in create_sid */
> -	selinux_inode_getsecid(d_inode(src), &sid);
> -	tsec->create_sid = sid;
> +	isec = inode_security_novalidate(d_inode(src));
> +	tsec->create_sid = isec->sid;
>  	*new = new_creds;
>  	return 0;
>  }
>  
>  static int selinux_inode_copy_up_xattr(const char *name)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return -EOPNOTSUPP;
> +
>  	/* The copy_up hook above sets the initial context on an inode, but we
>  	 * don't then want to overwrite it by blindly copying all the lower
>  	 * xattrs up.  Instead, we have to filter out SELinux-related xattrs.
> @@ -3466,6 +3645,9 @@ static int selinux_kernfs_init_security(struct kernfs_node *kn_dir,
>  	int rc;
>  	char *context;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	rc = kernfs_xattr_get(kn_dir, XATTR_NAME_SELINUX, NULL, 0);
>  	if (rc == -ENODATA)
>  		return 0;
> @@ -3537,14 +3719,16 @@ static int selinux_file_permission(struct file *file, int mask)
>  	struct inode *inode = file_inode(file);
>  	struct file_security_struct *fsec = selinux_file(file);
>  	struct inode_security_struct *isec;
> -	u32 sid = current_sid();
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
>  	if (!mask)
>  		/* No permission to check.  Existence test. */
>  		return 0;
>  
>  	isec = inode_security(inode);
> -	if (sid == fsec->sid && fsec->isid == isec->sid &&
> +	if (current_sid() == fsec->sid && fsec->isid == isec->sid &&
>  	    fsec->pseqno == avc_policy_seqno(&selinux_state))
>  		/* No change since file_open check. */
>  		return 0;
> @@ -3554,6 +3738,9 @@ static int selinux_file_permission(struct file *file, int mask)
>  
>  static int selinux_file_alloc_security(struct file *file)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return file_alloc_security(file);
>  }
>  
> @@ -3606,6 +3793,9 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
>  	const struct cred *cred = current_cred();
>  	int error = 0;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	switch (cmd) {
>  	case FIONREAD:
>  	/* fall through */
> @@ -3692,6 +3882,9 @@ static int selinux_mmap_addr(unsigned long addr)
>  {
>  	int rc = 0;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
>  		u32 sid = current_sid();
>  		rc = avc_has_perm(&selinux_state,
> @@ -3708,6 +3901,9 @@ static int selinux_mmap_file(struct file *file, unsigned long reqprot,
>  	struct common_audit_data ad;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (file) {
>  		ad.type = LSM_AUDIT_DATA_FILE;
>  		ad.u.file = file;
> @@ -3729,7 +3925,12 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
>  				 unsigned long prot)
>  {
>  	const struct cred *cred = current_cred();
> -	u32 sid = cred_sid(cred);
> +	u32 sid;
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	sid = cred_sid(cred);
>  
>  	if (selinux_state.checkreqprot)
>  		prot = reqprot;
> @@ -3768,9 +3969,10 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
>  
>  static int selinux_file_lock(struct file *file, unsigned int cmd)
>  {
> -	const struct cred *cred = current_cred();
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
> -	return file_has_perm(cred, file, FILE__LOCK);
> +	return file_has_perm(current_cred(), file, FILE__LOCK);
>  }
>  
>  static int selinux_file_fcntl(struct file *file, unsigned int cmd,
> @@ -3779,6 +3981,9 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
>  	const struct cred *cred = current_cred();
>  	int err = 0;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	switch (cmd) {
>  	case F_SETFL:
>  		if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
> @@ -3817,6 +4022,9 @@ static void selinux_file_set_fowner(struct file *file)
>  {
>  	struct file_security_struct *fsec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	fsec = selinux_file(file);
>  	fsec->fown_sid = current_sid();
>  }
> @@ -3825,10 +4033,12 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk,
>  				       struct fown_struct *fown, int signum)
>  {
>  	struct file *file;
> -	u32 sid = task_sid(tsk);
>  	u32 perm;
>  	struct file_security_struct *fsec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	/* struct fown_struct is never outside the context of a struct file */
>  	file = container_of(fown, struct file, f_owner);
>  
> @@ -3840,15 +4050,16 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk,
>  		perm = signal_to_av(signum);
>  
>  	return avc_has_perm(&selinux_state,
> -			    fsec->fown_sid, sid,
> +			    fsec->fown_sid, task_sid(tsk),
>  			    SECCLASS_PROCESS, perm, NULL);
>  }
>  
>  static int selinux_file_receive(struct file *file)
>  {
> -	const struct cred *cred = current_cred();
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
> -	return file_has_perm(cred, file, file_to_av(file));
> +	return file_has_perm(current_cred(), file, file_to_av(file));
>  }
>  
>  static int selinux_file_open(struct file *file)
> @@ -3856,6 +4067,9 @@ static int selinux_file_open(struct file *file)
>  	struct file_security_struct *fsec;
>  	struct inode_security_struct *isec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	fsec = selinux_file(file);
>  	isec = inode_security(file_inode(file));
>  	/*
> @@ -3883,7 +4097,12 @@ static int selinux_file_open(struct file *file)
>  static int selinux_task_alloc(struct task_struct *task,
>  			      unsigned long clone_flags)
>  {
> -	u32 sid = current_sid();
> +	u32 sid;
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	sid = current_sid();
>  
>  	return avc_has_perm(&selinux_state,
>  			    sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL);
> @@ -3898,6 +4117,9 @@ static int selinux_cred_prepare(struct cred *new, const struct cred *old,
>  	const struct task_security_struct *old_tsec = selinux_cred(old);
>  	struct task_security_struct *tsec = selinux_cred(new);
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	*tsec = *old_tsec;
>  	return 0;
>  }
> @@ -3910,11 +4132,17 @@ static void selinux_cred_transfer(struct cred *new, const struct cred *old)
>  	const struct task_security_struct *old_tsec = selinux_cred(old);
>  	struct task_security_struct *tsec = selinux_cred(new);
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	*tsec = *old_tsec;
>  }
>  
>  static void selinux_cred_getsecid(const struct cred *c, u32 *secid)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	*secid = cred_sid(c);
>  }
>  
> @@ -3925,11 +4153,13 @@ static void selinux_cred_getsecid(const struct cred *c, u32 *secid)
>  static int selinux_kernel_act_as(struct cred *new, u32 secid)
>  {
>  	struct task_security_struct *tsec = selinux_cred(new);
> -	u32 sid = current_sid();
>  	int ret;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	ret = avc_has_perm(&selinux_state,
> -			   sid, secid,
> +			   current_sid(), secid,
>  			   SECCLASS_KERNEL_SERVICE,
>  			   KERNEL_SERVICE__USE_AS_OVERRIDE,
>  			   NULL);
> @@ -3950,11 +4180,13 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
>  {
>  	struct inode_security_struct *isec = inode_security(inode);
>  	struct task_security_struct *tsec = selinux_cred(new);
> -	u32 sid = current_sid();
>  	int ret;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	ret = avc_has_perm(&selinux_state,
> -			   sid, isec->sid,
> +			   current_sid(), isec->sid,
>  			   SECCLASS_KERNEL_SERVICE,
>  			   KERNEL_SERVICE__CREATE_FILES_AS,
>  			   NULL);
> @@ -3968,6 +4200,9 @@ static int selinux_kernel_module_request(char *kmod_name)
>  {
>  	struct common_audit_data ad;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	ad.type = LSM_AUDIT_DATA_KMOD;
>  	ad.u.kmod_name = kmod_name;
>  
> @@ -4012,35 +4247,37 @@ static int selinux_kernel_module_from_file(struct file *file)
>  static int selinux_kernel_read_file(struct file *file,
>  				    enum kernel_read_file_id id)
>  {
> -	int rc = 0;
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
>  	switch (id) {
>  	case READING_MODULE:
> -		rc = selinux_kernel_module_from_file(file);
> -		break;
> +		return selinux_kernel_module_from_file(file);
>  	default:
>  		break;
>  	}
> -
> -	return rc;
> +	return 0;
>  }
>  
>  static int selinux_kernel_load_data(enum kernel_load_data_id id)
>  {
> -	int rc = 0;
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
>  	switch (id) {
>  	case LOADING_MODULE:
> -		rc = selinux_kernel_module_from_file(NULL);
> +		return selinux_kernel_module_from_file(NULL);
>  	default:
>  		break;
>  	}
> -
> -	return rc;
> +	return 0;
>  }
>  
>  static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>  			    PROCESS__SETPGID, NULL);
> @@ -4048,6 +4285,9 @@ static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
>  
>  static int selinux_task_getpgid(struct task_struct *p)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>  			    PROCESS__GETPGID, NULL);
> @@ -4055,6 +4295,9 @@ static int selinux_task_getpgid(struct task_struct *p)
>  
>  static int selinux_task_getsid(struct task_struct *p)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>  			    PROCESS__GETSESSION, NULL);
> @@ -4062,11 +4305,17 @@ static int selinux_task_getsid(struct task_struct *p)
>  
>  static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	*secid = task_sid(p);
>  }
>  
>  static int selinux_task_setnice(struct task_struct *p, int nice)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>  			    PROCESS__SETSCHED, NULL);
> @@ -4074,6 +4323,9 @@ static int selinux_task_setnice(struct task_struct *p, int nice)
>  
>  static int selinux_task_setioprio(struct task_struct *p, int ioprio)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>  			    PROCESS__SETSCHED, NULL);
> @@ -4081,6 +4333,9 @@ static int selinux_task_setioprio(struct task_struct *p, int ioprio)
>  
>  static int selinux_task_getioprio(struct task_struct *p)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>  			    PROCESS__GETSCHED, NULL);
> @@ -4091,6 +4346,9 @@ static int selinux_task_prlimit(const struct cred *cred, const struct cred *tcre
>  {
>  	u32 av = 0;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (!flags)
>  		return 0;
>  	if (flags & LSM_PRLIMIT_WRITE)
> @@ -4107,6 +4365,9 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
>  {
>  	struct rlimit *old_rlim = p->signal->rlim + resource;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	/* 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
> @@ -4121,6 +4382,9 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
>  
>  static int selinux_task_setscheduler(struct task_struct *p)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>  			    PROCESS__SETSCHED, NULL);
> @@ -4128,6 +4392,9 @@ static int selinux_task_setscheduler(struct task_struct *p)
>  
>  static int selinux_task_getscheduler(struct task_struct *p)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>  			    PROCESS__GETSCHED, NULL);
> @@ -4135,6 +4402,9 @@ static int selinux_task_getscheduler(struct task_struct *p)
>  
>  static int selinux_task_movememory(struct task_struct *p)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    current_sid(), task_sid(p), SECCLASS_PROCESS,
>  			    PROCESS__SETSCHED, NULL);
> @@ -4146,6 +4416,9 @@ static int selinux_task_kill(struct task_struct *p, struct kernel_siginfo *info,
>  	u32 secid;
>  	u32 perm;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (!sig)
>  		perm = PROCESS__SIGNULL; /* null signal; existence test */
>  	else
> @@ -4162,11 +4435,13 @@ static void selinux_task_to_inode(struct task_struct *p,
>  				  struct inode *inode)
>  {
>  	struct inode_security_struct *isec = selinux_inode(inode);
> -	u32 sid = task_sid(p);
> +
> +	if (selinux_disabled(&selinux_state))
> +		return;
>  
>  	spin_lock(&isec->lock);
>  	isec->sclass = inode_mode_to_security_class(inode->i_mode);
> -	isec->sid = sid;
> +	isec->sid = task_sid(p);
>  	isec->initialized = LABEL_INITIALIZED;
>  	spin_unlock(&isec->lock);
>  }
> @@ -4506,6 +4781,9 @@ static int selinux_socket_create(int family, int type,
>  	if (kern)
>  		return 0;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	secclass = socket_type_to_security_class(family, type, protocol);
>  	rc = socket_sockcreate_sid(tsec, secclass, &newsid);
>  	if (rc)
> @@ -4525,6 +4803,9 @@ static int selinux_socket_post_create(struct socket *sock, int family,
>  	u32 sid = SECINITSID_KERNEL;
>  	int err = 0;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (!kern) {
>  		err = socket_sockcreate_sid(tsec, sclass, &sid);
>  		if (err)
> @@ -4555,6 +4836,9 @@ static int selinux_socket_socketpair(struct socket *socka,
>  	struct sk_security_struct *sksec_a = socka->sk->sk_security;
>  	struct sk_security_struct *sksec_b = sockb->sk->sk_security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	sksec_a->peer_sid = sksec_b->sid;
>  	sksec_b->peer_sid = sksec_a->sid;
>  
> @@ -4572,6 +4856,9 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
>  	u16 family;
>  	int err;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	err = sock_has_perm(sk, SOCKET__BIND);
>  	if (err)
>  		goto out;
> @@ -4796,6 +5083,9 @@ static int selinux_socket_connect(struct socket *sock,
>  	int err;
>  	struct sock *sk = sock->sk;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	err = selinux_socket_connect_helper(sock, address, addrlen);
>  	if (err)
>  		return err;
> @@ -4805,6 +5095,9 @@ static int selinux_socket_connect(struct socket *sock,
>  
>  static int selinux_socket_listen(struct socket *sock, int backlog)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return sock_has_perm(sock->sk, SOCKET__LISTEN);
>  }
>  
> @@ -4816,6 +5109,9 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
>  	u16 sclass;
>  	u32 sid;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	err = sock_has_perm(sock->sk, SOCKET__ACCEPT);
>  	if (err)
>  		return err;
> @@ -4837,22 +5133,34 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
>  static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
>  				  int size)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return sock_has_perm(sock->sk, SOCKET__WRITE);
>  }
>  
>  static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
>  				  int size, int flags)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return sock_has_perm(sock->sk, SOCKET__READ);
>  }
>  
>  static int selinux_socket_getsockname(struct socket *sock)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return sock_has_perm(sock->sk, SOCKET__GETATTR);
>  }
>  
>  static int selinux_socket_getpeername(struct socket *sock)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return sock_has_perm(sock->sk, SOCKET__GETATTR);
>  }
>  
> @@ -4860,6 +5168,9 @@ static int selinux_socket_setsockopt(struct socket *sock, int level, int optname
>  {
>  	int err;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	err = sock_has_perm(sock->sk, SOCKET__SETOPT);
>  	if (err)
>  		return err;
> @@ -4870,11 +5181,17 @@ static int selinux_socket_setsockopt(struct socket *sock, int level, int optname
>  static int selinux_socket_getsockopt(struct socket *sock, int level,
>  				     int optname)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return sock_has_perm(sock->sk, SOCKET__GETOPT);
>  }
>  
>  static int selinux_socket_shutdown(struct socket *sock, int how)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return sock_has_perm(sock->sk, SOCKET__SHUTDOWN);
>  }
>  
> @@ -4889,6 +5206,9 @@ static int selinux_socket_unix_stream_connect(struct sock *sock,
>  	struct lsm_network_audit net = {0,};
>  	int err;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	ad.type = LSM_AUDIT_DATA_NET;
>  	ad.u.net = &net;
>  	ad.u.net->sk = other;
> @@ -4921,6 +5241,9 @@ static int selinux_socket_unix_may_send(struct socket *sock,
>  	struct common_audit_data ad;
>  	struct lsm_network_audit net = {0,};
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	ad.type = LSM_AUDIT_DATA_NET;
>  	ad.u.net = &net;
>  	ad.u.net->sk = other->sk;
> @@ -4994,13 +5317,15 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
>  	int err;
>  	struct sk_security_struct *sksec = sk->sk_security;
>  	u16 family = sk->sk_family;
> -	u32 sk_sid = sksec->sid;
>  	struct common_audit_data ad;
>  	struct lsm_network_audit net = {0,};
>  	char *addrp;
>  	u8 secmark_active;
>  	u8 peerlbl_active;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (family != PF_INET && family != PF_INET6)
>  		return 0;
>  
> @@ -5041,7 +5366,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
>  			return err;
>  		}
>  		err = avc_has_perm(&selinux_state,
> -				   sk_sid, peer_sid, SECCLASS_PEER,
> +				   sksec->sid, peer_sid, SECCLASS_PEER,
>  				   PEER__RECV, &ad);
>  		if (err) {
>  			selinux_netlbl_err(skb, family, err, 0);
> @@ -5051,7 +5376,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
>  
>  	if (secmark_active) {
>  		err = avc_has_perm(&selinux_state,
> -				   sk_sid, skb->secmark, SECCLASS_PACKET,
> +				   sksec->sid, skb->secmark, SECCLASS_PACKET,
>  				   PACKET__RECV, &ad);
>  		if (err)
>  			return err;
> @@ -5069,6 +5394,9 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op
>  	struct sk_security_struct *sksec = sock->sk->sk_security;
>  	u32 peer_sid = SECSID_NULL;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
>  	    sksec->sclass == SECCLASS_TCP_SOCKET ||
>  	    sksec->sclass == SECCLASS_SCTP_SOCKET)
> @@ -5102,6 +5430,9 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
>  	u16 family;
>  	struct inode_security_struct *isec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (skb && skb->protocol == htons(ETH_P_IP))
>  		family = PF_INET;
>  	else if (skb && skb->protocol == htons(ETH_P_IPV6))
> @@ -5128,6 +5459,9 @@ static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority
>  {
>  	struct sk_security_struct *sksec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	sksec = kzalloc(sizeof(*sksec), priority);
>  	if (!sksec)
>  		return -ENOMEM;
> @@ -5145,6 +5479,9 @@ static void selinux_sk_free_security(struct sock *sk)
>  {
>  	struct sk_security_struct *sksec = sk->sk_security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	sk->sk_security = NULL;
>  	selinux_netlbl_sk_security_free(sksec);
>  	kfree(sksec);
> @@ -5155,6 +5492,9 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
>  	struct sk_security_struct *sksec = sk->sk_security;
>  	struct sk_security_struct *newsksec = newsk->sk_security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	newsksec->sid = sksec->sid;
>  	newsksec->peer_sid = sksec->peer_sid;
>  	newsksec->sclass = sksec->sclass;
> @@ -5164,6 +5504,9 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
>  
>  static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	if (!sk)
>  		*secid = SECINITSID_ANY_SOCKET;
>  	else {
> @@ -5175,10 +5518,14 @@ static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
>  
>  static void selinux_sock_graft(struct sock *sk, struct socket *parent)
>  {
> -	struct inode_security_struct *isec =
> -		inode_security_novalidate(SOCK_INODE(parent));
> +	struct inode_security_struct *isec;
>  	struct sk_security_struct *sksec = sk->sk_security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
> +	isec = inode_security_novalidate(SOCK_INODE(parent));
> +
>  	if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
>  	    sk->sk_family == PF_UNIX)
>  		isec->sid = sksec->sid;
> @@ -5200,6 +5547,9 @@ static int selinux_sctp_assoc_request(struct sctp_endpoint *ep,
>  	u32 conn_sid;
>  	int err = 0;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (!selinux_policycap_extsockclass())
>  		return 0;
>  
> @@ -5270,6 +5620,9 @@ static int selinux_sctp_bind_connect(struct sock *sk, int optname,
>  	struct sockaddr *addr;
>  	struct socket *sock;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (!selinux_policycap_extsockclass())
>  		return 0;
>  
> @@ -5346,6 +5699,9 @@ static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk,
>  	struct sk_security_struct *sksec = sk->sk_security;
>  	struct sk_security_struct *newsksec = newsk->sk_security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	/* If policy does not support SECCLASS_SCTP_SOCKET then call
>  	 * the non-sctp clone version.
>  	 */
> @@ -5367,6 +5723,9 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
>  	u32 connsid;
>  	u32 peersid;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	err = selinux_skb_peerlbl_sid(skb, family, &peersid);
>  	if (err)
>  		return err;
> @@ -5384,6 +5743,9 @@ static void selinux_inet_csk_clone(struct sock *newsk,
>  {
>  	struct sk_security_struct *newsksec = newsk->sk_security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	newsksec->sid = req->secid;
>  	newsksec->peer_sid = req->peer_secid;
>  	/* NOTE: Ideally, we should also get the isec->sid for the
> @@ -5401,6 +5763,9 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
>  	u16 family = sk->sk_family;
>  	struct sk_security_struct *sksec = sk->sk_security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	/* handle mapped IPv4 packets arriving via IPv6 sockets */
>  	if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
>  		family = PF_INET;
> @@ -5413,6 +5778,9 @@ static int selinux_secmark_relabel_packet(u32 sid)
>  	const struct task_security_struct *__tsec;
>  	u32 tsid;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	__tsec = selinux_cred(current_cred());
>  	tsid = __tsec->sid;
>  
> @@ -5423,17 +5791,26 @@ static int selinux_secmark_relabel_packet(u32 sid)
>  
>  static void selinux_secmark_refcount_inc(void)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	atomic_inc(&selinux_secmark_refcount);
>  }
>  
>  static void selinux_secmark_refcount_dec(void)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	atomic_dec(&selinux_secmark_refcount);
>  }
>  
>  static void selinux_req_classify_flow(const struct request_sock *req,
>  				      struct flowi *fl)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	fl->flowi_secid = req->secid;
>  }
>  
> @@ -5441,6 +5818,9 @@ static int selinux_tun_dev_alloc_security(void **security)
>  {
>  	struct tun_security_struct *tunsec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
>  	if (!tunsec)
>  		return -ENOMEM;
> @@ -5452,12 +5832,20 @@ static int selinux_tun_dev_alloc_security(void **security)
>  
>  static void selinux_tun_dev_free_security(void *security)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	kfree(security);
>  }
>  
>  static int selinux_tun_dev_create(void)
>  {
> -	u32 sid = current_sid();
> +	u32 sid;
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	sid = current_sid();
>  
>  	/* we aren't taking into account the "sockcreate" SID since the socket
>  	 * that is being created here is not a socket in the traditional sense,
> @@ -5475,6 +5863,9 @@ static int selinux_tun_dev_attach_queue(void *security)
>  {
>  	struct tun_security_struct *tunsec = security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return avc_has_perm(&selinux_state,
>  			    current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
>  			    TUN_SOCKET__ATTACH_QUEUE, NULL);
> @@ -5485,6 +5876,9 @@ static int selinux_tun_dev_attach(struct sock *sk, void *security)
>  	struct tun_security_struct *tunsec = security;
>  	struct sk_security_struct *sksec = sk->sk_security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	/* we don't currently perform any NetLabel based labeling here and it
>  	 * isn't clear that we would want to do so anyway; while we could apply
>  	 * labeling without the support of the TUN user the resulting labeled
> @@ -5501,8 +5895,13 @@ static int selinux_tun_dev_attach(struct sock *sk, void *security)
>  static int selinux_tun_dev_open(void *security)
>  {
>  	struct tun_security_struct *tunsec = security;
> -	u32 sid = current_sid();
>  	int err;
> +	u32 sid;
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	sid = current_sid();
>  
>  	err = avc_has_perm(&selinux_state,
>  			   sid, tunsec->sid, SECCLASS_TUN_SOCKET,
> @@ -5885,6 +6284,9 @@ static unsigned int selinux_ipv6_postroute(void *priv,
>  
>  static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return selinux_nlmsg_perm(sk, skb);
>  }
>  
> @@ -5922,6 +6324,9 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
>  
>  static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return msg_msg_alloc_security(msg);
>  }
>  
> @@ -5930,9 +6335,11 @@ static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
>  {
>  	struct ipc_security_struct *isec;
>  	struct common_audit_data ad;
> -	u32 sid = current_sid();
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	isec = selinux_ipc(msq);
>  	ipc_init_security(isec, SECCLASS_MSGQ);
>  
> @@ -5940,7 +6347,7 @@ static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
>  	ad.u.ipc_id = msq->key;
>  
>  	rc = avc_has_perm(&selinux_state,
> -			  sid, isec->sid, SECCLASS_MSGQ,
> +			  current_sid(), isec->sid, SECCLASS_MSGQ,
>  			  MSGQ__CREATE, &ad);
>  	return rc;
>  }
> @@ -5949,7 +6356,9 @@ static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
>  {
>  	struct ipc_security_struct *isec;
>  	struct common_audit_data ad;
> -	u32 sid = current_sid();
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
>  	isec = selinux_ipc(msq);
>  
> @@ -5957,7 +6366,7 @@ static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
>  	ad.u.ipc_id = msq->key;
>  
>  	return avc_has_perm(&selinux_state,
> -			    sid, isec->sid, SECCLASS_MSGQ,
> +			    current_sid(), isec->sid, SECCLASS_MSGQ,
>  			    MSGQ__ASSOCIATE, &ad);
>  }
>  
> @@ -5966,6 +6375,9 @@ static int selinux_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd)
>  	int err;
>  	int perms;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	switch (cmd) {
>  	case IPC_INFO:
>  	case MSG_INFO:
> @@ -5997,9 +6409,14 @@ static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *m
>  	struct ipc_security_struct *isec;
>  	struct msg_security_struct *msec;
>  	struct common_audit_data ad;
> -	u32 sid = current_sid();
> +	u32 sid;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	sid = current_sid();
> +
>  	isec = selinux_ipc(msq);
>  	msec = selinux_msg_msg(msg);
>  
> @@ -6045,9 +6462,14 @@ static int selinux_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *m
>  	struct ipc_security_struct *isec;
>  	struct msg_security_struct *msec;
>  	struct common_audit_data ad;
> -	u32 sid = task_sid(target);
> +	u32 sid;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	sid = task_sid(target);
> +
>  	isec = selinux_ipc(msq);
>  	msec = selinux_msg_msg(msg);
>  
> @@ -6069,9 +6491,11 @@ static int selinux_shm_alloc_security(struct kern_ipc_perm *shp)
>  {
>  	struct ipc_security_struct *isec;
>  	struct common_audit_data ad;
> -	u32 sid = current_sid();
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	isec = selinux_ipc(shp);
>  	ipc_init_security(isec, SECCLASS_SHM);
>  
> @@ -6079,8 +6503,8 @@ static int selinux_shm_alloc_security(struct kern_ipc_perm *shp)
>  	ad.u.ipc_id = shp->key;
>  
>  	rc = avc_has_perm(&selinux_state,
> -			  sid, isec->sid, SECCLASS_SHM,
> -			  SHM__CREATE, &ad);
> +			  current_sid(), isec->sid,
> +			  SECCLASS_SHM, SHM__CREATE, &ad);
>  	return rc;
>  }
>  
> @@ -6088,7 +6512,9 @@ static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg)
>  {
>  	struct ipc_security_struct *isec;
>  	struct common_audit_data ad;
> -	u32 sid = current_sid();
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
>  	isec = selinux_ipc(shp);
>  
> @@ -6096,8 +6522,8 @@ static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg)
>  	ad.u.ipc_id = shp->key;
>  
>  	return avc_has_perm(&selinux_state,
> -			    sid, isec->sid, SECCLASS_SHM,
> -			    SHM__ASSOCIATE, &ad);
> +			    current_sid(), isec->sid,
> +			    SECCLASS_SHM, SHM__ASSOCIATE, &ad);
>  }
>  
>  /* Note, at this point, shp is locked down */
> @@ -6106,6 +6532,9 @@ static int selinux_shm_shmctl(struct kern_ipc_perm *shp, int cmd)
>  	int perms;
>  	int err;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	switch (cmd) {
>  	case IPC_INFO:
>  	case SHM_INFO:
> @@ -6141,6 +6570,9 @@ static int selinux_shm_shmat(struct kern_ipc_perm *shp,
>  {
>  	u32 perms;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (shmflg & SHM_RDONLY)
>  		perms = SHM__READ;
>  	else
> @@ -6154,9 +6586,11 @@ static int selinux_sem_alloc_security(struct kern_ipc_perm *sma)
>  {
>  	struct ipc_security_struct *isec;
>  	struct common_audit_data ad;
> -	u32 sid = current_sid();
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	isec = selinux_ipc(sma);
>  	ipc_init_security(isec, SECCLASS_SEM);
>  
> @@ -6164,8 +6598,8 @@ static int selinux_sem_alloc_security(struct kern_ipc_perm *sma)
>  	ad.u.ipc_id = sma->key;
>  
>  	rc = avc_has_perm(&selinux_state,
> -			  sid, isec->sid, SECCLASS_SEM,
> -			  SEM__CREATE, &ad);
> +			  current_sid(), isec->sid,
> +			  SECCLASS_SEM, SEM__CREATE, &ad);
>  	return rc;
>  }
>  
> @@ -6173,7 +6607,9 @@ static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg)
>  {
>  	struct ipc_security_struct *isec;
>  	struct common_audit_data ad;
> -	u32 sid = current_sid();
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
>  	isec = selinux_ipc(sma);
>  
> @@ -6181,8 +6617,8 @@ static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg)
>  	ad.u.ipc_id = sma->key;
>  
>  	return avc_has_perm(&selinux_state,
> -			    sid, isec->sid, SECCLASS_SEM,
> -			    SEM__ASSOCIATE, &ad);
> +			    current_sid(), isec->sid,
> +			    SECCLASS_SEM, SEM__ASSOCIATE, &ad);
>  }
>  
>  /* Note, at this point, sma is locked down */
> @@ -6191,6 +6627,9 @@ static int selinux_sem_semctl(struct kern_ipc_perm *sma, int cmd)
>  	int err;
>  	u32 perms;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	switch (cmd) {
>  	case IPC_INFO:
>  	case SEM_INFO:
> @@ -6235,6 +6674,9 @@ static int selinux_sem_semop(struct kern_ipc_perm *sma,
>  {
>  	u32 perms;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (alter)
>  		perms = SEM__READ | SEM__WRITE;
>  	else
> @@ -6247,7 +6689,9 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
>  {
>  	u32 av = 0;
>  
> -	av = 0;
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (flag & S_IRUGO)
>  		av |= IPC__UNIX_READ;
>  	if (flag & S_IWUGO)
> @@ -6261,12 +6705,17 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
>  
>  static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
>  {
> -	struct ipc_security_struct *isec = selinux_ipc(ipcp);
> -	*secid = isec->sid;
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
> +	*secid = selinux_ipc(ipcp)->sid;
>  }
>  
>  static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	if (inode)
>  		inode_doinit_with_dentry(inode, dentry);
>  }
> @@ -6279,6 +6728,9 @@ static int selinux_getprocattr(struct task_struct *p,
>  	int error;
>  	unsigned len;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return -EINVAL;
> +
>  	rcu_read_lock();
>  	__tsec = selinux_cred(__task_cred(p));
>  
> @@ -6325,10 +6777,15 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)
>  {
>  	struct task_security_struct *tsec;
>  	struct cred *new;
> -	u32 mysid = current_sid(), sid = 0, ptsid;
> +	u32 mysid, sid = 0, ptsid;
>  	int error;
>  	char *str = value;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return -EINVAL;
> +
> +	mysid = current_sid();
> +
>  	/*
>  	 * Basic control over ability to set these attributes at all.
>  	 */
> @@ -6466,17 +6923,26 @@ abort_change:
>  
>  static int selinux_ismaclabel(const char *name)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
>  }
>  
>  static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return -EOPNOTSUPP;
> +
>  	return security_sid_to_context(&selinux_state, secid,
>  				       secdata, seclen);
>  }
>  
>  static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return security_context_to_sid(&selinux_state, secdata, seclen,
>  				       secid, GFP_KERNEL);
>  }
> @@ -6490,6 +6956,9 @@ static void selinux_inode_invalidate_secctx(struct inode *inode)
>  {
>  	struct inode_security_struct *isec = selinux_inode(inode);
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	spin_lock(&isec->lock);
>  	isec->initialized = LABEL_INVALID;
>  	spin_unlock(&isec->lock);
> @@ -6511,6 +6980,9 @@ static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen
>   */
>  static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
>  }
>  
> @@ -6532,6 +7004,9 @@ static int selinux_key_alloc(struct key *k, const struct cred *cred,
>  	const struct task_security_struct *tsec;
>  	struct key_security_struct *ksec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
>  	if (!ksec)
>  		return -ENOMEM;
> @@ -6550,6 +7025,9 @@ static void selinux_key_free(struct key *k)
>  {
>  	struct key_security_struct *ksec = k->security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	k->security = NULL;
>  	kfree(ksec);
>  }
> @@ -6568,6 +7046,9 @@ static int selinux_key_permission(key_ref_t key_ref,
>  	if (perm == 0)
>  		return 0;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	sid = cred_sid(cred);
>  
>  	key = key_ref_to_ptr(key_ref);
> @@ -6584,6 +7065,9 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)
>  	unsigned len;
>  	int rc;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	rc = security_sid_to_context(&selinux_state, ksec->sid,
>  				     &context, &len);
>  	if (!rc)
> @@ -6602,6 +7086,9 @@ static int selinux_ib_pkey_access(void *ib_sec, u64 subnet_prefix, u16 pkey_val)
>  	struct ib_security_struct *sec = ib_sec;
>  	struct lsm_ibpkey_audit ibpkey;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	err = sel_ib_pkey_sid(subnet_prefix, pkey_val, &sid);
>  	if (err)
>  		return err;
> @@ -6625,6 +7112,9 @@ static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name,
>  	struct ib_security_struct *sec = ib_sec;
>  	struct lsm_ibendport_audit ibendport;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	err = security_ib_endport_sid(&selinux_state, dev_name, port_num,
>  				      &sid);
>  
> @@ -6645,6 +7135,9 @@ static int selinux_ib_alloc_security(void **ib_sec)
>  {
>  	struct ib_security_struct *sec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	sec = kzalloc(sizeof(*sec), GFP_KERNEL);
>  	if (!sec)
>  		return -ENOMEM;
> @@ -6656,6 +7149,9 @@ static int selinux_ib_alloc_security(void **ib_sec)
>  
>  static void selinux_ib_free_security(void *ib_sec)
>  {
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	kfree(ib_sec);
>  }
>  #endif
> @@ -6667,6 +7163,9 @@ static int selinux_bpf(int cmd, union bpf_attr *attr,
>  	u32 sid = current_sid();
>  	int ret;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	switch (cmd) {
>  	case BPF_MAP_CREATE:
>  		ret = avc_has_perm(&selinux_state,
> @@ -6734,23 +7233,27 @@ static int bpf_fd_pass(struct file *file, u32 sid)
>  
>  static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode)
>  {
> -	u32 sid = current_sid();
>  	struct bpf_security_struct *bpfsec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	bpfsec = map->security;
>  	return avc_has_perm(&selinux_state,
> -			    sid, bpfsec->sid, SECCLASS_BPF,
> +			    current_sid(), bpfsec->sid, SECCLASS_BPF,
>  			    bpf_map_fmode_to_av(fmode), NULL);
>  }
>  
>  static int selinux_bpf_prog(struct bpf_prog *prog)
>  {
> -	u32 sid = current_sid();
>  	struct bpf_security_struct *bpfsec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	bpfsec = prog->aux->security;
>  	return avc_has_perm(&selinux_state,
> -			    sid, bpfsec->sid, SECCLASS_BPF,
> +			    current_sid(), bpfsec->sid, SECCLASS_BPF,
>  			    BPF__PROG_RUN, NULL);
>  }
>  
> @@ -6758,6 +7261,9 @@ static int selinux_bpf_map_alloc(struct bpf_map *map)
>  {
>  	struct bpf_security_struct *bpfsec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
>  	if (!bpfsec)
>  		return -ENOMEM;
> @@ -6772,6 +7278,9 @@ static void selinux_bpf_map_free(struct bpf_map *map)
>  {
>  	struct bpf_security_struct *bpfsec = map->security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	map->security = NULL;
>  	kfree(bpfsec);
>  }
> @@ -6780,6 +7289,9 @@ static int selinux_bpf_prog_alloc(struct bpf_prog_aux *aux)
>  {
>  	struct bpf_security_struct *bpfsec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
>  	if (!bpfsec)
>  		return -ENOMEM;
> @@ -6794,6 +7306,9 @@ static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
>  {
>  	struct bpf_security_struct *bpfsec = aux->security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	aux->security = NULL;
>  	kfree(bpfsec);
>  }
> @@ -6802,11 +7317,14 @@ static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
>  static int selinux_lockdown(enum lockdown_reason what)
>  {
>  	struct common_audit_data ad;
> -	u32 sid = current_sid();
> +	u32 sid;
>  	int invalid_reason = (what <= LOCKDOWN_NONE) ||
>  			     (what == LOCKDOWN_INTEGRITY_MAX) ||
>  			     (what >= LOCKDOWN_CONFIDENTIALITY_MAX);
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	if (WARN(invalid_reason, "Invalid lockdown reason")) {
>  		audit_log(audit_context(),
>  			  GFP_ATOMIC, AUDIT_SELINUX_ERR,
> @@ -6814,6 +7332,8 @@ static int selinux_lockdown(enum lockdown_reason what)
>  		return -EINVAL;
>  	}
>  
> +	sid = current_sid();
> +
>  	ad.type = LSM_AUDIT_DATA_LOCKDOWN;
>  	ad.u.reason = what;
>  
> @@ -6827,7 +7347,7 @@ static int selinux_lockdown(enum lockdown_reason what)
>  				    LOCKDOWN__CONFIDENTIALITY, &ad);
>  }
>  
> -struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = {
> +struct lsm_blob_sizes selinux_blob_sizes __ro_after_init = {
>  	.lbs_cred = sizeof(struct task_security_struct),
>  	.lbs_file = sizeof(struct file_security_struct),
>  	.lbs_inode = sizeof(struct inode_security_struct),
> @@ -6838,7 +7358,12 @@ struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = {
>  #ifdef CONFIG_PERF_EVENTS
>  static int selinux_perf_event_open(struct perf_event_attr *attr, int type)
>  {
> -	u32 requested, sid = current_sid();
> +	u32 requested, sid;
> +
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	sid = current_sid();
>  
>  	if (type == PERF_SECURITY_OPEN)
>  		requested = PERF_EVENT__OPEN;
> @@ -6859,6 +7384,9 @@ static int selinux_perf_event_alloc(struct perf_event *event)
>  {
>  	struct perf_event_security_struct *perfsec;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
>  	perfsec = kzalloc(sizeof(*perfsec), GFP_KERNEL);
>  	if (!perfsec)
>  		return -ENOMEM;
> @@ -6873,6 +7401,9 @@ static void selinux_perf_event_free(struct perf_event *event)
>  {
>  	struct perf_event_security_struct *perfsec = event->security;
>  
> +	if (selinux_disabled(&selinux_state))
> +		return;
> +
>  	event->security = NULL;
>  	kfree(perfsec);
>  }
> @@ -6880,23 +7411,27 @@ static void selinux_perf_event_free(struct perf_event *event)
>  static int selinux_perf_event_read(struct perf_event *event)
>  {
>  	struct perf_event_security_struct *perfsec = event->security;
> -	u32 sid = current_sid();
>  
> -	return avc_has_perm(&selinux_state, sid, perfsec->sid,
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	return avc_has_perm(&selinux_state, current_sid(), perfsec->sid,
>  			    SECCLASS_PERF_EVENT, PERF_EVENT__READ, NULL);
>  }
>  
>  static int selinux_perf_event_write(struct perf_event *event)
>  {
>  	struct perf_event_security_struct *perfsec = event->security;
> -	u32 sid = current_sid();
>  
> -	return avc_has_perm(&selinux_state, sid, perfsec->sid,
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
> +
> +	return avc_has_perm(&selinux_state, current_sid(), perfsec->sid,
>  			    SECCLASS_PERF_EVENT, PERF_EVENT__WRITE, NULL);
>  }
>  #endif
>  
> -static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
> +static struct security_hook_list selinux_hooks[] __ro_after_init = {
>  	LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
>  	LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
>  	LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
> @@ -7315,18 +7850,19 @@ int selinux_disable(struct selinux_state *state)
>  		return -EINVAL;
>  	}
>  
> +	/*
> +	 * Unregister netfilter hooks (must be done before
> +	 * selinux_mark_disabled()).
> +	 */
> +	selinux_nf_ip_exit();
> +
>  	selinux_mark_disabled(state);
>  
>  	pr_info("SELinux:  Disabled at runtime.\n");
>  
> -	security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
> -
>  	/* Try to destroy the avc node cache */
>  	avc_disable();
>  
> -	/* Unregister netfilter hooks. */
> -	selinux_nf_ip_exit();
> -
>  	/* Unregister selinuxfs. */
>  	exit_sel_fs();
>  
> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> index ecea41ce919b..de50c69846e0 100644
> --- a/security/smack/smack_lsm.c
> +++ b/security/smack/smack_lsm.c
> @@ -4583,7 +4583,7 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode,
>  	return 0;
>  }
>  
> -struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
> +struct lsm_blob_sizes smack_blob_sizes __ro_after_init = {
>  	.lbs_cred = sizeof(struct task_smack),
>  	.lbs_file = sizeof(struct smack_known *),
>  	.lbs_inode = sizeof(struct inode_smack),
> @@ -4591,7 +4591,7 @@ struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
>  	.lbs_msg_msg = sizeof(struct smack_known *),
>  };
>  
> -static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
> +static struct security_hook_list smack_hooks[] __ro_after_init = {
>  	LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check),
>  	LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme),
>  	LSM_HOOK_INIT(syslog, smack_syslog),
> diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
> index 716c92ec941a..9dcdef99d431 100644
> --- a/security/tomoyo/tomoyo.c
> +++ b/security/tomoyo/tomoyo.c
> @@ -486,7 +486,7 @@ static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg,
>  	return tomoyo_socket_sendmsg_permission(sock, msg, size);
>  }
>  
> -struct lsm_blob_sizes tomoyo_blob_sizes __lsm_ro_after_init = {
> +struct lsm_blob_sizes tomoyo_blob_sizes __ro_after_init = {
>  	.lbs_task = sizeof(struct tomoyo_task),
>  };
>  
> @@ -533,7 +533,7 @@ static void tomoyo_task_free(struct task_struct *task)
>   * tomoyo_security_ops is a "struct security_operations" which is used for
>   * registering TOMOYO.
>   */
> -static struct security_hook_list tomoyo_hooks[] __lsm_ro_after_init = {
> +static struct security_hook_list tomoyo_hooks[] __ro_after_init = {
>  	LSM_HOOK_INIT(cred_prepare, tomoyo_cred_prepare),
>  	LSM_HOOK_INIT(bprm_committed_creds, tomoyo_bprm_committed_creds),
>  	LSM_HOOK_INIT(task_alloc, tomoyo_task_alloc),
> @@ -569,7 +569,7 @@ static struct security_hook_list tomoyo_hooks[] __lsm_ro_after_init = {
>  /* Lock for GC. */
>  DEFINE_SRCU(tomoyo_ss);
>  
> -int tomoyo_enabled __lsm_ro_after_init = 1;
> +int tomoyo_enabled __ro_after_init = 1;
>  
>  /**
>   * tomoyo_init - Register TOMOYO Linux as a LSM module.
> diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
> index 94dc346370b1..c47d4e09bfb4 100644
> --- a/security/yama/yama_lsm.c
> +++ b/security/yama/yama_lsm.c
> @@ -421,7 +421,7 @@ static int yama_ptrace_traceme(struct task_struct *parent)
>  	return rc;
>  }
>  
> -static struct security_hook_list yama_hooks[] __lsm_ro_after_init = {
> +static struct security_hook_list yama_hooks[] __ro_after_init = {
>  	LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check),
>  	LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme),
>  	LSM_HOOK_INIT(task_prctl, yama_task_prctl),
> -- 
> 2.24.1
> 

-- 
Kees Cook

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

* Re: [PATCH 1/2] selinux: treat atomic flags more carefully
  2020-01-07 13:31 ` [PATCH 1/2] selinux: treat atomic flags more carefully Ondrej Mosnacek
  2020-01-07 14:45   ` Stephen Smalley
  2020-01-07 18:09   ` Kees Cook
@ 2020-01-07 19:45   ` James Morris
  2020-01-10 20:22     ` Paul Moore
  2020-01-10 20:21   ` Paul Moore
  3 siblings, 1 reply; 18+ messages in thread
From: James Morris @ 2020-01-07 19:45 UTC (permalink / raw)
  To: Ondrej Mosnacek
  Cc: linux-security-module, Serge E. Hallyn, Casey Schaufler, selinux,
	Paul Moore, Stephen Smalley, John Johansen, Kees Cook,
	Micah Morton, Tetsuo Handa

On Tue, 7 Jan 2020, Ondrej Mosnacek wrote:

> The disabled/enforcing/initialized flags are all accessed concurrently
> by threads so use the appropriate accessors that ensure atomicity and
> document that it is expected.
> 
> Use smp_load/acquire...() helpers (with memory barriers) for the
> initialized flag, since it gates access to the rest of the state
> structures.
> 
> Note that the disabled flag is currently not used for anything other
> than avoiding double disable, but it will be used for bailing out of
> hooks once security_delete_hooks() is removed.
> 
> Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>


Reviewed-by: James Morris <jamorris@linux.microsoft.com>

-- 
James Morris
<jmorris@namei.org>


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

* Re: [PATCH 2/2] security,selinux: get rid of security_delete_hooks()
  2020-01-07 13:31 ` [PATCH 2/2] security,selinux: get rid of security_delete_hooks() Ondrej Mosnacek
                     ` (2 preceding siblings ...)
  2020-01-07 18:10   ` Kees Cook
@ 2020-01-07 19:59   ` James Morris
  2020-01-08  8:21     ` Ondrej Mosnacek
  3 siblings, 1 reply; 18+ messages in thread
From: James Morris @ 2020-01-07 19:59 UTC (permalink / raw)
  To: Ondrej Mosnacek
  Cc: linux-security-module, Serge E. Hallyn, Casey Schaufler, selinux,
	Paul Moore, Stephen Smalley, John Johansen, Kees Cook,
	Micah Morton, Tetsuo Handa

On Tue, 7 Jan 2020, Ondrej Mosnacek wrote:

> The only user is SELinux, which is hereby converted to check the
> disabled flag in each hook instead of removing the hooks from the list.
> 
> The __lsm_ro_after_init macro is now removed and replaced with
> __ro_after_init directly.
> 
> This fixes a race condition in SELinux runtime disable, which was
> introduced with the switch to hook lists in b1d9e6b0646d ("LSM: Switch
> to lists of hooks").
> 
> Suggested-by: Stephen Smalley <sds@tycho.nsa.gov>
> Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
> ---
>  include/linux/lsm_hooks.h    |  31 --
>  security/Kconfig             |   5 -
>  security/apparmor/lsm.c      |   6 +-
>  security/commoncap.c         |   2 +-
>  security/loadpin/loadpin.c   |   2 +-
>  security/lockdown/lockdown.c |   2 +-
>  security/security.c          |   5 +-
>  security/selinux/Kconfig     |   6 -
>  security/selinux/hooks.c     | 742 ++++++++++++++++++++++++++++++-----
>  security/smack/smack_lsm.c   |   4 +-
>  security/tomoyo/tomoyo.c     |   6 +-
>  security/yama/yama_lsm.c     |   2 +-
>  12 files changed, 654 insertions(+), 159 deletions(-)

Please separate the changes for each LSM into separate patches (the 
__lsm_ro_after_init removal patch can be last).

>  config SECURITY_SELINUX_DEVELOP
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 47ad4db925cf..9ac2b6b69ff9 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -650,13 +650,15 @@ static int selinux_set_mnt_opts(struct super_block *sb,
>  {
>  	const struct cred *cred = current_cred();
>  	struct superblock_security_struct *sbsec = sb->s_security;
> -	struct dentry *root = sbsec->sb->s_root;
>  	struct selinux_mnt_opts *opts = mnt_opts;

Seems like there are a bunch of unrelated cleanups mixed in here.

> -	int set_fscontext =	(oldsbsec->flags & FSCONTEXT_MNT);
> -	int set_context =	(oldsbsec->flags & CONTEXT_MNT);
> -	int set_rootcontext =	(oldsbsec->flags & ROOTCONTEXT_MNT);
> +	set_fscontext =		(oldsbsec->flags & FSCONTEXT_MNT);
> +	set_context =		(oldsbsec->flags & CONTEXT_MNT);
> +	set_rootcontext =	(oldsbsec->flags & ROOTCONTEXT_MNT);
>  

...

>  static int selinux_binder_set_context_mgr(struct task_struct *mgr)
>  {
> -	u32 mysid = current_sid();
> -	u32 mgrsid = task_sid(mgr);
> +	if (selinux_disabled(&selinux_state))
> +		return 0;
>  
>  	return avc_has_perm(&selinux_state,
> -			    mysid, mgrsid, SECCLASS_BINDER,
> +			    current_sid(), task_sid(mgr), SECCLASS_BINDER,
>  			    BINDER__SET_CONTEXT_MGR, NULL);
>  }
>  

Ditto, etc.

Please don't do this.


-- 
James Morris
<jmorris@namei.org>


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

* Re: [PATCH 2/2] security, selinux: get rid of security_delete_hooks()
  2020-01-07 14:47   ` [PATCH 2/2] security, selinux: " Stephen Smalley
@ 2020-01-08  5:31     ` Paul Moore
  2020-01-08  8:15       ` Ondrej Mosnacek
  2020-01-08 14:49       ` Stephen Smalley
  0 siblings, 2 replies; 18+ messages in thread
From: Paul Moore @ 2020-01-08  5:31 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Ondrej Mosnacek, linux-security-module, James Morris,
	Serge E. Hallyn, Casey Schaufler, selinux, John Johansen,
	Kees Cook, Micah Morton, Tetsuo Handa

On Tue, Jan 7, 2020 at 9:46 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
> On 1/7/20 8:31 AM, Ondrej Mosnacek wrote:
> > The only user is SELinux, which is hereby converted to check the
> > disabled flag in each hook instead of removing the hooks from the list.
> >
> > The __lsm_ro_after_init macro is now removed and replaced with
> > __ro_after_init directly.
> >
> > This fixes a race condition in SELinux runtime disable, which was
> > introduced with the switch to hook lists in b1d9e6b0646d ("LSM: Switch
> > to lists of hooks").
>
> Not opposed (naturally, since I suggested it) but my impression from the
> earlier thread was that Paul preferred the less invasive approach of
> your original patch (just reordering the hooks) as a short term fix with
> an eye toward full removal of disable support in the not-too-distant future.

Unless we are seeing wide spread breakages (I don't think we are), or
we decide we can never remove the runtime disable, I still prefer the
hook-shuffle over the changes proposed in this patchset.

-- 
paul moore
www.paul-moore.com

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

* Re: [PATCH 2/2] security, selinux: get rid of security_delete_hooks()
  2020-01-08  5:31     ` Paul Moore
@ 2020-01-08  8:15       ` Ondrej Mosnacek
  2020-01-08 13:45         ` Paul Moore
  2020-01-08 14:49       ` Stephen Smalley
  1 sibling, 1 reply; 18+ messages in thread
From: Ondrej Mosnacek @ 2020-01-08  8:15 UTC (permalink / raw)
  To: Paul Moore
  Cc: Stephen Smalley, Linux Security Module list, James Morris,
	Serge E. Hallyn, Casey Schaufler, SElinux list, John Johansen,
	Kees Cook, Micah Morton, Tetsuo Handa

On Wed, Jan 8, 2020 at 6:32 AM Paul Moore <paul@paul-moore.com> wrote:
> On Tue, Jan 7, 2020 at 9:46 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
> > On 1/7/20 8:31 AM, Ondrej Mosnacek wrote:
> > > The only user is SELinux, which is hereby converted to check the
> > > disabled flag in each hook instead of removing the hooks from the list.
> > >
> > > The __lsm_ro_after_init macro is now removed and replaced with
> > > __ro_after_init directly.
> > >
> > > This fixes a race condition in SELinux runtime disable, which was
> > > introduced with the switch to hook lists in b1d9e6b0646d ("LSM: Switch
> > > to lists of hooks").
> >
> > Not opposed (naturally, since I suggested it) but my impression from the
> > earlier thread was that Paul preferred the less invasive approach of
> > your original patch (just reordering the hooks) as a short term fix with
> > an eye toward full removal of disable support in the not-too-distant future.
>
> Unless we are seeing wide spread breakages (I don't think we are), or
> we decide we can never remove the runtime disable, I still prefer the
> hook-shuffle over the changes proposed in this patchset.

OK, I'm fine with either solution. Do you want me to rebase and resend
the reorder patch? There are some minor conflicts with Stephen's
recently merged patches.

-- 
Ondrej Mosnacek <omosnace at redhat dot com>
Software Engineer, Security Technologies
Red Hat, Inc.


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

* Re: [PATCH 2/2] security,selinux: get rid of security_delete_hooks()
  2020-01-07 19:59   ` James Morris
@ 2020-01-08  8:21     ` Ondrej Mosnacek
  2020-01-08 18:47       ` James Morris
  0 siblings, 1 reply; 18+ messages in thread
From: Ondrej Mosnacek @ 2020-01-08  8:21 UTC (permalink / raw)
  To: James Morris
  Cc: Linux Security Module list, Serge E. Hallyn, Casey Schaufler,
	SElinux list, Paul Moore, Stephen Smalley, John Johansen,
	Kees Cook, Micah Morton, Tetsuo Handa

On Tue, Jan 7, 2020 at 9:00 PM James Morris <jmorris@namei.org> wrote:
> On Tue, 7 Jan 2020, Ondrej Mosnacek wrote:
>
> > The only user is SELinux, which is hereby converted to check the
> > disabled flag in each hook instead of removing the hooks from the list.
> >
> > The __lsm_ro_after_init macro is now removed and replaced with
> > __ro_after_init directly.
> >
> > This fixes a race condition in SELinux runtime disable, which was
> > introduced with the switch to hook lists in b1d9e6b0646d ("LSM: Switch
> > to lists of hooks").
> >
> > Suggested-by: Stephen Smalley <sds@tycho.nsa.gov>
> > Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
> > ---
> >  include/linux/lsm_hooks.h    |  31 --
> >  security/Kconfig             |   5 -
> >  security/apparmor/lsm.c      |   6 +-
> >  security/commoncap.c         |   2 +-
> >  security/loadpin/loadpin.c   |   2 +-
> >  security/lockdown/lockdown.c |   2 +-
> >  security/security.c          |   5 +-
> >  security/selinux/Kconfig     |   6 -
> >  security/selinux/hooks.c     | 742 ++++++++++++++++++++++++++++++-----
> >  security/smack/smack_lsm.c   |   4 +-
> >  security/tomoyo/tomoyo.c     |   6 +-
> >  security/yama/yama_lsm.c     |   2 +-
> >  12 files changed, 654 insertions(+), 159 deletions(-)
>
> Please separate the changes for each LSM into separate patches (the
> __lsm_ro_after_init removal patch can be last).
>
> >  config SECURITY_SELINUX_DEVELOP
> > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> > index 47ad4db925cf..9ac2b6b69ff9 100644
> > --- a/security/selinux/hooks.c
> > +++ b/security/selinux/hooks.c
> > @@ -650,13 +650,15 @@ static int selinux_set_mnt_opts(struct super_block *sb,
> >  {
> >       const struct cred *cred = current_cred();
> >       struct superblock_security_struct *sbsec = sb->s_security;
> > -     struct dentry *root = sbsec->sb->s_root;
> >       struct selinux_mnt_opts *opts = mnt_opts;
>
> Seems like there are a bunch of unrelated cleanups mixed in here.

These are not unrelated - we need to avoid dereferencing the security
structs before checking selinux_disabled(), because they may be NULL
or uninitialized when SELinux has been diabled.

-- 
Ondrej Mosnacek <omosnace at redhat dot com>
Software Engineer, Security Technologies
Red Hat, Inc.


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

* Re: [PATCH 2/2] security, selinux: get rid of security_delete_hooks()
  2020-01-08  8:15       ` Ondrej Mosnacek
@ 2020-01-08 13:45         ` Paul Moore
  0 siblings, 0 replies; 18+ messages in thread
From: Paul Moore @ 2020-01-08 13:45 UTC (permalink / raw)
  To: Ondrej Mosnacek
  Cc: Stephen Smalley, Linux Security Module list, James Morris,
	Serge E. Hallyn, Casey Schaufler, SElinux list, John Johansen,
	Kees Cook, Micah Morton, Tetsuo Handa

On Wed, Jan 8, 2020 at 3:15 AM Ondrej Mosnacek <omosnace@redhat.com> wrote:
> On Wed, Jan 8, 2020 at 6:32 AM Paul Moore <paul@paul-moore.com> wrote:
> > On Tue, Jan 7, 2020 at 9:46 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
> > > On 1/7/20 8:31 AM, Ondrej Mosnacek wrote:
> > > > The only user is SELinux, which is hereby converted to check the
> > > > disabled flag in each hook instead of removing the hooks from the list.
> > > >
> > > > The __lsm_ro_after_init macro is now removed and replaced with
> > > > __ro_after_init directly.
> > > >
> > > > This fixes a race condition in SELinux runtime disable, which was
> > > > introduced with the switch to hook lists in b1d9e6b0646d ("LSM: Switch
> > > > to lists of hooks").
> > >
> > > Not opposed (naturally, since I suggested it) but my impression from the
> > > earlier thread was that Paul preferred the less invasive approach of
> > > your original patch (just reordering the hooks) as a short term fix with
> > > an eye toward full removal of disable support in the not-too-distant future.
> >
> > Unless we are seeing wide spread breakages (I don't think we are), or
> > we decide we can never remove the runtime disable, I still prefer the
> > hook-shuffle over the changes proposed in this patchset.
>
> OK, I'm fine with either solution. Do you want me to rebase and resend
> the reorder patch? There are some minor conflicts with Stephen's
> recently merged patches.

Yes please.

-- 
paul moore
www.paul-moore.com

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

* Re: [PATCH 2/2] security, selinux: get rid of security_delete_hooks()
  2020-01-08  5:31     ` Paul Moore
  2020-01-08  8:15       ` Ondrej Mosnacek
@ 2020-01-08 14:49       ` Stephen Smalley
  1 sibling, 0 replies; 18+ messages in thread
From: Stephen Smalley @ 2020-01-08 14:49 UTC (permalink / raw)
  To: Paul Moore
  Cc: Ondrej Mosnacek, linux-security-module, James Morris,
	Serge E. Hallyn, Casey Schaufler, selinux, John Johansen,
	Kees Cook, Micah Morton, Tetsuo Handa

On 1/8/20 12:31 AM, Paul Moore wrote:
> On Tue, Jan 7, 2020 at 9:46 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
>> On 1/7/20 8:31 AM, Ondrej Mosnacek wrote:
>>> The only user is SELinux, which is hereby converted to check the
>>> disabled flag in each hook instead of removing the hooks from the list.
>>>
>>> The __lsm_ro_after_init macro is now removed and replaced with
>>> __ro_after_init directly.
>>>
>>> This fixes a race condition in SELinux runtime disable, which was
>>> introduced with the switch to hook lists in b1d9e6b0646d ("LSM: Switch
>>> to lists of hooks").
>>
>> Not opposed (naturally, since I suggested it) but my impression from the
>> earlier thread was that Paul preferred the less invasive approach of
>> your original patch (just reordering the hooks) as a short term fix with
>> an eye toward full removal of disable support in the not-too-distant future.
> 
> Unless we are seeing wide spread breakages (I don't think we are), or
> we decide we can never remove the runtime disable, I still prefer the
> hook-shuffle over the changes proposed in this patchset.

Note that the first patch is a necessary and correct cleanup regardless 
of this one.



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

* Re: [PATCH 2/2] security,selinux: get rid of security_delete_hooks()
  2020-01-08  8:21     ` Ondrej Mosnacek
@ 2020-01-08 18:47       ` James Morris
  0 siblings, 0 replies; 18+ messages in thread
From: James Morris @ 2020-01-08 18:47 UTC (permalink / raw)
  To: Ondrej Mosnacek
  Cc: Linux Security Module list, Serge E. Hallyn, Casey Schaufler,
	SElinux list, Paul Moore, Stephen Smalley, John Johansen,
	Kees Cook, Micah Morton, Tetsuo Handa

On Wed, 8 Jan 2020, Ondrej Mosnacek wrote:

> > >  {
> > >       const struct cred *cred = current_cred();
> > >       struct superblock_security_struct *sbsec = sb->s_security;
> > > -     struct dentry *root = sbsec->sb->s_root;
> > >       struct selinux_mnt_opts *opts = mnt_opts;
> >
> > Seems like there are a bunch of unrelated cleanups mixed in here.
> 
> These are not unrelated - we need to avoid dereferencing the security
> structs before checking selinux_disabled(), because they may be NULL
> or uninitialized when SELinux has been diabled.

Ok.

-- 
James Morris
<jmorris@namei.org>


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

* Re: [PATCH 1/2] selinux: treat atomic flags more carefully
  2020-01-07 13:31 ` [PATCH 1/2] selinux: treat atomic flags more carefully Ondrej Mosnacek
                     ` (2 preceding siblings ...)
  2020-01-07 19:45   ` James Morris
@ 2020-01-10 20:21   ` Paul Moore
  3 siblings, 0 replies; 18+ messages in thread
From: Paul Moore @ 2020-01-10 20:21 UTC (permalink / raw)
  To: Ondrej Mosnacek
  Cc: linux-security-module, James Morris, Serge E. Hallyn,
	Casey Schaufler, selinux, Stephen Smalley, John Johansen,
	Kees Cook, Micah Morton, Tetsuo Handa

On Tue, Jan 7, 2020 at 8:32 AM Ondrej Mosnacek <omosnace@redhat.com> wrote:
> The disabled/enforcing/initialized flags are all accessed concurrently
> by threads so use the appropriate accessors that ensure atomicity and
> document that it is expected.
>
> Use smp_load/acquire...() helpers (with memory barriers) for the
> initialized flag, since it gates access to the rest of the state
> structures.
>
> Note that the disabled flag is currently not used for anything other
> than avoiding double disable, but it will be used for bailing out of
> hooks once security_delete_hooks() is removed.
>
> Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
> ---
>  security/selinux/hooks.c            | 21 ++++++++--------
>  security/selinux/include/security.h | 33 +++++++++++++++++++++++--
>  security/selinux/ss/services.c      | 38 ++++++++++++++---------------
>  3 files changed, 61 insertions(+), 31 deletions(-)

Merged into selinux/next, thanks Ondrej!

-- 
paul moore
www.paul-moore.com

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

* Re: [PATCH 1/2] selinux: treat atomic flags more carefully
  2020-01-07 19:45   ` James Morris
@ 2020-01-10 20:22     ` Paul Moore
  0 siblings, 0 replies; 18+ messages in thread
From: Paul Moore @ 2020-01-10 20:22 UTC (permalink / raw)
  To: James Morris
  Cc: Ondrej Mosnacek, linux-security-module, Serge E. Hallyn,
	Casey Schaufler, selinux, Stephen Smalley, John Johansen,
	Kees Cook, Micah Morton, Tetsuo Handa

On Tue, Jan 7, 2020 at 2:46 PM James Morris <jmorris@namei.org> wrote:
> On Tue, 7 Jan 2020, Ondrej Mosnacek wrote:
>
> > The disabled/enforcing/initialized flags are all accessed concurrently
> > by threads so use the appropriate accessors that ensure atomicity and
> > document that it is expected.
> >
> > Use smp_load/acquire...() helpers (with memory barriers) for the
> > initialized flag, since it gates access to the rest of the state
> > structures.
> >
> > Note that the disabled flag is currently not used for anything other
> > than avoiding double disable, but it will be used for bailing out of
> > hooks once security_delete_hooks() is removed.
> >
> > Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
>
>
> Reviewed-by: James Morris <jamorris@linux.microsoft.com>

You get an extra helping of gratitude James for being the only one to
properly trim your reply ;)

-- 
paul moore
www.paul-moore.com

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

end of thread, other threads:[~2020-01-10 20:23 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-07 13:31 [PATCH 0/2] LSM: Drop security_delete_hooks() Ondrej Mosnacek
2020-01-07 13:31 ` [PATCH 1/2] selinux: treat atomic flags more carefully Ondrej Mosnacek
2020-01-07 14:45   ` Stephen Smalley
2020-01-07 18:09   ` Kees Cook
2020-01-07 19:45   ` James Morris
2020-01-10 20:22     ` Paul Moore
2020-01-10 20:21   ` Paul Moore
2020-01-07 13:31 ` [PATCH 2/2] security,selinux: get rid of security_delete_hooks() Ondrej Mosnacek
2020-01-07 14:47   ` [PATCH 2/2] security, selinux: " Stephen Smalley
2020-01-08  5:31     ` Paul Moore
2020-01-08  8:15       ` Ondrej Mosnacek
2020-01-08 13:45         ` Paul Moore
2020-01-08 14:49       ` Stephen Smalley
2020-01-07 16:46   ` [PATCH 2/2] security,selinux: " Casey Schaufler
2020-01-07 18:10   ` Kees Cook
2020-01-07 19:59   ` James Morris
2020-01-08  8:21     ` Ondrej Mosnacek
2020-01-08 18:47       ` James Morris

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.