All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sean Christopherson <sean.j.christopherson@intel.com>
To: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Cc: Andy Lutomirski <luto@kernel.org>,
	Cedric Xing <cedric.xing@intel.com>,
	Stephen Smalley <sds@tycho.nsa.gov>,
	James Morris <jmorris@namei.org>,
	"Serge E . Hallyn" <serge@hallyn.com>,
	LSM List <linux-security-module@vger.kernel.org>,
	Paul Moore <paul@paul-moore.com>,
	Eric Paris <eparis@parisplace.org>,
	selinux@vger.kernel.org, Jethro Beekman <jethro@fortanix.com>,
	Dave Hansen <dave.hansen@intel.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	LKML <linux-kernel@vger.kernel.org>, X86 ML <x86@kernel.org>,
	linux-sgx@vger.kernel.org,
	Andrew Morton <akpm@linux-foundation.org>,
	nhorman@redhat.com, npmccallum@redhat.com,
	Serge Ayoun <serge.ayoun@intel.com>,
	Shay Katz-zamir <shay.katz-zamir@intel.com>,
	Haitao Huang <haitao.huang@intel.com>,
	Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
	Kai Svahn <kai.svahn@intel.com>, Borislav Petkov <bp@alien8.de>,
	Josh Triplett <josh@joshtriplett.org>,
	Kai Huang <kai.huang@intel.com>,
	David Rientjes <rientjes@google.com>,
	William Roberts <william.c.roberts@intel.com>,
	Philip Tricca <philip.b.tricca@intel.com>
Subject: [RFC PATCH 9/9] security/selinux: Add enclave_load() implementation
Date: Fri, 31 May 2019 16:31:59 -0700	[thread overview]
Message-ID: <20190531233159.30992-10-sean.j.christopherson@intel.com> (raw)
In-Reply-To: <20190531233159.30992-1-sean.j.christopherson@intel.com>

The goal of selinux_enclave_load() is to provide a facsimile of the
existing selinux_file_mprotect() and file_map_prot_check() policies,
but tailored to the unique properties of SGX.

For example, an enclave page is technically backed by a MAP_SHARED file,
but the "file" is essentially shared memory that is never persisted
anywhere and also requires execute permissions (for some pages).

The basic concept is to require appropriate execute permissions on the
source of the enclave for pages that are requesting PROT_EXEC, e.g. if
an enclave page is being loaded from a regular file, require
FILE__EXECUTE and/or FILE__EXECMOND, and if it's coming from an
anonymous/private mapping, require PROCESS__EXECMEM since the process
is essentially executing from the mapping, albeit in a roundabout way.

Note, FILE__READ and FILE__WRITE are intentionally not required even if
the source page is backed by a regular file.  Writes to the enclave page
are contained to the EPC, i.e. never hit the original file, and read
permissions have already been vetted (or the VMA doesn't have PROT_READ,
in which case loading the page into the enclave will fail).

Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
 security/selinux/hooks.c | 85 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 85 insertions(+)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 3ec702cf46ca..f436a055dda7 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -6726,6 +6726,87 @@ static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
 }
 #endif
 
+#ifdef CONFIG_INTEL_SGX
+int selinux_enclave_load(struct vm_area_struct *vma, unsigned long prot,
+			 unsigned long *allowed_prot)
+{
+	const struct cred *cred = current_cred();
+	u32 sid = cred_sid(cred);
+	int rc;
+
+	/* SGX is supported only in 64-bit kernels. */
+	WARN_ON_ONCE(!default_noexec);
+
+	/*
+	 * SGX is responsible for checking @prot vs @allowed_prot, and SELinux
+	 * only cares about execute related permissions for enclaves.
+	 */
+	if (!(*allowed_prot & PROT_EXEC))
+		return 0;
+
+	/*
+	 * Loading an executable enclave page from a VMA that is not executable
+	 * itself requires EXECUTE permissions on the source file, or if there
+	 * is no regular source file, EXECMEM since the page is being loaded
+	 * from a non-executable anonymous mapping.
+	 */
+	if (!(vma->vm_flags & VM_EXEC)) {
+		if (vma->vm_file && !IS_PRIVATE(file_inode(vma->vm_file)))
+			rc = file_has_perm(cred, vma->vm_file, FILE__EXECUTE);
+		else
+			rc = avc_has_perm(&selinux_state,
+					  sid, sid, SECCLASS_PROCESS,
+					  PROCESS__EXECMEM, NULL);
+
+		/*
+		 * Reject the load if the enclave *needs* the page to be
+		 * executable, otherwise prevent it from becoming executable.
+		 */
+		if (rc) {
+			if (prot & PROT_EXEC)
+				return rc;
+
+			*allowed_prot &= ~PROT_EXEC;
+		}
+	}
+
+	/*
+	 * An enclave page that may do RW->RX or W+X requires EXECMOD (backed
+	 * by a regular file) or EXECMEM (loaded from an anonymous mapping).
+	 * Note, this hybrid EXECMOD and EXECMEM behavior is intentional and
+	 * reflects the nature of enclaves and the EPC, e.g. EPC is effectively
+	 * a non-persistent shared file, but each enclave is a private domain
+	 * within that shared file, so delegate to the source of the enclave.
+	 */
+	if ((*allowed_prot & PROT_EXEC) && (*allowed_prot & PROT_WRITE)) {
+		if (vma->vm_file && !IS_PRIVATE(file_inode(vma->vm_file)))
+			rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
+		else
+			rc = avc_has_perm(&selinux_state,
+					  sid, sid, SECCLASS_PROCESS,
+					  PROCESS__EXECMEM, NULL);
+		/*
+		 * Clear ALLOW_EXEC instead of ALLOWED_WRITE if permissions are
+		 * lacking and @prot has neither PROT_WRITE or PROT_EXEC.  If
+		 * userspace wanted RX they would have requested RX, and due to
+		 * lack of permissions they can never get RW->RX, i.e. the only
+		 * useful transition is R->RW.
+		 */
+		if (rc) {
+			if ((prot & PROT_EXEC) && (prot & PROT_WRITE))
+				return rc;
+
+			if (prot & PROT_EXEC)
+				*allowed_prot &= ~PROT_WRITE;
+			else
+				*allowed_prot &= ~PROT_EXEC;
+		}
+	}
+
+	return 0;
+}
+#endif
+
 struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = {
 	.lbs_cred = sizeof(struct task_security_struct),
 	.lbs_file = sizeof(struct file_security_struct),
@@ -6968,6 +7049,10 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
 	LSM_HOOK_INIT(bpf_map_free_security, selinux_bpf_map_free),
 	LSM_HOOK_INIT(bpf_prog_free_security, selinux_bpf_prog_free),
 #endif
+
+#ifdef CONFIG_INTEL_SGX
+	LSM_HOOK_INIT(enclave_load, selinux_enclave_load),
+#endif
 };
 
 static __init int selinux_init(void)
-- 
2.21.0


  parent reply	other threads:[~2019-05-31 23:32 UTC|newest]

Thread overview: 77+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-05-31 23:31 [RFC PATCH 0/9] security: x86/sgx: SGX vs. LSM Sean Christopherson
2019-05-31 23:31 ` [RFC PATCH 1/9] x86/sgx: Remove unused local variable in sgx_encl_release() Sean Christopherson
2019-06-04 11:41   ` Jarkko Sakkinen
2019-05-31 23:31 ` [RFC PATCH 2/9] x86/sgx: Do not naturally align MAP_FIXED address Sean Christopherson
2019-06-04 11:49   ` Jarkko Sakkinen
2019-06-04 20:16     ` Andy Lutomirski
2019-06-04 22:10       ` Xing, Cedric
2019-06-05 14:08         ` Sean Christopherson
2019-06-05 15:17         ` Jarkko Sakkinen
2019-06-05 20:14           ` Andy Lutomirski
2019-06-06 15:37             ` Jarkko Sakkinen
2019-06-13 13:48               ` Jarkko Sakkinen
2019-06-13 16:47                 ` Xing, Cedric
2019-06-13 17:14                   ` Sean Christopherson
2019-06-14 15:18                     ` Jarkko Sakkinen
2019-06-05 15:15       ` Jarkko Sakkinen
2019-05-31 23:31 ` [RFC PATCH 3/9] x86/sgx: Allow userspace to add multiple pages in single ioctl() Sean Christopherson
2019-06-03  6:26   ` Xing, Cedric
2019-06-03 20:08     ` Sean Christopherson
2019-06-03 20:39       ` Sean Christopherson
2019-06-03 23:45         ` Xing, Cedric
2019-06-04  0:54           ` Sean Christopherson
2019-06-04 20:18         ` Andy Lutomirski
2019-06-04 22:02           ` Xing, Cedric
2019-06-03 20:14   ` Dave Hansen
2019-06-03 20:37     ` Sean Christopherson
2019-06-03 20:39       ` Dave Hansen
2019-06-03 23:48       ` Xing, Cedric
2019-06-04  0:55         ` Sean Christopherson
2019-06-04 11:55   ` Jarkko Sakkinen
2019-05-31 23:31 ` [RFC PATCH 4/9] mm: Introduce vm_ops->mprotect() Sean Christopherson
2019-06-03  6:27   ` Xing, Cedric
2019-06-04 12:24   ` Jarkko Sakkinen
2019-06-04 14:51   ` Andy Lutomirski
2019-05-31 23:31 ` [RFC PATCH 5/9] x86/sgx: Restrict mapping without an enclave page to PROT_NONE Sean Christopherson
2019-06-03  6:28   ` Xing, Cedric
2019-06-04 15:32   ` Jarkko Sakkinen
2019-05-31 23:31 ` [RFC PATCH 6/9] x86/sgx: Require userspace to provide allowed prots to ADD_PAGES Sean Christopherson
2019-06-03  6:28   ` Xing, Cedric
2019-06-04 16:23   ` Jarkko Sakkinen
2019-06-04 16:45     ` Sean Christopherson
2019-06-05 15:06       ` Jarkko Sakkinen
2019-06-04 20:23   ` Andy Lutomirski
2019-06-05 11:10   ` Ayoun, Serge
2019-06-05 23:58     ` Sean Christopherson
2019-05-31 23:31 ` [RFC PATCH 7/9] x86/sgx: Enforce noexec filesystem restriction for enclaves Sean Christopherson
2019-06-03  6:29   ` Xing, Cedric
2019-06-04 20:26     ` Andy Lutomirski
2019-06-04 16:25   ` Jarkko Sakkinen
2019-06-04 20:25     ` Andy Lutomirski
2019-06-04 20:34       ` Sean Christopherson
2019-06-04 21:54       ` Xing, Cedric
2019-06-05 15:10       ` Jarkko Sakkinen
2019-06-06  1:01         ` Sean Christopherson
2019-05-31 23:31 ` [RFC PATCH 8/9] LSM: x86/sgx: Introduce ->enclave_load() hook for Intel SGX Sean Christopherson
2019-06-03  6:28   ` Xing, Cedric
2019-06-03 14:19   ` Stephen Smalley
2019-06-03 14:42     ` Sean Christopherson
2019-06-03 18:38       ` Stephen Smalley
2019-06-03 18:45         ` Dave Hansen
2019-06-04 20:29   ` Andy Lutomirski
2019-06-04 20:36     ` Sean Christopherson
2019-06-04 21:43       ` Xing, Cedric
2019-06-06  2:04         ` Sean Christopherson
2019-05-31 23:31 ` Sean Christopherson [this message]
2019-06-03 15:01   ` [RFC PATCH 9/9] security/selinux: Add enclave_load() implementation Stephen Smalley
2019-06-03 15:50     ` Sean Christopherson
2019-06-02  7:29 ` [RFC PATCH 0/9] security: x86/sgx: SGX vs. LSM Xing, Cedric
2019-06-03 17:15   ` Sean Christopherson
2019-06-03 18:30     ` Xing, Cedric
2019-06-04  1:36       ` Sean Christopherson
2019-06-04 15:33       ` Stephen Smalley
2019-06-04 16:30         ` Sean Christopherson
2019-06-04 21:38         ` Xing, Cedric
2019-06-03 17:47   ` Stephen Smalley
2019-06-03 18:02     ` Xing, Cedric
2019-06-04 11:15 ` Jarkko Sakkinen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190531233159.30992-10-sean.j.christopherson@intel.com \
    --to=sean.j.christopherson@intel.com \
    --cc=akpm@linux-foundation.org \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=bp@alien8.de \
    --cc=cedric.xing@intel.com \
    --cc=dave.hansen@intel.com \
    --cc=eparis@parisplace.org \
    --cc=haitao.huang@intel.com \
    --cc=jarkko.sakkinen@linux.intel.com \
    --cc=jethro@fortanix.com \
    --cc=jmorris@namei.org \
    --cc=josh@joshtriplett.org \
    --cc=kai.huang@intel.com \
    --cc=kai.svahn@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=linux-sgx@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=nhorman@redhat.com \
    --cc=npmccallum@redhat.com \
    --cc=paul@paul-moore.com \
    --cc=philip.b.tricca@intel.com \
    --cc=rientjes@google.com \
    --cc=sds@tycho.nsa.gov \
    --cc=selinux@vger.kernel.org \
    --cc=serge.ayoun@intel.com \
    --cc=serge@hallyn.com \
    --cc=shay.katz-zamir@intel.com \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.org \
    --cc=william.c.roberts@intel.com \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.