From patchwork Tue Jan 7 13:31:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ondrej Mosnacek X-Patchwork-Id: 11320905 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6A96B6C1 for ; Tue, 7 Jan 2020 13:32:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3F9A3208C4 for ; Tue, 7 Jan 2020 13:32:05 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="dUAnfBmu" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728006AbgAGNcF (ORCPT ); Tue, 7 Jan 2020 08:32:05 -0500 Received: from us-smtp-1.mimecast.com ([205.139.110.61]:46284 "EHLO us-smtp-delivery-1.mimecast.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728115AbgAGNcE (ORCPT ); Tue, 7 Jan 2020 08:32:04 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1578403922; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=qyaqqREnkpVhglZ516gFAkxLLNwR7BKT/czon5pgNjM=; b=dUAnfBmuoeleYXj+sxUT6sxJy3WhDOsI8X3d8iTBLG2t9Lo9kq6g9VHvoLWyRTpGjvvUSy q5bRfLPQCrNzlRuW23Lp0S87zh6UVkshhl2Sxdtg0dERadJt3ioolVIzzV/OlsS9sPpydK afYFlllIogh6quaZDy8kmL4837vuiQc= Received: from mail-wr1-f72.google.com (mail-wr1-f72.google.com [209.85.221.72]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-244-MkLH1xsINe6fiEHFZxeEMw-1; Tue, 07 Jan 2020 08:32:00 -0500 X-MC-Unique: MkLH1xsINe6fiEHFZxeEMw-1 Received: by mail-wr1-f72.google.com with SMTP id v17so27016724wrm.17 for ; Tue, 07 Jan 2020 05:31:59 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=qyaqqREnkpVhglZ516gFAkxLLNwR7BKT/czon5pgNjM=; b=uOdZPql6vT2cTazdALl+IhmZ5+gqatrmqDg7Jnr7YHuw9ox8A8imXegEfzKqp11V6A +tf24k2Ed82JFy4T8nhIBIihpx6cLpeCkMqRnOKx2+dC1ns/7+oPDCrDOyPajs6fvJv3 U2hUjPrCa34fXGqUH/AfedsboPBPiwkVbnsweYcPZ0wcat9MWcnKvvspiigzuV8n8l2i QhU1on+VWps3RF33cqOLH/JNNPdcFhtOfpUDr6pPFol4lRUbDq8EvkkTpaybPAnuqMhU YXx3Fx+WkcgEorhoa0Z/uaFeUD1rL8hNwwnfsL7AlkRESnuARl2/wGgdhjRM8Fqvg556 MM1A== X-Gm-Message-State: APjAAAVYRrGOtHMzTioeY+jzr0U9k+MEKmfM5gKt2I774WwhDbaKa9L6 q2zjezGnoephNgG//OB1oJu2j53RSnU40H//aIpwnjxVOLTh6A2H73UbEU0GLbDUjmSl8Be49+q XeW1XW+4cwK0SJs6UMA== X-Received: by 2002:a7b:cbcd:: with SMTP id n13mr39916406wmi.104.1578403918941; Tue, 07 Jan 2020 05:31:58 -0800 (PST) X-Google-Smtp-Source: APXvYqxGDrhx9S7+S433gHy6DUA1BbyIzCh/vT9XirfjS+1A5A9CZ87irnpGvLqV9bd7Rtu3z88nZw== X-Received: by 2002:a7b:cbcd:: with SMTP id n13mr39916362wmi.104.1578403918528; Tue, 07 Jan 2020 05:31:58 -0800 (PST) Received: from omos.redhat.com (nat-pool-brq-t.redhat.com. [213.175.37.10]) by smtp.gmail.com with ESMTPSA id f207sm29097127wme.9.2020.01.07.05.31.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Jan 2020 05:31:57 -0800 (PST) From: Ondrej Mosnacek To: linux-security-module@vger.kernel.org, James Morris , "Serge E. Hallyn" Cc: Casey Schaufler , selinux@vger.kernel.org, Paul Moore , Stephen Smalley , John Johansen , Kees Cook , Micah Morton , Tetsuo Handa Subject: [PATCH 1/2] selinux: treat atomic flags more carefully Date: Tue, 7 Jan 2020 14:31:53 +0100 Message-Id: <20200107133154.588958-2-omosnace@redhat.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200107133154.588958-1-omosnace@redhat.com> References: <20200107133154.588958-1-omosnace@redhat.com> MIME-Version: 1.0 Sender: selinux-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org 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 Acked-by: Stephen Smalley Reviewed-by: Kees Cook Reviewed-by: James Morris --- 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); From patchwork Tue Jan 7 13:31:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ondrej Mosnacek X-Patchwork-Id: 11320907 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 21A056C1 for ; Tue, 7 Jan 2020 13:32:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C22BC2146E for ; Tue, 7 Jan 2020 13:32:08 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="A/pHyLmq" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728172AbgAGNcI (ORCPT ); Tue, 7 Jan 2020 08:32:08 -0500 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:57174 "EHLO us-smtp-1.mimecast.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728115AbgAGNcI (ORCPT ); Tue, 7 Jan 2020 08:32:08 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1578403925; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=NThNQIyGC7lxATvQzw927ctg+bT4CrbGBjSVXk1Dh9Y=; b=A/pHyLmqDS5/H63mw/3Y0ffTPLdh8eQKWx1Wl6dsBTqC7UCE9IsBVOne7aZZSTNA+8dkv2 on7JFPjFHPuTYMcoAI8MgS+7n10f7tcBCoAnOBVsaOLmt3ft/igg28OfUWXyQfYmGBLbsZ yHtLsr9HuROglqjjwLhYfWTqDMianFY= Received: from mail-wr1-f71.google.com (mail-wr1-f71.google.com [209.85.221.71]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-156-bcF5M2C-OV6TqhmO7GLpmA-1; Tue, 07 Jan 2020 08:32:04 -0500 X-MC-Unique: bcF5M2C-OV6TqhmO7GLpmA-1 Received: by mail-wr1-f71.google.com with SMTP id z10so24411139wrt.21 for ; Tue, 07 Jan 2020 05:32:03 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=NThNQIyGC7lxATvQzw927ctg+bT4CrbGBjSVXk1Dh9Y=; b=GLi79PrOyl3Qz8jjcQdWWhqHhmd0dfc+hs3UZT4FuARRsoxjRD6A2lbc9uoJEJaZHO HHjSNK6Kis4n9ZdL4QhbjvRczcC0fHtXKPRwj8d8FTkeqnq4tHvYXLxVBcZ3dmZr7ohP ECY1VW28CR+CaCtj6iaBWjcdutFUnJzKTwsZqCNUA271pkApm49+fDA9mv2ddNWXq4K5 lZ4Ij4Li/PaHaf668OAZUB7pkPdURu4EdOs9BRZA19goUKOxKfL2IPc2WwsEW5By1WCX qcQw/f9atLQALULjI3SouiGb1CGXgnMW8n4Yjl3XXSas3FmOzDv8ugfaE8aIYwn4W9zV ToQQ== X-Gm-Message-State: APjAAAVCY60OKuk4PJ9U9xykKllMoLeKK2X3CvwW9yKf/W5zdGYTzUr+ 8UpBFYAOgDEJtcK7O4fSPh03RI8KvZrc+1YCXjEvp1ZQDIyWKlwWLQStAol3LNIa/rYb/AAhucG k1WYvfoRJ1ghOxepuSg== X-Received: by 2002:a1c:f407:: with SMTP id z7mr38520034wma.72.1578403921602; Tue, 07 Jan 2020 05:32:01 -0800 (PST) X-Google-Smtp-Source: APXvYqwPQ/7iWzMfKr7H5F96yNP+TX4ovzy5oUgN7+J5vIRc4APh+2GfCjia6pApmkB5cg+FQ1z1Gg== X-Received: by 2002:a1c:f407:: with SMTP id z7mr38519890wma.72.1578403920013; Tue, 07 Jan 2020 05:32:00 -0800 (PST) Received: from omos.redhat.com (nat-pool-brq-t.redhat.com. [213.175.37.10]) by smtp.gmail.com with ESMTPSA id f207sm29097127wme.9.2020.01.07.05.31.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Jan 2020 05:31:59 -0800 (PST) From: Ondrej Mosnacek To: linux-security-module@vger.kernel.org, James Morris , "Serge E. Hallyn" Cc: Casey Schaufler , selinux@vger.kernel.org, Paul Moore , Stephen Smalley , John Johansen , Kees Cook , Micah Morton , Tetsuo Handa Subject: [PATCH 2/2] security,selinux: get rid of security_delete_hooks() Date: Tue, 7 Jan 2020 14:31:54 +0100 Message-Id: <20200107133154.588958-3-omosnace@redhat.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200107133154.588958-1-omosnace@redhat.com> References: <20200107133154.588958-1-omosnace@redhat.com> MIME-Version: 1.0 Sender: selinux-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org 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 Signed-off-by: Ondrej Mosnacek Acked-by: Casey Schaufler Reviewed-by: Kees Cook --- 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 #include -#include /** * 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 #include #include +#include #include #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),