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 6/9] x86/sgx: Require userspace to provide allowed prots to ADD_PAGES
Date: Fri, 31 May 2019 16:31:56 -0700	[thread overview]
Message-ID: <20190531233159.30992-7-sean.j.christopherson@intel.com> (raw)
In-Reply-To: <20190531233159.30992-1-sean.j.christopherson@intel.com>

...to support (the equivalent) of existing Linux Security Module
functionality.

Because SGX manually manages EPC memory, all enclave VMAs are backed by
the same vm_file, i.e. /dev/sgx/enclave, so that SGX can implement the
necessary hooks to move pages in/out of the EPC.  And because EPC pages
for any given enclave are fundamentally shared between processes, i.e.
CoW semantics are not possible with EPC pages, /dev/sgx/enclave must
always be MAP_SHARED.  Lastly, all real world enclaves will need read,
write and execute permissions to EPC pages.  As a result, SGX does not
play nice with existing LSM behavior as it is impossible to apply
policies to enclaves with any reasonable granularity, e.g. an LSM can
deny access to EPC altogether, but can't deny potentially dangerous
behavior such as mapping pages RW->RW or RWX.

To give LSMs enough information to implement their policies without
having to resort to ugly things, e.g. holding a reference to the vm_file
of each enclave page, require userspace to explicitly state the allowed
protections for each page (region), i.e. take ALLOW_{READ,WRITE,EXEC}
in the ADD_PAGES ioctl.

The ALLOW_* flags will be passed to LSMs so that they can make informed
decisions when the enclave is being built, i.e. when the source vm_file
is available.  For example, SELinux's EXECMOD permission can be
required if an enclave is requesting both ALLOW_WRITE and ALLOW_EXEC.

Update the mmap()/mprotect() hooks to enforce the ALLOW_* protections,
a la the standard VM_MAY{READ,WRITE,EXEC} flags.

The ALLOW_EXEC flag also has a second (important) use in that it can
be used to prevent loading an enclave from a noexec file system, on
SGX2 hardware (regardless of kernel support for SGX2), userspace could
EADD from a noexec path using read-only permissions and later mprotect()
and ENCLU[EMODPE] the page to gain execute permissions.  By requiring
ALLOW_EXEC up front, SGX will be able to enforce noexec paths when
building the enclave.

Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
 arch/x86/include/uapi/asm/sgx.h        |  9 ++++++++-
 arch/x86/kernel/cpu/sgx/driver/ioctl.c | 23 +++++++++++++++++------
 arch/x86/kernel/cpu/sgx/encl.c         |  2 +-
 arch/x86/kernel/cpu/sgx/encl.h         |  1 +
 4 files changed, 27 insertions(+), 8 deletions(-)

diff --git a/arch/x86/include/uapi/asm/sgx.h b/arch/x86/include/uapi/asm/sgx.h
index 4a12d6abbcb7..4489e92fa0dc 100644
--- a/arch/x86/include/uapi/asm/sgx.h
+++ b/arch/x86/include/uapi/asm/sgx.h
@@ -31,6 +31,11 @@ struct sgx_enclave_create  {
 	__u64	src;
 };
 
+/* Supported flags for struct sgx_enclave_add_pages. */
+#define SGX_ALLOW_READ	VM_READ
+#define SGX_ALLOW_WRITE	VM_WRITE
+#define SGX_ALLOW_EXEC	VM_EXEC
+
 /**
  * struct sgx_enclave_add_pages - parameter structure for the
  *                                %SGX_IOC_ENCLAVE_ADD_PAGES ioctl
@@ -39,6 +44,7 @@ struct sgx_enclave_create  {
  * @secinfo:	address for the SECINFO data (common to all pages)
  * @nr_pages:	number of pages (must be virtually contiguous)
  * @mrmask:	bitmask for the measured 256 byte chunks (common to all pages)
+ * @flags:	flags, e.g. SGX_ALLOW_{READ,WRITE,EXEC} (common to all pages)
  */
 struct sgx_enclave_add_pages {
 	__u64	addr;
@@ -46,7 +52,8 @@ struct sgx_enclave_add_pages {
 	__u64	secinfo;
 	__u32	nr_pages;
 	__u16	mrmask;
-} __attribute__((__packed__));
+	__u16	flags;
+};
 
 /**
  * struct sgx_enclave_init - parameter structure for the
diff --git a/arch/x86/kernel/cpu/sgx/driver/ioctl.c b/arch/x86/kernel/cpu/sgx/driver/ioctl.c
index 6acfcbdeca9a..c30acd3fbbdd 100644
--- a/arch/x86/kernel/cpu/sgx/driver/ioctl.c
+++ b/arch/x86/kernel/cpu/sgx/driver/ioctl.c
@@ -235,7 +235,8 @@ static int sgx_validate_secs(const struct sgx_secs *secs,
 }
 
 static struct sgx_encl_page *sgx_encl_page_alloc(struct sgx_encl *encl,
-						 unsigned long addr)
+						 unsigned long addr,
+						 unsigned long allowed_prot)
 {
 	struct sgx_encl_page *encl_page;
 	int ret;
@@ -247,6 +248,7 @@ static struct sgx_encl_page *sgx_encl_page_alloc(struct sgx_encl *encl,
 		return ERR_PTR(-ENOMEM);
 	encl_page->desc = addr;
 	encl_page->encl = encl;
+	encl_page->allowed_prot = allowed_prot;
 	ret = radix_tree_insert(&encl->page_tree, PFN_DOWN(encl_page->desc),
 				encl_page);
 	if (ret) {
@@ -530,7 +532,7 @@ static int sgx_encl_queue_page(struct sgx_encl *encl,
 
 static int __sgx_encl_add_page(struct sgx_encl *encl, unsigned long addr,
 			       void *data, struct sgx_secinfo *secinfo,
-			       unsigned int mrmask)
+			       unsigned int mrmask, unsigned long allowed_prot)
 {
 	u64 page_type = secinfo->flags & SGX_SECINFO_PAGE_TYPE_MASK;
 	struct sgx_encl_page *encl_page;
@@ -556,7 +558,7 @@ static int __sgx_encl_add_page(struct sgx_encl *encl, unsigned long addr,
 		goto out;
 	}
 
-	encl_page = sgx_encl_page_alloc(encl, addr);
+	encl_page = sgx_encl_page_alloc(encl, addr, allowed_prot);
 	if (IS_ERR(encl_page)) {
 		ret = PTR_ERR(encl_page);
 		goto out;
@@ -576,12 +578,20 @@ static int __sgx_encl_add_page(struct sgx_encl *encl, unsigned long addr,
 
 static int sgx_encl_add_page(struct sgx_encl *encl, unsigned long addr,
 			     unsigned long src, struct sgx_secinfo *secinfo,
-			     unsigned int mrmask)
+			     unsigned int mrmask, unsigned int flags)
 {
+	unsigned long prot = secinfo->flags & (VM_READ | VM_WRITE | VM_EXEC);
+	unsigned long allowed_prot = flags & (VM_READ | VM_WRITE | VM_EXEC);
 	struct page *data_page;
 	void *data;
 	int ret;
 
+	BUILD_BUG_ON(SGX_SECINFO_R != VM_READ || SGX_SECINFO_W != VM_WRITE ||
+		     SGX_SECINFO_X != VM_EXEC);
+
+	if (prot & ~allowed_prot)
+		return -EACCES;
+
 	data_page = alloc_page(GFP_HIGHUSER);
 	if (!data_page)
 		return -ENOMEM;
@@ -593,7 +603,8 @@ static int sgx_encl_add_page(struct sgx_encl *encl, unsigned long addr,
 		goto out;
 	}
 
-	ret = __sgx_encl_add_page(encl, addr, data, secinfo, mrmask);
+	ret = __sgx_encl_add_page(encl, addr, data, secinfo, mrmask,
+				  allowed_prot);
 out:
 	kunmap(data_page);
 	__free_page(data_page);
@@ -645,7 +656,7 @@ static long sgx_ioc_enclave_add_pages(struct file *filep, unsigned int cmd,
 
 		ret = sgx_encl_add_page(encl, addp->addr + i*PAGE_SIZE,
 					addp->src + i*PAGE_SIZE,
-					&secinfo, addp->mrmask);
+					&secinfo, addp->mrmask, addp->flags);
 	}
 	return ret;
 }
diff --git a/arch/x86/kernel/cpu/sgx/encl.c b/arch/x86/kernel/cpu/sgx/encl.c
index 955d4f430adc..e5847571a265 100644
--- a/arch/x86/kernel/cpu/sgx/encl.c
+++ b/arch/x86/kernel/cpu/sgx/encl.c
@@ -249,7 +249,7 @@ int sgx_map_allowed(struct sgx_encl *encl, unsigned long start,
 
 	for (addr = start; addr < end; addr += PAGE_SIZE) {
 		page = radix_tree_lookup(&encl->page_tree, addr >> PAGE_SHIFT);
-		if (!page)
+		if (!page || (prot & ~page->allowed_prot))
 			return -EACCES;
 	}
 
diff --git a/arch/x86/kernel/cpu/sgx/encl.h b/arch/x86/kernel/cpu/sgx/encl.h
index 6e310e3b3fff..7cca076a4987 100644
--- a/arch/x86/kernel/cpu/sgx/encl.h
+++ b/arch/x86/kernel/cpu/sgx/encl.h
@@ -41,6 +41,7 @@ enum sgx_encl_page_desc {
 
 struct sgx_encl_page {
 	unsigned long desc;
+	unsigned long allowed_prot;
 	struct sgx_epc_page *epc_page;
 	struct sgx_va_page *va_page;
 	struct sgx_encl *encl;
-- 
2.21.0


  parent reply	other threads:[~2019-05-31 23:33 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 ` Sean Christopherson [this message]
2019-06-03  6:28   ` [RFC PATCH 6/9] x86/sgx: Require userspace to provide allowed prots to ADD_PAGES 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 ` [RFC PATCH 9/9] security/selinux: Add enclave_load() implementation Sean Christopherson
2019-06-03 15:01   ` 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-7-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.