Linux Security Modules development
 help / color / mirror / Atom feed
* Re: [PATCH bpf-next] bpf: Make trampolines W^X
From: Peter Zijlstra @ 2020-01-07  9:11 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Andy Lutomirski, Justin Capella, KP Singh, Rick Edgecombe,
	linux-kernel, bpf, x86, linux-security-module, Kees Cook,
	David S. Miller, Alexey Kuznetsov, Hideaki YOSHIFUJI,
	Alexei Starovoitov, Daniel Borkmann, Martin KaFai Lau, Song Liu,
	Yonghong Song, Andrii Nakryiko, Thomas Garnier, Florent Revest,
	Brendan Jackman, Jann Horn, Matthew Garrett, Michael Halcrow
In-Reply-To: <20200106221317.wpwut2rgw23tdaoo@ast-mbp>

On Mon, Jan 06, 2020 at 02:13:18PM -0800, Alexei Starovoitov wrote:
> On Sun, Jan 05, 2020 at 10:33:54AM +0900, Andy Lutomirski wrote:
> > 
> > >> On Jan 4, 2020, at 8:03 PM, Justin Capella <justincapella@gmail.com> wrote:
> > > 
> > > I'm rather ignorant about this topic but it would make sense to check prior to making executable from a security standpoint wouldn't it? (In support of the (set_memory_ro + set_memory_x)
> > > 
> > 
> > Maybe, depends if it’s structured in a way that’s actually helpful from a security perspective.
> > 
> > It doesn’t help that set_memory_x and friends are not optimized at all. These functions are very, very, very slow and adversely affect all CPUs.
> 
> That was one of the reason it wasn't done in the first.
> Also ftrace trampoline break w^x as well.

Didn't I fix that?

^ permalink raw reply

* Re: INFO: rcu detected stall in sys_sendfile64
From: Dmitry Vyukov @ 2020-01-07 13:02 UTC (permalink / raw)
  To: Tetsuo Handa
  Cc: syzbot, syzkaller-bugs, Ingo Molnar, Peter Zijlstra, James Morris,
	LKML, linux-security-module, Serge E. Hallyn, syzkaller
In-Reply-To: <bc53fe0b-2c17-4d4f-1c40-f290997d0521@i-love.sakura.ne.jp>

On Sat, Jan 4, 2020 at 12:09 PM Tetsuo Handa
<penguin-kernel@i-love.sakura.ne.jp> wrote:
>
> On 2018/12/20 3:42, Dmitry Vyukov wrote:
> > On Wed, Dec 19, 2018 at 11:13 AM Tetsuo Handa
> > <penguin-kernel@i-love.sakura.ne.jp> wrote:
> >>
> >> On 2018/12/19 18:27, syzbot wrote:
> >>> HEAD commit:    ddfbab46539f Merge tag 'scsi-fixes' of git://git.kernel.or..
> >>> git tree:       upstream
> >>> console output: https://syzkaller.appspot.com/x/log.txt?x=15b87fa3400000
> >>> kernel config:  https://syzkaller.appspot.com/x/.config?x=861a3573f4e78ba1
> >>> dashboard link: https://syzkaller.appspot.com/bug?extid=bcad772bbc241b4c6147
> >>> compiler:       gcc (GCC) 8.0.1 20180413 (experimental)
> >>> syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=13912ccd400000
> >>> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=145781db400000
> >>
> >> This is not a LSM problem, for the reproducer is calling
> >> sched_setattr(SCHED_DEADLINE) with very large values.
> >>
> >>   sched_setattr(0, {size=0, sched_policy=0x6 /* SCHED_??? */, sched_flags=0, sched_nice=0, sched_priority=0, sched_runtime=2251799813724439, sched_deadline=4611686018427453437, sched_period=0}, 0) = 0
> >>
> >> I think that this problem is nothing but an insane sched_setattr() parameter.
> >>
> >> #syz invalid
> >
> > Note there was another one with sched_setattr, which turned out to be
> > some serious problem in kernel (sched_setattr should not cause CPU
> > stall for 3 minutes):
> > INFO: rcu detected stall in do_idle
> > https://syzkaller.appspot.com/bug?extid=385468161961cee80c31
> > https://groups.google.com/forum/#!msg/syzkaller-bugs/crrfvusGtwI/IoD_zus4BgAJ
> >
> > Maybe it another incarnation of the same bug, that one is still not fixed.
> >
>
> Can we let syzbot blacklist sched_setattr() for now? There are many stall reports
> doing sched_setattr(SCHED_RR) which makes it difficult to find stall reports not
> using sched_setattr().

Hi Tetsuo,

If we start practice of disabling whole syscalls, I would really like
"for now" to be very well defined. When will it end? How will it
happen? Is the problem on the radar of relevant people? Will it stay
on somebody's radar until it's fixed? Normal practise of project
sheriffing is to file a P1 bug assigned to somebody when something
gets disabled. But I am not sure how we implement this for kernel.
Since the problem is there for a long time and we disable it without
defining any criteria, I afraid we disable it forever (then more bugs
will pile and re-enabling it will be painful). At the very least we
need to acknowledge that we stopping testing schedler for foreseeable
future and schedler maintainers need to be notified about this.
Blacklisting it and un-blacklisting will cause some churn. Was the bug
given at least some attention? Significant number of bugs are
relatively easy to fix and fixing it would solve all of the problems
in a much better way.

^ permalink raw reply

* Re: INFO: rcu detected stall in sys_sendfile64
From: Peter Zijlstra @ 2020-01-07 13:11 UTC (permalink / raw)
  To: Dmitry Vyukov
  Cc: Tetsuo Handa, syzbot, syzkaller-bugs, Ingo Molnar, James Morris,
	LKML, linux-security-module, Serge E. Hallyn, syzkaller
In-Reply-To: <CACT4Y+bEi9ZsJn0Jm2Lwt-1cijQq=wc5MqYh0qf6R6+wpZVD2Q@mail.gmail.com>

On Tue, Jan 07, 2020 at 02:02:47PM +0100, Dmitry Vyukov wrote:
> > >> This is not a LSM problem, for the reproducer is calling
> > >> sched_setattr(SCHED_DEADLINE) with very large values.
> > >>
> > >>   sched_setattr(0, {size=0, sched_policy=0x6 /* SCHED_??? */, sched_flags=0, sched_nice=0, sched_priority=0, sched_runtime=2251799813724439, sched_deadline=4611686018427453437, sched_period=0}, 0) = 0
> > >>
> > >> I think that this problem is nothing but an insane sched_setattr() parameter.

Argh, I had a patch for that somewhere. Let me go dig that out.

^ permalink raw reply

* [PATCH 0/2] LSM: Drop security_delete_hooks()
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

* [PATCH 1/2] selinux: treat atomic flags more carefully
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
In-Reply-To: <20200107133154.588958-1-omosnace@redhat.com>

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

* [PATCH 2/2] security,selinux: get rid of security_delete_hooks()
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
In-Reply-To: <20200107133154.588958-1-omosnace@redhat.com>

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

* Re: [PATCH v2] selinux: deprecate disabling SELinux and runtime
From: Stephen Smalley @ 2020-01-07 14:35 UTC (permalink / raw)
  To: Paul Moore, selinux; +Cc: linux-security-module
In-Reply-To: <157836784986.560897.13893922675143903084.stgit@chester>

On 1/6/20 10:30 PM, Paul Moore wrote:
> Deprecate the CONFIG_SECURITY_SELINUX_DISABLE functionality.  The
> code was originally developed to make it easier for Linux
> distributions to support architectures where adding parameters to the
> kernel command line was difficult.  Unfortunately, supporting runtime
> disable meant we had to make some security trade-offs when it came to
> the LSM hooks, as documented in the Kconfig help text:
> 
>    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.
> 
> Fortunately it looks as if that the original motivation for the
> runtime disable functionality is gone, and Fedora/RHEL appears to be
> the only major distribution enabling this capability at build time
> so we are now taking steps to remove it entirely from the kernel.
> The first step is to mark the functionality as deprecated and print
> an error when it is used (what this patch is doing).  As Fedora/RHEL
> makes progress in transitioning the distribution away from runtime
> disable, we will introduce follow-up patches over several kernel
> releases which will block for increasing periods of time when the
> runtime disable is used.  Finally we will remove the option entirely
> once we believe all users have moved to the kernel cmdline approach.
> 
> Acked-by: Casey Schaufler <casey@schaufler-ca.com>
> Acked-by: Ondrej Mosnacek <omosnace@redhat.com>
> Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
> Signed-off-by: Paul Moore <paul@paul-moore.com>

checkpatch.pl has two warnings on this patch, one about the new 
Documentation/ABI/obsolete/sysfs-selinux-disable file not being listed 
in MAINTAINERS (looks like others are) and one about the comment block 
style being wrong.  Also not entirely sure if the file should be 
sysfs-selinux-disable or selinuxfs-disable; it gets mounted under sysfs 
but isn't part of it per se.  Otherwise, LGTM.

> ---
>   Documentation/ABI/obsolete/sysfs-selinux-disable |   26 ++++++++++++++++++++++
>   security/selinux/Kconfig                         |    3 +++
>   security/selinux/selinuxfs.c                     |    6 +++++
>   3 files changed, 35 insertions(+)
>   create mode 100644 Documentation/ABI/obsolete/sysfs-selinux-disable
> 
> diff --git a/Documentation/ABI/obsolete/sysfs-selinux-disable b/Documentation/ABI/obsolete/sysfs-selinux-disable
> new file mode 100644
> index 000000000000..c340278e3cf8
> --- /dev/null
> +++ b/Documentation/ABI/obsolete/sysfs-selinux-disable
> @@ -0,0 +1,26 @@
> +What:		/sys/fs/selinux/disable
> +Date:		April 2005 (predates git)
> +KernelVersion:	2.6.12-rc2 (predates git)
> +Contact:	selinux@vger.kernel.org
> +Description:
> +
> +	The selinuxfs "disable" node allows SELinux to be disabled at runtime
> +	prior to a policy being loaded into the kernel.  If disabled via this
> +	mechanism, SELinux will remain disabled until the system is rebooted.
> +
> +	The preferred method of disabling SELinux is via the "selinux=0" boot
> +	parameter, but the selinuxfs "disable" node was created to make it
> +	easier for systems with primitive bootloaders that did not allow for
> +	easy modification of the kernel command line.  Unfortunately, allowing
> +	for SELinux to be disabled at runtime makes it difficult to secure the
> +	kernel's LSM hooks using the "__ro_after_init" feature.
> +
> +	Thankfully, the need for the SELinux runtime disable appears to be
> +	gone, the default Kconfig configuration disables this selinuxfs node,
> +	and only one of the major distributions, Fedora, supports disabling
> +	SELinux at runtime.  Fedora is in the process of removing the
> +	selinuxfs "disable" node and once that is complete we will start the
> +	slow process of removing this code from the kernel.
> +
> +	More information on /sys/fs/selinux/disable can be found under the
> +	CONFIG_SECURITY_SELINUX_DISABLE Kconfig option.
> diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
> index 996d35d950f7..580ac24c7aa1 100644
> --- a/security/selinux/Kconfig
> +++ b/security/selinux/Kconfig
> @@ -42,6 +42,9 @@ config SECURITY_SELINUX_DISABLE
>   	  using the selinux=0 boot parameter instead of enabling this
>   	  option.
>   
> +	  WARNING: this option is deprecated and will be removed in a future
> +	  kernel release.
> +
>   	  If you are unsure how to answer this question, answer N.
>   
>   config SECURITY_SELINUX_DEVELOP
> diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
> index 278417e67b4c..adbe2dd35202 100644
> --- a/security/selinux/selinuxfs.c
> +++ b/security/selinux/selinuxfs.c
> @@ -281,6 +281,12 @@ static ssize_t sel_write_disable(struct file *file, const char __user *buf,
>   	int new_value;
>   	int enforcing;
>   
> +	/* NOTE: we are now officially considering runtime disable as
> +	 *       deprecated, and using it will become increasingly painful
> +	 *       (e.g. sleeping/blocking) as we progress through future
> +	 *       kernel releases until eventually it is removed */
> +	pr_err("SELinux:  Runtime disable is deprecated, use selinux=0 on the kernel cmdline.\n");
> +
>   	if (count >= PAGE_SIZE)
>   		return -ENOMEM;
>   
> 


^ permalink raw reply

* Re: [PATCH 1/2] selinux: treat atomic flags more carefully
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
In-Reply-To: <20200107133154.588958-2-omosnace@redhat.com>

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

* Re: [PATCH 2/2] security, selinux: get rid of security_delete_hooks()
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
In-Reply-To: <20200107133154.588958-3-omosnace@redhat.com>

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

* Re: [PATCH v2] selinux: deprecate disabling SELinux and runtime
From: Paul Moore @ 2020-01-07 15:28 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: selinux, linux-security-module
In-Reply-To: <43f27f76-f3ca-7ea2-7820-da56bb53fd0e@tycho.nsa.gov>

On Tue, Jan 7, 2020 at 9:34 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
> On 1/6/20 10:30 PM, Paul Moore wrote:
> > Deprecate the CONFIG_SECURITY_SELINUX_DISABLE functionality.  The
> > code was originally developed to make it easier for Linux
> > distributions to support architectures where adding parameters to the
> > kernel command line was difficult.  Unfortunately, supporting runtime
> > disable meant we had to make some security trade-offs when it came to
> > the LSM hooks, as documented in the Kconfig help text:
> >
> >    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.
> >
> > Fortunately it looks as if that the original motivation for the
> > runtime disable functionality is gone, and Fedora/RHEL appears to be
> > the only major distribution enabling this capability at build time
> > so we are now taking steps to remove it entirely from the kernel.
> > The first step is to mark the functionality as deprecated and print
> > an error when it is used (what this patch is doing).  As Fedora/RHEL
> > makes progress in transitioning the distribution away from runtime
> > disable, we will introduce follow-up patches over several kernel
> > releases which will block for increasing periods of time when the
> > runtime disable is used.  Finally we will remove the option entirely
> > once we believe all users have moved to the kernel cmdline approach.
> >
> > Acked-by: Casey Schaufler <casey@schaufler-ca.com>
> > Acked-by: Ondrej Mosnacek <omosnace@redhat.com>
> > Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
> > Signed-off-by: Paul Moore <paul@paul-moore.com>
>
> checkpatch.pl has two warnings on this patch, one about the new
> Documentation/ABI/obsolete/sysfs-selinux-disable file not being listed
> in MAINTAINERS (looks like others are) and one about the comment block
> style being wrong.

Fixed.

> Also not entirely sure if the file should be
> sysfs-selinux-disable or selinuxfs-disable; it gets mounted under sysfs
> but isn't part of it per se.  Otherwise, LGTM.

I wondered about that too, but decided the selinuxfs vs sysfs
distinction didn't matter much here as /sys/fs/selinux *looks* like
sysfs to admins/users (outside of the separate mount, but that is
typically handled by the distro's init system).

Anyway, it's merged into selinux/next now.

-- 
paul moore
www.paul-moore.com

^ permalink raw reply

* Re: [PATCH 2/2] security,selinux: get rid of security_delete_hooks()
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
In-Reply-To: <20200107133154.588958-3-omosnace@redhat.com>

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

* Re: [PATCH v13 06/25] Use lsmblob in security_secctx_to_secid
From: Stephen Smalley @ 2020-01-07 17:45 UTC (permalink / raw)
  To: Casey Schaufler, casey.schaufler, jmorris, linux-security-module,
	selinux
  Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20191224235939.7483-7-casey@schaufler-ca.com>

On 12/24/19 6:59 PM, Casey Schaufler wrote:
> Change security_secctx_to_secid() to fill in a lsmblob instead
> of a u32 secid. Multiple LSMs may be able to interpret the
> string, and this allows for setting whichever secid is
> appropriate. In some cases there is scaffolding where other
> interfaces have yet to be converted.
> 
> Reviewed-by: Kees Cook <keescook@chromium.org>
> Reviewed-by: John Johansen <john.johansen@canonical.com>
> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>

This addressed my comment on the previous version, so I'll add my ack. 
However, I noticed that even after the entire series is applied, at 
least some of the scaffolding remains.  Wondering whether that 
scaffolding is completely removed by the next series (i.e. full stacking 
for Smack) or still TBD.

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

> ---
>   include/linux/security.h          |  5 +++--
>   kernel/cred.c                     |  4 +---
>   net/netfilter/nft_meta.c          | 12 +++++++-----
>   net/netfilter/xt_SECMARK.c        |  5 ++++-
>   net/netlabel/netlabel_unlabeled.c | 14 ++++++++------
>   security/security.c               | 18 +++++++++++++++---
>   6 files changed, 38 insertions(+), 20 deletions(-)
> 
> diff --git a/include/linux/security.h b/include/linux/security.h
> index 995faba7393f..8cae9e4bd760 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -496,7 +496,8 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
>   int security_netlink_send(struct sock *sk, struct sk_buff *skb);
>   int security_ismaclabel(const char *name);
>   int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
> -int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid);
> +int security_secctx_to_secid(const char *secdata, u32 seclen,
> +			     struct lsmblob *blob);
>   void security_release_secctx(char *secdata, u32 seclen);
>   void security_inode_invalidate_secctx(struct inode *inode);
>   int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen);
> @@ -1302,7 +1303,7 @@ static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *secle
>   
>   static inline int security_secctx_to_secid(const char *secdata,
>   					   u32 seclen,
> -					   u32 *secid)
> +					   struct lsmblob *blob)
>   {
>   	return -EOPNOTSUPP;
>   }
> diff --git a/kernel/cred.c b/kernel/cred.c
> index 846ac4b23c16..7fef90f3f10b 100644
> --- a/kernel/cred.c
> +++ b/kernel/cred.c
> @@ -756,14 +756,12 @@ EXPORT_SYMBOL(set_security_override);
>   int set_security_override_from_ctx(struct cred *new, const char *secctx)
>   {
>   	struct lsmblob blob;
> -	u32 secid;
>   	int ret;
>   
> -	ret = security_secctx_to_secid(secctx, strlen(secctx), &secid);
> +	ret = security_secctx_to_secid(secctx, strlen(secctx), &blob);
>   	if (ret < 0)
>   		return ret;
>   
> -	lsmblob_init(&blob, secid);
>   	return set_security_override(new, &blob);
>   }
>   EXPORT_SYMBOL(set_security_override_from_ctx);
> diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
> index 9740b554fdb3..259c78d2f371 100644
> --- a/net/netfilter/nft_meta.c
> +++ b/net/netfilter/nft_meta.c
> @@ -625,21 +625,23 @@ static const struct nla_policy nft_secmark_policy[NFTA_SECMARK_MAX + 1] = {
>   
>   static int nft_secmark_compute_secid(struct nft_secmark *priv)
>   {
> -	u32 tmp_secid = 0;
> +	struct lsmblob blob;
>   	int err;
>   
> -	err = security_secctx_to_secid(priv->ctx, strlen(priv->ctx), &tmp_secid);
> +	err = security_secctx_to_secid(priv->ctx, strlen(priv->ctx), &blob);
>   	if (err)
>   		return err;
>   
> -	if (!tmp_secid)
> +	if (!lsmblob_is_set(&blob))
>   		return -ENOENT;
>   
> -	err = security_secmark_relabel_packet(tmp_secid);
> +	/* Using le[0] is scaffolding */
> +	err = security_secmark_relabel_packet(blob.secid[0]);
>   	if (err)
>   		return err;
>   
> -	priv->secid = tmp_secid;
> +	/* Using le[0] is scaffolding */
> +	priv->secid = blob.secid[0];
>   	return 0;
>   }
>   
> diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
> index 2317721f3ecb..2d68416b4552 100644
> --- a/net/netfilter/xt_SECMARK.c
> +++ b/net/netfilter/xt_SECMARK.c
> @@ -45,13 +45,14 @@ secmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
>   
>   static int checkentry_lsm(struct xt_secmark_target_info *info)
>   {
> +	struct lsmblob blob;
>   	int err;
>   
>   	info->secctx[SECMARK_SECCTX_MAX - 1] = '\0';
>   	info->secid = 0;
>   
>   	err = security_secctx_to_secid(info->secctx, strlen(info->secctx),
> -				       &info->secid);
> +				       &blob);
>   	if (err) {
>   		if (err == -EINVAL)
>   			pr_info_ratelimited("invalid security context \'%s\'\n",
> @@ -59,6 +60,8 @@ static int checkentry_lsm(struct xt_secmark_target_info *info)
>   		return err;
>   	}
>   
> +	/* scaffolding during the transition */
> +	info->secid = blob.secid[0];
>   	if (!info->secid) {
>   		pr_info_ratelimited("unable to map security context \'%s\'\n",
>   				    info->secctx);
> diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
> index d2e4ab8d1cb1..7a5a87f15736 100644
> --- a/net/netlabel/netlabel_unlabeled.c
> +++ b/net/netlabel/netlabel_unlabeled.c
> @@ -881,7 +881,7 @@ static int netlbl_unlabel_staticadd(struct sk_buff *skb,
>   	void *addr;
>   	void *mask;
>   	u32 addr_len;
> -	u32 secid;
> +	struct lsmblob blob;
>   	struct netlbl_audit audit_info;
>   
>   	/* Don't allow users to add both IPv4 and IPv6 addresses for a
> @@ -905,12 +905,13 @@ static int netlbl_unlabel_staticadd(struct sk_buff *skb,
>   	ret_val = security_secctx_to_secid(
>   		                  nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]),
>   				  nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]),
> -				  &secid);
> +				  &blob);
>   	if (ret_val != 0)
>   		return ret_val;
>   
> +	/* scaffolding with the [0] */
>   	return netlbl_unlhsh_add(&init_net,
> -				 dev_name, addr, mask, addr_len, secid,
> +				 dev_name, addr, mask, addr_len, blob.secid[0],
>   				 &audit_info);
>   }
>   
> @@ -932,7 +933,7 @@ static int netlbl_unlabel_staticadddef(struct sk_buff *skb,
>   	void *addr;
>   	void *mask;
>   	u32 addr_len;
> -	u32 secid;
> +	struct lsmblob blob;
>   	struct netlbl_audit audit_info;
>   
>   	/* Don't allow users to add both IPv4 and IPv6 addresses for a
> @@ -954,12 +955,13 @@ static int netlbl_unlabel_staticadddef(struct sk_buff *skb,
>   	ret_val = security_secctx_to_secid(
>   		                  nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]),
>   				  nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]),
> -				  &secid);
> +				  &blob);
>   	if (ret_val != 0)
>   		return ret_val;
>   
> +	/* scaffolding with the [0] */
>   	return netlbl_unlhsh_add(&init_net,
> -				 NULL, addr, mask, addr_len, secid,
> +				 NULL, addr, mask, addr_len, blob.secid[0],
>   				 &audit_info);
>   }
>   
> diff --git a/security/security.c b/security/security.c
> index 33563963cd45..9dc0bbfe567e 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -1970,10 +1970,22 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
>   }
>   EXPORT_SYMBOL(security_secid_to_secctx);
>   
> -int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
> +int security_secctx_to_secid(const char *secdata, u32 seclen,
> +			     struct lsmblob *blob)
>   {
> -	*secid = 0;
> -	return call_int_hook(secctx_to_secid, 0, secdata, seclen, secid);
> +	struct security_hook_list *hp;
> +	int rc;
> +
> +	lsmblob_init(blob, 0);
> +	hlist_for_each_entry(hp, &security_hook_heads.secctx_to_secid, list) {
> +		if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
> +			continue;
> +		rc = hp->hook.secctx_to_secid(secdata, seclen,
> +					      &blob->secid[hp->lsmid->slot]);
> +		if (rc != 0)
> +			return rc;
> +	}
> +	return 0;
>   }
>   EXPORT_SYMBOL(security_secctx_to_secid);
>   
> 


^ permalink raw reply

* Re: [PATCH v13 09/25] LSM: Use lsmblob in security_task_getsecid
From: Stephen Smalley @ 2020-01-07 17:53 UTC (permalink / raw)
  To: Casey Schaufler, casey.schaufler, jmorris, linux-security-module,
	selinux
  Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20191224235939.7483-10-casey@schaufler-ca.com>

On 12/24/19 6:59 PM, Casey Schaufler wrote:
> Change the security_task_getsecid() interface to fill in
> a lsmblob structure instead of a u32 secid in support of
> LSM stacking. Audit interfaces will need to collect all
> possible secids for possible reporting.
> 
> Reviewed-by: Kees Cook <keescook@chromium.org>
> Reviewed-by: John Johansen <john.johansen@canonical.com>
> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>

You can drop one of your SOBs and add my Ack,

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

> cc: linux-integrity@vger.kernel.org
> ---
>   drivers/android/binder.c              |  4 +--
>   include/linux/security.h              |  7 +++--
>   kernel/audit.c                        | 11 +++----
>   kernel/auditfilter.c                  |  4 +--
>   kernel/auditsc.c                      | 18 ++++++++----
>   net/netlabel/netlabel_unlabeled.c     |  5 +++-
>   net/netlabel/netlabel_user.h          |  6 +++-
>   security/integrity/ima/ima_appraise.c |  9 +++---
>   security/integrity/ima/ima_main.c     | 42 +++++++++++++++------------
>   security/security.c                   | 12 ++++++--
>   10 files changed, 71 insertions(+), 47 deletions(-)
> 
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index f9b67f585e06..22fef6e130df 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -3104,12 +3104,10 @@ static void binder_transaction(struct binder_proc *proc,
>   	t->priority = task_nice(current);
>   
>   	if (target_node && target_node->txn_security_ctx) {
> -		u32 secid;
>   		struct lsmblob blob;
>   		size_t added_size;
>   
> -		security_task_getsecid(proc->tsk, &secid);
> -		lsmblob_init(&blob, secid);
> +		security_task_getsecid(proc->tsk, &blob);
>   		ret = security_secid_to_secctx(&blob, &secctx, &secctx_sz);
>   		if (ret) {
>   			return_error = BR_FAILED_REPLY;
> diff --git a/include/linux/security.h b/include/linux/security.h
> index 61a80afbbdba..b6d5475f8196 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -449,7 +449,7 @@ int security_task_fix_setuid(struct cred *new, const struct cred *old,
>   int security_task_setpgid(struct task_struct *p, pid_t pgid);
>   int security_task_getpgid(struct task_struct *p);
>   int security_task_getsid(struct task_struct *p);
> -void security_task_getsecid(struct task_struct *p, u32 *secid);
> +void security_task_getsecid(struct task_struct *p, struct lsmblob *blob);
>   int security_task_setnice(struct task_struct *p, int nice);
>   int security_task_setioprio(struct task_struct *p, int ioprio);
>   int security_task_getioprio(struct task_struct *p);
> @@ -1101,9 +1101,10 @@ static inline int security_task_getsid(struct task_struct *p)
>   	return 0;
>   }
>   
> -static inline void security_task_getsecid(struct task_struct *p, u32 *secid)
> +static inline void security_task_getsecid(struct task_struct *p,
> +					  struct lsmblob *blob)
>   {
> -	*secid = 0;
> +	lsmblob_init(blob, 0);
>   }
>   
>   static inline int security_task_setnice(struct task_struct *p, int nice)
> diff --git a/kernel/audit.c b/kernel/audit.c
> index e3e515158295..6ee53e43c986 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -2062,14 +2062,12 @@ int audit_log_task_context(struct audit_buffer *ab)
>   	char *ctx = NULL;
>   	unsigned len;
>   	int error;
> -	u32 sid;
>   	struct lsmblob blob;
>   
> -	security_task_getsecid(current, &sid);
> -	if (!sid)
> +	security_task_getsecid(current, &blob);
> +	if (!lsmblob_is_set(&blob))
>   		return 0;
>   
> -	lsmblob_init(&blob, sid);
>   	error = security_secid_to_secctx(&blob, &ctx, &len);
>   	if (error) {
>   		if (error != -EINVAL)
> @@ -2277,6 +2275,7 @@ int audit_set_loginuid(kuid_t loginuid)
>   int audit_signal_info(int sig, struct task_struct *t)
>   {
>   	kuid_t uid = current_uid(), auid;
> +	struct lsmblob blob;
>   
>   	if (auditd_test_task(t) &&
>   	    (sig == SIGTERM || sig == SIGHUP ||
> @@ -2287,7 +2286,9 @@ int audit_signal_info(int sig, struct task_struct *t)
>   			audit_sig_uid = auid;
>   		else
>   			audit_sig_uid = uid;
> -		security_task_getsecid(current, &audit_sig_sid);
> +		security_task_getsecid(current, &blob);
> +		/* scaffolding until audit_sig_sid is converted */
> +		audit_sig_sid = blob.secid[0];
>   	}
>   
>   	return audit_signal_info_syscall(t);
> diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
> index 356db1dd276c..19cfbe716f9d 100644
> --- a/kernel/auditfilter.c
> +++ b/kernel/auditfilter.c
> @@ -1324,7 +1324,6 @@ int audit_filter(int msgtype, unsigned int listtype)
>   		for (i = 0; i < e->rule.field_count; i++) {
>   			struct audit_field *f = &e->rule.fields[i];
>   			pid_t pid;
> -			u32 sid;
>   			struct lsmblob blob;
>   
>   			switch (f->type) {
> @@ -1355,8 +1354,7 @@ int audit_filter(int msgtype, unsigned int listtype)
>   			case AUDIT_SUBJ_SEN:
>   			case AUDIT_SUBJ_CLR:
>   				if (f->lsm_rule) {
> -					security_task_getsecid(current, &sid);
> -					lsmblob_init(&blob, sid);
> +					security_task_getsecid(current, &blob);
>   					result = security_audit_rule_match(
>   							&blob, f->type,
>   							f->op, f->lsm_rule);
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index ce8bf2d8f8d2..cccb681ad081 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -444,7 +444,6 @@ static int audit_filter_rules(struct task_struct *tsk,
>   {
>   	const struct cred *cred;
>   	int i, need_sid = 1;
> -	u32 sid;
>   	struct lsmblob blob;
>   	unsigned int sessionid;
>   
> @@ -641,10 +640,9 @@ static int audit_filter_rules(struct task_struct *tsk,
>   			   logged upon error */
>   			if (f->lsm_rule) {
>   				if (need_sid) {
> -					security_task_getsecid(tsk, &sid);
> +					security_task_getsecid(tsk, &blob);
>   					need_sid = 0;
>   				}
> -				lsmblob_init(&blob, sid);
>   				result = security_audit_rule_match(&blob,
>   								   f->type,
>   								   f->op,
> @@ -2382,12 +2380,15 @@ int __audit_sockaddr(int len, void *a)
>   void __audit_ptrace(struct task_struct *t)
>   {
>   	struct audit_context *context = audit_context();
> +	struct lsmblob blob;
>   
>   	context->target_pid = task_tgid_nr(t);
>   	context->target_auid = audit_get_loginuid(t);
>   	context->target_uid = task_uid(t);
>   	context->target_sessionid = audit_get_sessionid(t);
> -	security_task_getsecid(t, &context->target_sid);
> +	security_task_getsecid(t, &blob);
> +	/* scaffolding - until target_sid is converted */
> +	context->target_sid = blob.secid[0];
>   	memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
>   }
>   
> @@ -2403,6 +2404,7 @@ int audit_signal_info_syscall(struct task_struct *t)
>   	struct audit_aux_data_pids *axp;
>   	struct audit_context *ctx = audit_context();
>   	kuid_t t_uid = task_uid(t);
> +	struct lsmblob blob;
>   
>   	if (!audit_signals || audit_dummy_context())
>   		return 0;
> @@ -2414,7 +2416,9 @@ int audit_signal_info_syscall(struct task_struct *t)
>   		ctx->target_auid = audit_get_loginuid(t);
>   		ctx->target_uid = t_uid;
>   		ctx->target_sessionid = audit_get_sessionid(t);
> -		security_task_getsecid(t, &ctx->target_sid);
> +		security_task_getsecid(t, &blob);
> +		/* scaffolding until target_sid is converted */
> +		ctx->target_sid = blob.secid[0];
>   		memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
>   		return 0;
>   	}
> @@ -2435,7 +2439,9 @@ int audit_signal_info_syscall(struct task_struct *t)
>   	axp->target_auid[axp->pid_count] = audit_get_loginuid(t);
>   	axp->target_uid[axp->pid_count] = t_uid;
>   	axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
> -	security_task_getsecid(t, &axp->target_sid[axp->pid_count]);
> +	security_task_getsecid(t, &blob);
> +	/* scaffolding until target_sid is converted */
> +	axp->target_sid[axp->pid_count] = blob.secid[0];
>   	memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
>   	axp->pid_count++;
>   
> diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
> index 0cda17cb44a0..e279b81d9545 100644
> --- a/net/netlabel/netlabel_unlabeled.c
> +++ b/net/netlabel/netlabel_unlabeled.c
> @@ -1539,11 +1539,14 @@ int __init netlbl_unlabel_defconf(void)
>   	int ret_val;
>   	struct netlbl_dom_map *entry;
>   	struct netlbl_audit audit_info;
> +	struct lsmblob blob;
>   
>   	/* Only the kernel is allowed to call this function and the only time
>   	 * it is called is at bootup before the audit subsystem is reporting
>   	 * messages so don't worry to much about these values. */
> -	security_task_getsecid(current, &audit_info.secid);
> +	security_task_getsecid(current, &blob);
> +	/* scaffolding until audit_info.secid is converted */
> +	audit_info.secid = blob.secid[0];
>   	audit_info.loginuid = GLOBAL_ROOT_UID;
>   	audit_info.sessionid = 0;
>   
> diff --git a/net/netlabel/netlabel_user.h b/net/netlabel/netlabel_user.h
> index 3c67afce64f1..438b5db6c714 100644
> --- a/net/netlabel/netlabel_user.h
> +++ b/net/netlabel/netlabel_user.h
> @@ -34,7 +34,11 @@
>   static inline void netlbl_netlink_auditinfo(struct sk_buff *skb,
>   					    struct netlbl_audit *audit_info)
>   {
> -	security_task_getsecid(current, &audit_info->secid);
> +	struct lsmblob blob;
> +
> +	security_task_getsecid(current, &blob);
> +	/* scaffolding until secid is converted */
> +	audit_info->secid = blob.secid[0];
>   	audit_info->loginuid = audit_get_loginuid(current);
>   	audit_info->sessionid = audit_get_sessionid(current);
>   }
> diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
> index 300c8d2943c5..37f540af45bb 100644
> --- a/security/integrity/ima/ima_appraise.c
> +++ b/security/integrity/ima/ima_appraise.c
> @@ -48,14 +48,15 @@ bool is_ima_appraise_enabled(void)
>    */
>   int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func)
>   {
> -	u32 secid;
> +	struct lsmblob blob;
>   
>   	if (!ima_appraise)
>   		return 0;
>   
> -	security_task_getsecid(current, &secid);
> -	return ima_match_policy(inode, current_cred(), secid, func, mask,
> -				IMA_APPRAISE | IMA_HASH, NULL, NULL);
> +	security_task_getsecid(current, &blob);
> +	/* scaffolding the .secid[0] */
> +	return ima_match_policy(inode, current_cred(), blob.secid[0], func,
> +				mask, IMA_APPRAISE | IMA_HASH, NULL, NULL);
>   }
>   
>   static int ima_fix_xattr(struct dentry *dentry,
> diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> index d7e987baf127..7c4bfc051ebc 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -384,12 +384,13 @@ static int process_measurement(struct file *file, const struct cred *cred,
>    */
>   int ima_file_mmap(struct file *file, unsigned long prot)
>   {
> -	u32 secid;
> +	struct lsmblob blob;
>   
>   	if (file && (prot & PROT_EXEC)) {
> -		security_task_getsecid(current, &secid);
> -		return process_measurement(file, current_cred(), secid, NULL,
> -					   0, MAY_EXEC, MMAP_CHECK);
> +		security_task_getsecid(current, &blob);
> +		/* scaffolding - until process_measurement changes */
> +		return process_measurement(file, current_cred(), blob.secid[0],
> +					   NULL, 0, MAY_EXEC, MMAP_CHECK);
>   	}
>   
>   	return 0;
> @@ -412,10 +413,12 @@ int ima_bprm_check(struct linux_binprm *bprm)
>   {
>   	int ret;
>   	u32 secid;
> +	struct lsmblob blob;
>   
> -	security_task_getsecid(current, &secid);
> -	ret = process_measurement(bprm->file, current_cred(), secid, NULL, 0,
> -				  MAY_EXEC, BPRM_CHECK);
> +	security_task_getsecid(current, &blob);
> +	/* scaffolding until process_measurement changes */
> +	ret = process_measurement(bprm->file, current_cred(), blob.secid[0],
> +				  NULL, 0, MAY_EXEC, BPRM_CHECK);
>   	if (ret)
>   		return ret;
>   
> @@ -436,10 +439,11 @@ int ima_bprm_check(struct linux_binprm *bprm)
>    */
>   int ima_file_check(struct file *file, int mask)
>   {
> -	u32 secid;
> +	struct lsmblob blob;
>   
> -	security_task_getsecid(current, &secid);
> -	return process_measurement(file, current_cred(), secid, NULL, 0,
> +	security_task_getsecid(current, &blob);
> +	/* scaffolding until process_measurement changes */
> +	return process_measurement(file, current_cred(), blob.secid[0], NULL, 0,
>   				   mask & (MAY_READ | MAY_WRITE | MAY_EXEC |
>   					   MAY_APPEND), FILE_CHECK);
>   }
> @@ -548,7 +552,7 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
>   		       enum kernel_read_file_id read_id)
>   {
>   	enum ima_hooks func;
> -	u32 secid;
> +	struct lsmblob blob;
>   
>   	if (!file && read_id == READING_FIRMWARE) {
>   		if ((ima_appraise & IMA_APPRAISE_FIRMWARE) &&
> @@ -570,9 +574,10 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
>   	}
>   
>   	func = read_idmap[read_id] ?: FILE_CHECK;
> -	security_task_getsecid(current, &secid);
> -	return process_measurement(file, current_cred(), secid, buf, size,
> -				   MAY_READ, func);
> +	security_task_getsecid(current, &blob);
> +	/* scaffolding until process_measurement changes */
> +	return process_measurement(file, current_cred(), blob.secid[0], buf,
> +				   size, MAY_READ, func);
>   }
>   
>   /**
> @@ -653,7 +658,7 @@ void process_buffer_measurement(const void *buf, int size,
>   	} hash = {};
>   	int violation = 0;
>   	int action = 0;
> -	u32 secid;
> +	struct lsmblob blob;
>   
>   	/*
>   	 * Both LSM hooks and auxilary based buffer measurements are
> @@ -663,9 +668,10 @@ void process_buffer_measurement(const void *buf, int size,
>   	 * buffer measurements.
>   	 */
>   	if (func) {
> -		security_task_getsecid(current, &secid);
> -		action = ima_get_action(NULL, current_cred(), secid, 0, func,
> -					&pcr, &template);
> +		security_task_getsecid(current, &blob);
> +		/* scaffolding */
> +		action = ima_get_action(NULL, current_cred(), blob.secid[0],
> +					0, func, &pcr, &template);
>   		if (!(action & IMA_MEASURE))
>   			return;
>   	}
> diff --git a/security/security.c b/security/security.c
> index 793c4ee0cf4e..7a170c02f8df 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -1700,10 +1700,16 @@ int security_task_getsid(struct task_struct *p)
>   	return call_int_hook(task_getsid, 0, p);
>   }
>   
> -void security_task_getsecid(struct task_struct *p, u32 *secid)
> +void security_task_getsecid(struct task_struct *p, struct lsmblob *blob)
>   {
> -	*secid = 0;
> -	call_void_hook(task_getsecid, p, secid);
> +	struct security_hook_list *hp;
> +
> +	lsmblob_init(blob, 0);
> +	hlist_for_each_entry(hp, &security_hook_heads.task_getsecid, list) {
> +		if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
> +			continue;
> +		hp->hook.task_getsecid(p, &blob->secid[hp->lsmid->slot]);
> +	}
>   }
>   EXPORT_SYMBOL(security_task_getsecid);
>   
> 


^ permalink raw reply

* Re: [PATCH 1/2] selinux: treat atomic flags more carefully
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
In-Reply-To: <20200107133154.588958-2-omosnace@redhat.com>

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

* Re: [PATCH 2/2] security,selinux: get rid of security_delete_hooks()
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
In-Reply-To: <20200107133154.588958-3-omosnace@redhat.com>

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

* Re: [PATCH bpf-next] bpf: Make trampolines W^X
From: Alexei Starovoitov @ 2020-01-07 18:55 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Andy Lutomirski, Justin Capella, KP Singh, Rick Edgecombe,
	linux-kernel, bpf, x86, linux-security-module, Kees Cook,
	David S. Miller, Alexey Kuznetsov, Hideaki YOSHIFUJI,
	Alexei Starovoitov, Daniel Borkmann, Martin KaFai Lau, Song Liu,
	Yonghong Song, Andrii Nakryiko, Thomas Garnier, Florent Revest,
	Brendan Jackman, Jann Horn, Matthew Garrett, Michael Halcrow
In-Reply-To: <20200107091132.GR2844@hirez.programming.kicks-ass.net>

On Tue, Jan 07, 2020 at 10:11:32AM +0100, Peter Zijlstra wrote:
> On Mon, Jan 06, 2020 at 02:13:18PM -0800, Alexei Starovoitov wrote:
> > On Sun, Jan 05, 2020 at 10:33:54AM +0900, Andy Lutomirski wrote:
> > > 
> > > >> On Jan 4, 2020, at 8:03 PM, Justin Capella <justincapella@gmail.com> wrote:
> > > > 
> > > > I'm rather ignorant about this topic but it would make sense to check prior to making executable from a security standpoint wouldn't it? (In support of the (set_memory_ro + set_memory_x)
> > > > 
> > > 
> > > Maybe, depends if it’s structured in a way that’s actually helpful from a security perspective.
> > > 
> > > It doesn’t help that set_memory_x and friends are not optimized at all. These functions are very, very, very slow and adversely affect all CPUs.
> > 
> > That was one of the reason it wasn't done in the first.
> > Also ftrace trampoline break w^x as well.
> 
> Didn't I fix that?

yes. in the tip. many months ago. that's why up-thread I was saying that I'm
waiting for all text_poke[_bp] patches to land upstream and do the same thing
for bpf trampoline and bpf dispatcher (which has the same issue).

^ permalink raw reply

* Re: [PATCH bpf-next] bpf: Make trampolines W^X
From: Edgecombe, Rick P @ 2020-01-07 19:01 UTC (permalink / raw)
  To: luto@amacapital.net
  Cc: songliubraving@fb.com, linux-kernel@vger.kernel.org,
	bpf@vger.kernel.org, keescook@chromium.org, jeyu@kernel.org,
	ast@kernel.org, kuznet@ms2.inr.ac.ru, daniel@iogearbox.net,
	mjg59@google.com, thgarnie@chromium.org, kpsingh@chromium.org,
	linux-security-module@vger.kernel.org, x86@kernel.org,
	revest@chromium.org, jannh@google.com, namit@vmware.com,
	jackmanb@chromium.org, kafai@fb.com, yhs@fb.com,
	davem@davemloft.net, yoshfuji@linux-ipv6.org, mhalcrow@google.com,
	andriin@fb.com
In-Reply-To: <DB882EE8-20B2-4631-A808-E5C968B24CEB@amacapital.net>

CC Nadav and Jessica.

On Mon, 2020-01-06 at 15:36 -1000, Andy Lutomirski wrote:
> > On Jan 6, 2020, at 12:25 PM, Edgecombe, Rick P <rick.p.edgecombe@intel.com>
> > wrote:
> > 
> > On Sat, 2020-01-04 at 09:49 +0900, Andy Lutomirski wrote:
> > > > > On Jan 4, 2020, at 8:47 AM, KP Singh <kpsingh@chromium.org> wrote:
> > > > 
> > > > From: KP Singh <kpsingh@google.com>
> > > > 
> > > > The image for the BPF trampolines is allocated with
> > > > bpf_jit_alloc_exe_page which marks this allocated page executable. This
> > > > means that the allocated memory is W and X at the same time making it
> > > > susceptible to WX based attacks.
> > > > 
> > > > Since the allocated memory is shared between two trampolines (the
> > > > current and the next), 2 pages must be allocated to adhere to W^X and
> > > > the following sequence is obeyed where trampolines are modified:
> > > 
> > > Can we please do better rather than piling garbage on top of garbage?
> > > 
> > > > 
> > > > - Mark memory as non executable (set_memory_nx). While module_alloc for
> > > > x86 allocates the memory as PAGE_KERNEL and not PAGE_KERNEL_EXEC, not
> > > > all implementations of module_alloc do so
> > > 
> > > How about fixing this instead?
> > > 
> > > > - Mark the memory as read/write (set_memory_rw)
> > > 
> > > Probably harmless, but see above about fixing it.
> > > 
> > > > - Modify the trampoline
> > > 
> > > Seems reasonable. It’s worth noting that this whole approach is
> > > suboptimal:
> > > the “module” allocator should really be returning a list of pages to be
> > > written (not at the final address!) with the actual executable mapping to
> > > be
> > > materialized later, but that’s a bigger project that you’re welcome to
> > > ignore
> > > for now.  (Concretely, it should produce a vmap address with backing pages
> > > but
> > > with the vmap alias either entirely unmapped or read-only. A subsequent
> > > healer
> > > would, all at once, make the direct map pages RO or not-present and make
> > > the
> > > vmap alias RX.)
> > > > - Mark the memory as read-only (set_memory_ro)
> > > > - Mark the memory as executable (set_memory_x)
> > > 
> > > No, thanks. There’s very little excuse for doing two IPI flushes when one
> > > would suffice.
> > > 
> > > As far as I know, all architectures can do this with a single flush
> > > without
> > > races  x86 certainly can. The module freeing code gets this sequence
> > > right.
> > > Please reuse its mechanism or, if needed, export the relevant interfaces.
> > 
> > So if I understand this right, some trampolines have been added that are
> > currently set as RWX at modification time AND left that way during runtime?
> > The
> > discussion on the order of set_memory_() calls in the commit message made me
> > think that this was just a modification time thing at first.
> 
> I’m not sure what the status quo is.
> 
> We really ought to have a genuinely good API for allocation and initialization
> of text.  We can do so much better than set_memory_blahblah.
> 
> FWIW, I have some ideas about making kernel flushes cheaper. It’s currently
> blocked on finding some time and on tglx’s irqtrace work.
> 

Makes sense to me. I guess there are 6 types of text allocations now:
 - These two BPF trampolines
 - BPF JITs
 - Modules
 - Kprobes
 - Ftrace

All doing (or should be doing) pretty much the same thing. I believe Jessica had
said at one point that she didn't like all the other features using
module_alloc() as it was supposed to be just for real modules. Where would the
API live?

> > 
> > Also, is there a reason you couldn't use text_poke() to modify the
> > trampoline
> > with a single flush?
> > 
> 
> Does text_poke to an IPI these days?

I don't think so since the RW mapping is just on a single CPU. That was one of
the benefits of the temporary mm struct based thing Nadav did. I haven't looked
into PeterZ's changes though.

^ permalink raw reply

* Re: [PATCH v13 13/25] LSM: Specify which LSM to display
From: Stephen Smalley @ 2020-01-07 19:02 UTC (permalink / raw)
  To: Casey Schaufler, casey.schaufler, jmorris, linux-security-module,
	selinux
  Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20191224235939.7483-14-casey@schaufler-ca.com>

On 12/24/19 6:59 PM, Casey Schaufler wrote:
> Create a new entry "display" in the procfs attr directory for
> controlling which LSM security information is displayed for a
> process. A process can only read or write its own display value.
> 
> The name of an active LSM that supplies hooks for
> human readable data may be written to "display" to set the
> value. The name of the LSM currently in use can be read from
> "display". At this point there can only be one LSM capable
> of display active. A helper function lsm_task_display() is
> provided to get the display slot for a task_struct.
> 
> Setting the "display" requires that all security modules using
> setprocattr hooks allow the action. Each security module is
> responsible for defining its policy.
> 
> AppArmor hook provided by John Johansen <john.johansen@canonical.com>
> SELinux hook provided by Stephen Smalley <sds@tycho.nsa.gov>
> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
> ---
>   fs/proc/base.c                       |   1 +
>   include/linux/lsm_hooks.h            |  15 +++
>   security/apparmor/include/apparmor.h |   3 +-
>   security/apparmor/lsm.c              |  32 +++++
>   security/security.c                  | 168 ++++++++++++++++++++++++---
>   security/selinux/hooks.c             |  11 ++
>   security/selinux/include/classmap.h  |   2 +-
>   security/smack/smack_lsm.c           |   7 ++
>   8 files changed, 220 insertions(+), 19 deletions(-)
> 
> diff --git a/fs/proc/base.c b/fs/proc/base.c
> index ebea9501afb8..950c200cb9ad 100644
> --- a/fs/proc/base.c
> +++ b/fs/proc/base.c
> @@ -2652,6 +2652,7 @@ static const struct pid_entry attr_dir_stuff[] = {
>   	ATTR(NULL, "fscreate",		0666),
>   	ATTR(NULL, "keycreate",		0666),
>   	ATTR(NULL, "sockcreate",	0666),
> +	ATTR(NULL, "display",		0666),
>   #ifdef CONFIG_SECURITY_SMACK
>   	DIR("smack",			0555,
>   	    proc_smack_attr_dir_inode_ops, proc_smack_attr_dir_ops),
> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
> index 7eb808cde051..2bf82e1cf347 100644
> --- a/include/linux/lsm_hooks.h
> +++ b/include/linux/lsm_hooks.h
> @@ -2186,4 +2186,19 @@ static inline void security_delete_hooks(struct security_hook_list *hooks,
>   
>   extern int lsm_inode_alloc(struct inode *inode);
>   
> +/**
> + * lsm_task_display - the "display" LSM for this task
> + * @task: The task to report on
> + *
> + * Returns the task's display LSM slot.
> + */
> +static inline int lsm_task_display(struct task_struct *task)
> +{
> +	int *display = task->security;
> +
> +	if (display)
> +		return *display;
> +	return LSMBLOB_INVALID;
> +}
> +
>   #endif /* ! __LINUX_LSM_HOOKS_H */
> diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
> index 1fbabdb565a8..b1622fcb4394 100644
> --- a/security/apparmor/include/apparmor.h
> +++ b/security/apparmor/include/apparmor.h
> @@ -28,8 +28,9 @@
>   #define AA_CLASS_SIGNAL		10
>   #define AA_CLASS_NET		14
>   #define AA_CLASS_LABEL		16
> +#define AA_CLASS_DISPLAY_LSM	17
>   
> -#define AA_CLASS_LAST		AA_CLASS_LABEL
> +#define AA_CLASS_LAST		AA_CLASS_DISPLAY_LSM
>   
>   /* Control parameters settable through module/boot flags */
>   extern enum audit_mode aa_g_audit;
> diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
> index 146d75e5e021..16b992235c11 100644
> --- a/security/apparmor/lsm.c
> +++ b/security/apparmor/lsm.c
> @@ -612,6 +612,25 @@ static int apparmor_getprocattr(struct task_struct *task, char *name,
>   	return error;
>   }
>   
> +
> +static int profile_display_lsm(struct aa_profile *profile,
> +			       struct common_audit_data *sa)
> +{
> +	struct aa_perms perms = { };
> +	unsigned int state;
> +
> +	state = PROFILE_MEDIATES(profile, AA_CLASS_DISPLAY_LSM);
> +	if (state) {
> +		aa_compute_perms(profile->policy.dfa, state, &perms);
> +		aa_apply_modes_to_perms(profile, &perms);
> +		aad(sa)->label = &profile->label;
> +
> +		return aa_check_perms(profile, &perms, AA_MAY_WRITE, sa, NULL);
> +	}
> +
> +	return 0;
> +}
> +
>   static int apparmor_setprocattr(const char *name, void *value,
>   				size_t size)
>   {
> @@ -623,6 +642,19 @@ static int apparmor_setprocattr(const char *name, void *value,
>   	if (size == 0)
>   		return -EINVAL;
>   
> +	/* LSM infrastructure does actual setting of display if allowed */
> +	if (!strcmp(name, "display")) {
> +		struct aa_profile *profile;
> +		struct aa_label *label;
> +
> +		aad(&sa)->info = "set display lsm";
> +		label = begin_current_label_crit_section();
> +		error = fn_for_each_confined(label, profile,
> +					     profile_display_lsm(profile, &sa));
> +		end_current_label_crit_section(label);
> +		return error;
> +	}
> +
>   	/* AppArmor requires that the buffer must be null terminated atm */
>   	if (args[size - 1] != '\0') {
>   		/* null terminate */
> diff --git a/security/security.c b/security/security.c
> index cf87e5ef2816..aaf6db47dd8a 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/binfmts.h>

What's this #include for?

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

>   #include <net/flow.h>
>   #include <net/sock.h>
>   
> @@ -43,7 +44,14 @@ 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;
> +
> +/*
> + * The task blob includes the "display" slot used for
> + * chosing which module presents contexts.
> + */
> +static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init = {
> +	.lbs_task = sizeof(int),
> +};
>   
>   /* Boot-time LSM user choice */
>   static __initdata const char *chosen_lsm_order;
> @@ -438,8 +446,10 @@ static int lsm_append(const char *new, char **result)
>   
>   /*
>    * Current index to use while initializing the lsmblob secid list.
> + * Pointers to the LSM id structures for local use.
>    */
>   static int lsm_slot __lsm_ro_after_init;
> +static struct lsm_id *lsm_slotlist[LSMBLOB_ENTRIES];
>   
>   /**
>    * security_add_hooks - Add a modules hooks to the hook lists.
> @@ -459,6 +469,7 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count,
>   	if (lsmid->slot == LSMBLOB_NEEDED) {
>   		if (lsm_slot >= LSMBLOB_ENTRIES)
>   			panic("%s Too many LSMs registered.\n", __func__);
> +		lsm_slotlist[lsm_slot] = lsmid;
>   		lsmid->slot = lsm_slot++;
>   		init_debug("%s assigned lsmblob slot %d\n", lsmid->lsm,
>   			   lsmid->slot);
> @@ -588,6 +599,8 @@ int lsm_inode_alloc(struct inode *inode)
>    */
>   static int lsm_task_alloc(struct task_struct *task)
>   {
> +	int *display;
> +
>   	if (blob_sizes.lbs_task == 0) {
>   		task->security = NULL;
>   		return 0;
> @@ -596,6 +609,15 @@ static int lsm_task_alloc(struct task_struct *task)
>   	task->security = kzalloc(blob_sizes.lbs_task, GFP_KERNEL);
>   	if (task->security == NULL)
>   		return -ENOMEM;
> +
> +	/*
> +	 * The start of the task blob contains the "display" LSM slot number.
> +	 * Start with it set to the invalid slot number, indicating that the
> +	 * default first registered LSM be displayed.
> +	 */
> +	display = task->security;
> +	*display = LSMBLOB_INVALID;
> +
>   	return 0;
>   }
>   
> @@ -1551,14 +1573,26 @@ int security_file_open(struct file *file)
>   
>   int security_task_alloc(struct task_struct *task, unsigned long clone_flags)
>   {
> +	int *odisplay = current->security;
> +	int *ndisplay;
>   	int rc = lsm_task_alloc(task);
>   
> -	if (rc)
> +	if (unlikely(rc))
>   		return rc;
> +
>   	rc = call_int_hook(task_alloc, 0, task, clone_flags);
> -	if (unlikely(rc))
> +	if (unlikely(rc)) {
>   		security_task_free(task);
> -	return rc;
> +		return rc;
> +	}
> +
> +	if (odisplay) {
> +		ndisplay = task->security;
> +		if (ndisplay)
> +			*ndisplay = *odisplay;
> +	}
> +
> +	return 0;
>   }
>   
>   void security_task_free(struct task_struct *task)
> @@ -1955,23 +1989,110 @@ int security_getprocattr(struct task_struct *p, const char *lsm, char *name,
>   				char **value)
>   {
>   	struct security_hook_list *hp;
> +	int display = lsm_task_display(current);
> +	int slot = 0;
> +
> +	if (!strcmp(name, "display")) {
> +		/*
> +		 * lsm_slot will be 0 if there are no displaying modules.
> +		 */
> +		if (lsm_slot == 0)
> +			return -EINVAL;
> +
> +		/*
> +		 * Only allow getting the current process' display.
> +		 * There are too few reasons to get another process'
> +		 * display and too many LSM policy issues.
> +		 */
> +		if (current != p)
> +			return -EINVAL;
> +
> +		display = lsm_task_display(p);
> +		if (display != LSMBLOB_INVALID)
> +			slot = display;
> +		*value = kstrdup(lsm_slotlist[slot]->lsm, GFP_KERNEL);
> +		if (*value)
> +			return strlen(*value);
> +		return -ENOMEM;
> +	}
>   
>   	hlist_for_each_entry(hp, &security_hook_heads.getprocattr, list) {
>   		if (lsm != NULL && strcmp(lsm, hp->lsmid->lsm))
>   			continue;
> +		if (lsm == NULL && display != LSMBLOB_INVALID &&
> +		    display != hp->lsmid->slot)
> +			continue;
>   		return hp->hook.getprocattr(p, name, value);
>   	}
>   	return -EINVAL;
>   }
>   
> +/**
> + * security_setprocattr - Set process attributes via /proc
> + * @lsm: name of module involved, or NULL
> + * @name: name of the attribute
> + * @value: value to set the attribute to
> + * @size: size of the value
> + *
> + * Set the process attribute for the specified security module
> + * to the specified value. Note that this can only be used to set
> + * the process attributes for the current, or "self" process.
> + * The /proc code has already done this check.
> + *
> + * Returns 0 on success, an appropriate code otherwise.
> + */
>   int security_setprocattr(const char *lsm, const char *name, void *value,
>   			 size_t size)
>   {
>   	struct security_hook_list *hp;
> +	char *termed;
> +	char *copy;
> +	int *display = current->security;
> +	int rc = -EINVAL;
> +	int slot = 0;
> +
> +	if (!strcmp(name, "display")) {
> +		/*
> +		 * Change the "display" value only if all the security
> +		 * modules that support setting a procattr allow it.
> +		 * It is assumed that all such security modules will be
> +		 * cooperative.
> +		 */
> +		if (size == 0)
> +			return -EINVAL;
> +
> +		hlist_for_each_entry(hp, &security_hook_heads.setprocattr,
> +				     list) {
> +			rc = hp->hook.setprocattr(name, value, size);
> +			if (rc < 0)
> +				return rc;
> +		}
> +
> +		rc = -EINVAL;
> +
> +		copy = kmemdup_nul(value, size, GFP_KERNEL);
> +		if (copy == NULL)
> +			return -ENOMEM;
> +
> +		termed = strsep(&copy, " \n");
> +
> +		for (slot = 0; slot < lsm_slot; slot++)
> +			if (!strcmp(termed, lsm_slotlist[slot]->lsm)) {
> +				*display = lsm_slotlist[slot]->slot;
> +				rc = size;
> +				break;
> +			}
> +
> +		kfree(copy);
> +		return rc;
> +	}
>   
>   	hlist_for_each_entry(hp, &security_hook_heads.setprocattr, list) {
>   		if (lsm != NULL && strcmp(lsm, hp->lsmid->lsm))
>   			continue;
> +		if (lsm == NULL && *display != LSMBLOB_INVALID &&
> +		    *display != hp->lsmid->slot)
> +			continue;
>   		return hp->hook.setprocattr(name, value, size);
>   	}
>   	return -EINVAL;
> @@ -1991,15 +2112,15 @@ EXPORT_SYMBOL(security_ismaclabel);
>   int security_secid_to_secctx(struct lsmblob *blob, char **secdata, u32 *seclen)
>   {
>   	struct security_hook_list *hp;
> -	int rc;
> +	int display = lsm_task_display(current);
>   
>   	hlist_for_each_entry(hp, &security_hook_heads.secid_to_secctx, list) {
>   		if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
>   			continue;
> -		rc = hp->hook.secid_to_secctx(blob->secid[hp->lsmid->slot],
> -					      secdata, seclen);
> -		if (rc != 0)
> -			return rc;
> +		if (display == LSMBLOB_INVALID || display == hp->lsmid->slot)
> +			return hp->hook.secid_to_secctx(
> +					blob->secid[hp->lsmid->slot],
> +					secdata, seclen);
>   	}
>   	return 0;
>   }
> @@ -2009,16 +2130,15 @@ int security_secctx_to_secid(const char *secdata, u32 seclen,
>   			     struct lsmblob *blob)
>   {
>   	struct security_hook_list *hp;
> -	int rc;
> +	int display = lsm_task_display(current);
>   
>   	lsmblob_init(blob, 0);
>   	hlist_for_each_entry(hp, &security_hook_heads.secctx_to_secid, list) {
>   		if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
>   			continue;
> -		rc = hp->hook.secctx_to_secid(secdata, seclen,
> -					      &blob->secid[hp->lsmid->slot]);
> -		if (rc != 0)
> -			return rc;
> +		if (display == LSMBLOB_INVALID || display == hp->lsmid->slot)
> +			return hp->hook.secctx_to_secid(secdata, seclen,
> +						&blob->secid[hp->lsmid->slot]);
>   	}
>   	return 0;
>   }
> @@ -2026,7 +2146,14 @@ EXPORT_SYMBOL(security_secctx_to_secid);
>   
>   void security_release_secctx(char *secdata, u32 seclen)
>   {
> -	call_void_hook(release_secctx, secdata, seclen);
> +	struct security_hook_list *hp;
> +	int display = lsm_task_display(current);
> +
> +	hlist_for_each_entry(hp, &security_hook_heads.release_secctx, list)
> +		if (display == LSMBLOB_INVALID || display == hp->lsmid->slot) {
> +			hp->hook.release_secctx(secdata, seclen);
> +			return;
> +		}
>   }
>   EXPORT_SYMBOL(security_release_secctx);
>   
> @@ -2151,8 +2278,15 @@ EXPORT_SYMBOL(security_sock_rcv_skb);
>   int security_socket_getpeersec_stream(struct socket *sock, char __user *optval,
>   				      int __user *optlen, unsigned len)
>   {
> -	return call_int_hook(socket_getpeersec_stream, -ENOPROTOOPT, sock,
> -				optval, optlen, len);
> +	int display = lsm_task_display(current);
> +	struct security_hook_list *hp;
> +
> +	hlist_for_each_entry(hp, &security_hook_heads.socket_getpeersec_stream,
> +			     list)
> +		if (display == LSMBLOB_INVALID || display == hp->lsmid->slot)
> +			return hp->hook.socket_getpeersec_stream(sock, optval,
> +								 optlen, len);
> +	return -ENOPROTOOPT;
>   }
>   
>   int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb,
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 97f2ee6e4080..b8501ca3c8f3 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -6323,6 +6323,17 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)
>   	/*
>   	 * Basic control over ability to set these attributes at all.
>   	 */
> +
> +	/*
> +	 * For setting display, we only perform a permission check;
> +	 * the actual update to the display value is handled by the
> +	 * LSM framework.
> +	 */
> +	if (!strcmp(name, "display"))
> +		return avc_has_perm(&selinux_state,
> +				    mysid, mysid, SECCLASS_PROCESS2,
> +				    PROCESS2__SETDISPLAY, NULL);
> +
>   	if (!strcmp(name, "exec"))
>   		error = avc_has_perm(&selinux_state,
>   				     mysid, mysid, SECCLASS_PROCESS,
> diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
> index 7db24855e12d..323da8a38c43 100644
> --- a/security/selinux/include/classmap.h
> +++ b/security/selinux/include/classmap.h
> @@ -52,7 +52,7 @@ struct security_class_mapping secclass_map[] = {
>   	    "execmem", "execstack", "execheap", "setkeycreate",
>   	    "setsockcreate", "getrlimit", NULL } },
>   	{ "process2",
> -	  { "nnp_transition", "nosuid_transition", NULL } },
> +	  { "nnp_transition", "nosuid_transition", "setdisplay", NULL } },
>   	{ "system",
>   	  { "ipc_info", "syslog_read", "syslog_mod",
>   	    "syslog_console", "module_request", "module_load", NULL } },
> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> index 82cbb3eeec76..9737ead06b39 100644
> --- a/security/smack/smack_lsm.c
> +++ b/security/smack/smack_lsm.c
> @@ -3518,6 +3518,13 @@ static int smack_setprocattr(const char *name, void *value, size_t size)
>   	struct smack_known_list_elem *sklep;
>   	int rc;
>   
> +	/*
> +	 * Allow the /proc/.../attr/current and SO_PEERSEC "display"
> +	 * to be reset at will.
> +	 */
> +	if (strcmp(name, "display") == 0)
> +		return 0;
> +
>   	if (!smack_privileged(CAP_MAC_ADMIN) && list_empty(&tsp->smk_relabel))
>   		return -EPERM;
>   
> 


^ permalink raw reply

* Re: [PATCH v13 14/25] LSM: Ensure the correct LSM context releaser
From: Stephen Smalley @ 2020-01-07 19:16 UTC (permalink / raw)
  To: Casey Schaufler, casey.schaufler, jmorris, linux-security-module,
	selinux
  Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20191224235939.7483-15-casey@schaufler-ca.com>

On 12/24/19 6:59 PM, Casey Schaufler wrote:
> Add a new lsmcontext data structure to hold all the information
> about a "security context", including the string, its size and
> which LSM allocated the string. The allocation information is
> necessary because LSMs have different policies regarding the
> lifecycle of these strings. SELinux allocates and destroys
> them on each use, whereas Smack provides a pointer to an entry
> in a list that never goes away.
> 
> Reviewed-by: Kees Cook <keescook@chromium.org>
> Reviewed-by: John Johansen <john.johansen@canonical.com>
> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
> cc: linux-integrity@vger.kernel.org
> cc: netdev@vger.kernel.org
> ---
>   drivers/android/binder.c                | 10 ++++---
>   fs/ceph/xattr.c                         |  6 ++++-
>   fs/nfs/nfs4proc.c                       |  8 ++++--
>   fs/nfsd/nfs4xdr.c                       |  7 +++--
>   include/linux/security.h                | 35 +++++++++++++++++++++++--
>   include/net/scm.h                       |  5 +++-
>   kernel/audit.c                          | 14 +++++++---
>   kernel/auditsc.c                        | 12 ++++++---
>   net/ipv4/ip_sockglue.c                  |  4 ++-
>   net/netfilter/nf_conntrack_netlink.c    |  4 ++-
>   net/netfilter/nf_conntrack_standalone.c |  4 ++-
>   net/netfilter/nfnetlink_queue.c         | 13 ++++++---
>   net/netlabel/netlabel_unlabeled.c       | 19 +++++++++++---
>   net/netlabel/netlabel_user.c            |  4 ++-
>   security/security.c                     | 11 ++++----
>   15 files changed, 121 insertions(+), 35 deletions(-)
> 


> diff --git a/include/linux/security.h b/include/linux/security.h
> index d12b5e828b8d..c040c959b413 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -128,6 +128,37 @@ enum lockdown_reason {
>   	LOCKDOWN_CONFIDENTIALITY_MAX,
>   };
>   
> +/*
> + * A "security context" is the text representation of
> + * the information used by LSMs.
> + * This structure contains the string, its length, and which LSM
> + * it is useful for.
> + */
> +struct lsmcontext {
> +	char	*context;	/* Provided by the module */
> +	u32	len;
> +	int	slot;		/* Identifies the module */
> +};
> +
> +/**
> + * lsmcontext_init - initialize an lsmcontext structure.
> + * @cp: Pointer to the context to initialize
> + * @context: Initial context, or NULL
> + * @size: Size of context, or 0
> + * @slot: Which LSM provided the context
> + *
> + * Fill in the lsmcontext from the provided information.
> + * This is a scaffolding function that will be removed when
> + * lsmcontext integration is complete.

Still present after the entire series is applied, with one residual user 
in ceph.  Intentional or an oversight?

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

> + */
> +static inline void lsmcontext_init(struct lsmcontext *cp, char *context,
> +				   u32 size, int slot)
> +{
> +	cp->slot = slot;
> +	cp->context = context;
> +	cp->len = size;
> +}
> +
>   /*
>    * Data exported by the security modules
>    *



^ permalink raw reply

* Re: [PATCH v13 16/25] LSM: Use lsmcontext in security_dentry_init_security
From: Stephen Smalley @ 2020-01-07 19:23 UTC (permalink / raw)
  To: Casey Schaufler, casey.schaufler, jmorris, linux-security-module,
	selinux
  Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20191224235939.7483-17-casey@schaufler-ca.com>

On 12/24/19 6:59 PM, Casey Schaufler wrote:
> Change the security_dentry_init_security() interface to
> fill an lsmcontext structure instead of a void * data area
> and a length. The lone caller of this interface is NFS4,
> which may make copies of the data using its own mechanisms.
> A rework of the nfs4 code to use the lsmcontext properly
> is a significant project. SELinux is handled correctly, and
> is the only current user.
> 
> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
> ---
>   fs/nfs/nfs4proc.c        | 15 ++++++++-------
>   include/linux/security.h |  7 +++----
>   security/security.c      | 29 +++++++++++++++++++++++++----
>   3 files changed, 36 insertions(+), 15 deletions(-)
> 
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index a30e36654c57..6cd2463f890b 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -112,6 +112,7 @@ static inline struct nfs4_label *
>   nfs4_label_init_security(struct inode *dir, struct dentry *dentry,
>   	struct iattr *sattr, struct nfs4_label *label)
>   {
> +	struct lsmcontext context;
>   	int err;
>   
>   	if (label == NULL)
> @@ -121,21 +122,21 @@ nfs4_label_init_security(struct inode *dir, struct dentry *dentry,
>   		return NULL;
>   
>   	err = security_dentry_init_security(dentry, sattr->ia_mode,
> -				&dentry->d_name, (void **)&label->label, &label->len);
> +					    &dentry->d_name, &context);
> +
> +	label->label = context.context;
> +	label->len = context.len;

No point in setting label->label/len if err != 0.

> +
>   	if (err == 0)
>   		return label;
>   
>   	return NULL;
> +
>   }

Leftover empty line.

>   static inline void
>   nfs4_label_release_security(struct nfs4_label *label)
>   {
> -	struct lsmcontext scaff; /* scaffolding */
> -
> -	if (label) {
> -		lsmcontext_init(&scaff, label->label, label->len, 0);
> -		security_release_secctx(&scaff);
> -	}
> +	kfree(label->label);
>   }
>   static inline u32 *nfs4_bitmask(struct nfs_server *server, struct nfs4_label *label)
>   {

Not sure why you don't just leave the scaffolding here?

^ permalink raw reply

* Re: [PATCH v13 19/25] NET: Store LSM netlabel data in a lsmblob
From: Stephen Smalley @ 2020-01-07 19:25 UTC (permalink / raw)
  To: Casey Schaufler, casey.schaufler, jmorris, linux-security-module,
	selinux
  Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20191224235939.7483-20-casey@schaufler-ca.com>

On 12/24/19 6:59 PM, Casey Schaufler wrote:
> Netlabel uses LSM interfaces requiring an lsmblob and
> the internal storage is used to pass information between
> these interfaces, so change the internal data from a secid
> to a lsmblob. Update the netlabel interfaces and their
> callers to accommodate the change. This requires that the
> modules using netlabel use the lsm_id.slot to access the
> correct secid when using netlabel.
> 
> Reviewed-by: Kees Cook <keescook@chromium.org>
> Reviewed-by: John Johansen <john.johansen@canonical.com>
> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>

Why is this needed for stacking AppArmor?  AA doesn't use NetLabel, at 
least not upstream AFAICS.

> ---
>   include/net/netlabel.h              |  8 ++--
>   net/ipv4/cipso_ipv4.c               | 23 +++++++-----
>   net/netlabel/netlabel_kapi.c        |  6 +--
>   net/netlabel/netlabel_unlabeled.c   | 57 +++++++++++------------------
>   net/netlabel/netlabel_unlabeled.h   |  2 +-
>   security/selinux/hooks.c            |  2 +-
>   security/selinux/include/security.h |  1 +
>   security/selinux/netlabel.c         |  2 +-
>   security/selinux/ss/services.c      |  4 +-
>   security/smack/smack.h              |  1 +
>   security/smack/smack_lsm.c          |  5 ++-
>   security/smack/smackfs.c            | 10 +++--
>   12 files changed, 59 insertions(+), 62 deletions(-)
> 
> diff --git a/include/net/netlabel.h b/include/net/netlabel.h
> index 43ae50337685..73fc25b4042b 100644
> --- a/include/net/netlabel.h
> +++ b/include/net/netlabel.h
> @@ -166,7 +166,7 @@ struct netlbl_lsm_catmap {
>    * @attr.mls: MLS sensitivity label
>    * @attr.mls.cat: MLS category bitmap
>    * @attr.mls.lvl: MLS sensitivity level
> - * @attr.secid: LSM specific secid token
> + * @attr.lsmblob: LSM specific data
>    *
>    * Description:
>    * This structure is used to pass security attributes between NetLabel and the
> @@ -201,7 +201,7 @@ struct netlbl_lsm_secattr {
>   			struct netlbl_lsm_catmap *cat;
>   			u32 lvl;
>   		} mls;
> -		u32 secid;
> +		struct lsmblob lsmblob;
>   	} attr;
>   };
>   
> @@ -415,7 +415,7 @@ int netlbl_cfg_unlbl_static_add(struct net *net,
>   				const void *addr,
>   				const void *mask,
>   				u16 family,
> -				u32 secid,
> +				struct lsmblob *lsmblob,
>   				struct netlbl_audit *audit_info);
>   int netlbl_cfg_unlbl_static_del(struct net *net,
>   				const char *dev_name,
> @@ -523,7 +523,7 @@ static inline int netlbl_cfg_unlbl_static_add(struct net *net,
>   					      const void *addr,
>   					      const void *mask,
>   					      u16 family,
> -					      u32 secid,
> +					      struct lsmblob *lsmblob,
>   					      struct netlbl_audit *audit_info)
>   {
>   	return -ENOSYS;
> diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
> index 376882215919..adb9dffc3952 100644
> --- a/net/ipv4/cipso_ipv4.c
> +++ b/net/ipv4/cipso_ipv4.c
> @@ -106,15 +106,17 @@ int cipso_v4_rbm_strictvalid = 1;
>   /* Base length of the local tag (non-standard tag).
>    *  Tag definition (may change between kernel versions)
>    *
> - * 0          8          16         24         32
> - * +----------+----------+----------+----------+
> - * | 10000000 | 00000110 | 32-bit secid value  |
> - * +----------+----------+----------+----------+
> - * | in (host byte order)|
> - * +----------+----------+
> - *
> + * 0          8          16                    16 + sizeof(struct lsmblob)
> + * +----------+----------+---------------------+
> + * | 10000000 | 00000110 | LSM blob data       |
> + * +----------+----------+---------------------+
> + *
> + * All secid and flag fields are in host byte order.
> + * The lsmblob structure size varies depending on which
> + * Linux security modules are built in the kernel.
> + * The data is opaque.
>    */
> -#define CIPSO_V4_TAG_LOC_BLEN         6
> +#define CIPSO_V4_TAG_LOC_BLEN         (2 + sizeof(struct lsmblob))
>   
>   /*
>    * Helper Functions
> @@ -1467,7 +1469,8 @@ static int cipso_v4_gentag_loc(const struct cipso_v4_doi *doi_def,
>   
>   	buffer[0] = CIPSO_V4_TAG_LOCAL;
>   	buffer[1] = CIPSO_V4_TAG_LOC_BLEN;
> -	*(u32 *)&buffer[2] = secattr->attr.secid;
> +	memcpy(&buffer[2], &secattr->attr.lsmblob,
> +	       sizeof(secattr->attr.lsmblob));
>   
>   	return CIPSO_V4_TAG_LOC_BLEN;
>   }
> @@ -1487,7 +1490,7 @@ static int cipso_v4_parsetag_loc(const struct cipso_v4_doi *doi_def,
>   				 const unsigned char *tag,
>   				 struct netlbl_lsm_secattr *secattr)
>   {
> -	secattr->attr.secid = *(u32 *)&tag[2];
> +	memcpy(&secattr->attr.lsmblob, &tag[2], sizeof(secattr->attr.lsmblob));
>   	secattr->flags |= NETLBL_SECATTR_SECID;
>   
>   	return 0;
> diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
> index 409a3ae47ce2..f2ebd43a7992 100644
> --- a/net/netlabel/netlabel_kapi.c
> +++ b/net/netlabel/netlabel_kapi.c
> @@ -196,7 +196,7 @@ int netlbl_cfg_unlbl_map_add(const char *domain,
>    * @addr: IP address in network byte order (struct in[6]_addr)
>    * @mask: address mask in network byte order (struct in[6]_addr)
>    * @family: address family
> - * @secid: LSM secid value for the entry
> + * @lsmblob: LSM data value for the entry
>    * @audit_info: NetLabel audit information
>    *
>    * Description:
> @@ -210,7 +210,7 @@ int netlbl_cfg_unlbl_static_add(struct net *net,
>   				const void *addr,
>   				const void *mask,
>   				u16 family,
> -				u32 secid,
> +				struct lsmblob *lsmblob,
>   				struct netlbl_audit *audit_info)
>   {
>   	u32 addr_len;
> @@ -230,7 +230,7 @@ int netlbl_cfg_unlbl_static_add(struct net *net,
>   
>   	return netlbl_unlhsh_add(net,
>   				 dev_name, addr, mask, addr_len,
> -				 secid, audit_info);
> +				 lsmblob, audit_info);
>   }
>   
>   /**
> diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
> index c03fe9a4f7b9..3b0f07b59436 100644
> --- a/net/netlabel/netlabel_unlabeled.c
> +++ b/net/netlabel/netlabel_unlabeled.c
> @@ -66,7 +66,7 @@ struct netlbl_unlhsh_tbl {
>   #define netlbl_unlhsh_addr4_entry(iter) \
>   	container_of(iter, struct netlbl_unlhsh_addr4, list)
>   struct netlbl_unlhsh_addr4 {
> -	u32 secid;
> +	struct lsmblob lsmblob;
>   
>   	struct netlbl_af4list list;
>   	struct rcu_head rcu;
> @@ -74,7 +74,7 @@ struct netlbl_unlhsh_addr4 {
>   #define netlbl_unlhsh_addr6_entry(iter) \
>   	container_of(iter, struct netlbl_unlhsh_addr6, list)
>   struct netlbl_unlhsh_addr6 {
> -	u32 secid;
> +	struct lsmblob lsmblob;
>   
>   	struct netlbl_af6list list;
>   	struct rcu_head rcu;
> @@ -219,7 +219,7 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex)
>    * @iface: the associated interface entry
>    * @addr: IPv4 address in network byte order
>    * @mask: IPv4 address mask in network byte order
> - * @secid: LSM secid value for entry
> + * @lsmblob: LSM data value for entry
>    *
>    * Description:
>    * Add a new address entry into the unlabeled connection hash table using the
> @@ -230,7 +230,7 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex)
>   static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface,
>   				   const struct in_addr *addr,
>   				   const struct in_addr *mask,
> -				   u32 secid)
> +				   struct lsmblob *lsmblob)
>   {
>   	int ret_val;
>   	struct netlbl_unlhsh_addr4 *entry;
> @@ -242,7 +242,7 @@ static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface,
>   	entry->list.addr = addr->s_addr & mask->s_addr;
>   	entry->list.mask = mask->s_addr;
>   	entry->list.valid = 1;
> -	entry->secid = secid;
> +	entry->lsmblob = *lsmblob;
>   
>   	spin_lock(&netlbl_unlhsh_lock);
>   	ret_val = netlbl_af4list_add(&entry->list, &iface->addr4_list);
> @@ -259,7 +259,7 @@ static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface,
>    * @iface: the associated interface entry
>    * @addr: IPv6 address in network byte order
>    * @mask: IPv6 address mask in network byte order
> - * @secid: LSM secid value for entry
> + * @lsmblob: LSM data value for entry
>    *
>    * Description:
>    * Add a new address entry into the unlabeled connection hash table using the
> @@ -270,7 +270,7 @@ static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface,
>   static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface,
>   				   const struct in6_addr *addr,
>   				   const struct in6_addr *mask,
> -				   u32 secid)
> +				   struct lsmblob *lsmblob)
>   {
>   	int ret_val;
>   	struct netlbl_unlhsh_addr6 *entry;
> @@ -286,7 +286,7 @@ static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface,
>   	entry->list.addr.s6_addr32[3] &= mask->s6_addr32[3];
>   	entry->list.mask = *mask;
>   	entry->list.valid = 1;
> -	entry->secid = secid;
> +	entry->lsmblob = *lsmblob;
>   
>   	spin_lock(&netlbl_unlhsh_lock);
>   	ret_val = netlbl_af6list_add(&entry->list, &iface->addr6_list);
> @@ -365,7 +365,7 @@ int netlbl_unlhsh_add(struct net *net,
>   		      const void *addr,
>   		      const void *mask,
>   		      u32 addr_len,
> -		      u32 secid,
> +		      struct lsmblob *lsmblob,
>   		      struct netlbl_audit *audit_info)
>   {
>   	int ret_val;
> @@ -374,7 +374,6 @@ int netlbl_unlhsh_add(struct net *net,
>   	struct netlbl_unlhsh_iface *iface;
>   	struct audit_buffer *audit_buf = NULL;
>   	struct lsmcontext context;
> -	struct lsmblob blob;
>   
>   	if (addr_len != sizeof(struct in_addr) &&
>   	    addr_len != sizeof(struct in6_addr))
> @@ -407,7 +406,7 @@ int netlbl_unlhsh_add(struct net *net,
>   		const struct in_addr *addr4 = addr;
>   		const struct in_addr *mask4 = mask;
>   
> -		ret_val = netlbl_unlhsh_add_addr4(iface, addr4, mask4, secid);
> +		ret_val = netlbl_unlhsh_add_addr4(iface, addr4, mask4, lsmblob);
>   		if (audit_buf != NULL)
>   			netlbl_af4list_audit_addr(audit_buf, 1,
>   						  dev_name,
> @@ -420,7 +419,7 @@ int netlbl_unlhsh_add(struct net *net,
>   		const struct in6_addr *addr6 = addr;
>   		const struct in6_addr *mask6 = mask;
>   
> -		ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, secid);
> +		ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, lsmblob);
>   		if (audit_buf != NULL)
>   			netlbl_af6list_audit_addr(audit_buf, 1,
>   						  dev_name,
> @@ -437,8 +436,7 @@ int netlbl_unlhsh_add(struct net *net,
>   unlhsh_add_return:
>   	rcu_read_unlock();
>   	if (audit_buf != NULL) {
> -		lsmblob_init(&blob, secid);
> -		if (security_secid_to_secctx(&blob, &context) == 0) {
> +		if (security_secid_to_secctx(lsmblob, &context) == 0) {
>   			audit_log_format(audit_buf, " sec_obj=%s",
>   					 context.context);
>   			security_release_secctx(&context);
> @@ -473,7 +471,6 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
>   	struct audit_buffer *audit_buf;
>   	struct net_device *dev;
>   	struct lsmcontext context;
> -	struct lsmblob blob;
>   
>   	spin_lock(&netlbl_unlhsh_lock);
>   	list_entry = netlbl_af4list_remove(addr->s_addr, mask->s_addr,
> @@ -493,10 +490,8 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
>   					  addr->s_addr, mask->s_addr);
>   		if (dev != NULL)
>   			dev_put(dev);
> -		if (entry != NULL)
> -			lsmblob_init(&blob, entry->secid);
>   		if (entry != NULL &&
> -		    security_secid_to_secctx(&blob, &context) == 0) {
> +		    security_secid_to_secctx(&entry->lsmblob, &context) == 0) {
>   			audit_log_format(audit_buf, " sec_obj=%s",
>   					 context.context);
>   			security_release_secctx(&context);
> @@ -537,7 +532,6 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
>   	struct audit_buffer *audit_buf;
>   	struct net_device *dev;
>   	struct lsmcontext context;
> -	struct lsmblob blob;
>   
>   	spin_lock(&netlbl_unlhsh_lock);
>   	list_entry = netlbl_af6list_remove(addr, mask, &iface->addr6_list);
> @@ -556,10 +550,8 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
>   					  addr, mask);
>   		if (dev != NULL)
>   			dev_put(dev);
> -		if (entry != NULL)
> -			lsmblob_init(&blob, entry->secid);
>   		if (entry != NULL &&
> -		    security_secid_to_secctx(&blob, &context) == 0) {
> +		    security_secid_to_secctx(&entry->lsmblob, &context) == 0) {
>   			audit_log_format(audit_buf, " sec_obj=%s",
>   					 context.context);
>   			security_release_secctx(&context);
> @@ -913,9 +905,8 @@ static int netlbl_unlabel_staticadd(struct sk_buff *skb,
>   	if (ret_val != 0)
>   		return ret_val;
>   
> -	/* scaffolding with the [0] */
>   	return netlbl_unlhsh_add(&init_net,
> -				 dev_name, addr, mask, addr_len, blob.secid[0],
> +				 dev_name, addr, mask, addr_len, &blob,
>   				 &audit_info);
>   }
>   
> @@ -963,10 +954,8 @@ static int netlbl_unlabel_staticadddef(struct sk_buff *skb,
>   	if (ret_val != 0)
>   		return ret_val;
>   
> -	/* scaffolding with the [0] */
>   	return netlbl_unlhsh_add(&init_net,
> -				 NULL, addr, mask, addr_len, blob.secid[0],
> -				 &audit_info);
> +				 NULL, addr, mask, addr_len, &blob, &audit_info);
>   }
>   
>   /**
> @@ -1078,8 +1067,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
>   	struct net_device *dev;
>   	struct lsmcontext context;
>   	void *data;
> -	u32 secid;
> -	struct lsmblob blob;
> +	struct lsmblob *lsmb;
>   
>   	data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
>   			   cb_arg->seq, &netlbl_unlabel_gnl_family,
> @@ -1117,7 +1105,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
>   		if (ret_val != 0)
>   			goto list_cb_failure;
>   
> -		secid = addr4->secid;
> +		lsmb = (struct lsmblob *)&addr4->lsmblob;
>   	} else {
>   		ret_val = nla_put_in6_addr(cb_arg->skb,
>   					   NLBL_UNLABEL_A_IPV6ADDR,
> @@ -1131,11 +1119,10 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
>   		if (ret_val != 0)
>   			goto list_cb_failure;
>   
> -		secid = addr6->secid;
> +		lsmb = (struct lsmblob *)&addr6->lsmblob;
>   	}
>   
> -	lsmblob_init(&blob, secid);
> -	ret_val = security_secid_to_secctx(&blob, &context);
> +	ret_val = security_secid_to_secctx(lsmb, &context);
>   	if (ret_val != 0)
>   		goto list_cb_failure;
>   	ret_val = nla_put(cb_arg->skb,
> @@ -1487,7 +1474,7 @@ int netlbl_unlabel_getattr(const struct sk_buff *skb,
>   					      &iface->addr4_list);
>   		if (addr4 == NULL)
>   			goto unlabel_getattr_nolabel;
> -		secattr->attr.secid = netlbl_unlhsh_addr4_entry(addr4)->secid;
> +		secattr->attr.lsmblob = netlbl_unlhsh_addr4_entry(addr4)->lsmblob;
>   		break;
>   	}
>   #if IS_ENABLED(CONFIG_IPV6)
> @@ -1500,7 +1487,7 @@ int netlbl_unlabel_getattr(const struct sk_buff *skb,
>   					      &iface->addr6_list);
>   		if (addr6 == NULL)
>   			goto unlabel_getattr_nolabel;
> -		secattr->attr.secid = netlbl_unlhsh_addr6_entry(addr6)->secid;
> +		secattr->attr.lsmblob = netlbl_unlhsh_addr6_entry(addr6)->lsmblob;
>   		break;
>   	}
>   #endif /* IPv6 */
> diff --git a/net/netlabel/netlabel_unlabeled.h b/net/netlabel/netlabel_unlabeled.h
> index 058e3a285d56..168920780994 100644
> --- a/net/netlabel/netlabel_unlabeled.h
> +++ b/net/netlabel/netlabel_unlabeled.h
> @@ -211,7 +211,7 @@ int netlbl_unlhsh_add(struct net *net,
>   		      const void *addr,
>   		      const void *mask,
>   		      u32 addr_len,
> -		      u32 secid,
> +		      struct lsmblob *lsmblob,
>   		      struct netlbl_audit *audit_info);
>   int netlbl_unlhsh_remove(struct net *net,
>   			 const char *dev_name,
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index b8501ca3c8f3..cd4743331800 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -6871,7 +6871,7 @@ static int selinux_perf_event_write(struct perf_event *event)
>   }
>   #endif
>   
> -static struct lsm_id selinux_lsmid __lsm_ro_after_init = {
> +struct lsm_id selinux_lsmid __lsm_ro_after_init = {
>   	.lsm  = "selinux",
>   	.slot = LSMBLOB_NEEDED
>   };
> diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
> index ae840634e3c7..741ba0e6dd83 100644
> --- a/security/selinux/include/security.h
> +++ b/security/selinux/include/security.h
> @@ -70,6 +70,7 @@
>   struct netlbl_lsm_secattr;
>   
>   extern int selinux_enabled;
> +extern struct lsm_id selinux_lsmid;
>   
>   /* Policy capabilities */
>   enum {
> diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
> index 6a94b31b5472..d8d7603ab14e 100644
> --- a/security/selinux/netlabel.c
> +++ b/security/selinux/netlabel.c
> @@ -108,7 +108,7 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_getattr(
>   		return NULL;
>   
>   	if ((secattr->flags & NETLBL_SECATTR_SECID) &&
> -	    (secattr->attr.secid == sid))
> +	    (secattr->attr.lsmblob.secid[selinux_lsmid.slot] == sid))
>   		return secattr;
>   
>   	return NULL;
> diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
> index a5813c7629c1..2b7680903b6b 100644
> --- a/security/selinux/ss/services.c
> +++ b/security/selinux/ss/services.c
> @@ -3599,7 +3599,7 @@ int security_netlbl_secattr_to_sid(struct selinux_state *state,
>   	if (secattr->flags & NETLBL_SECATTR_CACHE)
>   		*sid = *(u32 *)secattr->cache->data;
>   	else if (secattr->flags & NETLBL_SECATTR_SECID)
> -		*sid = secattr->attr.secid;
> +		*sid = secattr->attr.lsmblob.secid[selinux_lsmid.slot];
>   	else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) {
>   		rc = -EIDRM;
>   		ctx = sidtab_search(sidtab, SECINITSID_NETMSG);
> @@ -3672,7 +3672,7 @@ int security_netlbl_sid_to_secattr(struct selinux_state *state,
>   	if (secattr->domain == NULL)
>   		goto out;
>   
> -	secattr->attr.secid = sid;
> +	secattr->attr.lsmblob.secid[selinux_lsmid.slot] = sid;
>   	secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID;
>   	mls_export_netlbl_lvl(policydb, ctx, secattr);
>   	rc = mls_export_netlbl_cat(policydb, ctx, secattr);
> diff --git a/security/smack/smack.h b/security/smack/smack.h
> index 2836540f9577..6e76b6b33063 100644
> --- a/security/smack/smack.h
> +++ b/security/smack/smack.h
> @@ -316,6 +316,7 @@ void smk_destroy_label_list(struct list_head *list);
>    * Shared data.
>    */
>   extern int smack_enabled;
> +extern struct lsm_id smack_lsmid;
>   extern int smack_cipso_direct;
>   extern int smack_cipso_mapped;
>   extern struct smack_known *smack_net_ambient;
> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> index 9737ead06b39..9ce67e03ac49 100644
> --- a/security/smack/smack_lsm.c
> +++ b/security/smack/smack_lsm.c
> @@ -3775,7 +3775,8 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap,
>   		/*
>   		 * Looks like a fallback, which gives us a secid.
>   		 */
> -		return smack_from_secid(sap->attr.secid);
> +		return smack_from_secid(
> +				sap->attr.lsmblob.secid[smack_lsmid.slot]);
>   	/*
>   	 * Without guidance regarding the smack value
>   	 * for the packet fall back on the network
> @@ -4592,7 +4593,7 @@ struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
>   	.lbs_sock = sizeof(struct socket_smack),
>   };
>   
> -static struct lsm_id smack_lsmid __lsm_ro_after_init = {
> +struct lsm_id smack_lsmid __lsm_ro_after_init = {
>   	.lsm  = "smack",
>   	.slot = LSMBLOB_NEEDED
>   };
> diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
> index e3e05c04dbd1..d10e9c96717e 100644
> --- a/security/smack/smackfs.c
> +++ b/security/smack/smackfs.c
> @@ -1122,6 +1122,7 @@ static void smk_net4addr_insert(struct smk_net4addr *new)
>   static ssize_t smk_write_net4addr(struct file *file, const char __user *buf,
>   				size_t count, loff_t *ppos)
>   {
> +	struct lsmblob lsmblob;
>   	struct smk_net4addr *snp;
>   	struct sockaddr_in newname;
>   	char *smack;
> @@ -1253,10 +1254,13 @@ static ssize_t smk_write_net4addr(struct file *file, const char __user *buf,
>   	 * this host so that incoming packets get labeled.
>   	 * but only if we didn't get the special CIPSO option
>   	 */
> -	if (rc == 0 && skp != NULL)
> +	if (rc == 0 && skp != NULL) {
> +		lsmblob_init(&lsmblob, 0);
> +		lsmblob.secid[smack_lsmid.slot] = snp->smk_label->smk_secid;
>   		rc = netlbl_cfg_unlbl_static_add(&init_net, NULL,
> -			&snp->smk_host, &snp->smk_mask, PF_INET,
> -			snp->smk_label->smk_secid, &audit_info);
> +			&snp->smk_host, &snp->smk_mask, PF_INET, &lsmblob,
> +			&audit_info);
> +	}
>   
>   	if (rc == 0)
>   		rc = count;
> 


^ permalink raw reply

* Re: [PATCH 1/2] selinux: treat atomic flags more carefully
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
In-Reply-To: <20200107133154.588958-2-omosnace@redhat.com>

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

* Re: [PATCH 2/2] security,selinux: get rid of security_delete_hooks()
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
In-Reply-To: <20200107133154.588958-3-omosnace@redhat.com>

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

* [PATCH 5.4 020/191] afs: Fix SELinux setting security label on /afs
From: Greg Kroah-Hartman @ 2020-01-07 20:52 UTC (permalink / raw)
  To: linux-kernel
  Cc: Greg Kroah-Hartman, stable, David Howells, Marc Dionne, selinux,
	linux-security-module, Sasha Levin
In-Reply-To: <20200107205332.984228665@linuxfoundation.org>

From: David Howells <dhowells@redhat.com>

[ Upstream commit bcbccaf2edcf1b76f73f890e968babef446151a4 ]

Make the AFS dynamic root superblock R/W so that SELinux can set the
security label on it.  Without this, upgrades to, say, the Fedora
filesystem-afs RPM fail if afs is mounted on it because the SELinux label
can't be (re-)applied.

It might be better to make it possible to bypass the R/O check for LSM
label application through setxattr.

Fixes: 4d673da14533 ("afs: Support the AFS dynamic root")
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Marc Dionne <marc.dionne@auristor.com>
cc: selinux@vger.kernel.org
cc: linux-security-module@vger.kernel.org
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 fs/afs/super.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/fs/afs/super.c b/fs/afs/super.c
index 488641b1a418..d9a6036b70b9 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -448,7 +448,6 @@ static int afs_fill_super(struct super_block *sb, struct afs_fs_context *ctx)
 	/* allocate the root inode and dentry */
 	if (as->dyn_root) {
 		inode = afs_iget_pseudo_dir(sb, true);
-		sb->s_flags	|= SB_RDONLY;
 	} else {
 		sprintf(sb->s_id, "%llu", as->volume->vid);
 		afs_activate_volume(as->volume);
-- 
2.20.1




^ permalink raw reply related

* [PATCH 4.19 011/115] afs: Fix SELinux setting security label on /afs
From: Greg Kroah-Hartman @ 2020-01-07 20:53 UTC (permalink / raw)
  To: linux-kernel
  Cc: Greg Kroah-Hartman, stable, David Howells, Marc Dionne, selinux,
	linux-security-module, Sasha Levin
In-Reply-To: <20200107205240.283674026@linuxfoundation.org>

From: David Howells <dhowells@redhat.com>

[ Upstream commit bcbccaf2edcf1b76f73f890e968babef446151a4 ]

Make the AFS dynamic root superblock R/W so that SELinux can set the
security label on it.  Without this, upgrades to, say, the Fedora
filesystem-afs RPM fail if afs is mounted on it because the SELinux label
can't be (re-)applied.

It might be better to make it possible to bypass the R/O check for LSM
label application through setxattr.

Fixes: 4d673da14533 ("afs: Support the AFS dynamic root")
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Marc Dionne <marc.dionne@auristor.com>
cc: selinux@vger.kernel.org
cc: linux-security-module@vger.kernel.org
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 fs/afs/super.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/fs/afs/super.c b/fs/afs/super.c
index 4d3e274207fb..bd2608297473 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -404,7 +404,6 @@ static int afs_fill_super(struct super_block *sb,
 	/* allocate the root inode and dentry */
 	if (as->dyn_root) {
 		inode = afs_iget_pseudo_dir(sb, true);
-		sb->s_flags	|= SB_RDONLY;
 	} else {
 		sprintf(sb->s_id, "%u", as->volume->vid);
 		afs_activate_volume(as->volume);
-- 
2.20.1




^ permalink raw reply related


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