linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Reinette Chatre <reinette.chatre@intel.com>
To: dave.hansen@linux.intel.com, jarkko@kernel.org,
	tglx@linutronix.de, bp@alien8.de, luto@kernel.org,
	mingo@redhat.com, linux-sgx@vger.kernel.org, x86@kernel.org
Cc: seanjc@google.com, kai.huang@intel.com, cathy.zhang@intel.com,
	cedric.xing@intel.com, haitao.huang@intel.com,
	mark.shanahan@intel.com, hpa@zytor.com,
	linux-kernel@vger.kernel.org
Subject: [PATCH 13/25] x86/sgx: Support adding of pages to initialized enclave
Date: Wed,  1 Dec 2021 11:23:11 -0800	[thread overview]
Message-ID: <9ab661a845d242cb10a90ade997f8ebda33cc7c9.1638381245.git.reinette.chatre@intel.com> (raw)
In-Reply-To: <cover.1638381245.git.reinette.chatre@intel.com>

With SGX1 an enclave needs to be created with its maximum memory demands
allocated. Pages cannot be added to an enclave after it is initialized.
SGX2 introduces a new function, ENCLS[EAUG], that can be used to add
pages to an initialized enclave. With SGX2 the enclave still needs to
set aside address space for its maximum memory demands during enclave
creation, but all pages need not be added before enclave initialization.
Pages can be added during enclave runtime.

Add support for dynamically adding pages to an initialized enclave,
architecturally limited to RW permission. Add pages via the page fault
handler at the time an enclave address without a backing enclave page
is accessed, potentially directly reclaiming pages if no free pages
are available.

The enclave is still required to run ENCLU[EACCEPT] on the page before
it can be used. A useful flow is for the enclave to run ENCLU[EACCEPT]
on an uninitialized address. This will trigger the page fault handler
that will add the enclave page and return execution to the enclave to
repeat the ENCLU[EACCEPT] instruction, this time successful.

If the enclave accesses an uninitialized address in another way, for
example by expanding the enclave stack to a page that has not yet been
added, then the page fault handler would add the page on the first
write but upon returning to the enclave the instruction that triggered
the page fault would be repeated and since ENCLU[EACCEPT] was not run
yet it would trigger a second page fault, this time with the SGX flag
set in the page fault error code. This can only be recovered by entering
the enclave again and directly running the ENCLU[EACCEPT] instruction on
the now initialized address.

Accessing an uninitialized address from outside the enclave also triggers
this flow but the page will remain in PENDING state until accepted from
within the enclave.

The page is added with the architecturally constrained RW permissions
as runtime as well as maximum allowed permissions. It is understood that
there are some use cases, for example code relocation, that requires RWX
maximum permissions. Supporting these use cases require guidance from user
space policy before such maximum permissions can be allowed. Integration
with user policy is deferred to a follow-up series.

Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 arch/x86/kernel/cpu/sgx/encl.c  | 133 ++++++++++++++++++++++++++++++++
 arch/x86/kernel/cpu/sgx/encl.h  |   2 +
 arch/x86/kernel/cpu/sgx/ioctl.c |   4 +-
 3 files changed, 137 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/cpu/sgx/encl.c b/arch/x86/kernel/cpu/sgx/encl.c
index 03c4d7e00b44..342b97dd4c33 100644
--- a/arch/x86/kernel/cpu/sgx/encl.c
+++ b/arch/x86/kernel/cpu/sgx/encl.c
@@ -124,6 +124,128 @@ struct sgx_encl_page *sgx_encl_load_page(struct sgx_encl *encl,
 	return entry;
 }
 
+/**
+ * sgx_encl_eaug_page - Dynamically add page to initialized enclave
+ * @vma:	VMA obtained from fault info from where page is accessed
+ * @encl:	enclave accessing the page
+ * @addr:	address that triggered the page fault
+ *
+ * When an initialized enclave accesses a page with no backing EPC page
+ * on a SGX2 system then the EPC can be added dynamically via the SGX2
+ * ENCLS[EAUG] instruction.
+ *
+ * Returns: Appropriate vm_fault_t: VM_FAULT_NOPAGE when PTE was installed
+ * successfully, VM_FAULT_SIGBUS or VM_FAULT_OOM as error otherwise.
+ */
+static vm_fault_t sgx_encl_eaug_page(struct vm_area_struct *vma,
+				     struct sgx_encl *encl, unsigned long addr)
+{
+	struct sgx_pageinfo pginfo = {0};
+	struct sgx_encl_page *encl_page;
+	struct sgx_epc_page *epc_page;
+	struct sgx_va_page *va_page;
+	unsigned long phys_addr;
+	unsigned long prot;
+	vm_fault_t vmret;
+	int ret;
+
+	if (!test_bit(SGX_ENCL_INITIALIZED, &encl->flags))
+		return VM_FAULT_SIGBUS;
+
+	encl_page = kzalloc(sizeof(*encl_page), GFP_KERNEL);
+	if (!encl_page)
+		return VM_FAULT_OOM;
+
+	encl_page->desc = addr;
+	encl_page->encl = encl;
+
+	/*
+	 * Adding a regular page that is architecturally allowed to only
+	 * be created with RW permissions.
+	 * TBD: Interface with user space policy to support max permissions
+	 * of RWX.
+	 */
+	prot = PROT_READ | PROT_WRITE;
+	encl_page->vm_run_prot_bits = calc_vm_prot_bits(prot, 0);
+	encl_page->vm_max_prot_bits = encl_page->vm_run_prot_bits;
+
+	epc_page = sgx_alloc_epc_page(encl_page, true);
+	if (IS_ERR(epc_page)) {
+		kfree(encl_page);
+		return VM_FAULT_SIGBUS;
+	}
+
+	va_page = sgx_encl_grow(encl);
+	if (IS_ERR(va_page)) {
+		ret = PTR_ERR(va_page);
+		goto err_out_free;
+	}
+
+	mutex_lock(&encl->lock);
+
+	/*
+	 * Copy comment from sgx_encl_add_page() to maintain guidance in
+	 * this similar flow:
+	 * Adding to encl->va_pages must be done under encl->lock.  Ditto for
+	 * deleting (via sgx_encl_shrink()) in the error path.
+	 */
+	if (va_page)
+		list_add(&va_page->list, &encl->va_pages);
+
+	ret = xa_insert(&encl->page_array, PFN_DOWN(encl_page->desc),
+			encl_page, GFP_KERNEL);
+	/*
+	 * If ret == -EBUSY then page was created in another flow while
+	 * running without encl->lock
+	 */
+	if (ret)
+		goto err_out_unlock;
+
+	pginfo.secs = (unsigned long)sgx_get_epc_virt_addr(encl->secs.epc_page);
+	pginfo.addr = encl_page->desc & PAGE_MASK;
+	pginfo.metadata = 0;
+
+	ret = __eaug(&pginfo, sgx_get_epc_virt_addr(epc_page));
+	if (ret)
+		goto err_out;
+
+	encl_page->encl = encl;
+	encl_page->epc_page = epc_page;
+	encl_page->type = SGX_PAGE_TYPE_REG;
+	encl->secs_child_cnt++;
+
+	sgx_mark_page_reclaimable(encl_page->epc_page);
+
+	phys_addr = sgx_get_epc_phys_addr(epc_page);
+	/*
+	 * Do not undo everything when creating PTE entry fails - next #PF
+	 * would find page ready for a PTE.
+	 * PAGE_SHARED because protection is forced to be RW above and COW
+	 * is not supported.
+	 */
+	vmret = vmf_insert_pfn_prot(vma, addr, PFN_DOWN(phys_addr),
+				    PAGE_SHARED);
+	if (vmret != VM_FAULT_NOPAGE) {
+		mutex_unlock(&encl->lock);
+		return VM_FAULT_SIGBUS;
+	}
+	mutex_unlock(&encl->lock);
+	return VM_FAULT_NOPAGE;
+
+err_out:
+	xa_erase(&encl->page_array, PFN_DOWN(encl_page->desc));
+
+err_out_unlock:
+	sgx_encl_shrink(encl, va_page);
+	mutex_unlock(&encl->lock);
+
+err_out_free:
+	sgx_encl_free_epc_page(epc_page);
+	kfree(encl_page);
+
+	return VM_FAULT_SIGBUS;
+}
+
 static vm_fault_t sgx_vma_fault(struct vm_fault *vmf)
 {
 	unsigned long addr = (unsigned long)vmf->address;
@@ -145,6 +267,17 @@ static vm_fault_t sgx_vma_fault(struct vm_fault *vmf)
 	if (unlikely(!encl))
 		return VM_FAULT_SIGBUS;
 
+	/*
+	 * The page_array keeps track of all enclave pages, whether they
+	 * are swapped out or not. If there is no entry for this page and
+	 * the system supports SGX2 then it is possible to dynamically add
+	 * a new enclave page. This is only possible for an initialized
+	 * enclave that will be checked for right away.
+	 */
+	if (cpu_feature_enabled(X86_FEATURE_SGX2) &&
+	    (!xa_load(&encl->page_array, PFN_DOWN(addr))))
+		return sgx_encl_eaug_page(vma, encl, addr);
+
 	mutex_lock(&encl->lock);
 
 	entry = sgx_encl_load_page(encl, addr);
diff --git a/arch/x86/kernel/cpu/sgx/encl.h b/arch/x86/kernel/cpu/sgx/encl.h
index 848a28d28d3d..1b6ce1da7c92 100644
--- a/arch/x86/kernel/cpu/sgx/encl.h
+++ b/arch/x86/kernel/cpu/sgx/encl.h
@@ -123,4 +123,6 @@ void sgx_encl_free_epc_page(struct sgx_epc_page *page);
 struct sgx_encl_page *sgx_encl_load_page(struct sgx_encl *encl,
 					 unsigned long addr);
 
+struct sgx_va_page *sgx_encl_grow(struct sgx_encl *encl);
+void sgx_encl_shrink(struct sgx_encl *encl, struct sgx_va_page *va_page);
 #endif /* _X86_ENCL_H */
diff --git a/arch/x86/kernel/cpu/sgx/ioctl.c b/arch/x86/kernel/cpu/sgx/ioctl.c
index 5dddb3c9f742..de0bf68ee842 100644
--- a/arch/x86/kernel/cpu/sgx/ioctl.c
+++ b/arch/x86/kernel/cpu/sgx/ioctl.c
@@ -17,7 +17,7 @@
 #include "encl.h"
 #include "encls.h"
 
-static struct sgx_va_page *sgx_encl_grow(struct sgx_encl *encl)
+struct sgx_va_page *sgx_encl_grow(struct sgx_encl *encl)
 {
 	struct sgx_va_page *va_page = NULL;
 	void *err;
@@ -43,7 +43,7 @@ static struct sgx_va_page *sgx_encl_grow(struct sgx_encl *encl)
 	return va_page;
 }
 
-static void sgx_encl_shrink(struct sgx_encl *encl, struct sgx_va_page *va_page)
+void sgx_encl_shrink(struct sgx_encl *encl, struct sgx_va_page *va_page)
 {
 	encl->page_cnt--;
 
-- 
2.25.1


  parent reply	other threads:[~2021-12-01 19:24 UTC|newest]

Thread overview: 155+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-01 19:22 [PATCH 00/25] x86/sgx and selftests/sgx: Support SGX2 Reinette Chatre
2021-12-01 19:22 ` [PATCH 01/25] x86/sgx: Add shortlog descriptions to ENCLS wrappers Reinette Chatre
2021-12-04 18:30   ` Jarkko Sakkinen
2021-12-06 21:13     ` Reinette Chatre
2021-12-11  5:28       ` Jarkko Sakkinen
2021-12-13 22:06         ` Reinette Chatre
2021-12-01 19:23 ` [PATCH 02/25] x86/sgx: Add wrappers for SGX2 functions Reinette Chatre
2021-12-04 22:04   ` Jarkko Sakkinen
2021-12-06 21:15     ` Reinette Chatre
2021-12-01 19:23 ` [PATCH 03/25] x86/sgx: Support VMA permissions exceeding enclave permissions Reinette Chatre
2021-12-04 22:25   ` Jarkko Sakkinen
2021-12-04 22:27     ` Jarkko Sakkinen
2021-12-06 21:16       ` Reinette Chatre
2021-12-11  5:39         ` Jarkko Sakkinen
2021-12-13 22:08           ` Reinette Chatre
2021-12-01 19:23 ` [PATCH 04/25] x86/sgx: Add pfn_mkwrite() handler for present PTEs Reinette Chatre
2021-12-04 22:43   ` Jarkko Sakkinen
2021-12-06 21:18     ` Reinette Chatre
2021-12-11  7:37       ` Jarkko Sakkinen
2021-12-13 22:09         ` Reinette Chatre
2021-12-28 14:51           ` Jarkko Sakkinen
2021-12-01 19:23 ` [PATCH 05/25] x86/sgx: Introduce runtime protection bits Reinette Chatre
2021-12-03 19:28   ` Andy Lutomirski
2021-12-03 22:12     ` Reinette Chatre
2021-12-04  0:38       ` Andy Lutomirski
2021-12-04  1:14         ` Reinette Chatre
2021-12-04 17:56           ` Andy Lutomirski
2021-12-04 23:55             ` Reinette Chatre
2021-12-13 22:34               ` Reinette Chatre
2021-12-04 23:57     ` Jarkko Sakkinen
2021-12-06 21:20       ` Reinette Chatre
2021-12-11  7:42         ` Jarkko Sakkinen
2021-12-13 22:10           ` Reinette Chatre
2021-12-28 14:52             ` Jarkko Sakkinen
2022-01-06 17:46               ` Reinette Chatre
2022-01-07 12:16                 ` Jarkko Sakkinen
2022-01-07 16:14                   ` Haitao Huang
2022-01-08 15:45                     ` Jarkko Sakkinen
2022-01-08 15:51                       ` Jarkko Sakkinen
2022-01-08 16:22                         ` Jarkko Sakkinen
2022-01-10 22:05                           ` Haitao Huang
2022-01-11  1:53                             ` Jarkko Sakkinen
2022-01-11  1:55                               ` Jarkko Sakkinen
2022-01-11  2:03                                 ` Jarkko Sakkinen
2022-01-11  2:15                                   ` Jarkko Sakkinen
2022-01-11  3:48                                     ` Haitao Huang
2022-01-12 23:48                                       ` Jarkko Sakkinen
2022-01-13  2:41                                         ` Haitao Huang
2022-01-14 21:36                                           ` Jarkko Sakkinen
2022-01-11 17:13                               ` Reinette Chatre
2022-01-12 23:50                                 ` Jarkko Sakkinen
2022-01-12 23:56                                   ` Jarkko Sakkinen
2022-01-13 20:09                                     ` Nathaniel McCallum
2022-01-13 21:42                                       ` Reinette Chatre
2022-01-14 21:53                                         ` Jarkko Sakkinen
2022-01-14 21:57                                           ` Jarkko Sakkinen
2022-01-14 22:00                                             ` Jarkko Sakkinen
2022-01-14 22:17                                           ` Jarkko Sakkinen
2022-01-14 22:23                                             ` Jarkko Sakkinen
2022-01-14 22:34                                               ` Jarkko Sakkinen
2022-01-14 23:05                                           ` Reinette Chatre
2022-01-14 23:15                                             ` Jarkko Sakkinen
2022-01-15  0:01                                               ` Reinette Chatre
2022-01-15  0:27                                                 ` Jarkko Sakkinen
2022-01-15  0:41                                                   ` Reinette Chatre
2022-01-15  1:18                                                     ` Jarkko Sakkinen
2022-01-15 11:56                                                       ` Jarkko Sakkinen
2022-01-15 11:59                                                         ` Jarkko Sakkinen
2022-01-17 13:13                                                         ` Nathaniel McCallum
2022-01-18  1:59                                                           ` Jarkko Sakkinen
2022-01-18  2:22                                                             ` Jarkko Sakkinen
2022-01-18  3:31                                                               ` Jarkko Sakkinen
2022-01-18 20:59                                                               ` Reinette Chatre
2022-01-20 12:53                                                                 ` Jarkko Sakkinen
2022-01-20 16:52                                                                   ` Reinette Chatre
2022-01-26 14:41                                                                     ` Jarkko Sakkinen
2022-01-15 16:49                                               ` Jarkko Sakkinen
2022-01-18 21:18                                                 ` Reinette Chatre
2022-01-17 13:27                                         ` Nathaniel McCallum
2022-01-18 21:11                                           ` Reinette Chatre
2021-12-04 22:50   ` Jarkko Sakkinen
2021-12-06 21:28     ` Reinette Chatre
2021-12-01 19:23 ` [PATCH 06/25] x86/sgx: Use more generic name for enclave cpumask function Reinette Chatre
2021-12-04 22:56   ` Jarkko Sakkinen
2021-12-06 21:29     ` Reinette Chatre
2021-12-01 19:23 ` [PATCH 07/25] x86/sgx: Move PTE zap code to separate function Reinette Chatre
2021-12-04 22:59   ` Jarkko Sakkinen
2021-12-06 21:30     ` Reinette Chatre
2021-12-11  7:52       ` Jarkko Sakkinen
2021-12-13 22:11         ` Reinette Chatre
2021-12-28 14:55           ` Jarkko Sakkinen
2022-01-06 17:46             ` Reinette Chatre
2022-01-07 12:26               ` Jarkko Sakkinen
2021-12-01 19:23 ` [PATCH 08/25] x86/sgx: Make SGX IPI callback available internally Reinette Chatre
2021-12-04 23:00   ` Jarkko Sakkinen
2021-12-06 21:36     ` Reinette Chatre
2021-12-11  7:53       ` Jarkko Sakkinen
2021-12-01 19:23 ` [PATCH 09/25] x86/sgx: Keep record of SGX page type Reinette Chatre
2021-12-04 23:03   ` Jarkko Sakkinen
2021-12-01 19:23 ` [PATCH 10/25] x86/sgx: Support enclave page permission changes Reinette Chatre
2021-12-02 23:48   ` Dave Hansen
2021-12-03 18:18     ` Reinette Chatre
2021-12-03  0:32   ` Dave Hansen
2021-12-03 18:18     ` Reinette Chatre
2021-12-03 18:14   ` Dave Hansen
2021-12-03 18:49     ` Reinette Chatre
2021-12-03 19:38   ` Andy Lutomirski
2021-12-03 22:34     ` Reinette Chatre
2021-12-04  0:42       ` Andy Lutomirski
2021-12-04  1:35         ` Reinette Chatre
2021-12-04 23:08   ` Jarkko Sakkinen
2021-12-06 20:19     ` Dave Hansen
2021-12-11  5:17       ` Jarkko Sakkinen
2021-12-06 21:42     ` Reinette Chatre
2021-12-11  7:57       ` Jarkko Sakkinen
2021-12-13 22:12         ` Reinette Chatre
2021-12-28 14:56           ` Jarkko Sakkinen
2021-12-01 19:23 ` [PATCH 11/25] selftests/sgx: Add test for EPCM " Reinette Chatre
2021-12-01 19:23 ` [PATCH 12/25] selftests/sgx: Add test for TCS page " Reinette Chatre
2021-12-01 19:23 ` Reinette Chatre [this message]
2021-12-03  0:38   ` [PATCH 13/25] x86/sgx: Support adding of pages to initialized enclave Dave Hansen
2021-12-03 18:47     ` Reinette Chatre
2021-12-04 23:13   ` Jarkko Sakkinen
2021-12-06 21:44     ` Reinette Chatre
2021-12-11  8:00       ` Jarkko Sakkinen
2021-12-13 22:12         ` Reinette Chatre
2021-12-28 14:57           ` Jarkko Sakkinen
2022-03-01 15:13   ` Jarkko Sakkinen
2022-03-01 17:08     ` Reinette Chatre
2021-12-01 19:23 ` [PATCH 14/25] x86/sgx: Tighten accessible memory range after enclave initialization Reinette Chatre
2021-12-04 23:14   ` Jarkko Sakkinen
2021-12-06 21:45     ` Reinette Chatre
2021-12-11  8:01       ` Jarkko Sakkinen
2021-12-01 19:23 ` [PATCH 15/25] selftests/sgx: Test two different SGX2 EAUG flows Reinette Chatre
2021-12-01 19:23 ` [PATCH 16/25] x86/sgx: Support modifying SGX page type Reinette Chatre
2021-12-04 23:45   ` Jarkko Sakkinen
2021-12-06 21:48     ` Reinette Chatre
2021-12-11  8:02       ` Jarkko Sakkinen
2021-12-13 17:43         ` Dave Hansen
2021-12-21  8:52           ` Jarkko Sakkinen
2021-12-01 19:23 ` [PATCH 17/25] x86/sgx: Support complete page removal Reinette Chatre
2021-12-04 23:45   ` Jarkko Sakkinen
2021-12-06 21:49     ` Reinette Chatre
2021-12-01 19:23 ` [PATCH 18/25] selftests/sgx: Introduce dynamic entry point Reinette Chatre
2021-12-01 19:23 ` [PATCH 19/25] selftests/sgx: Introduce TCS initialization enclave operation Reinette Chatre
2021-12-01 19:23 ` [PATCH 20/25] selftests/sgx: Test complete changing of page type flow Reinette Chatre
2021-12-01 19:23 ` [PATCH 21/25] selftests/sgx: Test faulty enclave behavior Reinette Chatre
2021-12-01 19:23 ` [PATCH 22/25] selftests/sgx: Test invalid access to removed enclave page Reinette Chatre
2021-12-01 19:23 ` [PATCH 23/25] selftests/sgx: Test reclaiming of untouched page Reinette Chatre
2021-12-01 19:23 ` [PATCH 24/25] x86/sgx: Free up EPC pages directly to support large page ranges Reinette Chatre
2021-12-04 23:47   ` Jarkko Sakkinen
2021-12-06 22:07     ` Reinette Chatre
2021-12-01 19:23 ` [PATCH 25/25] selftests/sgx: Page removal stress test Reinette Chatre
2021-12-02 18:30 ` [PATCH 00/25] x86/sgx and selftests/sgx: Support SGX2 Dave Hansen
2021-12-02 20:38   ` Nathaniel McCallum

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=9ab661a845d242cb10a90ade997f8ebda33cc7c9.1638381245.git.reinette.chatre@intel.com \
    --to=reinette.chatre@intel.com \
    --cc=bp@alien8.de \
    --cc=cathy.zhang@intel.com \
    --cc=cedric.xing@intel.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=haitao.huang@intel.com \
    --cc=hpa@zytor.com \
    --cc=jarkko@kernel.org \
    --cc=kai.huang@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-sgx@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=mark.shanahan@intel.com \
    --cc=mingo@redhat.com \
    --cc=seanjc@google.com \
    --cc=tglx@linutronix.de \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).