From patchwork Fri Apr 1 14:24:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, Cathy" X-Patchwork-Id: 12798382 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 03FA3C433F5 for ; Fri, 1 Apr 2022 14:24:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346597AbiDAO0L (ORCPT ); Fri, 1 Apr 2022 10:26:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56162 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241890AbiDAO0K (ORCPT ); Fri, 1 Apr 2022 10:26:10 -0400 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AAD7E10DA42 for ; Fri, 1 Apr 2022 07:24:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1648823060; x=1680359060; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=xhNOuIlPAPb86LAZwPnhn5xZc+sRDzmGh3nI9D+YXTM=; b=SmgdNyeEB8Cj4X+ImC1zeE4PSyA621sefLSb4AhKyOvwPyUWu4q/YTmp 1NOkNLHAXKpzIrsjL9jTeAqjUMJ4LYnZ7YGr3Mcow5LPzB4q4Nx9AEuyl VBjJNa8pRZz6H+5RlbkCD80tck07Ds5ivzYdwuSaS9HrASKGXfCPTN9B6 IRLAZni+CYCT6YYPcsZf4o66980ZiJXTzj3vGLfaO5H3KkfC7yNDLNskb E/Q084oeRt5rMqlZKI0TR+gYW0gC61hsHLPTmOIkz1S7u3txjBUGnTFA1 NuVSrUPkjvF+wH1RFIlY70K2C0ic/X2gG6jt/bveKUG5cjV6LkMGSNywe A==; X-IronPort-AV: E=McAfee;i="6200,9189,10304"; a="240739861" X-IronPort-AV: E=Sophos;i="5.90,227,1643702400"; d="scan'208";a="240739861" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Apr 2022 07:24:20 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,227,1643702400"; d="scan'208";a="695908324" Received: from cathy-vostro-3670.bj.intel.com ([10.238.156.128]) by fmsmga001.fm.intel.com with ESMTP; 01 Apr 2022 07:24:18 -0700 From: Cathy Zhang To: linux-sgx@vger.kernel.org, x86@kernel.org Cc: jarkko@kernel.org, reinette.chatre@intel.com, dave.hansen@intel.com, ashok.raj@intel.com, cathy.zhang@intel.com Subject: [RFC PATCH v3 01/10] x86/sgx: Introduce mechanism to prevent new initializations of EPC pages Date: Fri, 1 Apr 2022 22:24:00 +0800 Message-Id: <20220401142409.26215-2-cathy.zhang@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220401142409.26215-1-cathy.zhang@intel.com> References: <20220401142409.26215-1-cathy.zhang@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-sgx@vger.kernel.org == Background == EUPDATESVN is a new SGX instruction which allows enclave attestation to include information about updated microcode without a reboot. The SGX hardware maintains metadata for each enclave page to help enforce its security guarantees. This includes things like a record of the enclave to which the page belongs and the type of the page: SGX metadata like "VA" or "SECS" pages, or regular enclave pages like those that store user data. Before an EUPDATESVN operation can be successful, all SGX memory (aka. EPC) must be marked as "unused" in the SGX hardware metadata (aka, EPCM). The SGX microcode now maintains a reference count of pages which are unused to aid in determining when all pages reach the "unused" state. Both bare-metal and KVM guest EPC must be made unused. To increase the chance of a successful EUPDATESVN, the kernel prevents existing enclaves from creating new, valid pages and prevents new enclave creation (creating an enclave involves initializing a "SECS" page). The entire EUPDATESVN process is very slow since it potentially affects gigabytes of enclave memory. It can potentially take seconds or minutes to complete. Userspace may encounter -EBUSY errors during the update and is expected to retry. == Patch contents == Introduce mechanism to prevent new initializations of EPC pages. Use a flag to indicate when SGX EPC pages are "locked", which means it's not allowed to allocate new EPC page for use. Check it in all paths that can initialize an EPC page. Use SRCU to ensure that the flag is visible across the system before proceeding with an update. Add checks to all sites that call SGX instructions that can transition pages from unused to initialized to ensure that the SRCU lock is held. Signed-off-by: Cathy Zhang --- Changes since v2: - Move out the SGX2 related change to remove the dependency. (Jarkko Sakkinen, Reinette Chatre). --- arch/x86/kernel/cpu/sgx/encls.h | 8 +++++++ arch/x86/kernel/cpu/sgx/sgx.h | 3 +++ arch/x86/kernel/cpu/sgx/encl.c | 19 +++++++++++++++++ arch/x86/kernel/cpu/sgx/ioctl.c | 25 +++++++++++++++++++++- arch/x86/kernel/cpu/sgx/main.c | 37 +++++++++++++++++++++++++++++++++ arch/x86/kernel/cpu/sgx/virt.c | 20 ++++++++++++++++++ 6 files changed, 111 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/sgx/encls.h b/arch/x86/kernel/cpu/sgx/encls.h index fa04a73daf9c..60321c5f5718 100644 --- a/arch/x86/kernel/cpu/sgx/encls.h +++ b/arch/x86/kernel/cpu/sgx/encls.h @@ -138,6 +138,8 @@ static inline bool encls_failed(int ret) static inline int __ecreate(struct sgx_pageinfo *pginfo, void *secs) { + lockdep_assert_held(&sgx_lock_epc_srcu); + return __encls_2(ECREATE, pginfo, secs); } @@ -148,6 +150,8 @@ static inline int __eextend(void *secs, void *addr) static inline int __eadd(struct sgx_pageinfo *pginfo, void *addr) { + lockdep_assert_held(&sgx_lock_epc_srcu); + return __encls_2(EADD, pginfo, addr); } @@ -179,6 +183,8 @@ static inline int __etrack(void *addr) static inline int __eldu(struct sgx_pageinfo *pginfo, void *addr, void *va) { + lockdep_assert_held(&sgx_lock_epc_srcu); + return __encls_ret_3(ELDU, pginfo, addr, va); } @@ -191,6 +197,8 @@ static inline int __epa(void *addr) { unsigned long rbx = SGX_PAGE_TYPE_VA; + lockdep_assert_held(&sgx_lock_epc_srcu); + return __encls_2(EPA, rbx, addr); } diff --git a/arch/x86/kernel/cpu/sgx/sgx.h b/arch/x86/kernel/cpu/sgx/sgx.h index b30cee4de903..d7a1490d90bb 100644 --- a/arch/x86/kernel/cpu/sgx/sgx.h +++ b/arch/x86/kernel/cpu/sgx/sgx.h @@ -103,4 +103,7 @@ static inline int __init sgx_vepc_init(void) void sgx_update_lepubkeyhash(u64 *lepubkeyhash); +extern struct srcu_struct sgx_lock_epc_srcu; +bool sgx_epc_is_locked(void); + #endif /* _X86_SGX_H */ diff --git a/arch/x86/kernel/cpu/sgx/encl.c b/arch/x86/kernel/cpu/sgx/encl.c index 02ff9ac83985..68c8d65a8dee 100644 --- a/arch/x86/kernel/cpu/sgx/encl.c +++ b/arch/x86/kernel/cpu/sgx/encl.c @@ -142,6 +142,7 @@ static vm_fault_t sgx_vma_fault(struct vm_fault *vmf) unsigned long phys_addr; struct sgx_encl *encl; vm_fault_t ret; + int srcu_idx; encl = vma->vm_private_data; @@ -153,11 +154,18 @@ static vm_fault_t sgx_vma_fault(struct vm_fault *vmf) if (unlikely(!encl)) return VM_FAULT_SIGBUS; + srcu_idx = srcu_read_lock(&sgx_lock_epc_srcu); + if (sgx_epc_is_locked()) { + srcu_read_unlock(&sgx_lock_epc_srcu, srcu_idx); + return VM_FAULT_SIGBUS; + } + mutex_lock(&encl->lock); entry = sgx_encl_load_page(encl, addr, vma->vm_flags); if (IS_ERR(entry)) { mutex_unlock(&encl->lock); + srcu_read_unlock(&sgx_lock_epc_srcu, srcu_idx); if (PTR_ERR(entry) == -EBUSY) return VM_FAULT_NOPAGE; @@ -170,12 +178,14 @@ static vm_fault_t sgx_vma_fault(struct vm_fault *vmf) ret = vmf_insert_pfn(vma, addr, PFN_DOWN(phys_addr)); if (ret != VM_FAULT_NOPAGE) { mutex_unlock(&encl->lock); + srcu_read_unlock(&sgx_lock_epc_srcu, srcu_idx); return VM_FAULT_SIGBUS; } sgx_encl_test_and_clear_young(vma->vm_mm, entry); mutex_unlock(&encl->lock); + srcu_read_unlock(&sgx_lock_epc_srcu, srcu_idx); return VM_FAULT_NOPAGE; } @@ -323,6 +333,7 @@ static int sgx_vma_access(struct vm_area_struct *vma, unsigned long addr, struct sgx_encl_page *entry = NULL; char data[sizeof(unsigned long)]; unsigned long align; + int srcu_idx; int offset; int cnt; int ret = 0; @@ -339,8 +350,15 @@ static int sgx_vma_access(struct vm_area_struct *vma, unsigned long addr, return -EFAULT; for (i = 0; i < len; i += cnt) { + srcu_idx = srcu_read_lock(&sgx_lock_epc_srcu); + if (sgx_epc_is_locked()) { + ret = -EBUSY; + goto out; + } + entry = sgx_encl_reserve_page(encl, (addr + i) & PAGE_MASK, vma->vm_flags); + if (IS_ERR(entry)) { ret = PTR_ERR(entry); break; @@ -366,6 +384,7 @@ static int sgx_vma_access(struct vm_area_struct *vma, unsigned long addr, out: mutex_unlock(&encl->lock); + srcu_read_unlock(&sgx_lock_epc_srcu, srcu_idx); if (ret) break; diff --git a/arch/x86/kernel/cpu/sgx/ioctl.c b/arch/x86/kernel/cpu/sgx/ioctl.c index b3c2e8d58142..00668e50848d 100644 --- a/arch/x86/kernel/cpu/sgx/ioctl.c +++ b/arch/x86/kernel/cpu/sgx/ioctl.c @@ -147,6 +147,7 @@ static int sgx_encl_create(struct sgx_encl *encl, struct sgx_secs *secs) static long sgx_ioc_enclave_create(struct sgx_encl *encl, void __user *arg) { struct sgx_enclave_create create_arg; + int srcu_idx; void *secs; int ret; @@ -162,9 +163,20 @@ static long sgx_ioc_enclave_create(struct sgx_encl *encl, void __user *arg) if (copy_from_user(secs, (void __user *)create_arg.src, PAGE_SIZE)) ret = -EFAULT; - else + else { + srcu_idx = srcu_read_lock(&sgx_lock_epc_srcu); + if (sgx_epc_is_locked()) { + srcu_read_unlock(&sgx_lock_epc_srcu, srcu_idx); + ret = -EBUSY; + goto out; + } + ret = sgx_encl_create(encl, secs); + srcu_read_unlock(&sgx_lock_epc_srcu, srcu_idx); + } + +out: kfree(secs); return ret; } @@ -418,6 +430,7 @@ static long sgx_ioc_enclave_add_pages(struct sgx_encl *encl, void __user *arg) struct sgx_enclave_add_pages add_arg; struct sgx_secinfo secinfo; unsigned long c; + int srcu_idx; int ret; if (!test_bit(SGX_ENCL_CREATED, &encl->flags) || @@ -455,8 +468,18 @@ static long sgx_ioc_enclave_add_pages(struct sgx_encl *encl, void __user *arg) if (need_resched()) cond_resched(); + srcu_idx = srcu_read_lock(&sgx_lock_epc_srcu); + if (sgx_epc_is_locked()) { + ret = -EBUSY; + srcu_read_unlock(&sgx_lock_epc_srcu, srcu_idx); + break; + } + ret = sgx_encl_add_page(encl, add_arg.src + c, add_arg.offset + c, &secinfo, add_arg.flags); + + srcu_read_unlock(&sgx_lock_epc_srcu, srcu_idx); + if (ret) break; } diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c index b3aba1e1274c..10360f06c0df 100644 --- a/arch/x86/kernel/cpu/sgx/main.c +++ b/arch/x86/kernel/cpu/sgx/main.c @@ -23,6 +23,17 @@ static int sgx_nr_epc_sections; static struct task_struct *ksgxd_tsk; static DECLARE_WAIT_QUEUE_HEAD(ksgxd_waitq); static DEFINE_XARRAY(sgx_epc_address_space); +/* + * The flag sgx_epc_locked prevents any new SGX flows that + * may attempt to allocate a new EPC page. + */ +static bool __rcu sgx_epc_locked; +/* + * By synchronizing around sgx_epc_locked SRCU ensures that any executing + * SGX flows have completed before proceeding with an SVN update. New SGX flows + * will be prevented from starting during an SVN update. + */ +DEFINE_SRCU(sgx_lock_epc_srcu); /* * These variables are part of the state of the reclaimer, and must be accessed @@ -407,6 +418,8 @@ static bool sgx_should_reclaim(unsigned long watermark) static int ksgxd(void *p) { + int srcu_idx; + set_freezable(); /* @@ -427,9 +440,15 @@ static int ksgxd(void *p) kthread_should_stop() || sgx_should_reclaim(SGX_NR_HIGH_PAGES)); + srcu_idx = srcu_read_lock(&sgx_lock_epc_srcu); + if (sgx_epc_is_locked()) + goto maybe_resched; + if (sgx_should_reclaim(SGX_NR_HIGH_PAGES)) sgx_reclaim_pages(); +maybe_resched: + srcu_read_unlock(&sgx_lock_epc_srcu, srcu_idx); cond_resched(); } @@ -972,3 +991,21 @@ static int __init sgx_init(void) } device_initcall(sgx_init); + +static void sgx_lock_epc(void) +{ + sgx_epc_locked = true; + synchronize_srcu(&sgx_lock_epc_srcu); +} + +static void sgx_unlock_epc(void) +{ + sgx_epc_locked = false; + synchronize_srcu(&sgx_lock_epc_srcu); +} + +bool sgx_epc_is_locked(void) +{ + lockdep_assert_held(&sgx_lock_epc_srcu); + return sgx_epc_locked; +} diff --git a/arch/x86/kernel/cpu/sgx/virt.c b/arch/x86/kernel/cpu/sgx/virt.c index 6a77a14eee38..e953816d7c8b 100644 --- a/arch/x86/kernel/cpu/sgx/virt.c +++ b/arch/x86/kernel/cpu/sgx/virt.c @@ -75,10 +75,21 @@ static vm_fault_t sgx_vepc_fault(struct vm_fault *vmf) { struct vm_area_struct *vma = vmf->vma; struct sgx_vepc *vepc = vma->vm_private_data; + int srcu_idx; int ret; mutex_lock(&vepc->lock); + srcu_idx = srcu_read_lock(&sgx_lock_epc_srcu); + + if (sgx_epc_is_locked()) { + ret = -EBUSY; + goto out_unlock; + } + ret = __sgx_vepc_fault(vepc, vma, vmf->address); + +out_unlock: + srcu_read_unlock(&sgx_lock_epc_srcu, srcu_idx); mutex_unlock(&vepc->lock); if (!ret) @@ -331,6 +342,7 @@ int __init sgx_vepc_init(void) int sgx_virt_ecreate(struct sgx_pageinfo *pageinfo, void __user *secs, int *trapnr) { + int srcu_idx; int ret; /* @@ -347,6 +359,12 @@ int sgx_virt_ecreate(struct sgx_pageinfo *pageinfo, void __user *secs, if (WARN_ON_ONCE(!access_ok(secs, PAGE_SIZE))) return -EINVAL; + srcu_idx = srcu_read_lock(&sgx_lock_epc_srcu); + if (sgx_epc_is_locked()) { + srcu_read_unlock(&sgx_lock_epc_srcu, srcu_idx); + return -EBUSY; + } + __uaccess_begin(); ret = __ecreate(pageinfo, (void *)secs); __uaccess_end(); @@ -356,6 +374,8 @@ int sgx_virt_ecreate(struct sgx_pageinfo *pageinfo, void __user *secs, return -EFAULT; } + srcu_read_unlock(&sgx_lock_epc_srcu, srcu_idx); + /* ECREATE doesn't return an error code, it faults or succeeds. */ WARN_ON_ONCE(ret); return 0; From patchwork Fri Apr 1 14:24:01 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, Cathy" X-Patchwork-Id: 12798383 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3F0DAC4332F for ; Fri, 1 Apr 2022 14:24:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240154AbiDAO0N (ORCPT ); Fri, 1 Apr 2022 10:26:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56332 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241890AbiDAO0M (ORCPT ); Fri, 1 Apr 2022 10:26:12 -0400 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 20DE910E57A for ; Fri, 1 Apr 2022 07:24:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1648823063; x=1680359063; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=Iifm94nrkrUn95r/4dwRoNZdpOmvhO/J9wedzDILcKw=; b=kj10YgY1ptjRjeMyE/meBD18GKIvKdJA9JVtUYWuUq77x1UDcS32nsMv pi7nfAbE0PS4gYeImYitsHm+tmfh9XsuN/D6p88QFfYgCobIdWwuVIg6S O/iidWGbvDykGogxZfUTB9/78SP6nOuSfRC4ccoY2+QxLKOurh9WvTIRX 8tHDTCAdfrYE9ksxFCr8s78+hpt4V0yhl3qNmYYB0w9FZjv94+RUY3+nu 8PMw3KC6zIlTGR0JjN0efqGg1tkwmoqMd91PAXaI1PoCOOZdJQCifU3jU oDla1CXA4FbtXS7dZzkIIhIgYnLcdgKeCrufcLpZlLc68h7DOGbRrFbiw Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10304"; a="240739867" X-IronPort-AV: E=Sophos;i="5.90,227,1643702400"; d="scan'208";a="240739867" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Apr 2022 07:24:23 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,227,1643702400"; d="scan'208";a="695908334" Received: from cathy-vostro-3670.bj.intel.com ([10.238.156.128]) by fmsmga001.fm.intel.com with ESMTP; 01 Apr 2022 07:24:20 -0700 From: Cathy Zhang To: linux-sgx@vger.kernel.org, x86@kernel.org Cc: jarkko@kernel.org, reinette.chatre@intel.com, dave.hansen@intel.com, ashok.raj@intel.com, cathy.zhang@intel.com Subject: [RFC PATCH v3 02/10] x86/sgx: Provide VA page non-NULL owner Date: Fri, 1 Apr 2022 22:24:01 +0800 Message-Id: <20220401142409.26215-3-cathy.zhang@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220401142409.26215-1-cathy.zhang@intel.com> References: <20220401142409.26215-1-cathy.zhang@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-sgx@vger.kernel.org Provide non-NULL owner for VA page, which tells that the EPC page is allocated for use. Signed-off-by: Cathy Zhang --- arch/x86/kernel/cpu/sgx/encl.h | 3 +-- arch/x86/kernel/cpu/sgx/sgx.h | 2 +- arch/x86/kernel/cpu/sgx/encl.c | 5 +++-- arch/x86/kernel/cpu/sgx/ioctl.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/cpu/sgx/encl.h b/arch/x86/kernel/cpu/sgx/encl.h index 7cdc351bc273..0c8571fc30cf 100644 --- a/arch/x86/kernel/cpu/sgx/encl.h +++ b/arch/x86/kernel/cpu/sgx/encl.h @@ -112,8 +112,7 @@ int sgx_encl_get_backing(struct sgx_encl *encl, unsigned long page_index, void sgx_encl_put_backing(struct sgx_backing *backing, bool do_write); int sgx_encl_test_and_clear_young(struct mm_struct *mm, struct sgx_encl_page *page); - -struct sgx_epc_page *sgx_alloc_va_page(void); +struct sgx_epc_page *sgx_alloc_va_page(struct sgx_va_page *va_page); unsigned int sgx_alloc_va_slot(struct sgx_va_page *va_page); void sgx_free_va_slot(struct sgx_va_page *va_page, unsigned int offset); bool sgx_va_page_full(struct sgx_va_page *va_page); diff --git a/arch/x86/kernel/cpu/sgx/sgx.h b/arch/x86/kernel/cpu/sgx/sgx.h index d7a1490d90bb..f8ed9deac18b 100644 --- a/arch/x86/kernel/cpu/sgx/sgx.h +++ b/arch/x86/kernel/cpu/sgx/sgx.h @@ -33,7 +33,7 @@ struct sgx_epc_page { unsigned int section; u16 flags; u16 poison; - struct sgx_encl_page *owner; + void *owner; struct list_head list; }; diff --git a/arch/x86/kernel/cpu/sgx/encl.c b/arch/x86/kernel/cpu/sgx/encl.c index 68c8d65a8dee..c0725111cc25 100644 --- a/arch/x86/kernel/cpu/sgx/encl.c +++ b/arch/x86/kernel/cpu/sgx/encl.c @@ -753,6 +753,7 @@ int sgx_encl_test_and_clear_young(struct mm_struct *mm, /** * sgx_alloc_va_page() - Allocate a Version Array (VA) page + * @va_page: struct sgx_va_page connected to this VA page * * Allocate a free EPC page and convert it to a Version Array (VA) page. * @@ -760,12 +761,12 @@ int sgx_encl_test_and_clear_young(struct mm_struct *mm, * a VA page, * -errno otherwise */ -struct sgx_epc_page *sgx_alloc_va_page(void) +struct sgx_epc_page *sgx_alloc_va_page(struct sgx_va_page *va_page) { struct sgx_epc_page *epc_page; int ret; - epc_page = sgx_alloc_epc_page(NULL, true); + epc_page = sgx_alloc_epc_page(va_page, true); if (IS_ERR(epc_page)) return ERR_CAST(epc_page); diff --git a/arch/x86/kernel/cpu/sgx/ioctl.c b/arch/x86/kernel/cpu/sgx/ioctl.c index 00668e50848d..f0ce96bd462a 100644 --- a/arch/x86/kernel/cpu/sgx/ioctl.c +++ b/arch/x86/kernel/cpu/sgx/ioctl.c @@ -30,7 +30,7 @@ static struct sgx_va_page *sgx_encl_grow(struct sgx_encl *encl) if (!va_page) return ERR_PTR(-ENOMEM); - va_page->epc_page = sgx_alloc_va_page(); + va_page->epc_page = sgx_alloc_va_page(va_page); if (IS_ERR(va_page->epc_page)) { err = ERR_CAST(va_page->epc_page); kfree(va_page); From patchwork Fri Apr 1 14:24:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, Cathy" X-Patchwork-Id: 12798384 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 51C9FC433FE for ; Fri, 1 Apr 2022 14:24:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346755AbiDAO0P (ORCPT ); Fri, 1 Apr 2022 10:26:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56534 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241890AbiDAO0O (ORCPT ); Fri, 1 Apr 2022 10:26:14 -0400 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5839E113D1D for ; Fri, 1 Apr 2022 07:24:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1648823065; x=1680359065; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=RHJkEHM62QCOCGe4xh/rn0AQ0pihJS1FZyaOKFYuUOE=; b=EnDe3SIrULV7PVZ6JNLcNG4qDPV9W+kdbNwfLptKqQQRnGW408T5Iso0 IPIyEwen3+w0TONLtCYGWOSuK5Q5C8+sensl1GX7ZNFMVPycz0Dxoi8gn GsVBs0dE9DHHhRg2C6op8KalXCMXv4EXpEa8TMc5tC06lNnJuL77MzWtf YENn/NBAdmz/22uizvkt8SQNtMl4jKvbrjrsaCgwTR1hurEfJvoLJvWxM AR3kqE6iyzqOzKw+nl/qizG7w5Wqi62VjF7F3+hV+qUXhGrbPMzT0Foxo MHA8gv77ZSdz8oLq+t/CWqaDf5sUemG09mbt5nICbZ5RZvv5MwdWZwuaX Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10304"; a="240739875" X-IronPort-AV: E=Sophos;i="5.90,227,1643702400"; d="scan'208";a="240739875" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Apr 2022 07:24:25 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,227,1643702400"; d="scan'208";a="695908338" Received: from cathy-vostro-3670.bj.intel.com ([10.238.156.128]) by fmsmga001.fm.intel.com with ESMTP; 01 Apr 2022 07:24:23 -0700 From: Cathy Zhang To: linux-sgx@vger.kernel.org, x86@kernel.org Cc: jarkko@kernel.org, reinette.chatre@intel.com, dave.hansen@intel.com, ashok.raj@intel.com, cathy.zhang@intel.com Subject: [RFC PATCH v3 03/10] x86/sgx: Save enclave pointer for VA page Date: Fri, 1 Apr 2022 22:24:02 +0800 Message-Id: <20220401142409.26215-4-cathy.zhang@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220401142409.26215-1-cathy.zhang@intel.com> References: <20220401142409.26215-1-cathy.zhang@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-sgx@vger.kernel.org Tearing down all enclaves is required by SGX SVN update, which involves running the ENCLS[EREMOVE] instruction on every EPC page. This (tearing down all enclaves) should be coordinated with any enclaves that may be in the process of existing and thus already be running ENCLS[EREMOVE] as part of enclave release. In support of this coordination, it is required to know which enclave owns each in-use EPC page. It is already possible to locate the owning enclave of SECS and regular pages but not for VA pages. Save the enclave pointer for each VA page to support locating its owning enclave. Note: to track 2T EPC memory, this scheme of tracking will use additional 8M memory. Signed-off-by: Cathy Zhang --- arch/x86/kernel/cpu/sgx/encl.h | 1 + arch/x86/kernel/cpu/sgx/ioctl.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/x86/kernel/cpu/sgx/encl.h b/arch/x86/kernel/cpu/sgx/encl.h index 0c8571fc30cf..59fbd4ed5c64 100644 --- a/arch/x86/kernel/cpu/sgx/encl.h +++ b/arch/x86/kernel/cpu/sgx/encl.h @@ -76,6 +76,7 @@ struct sgx_va_page { struct sgx_epc_page *epc_page; DECLARE_BITMAP(slots, SGX_VA_SLOT_COUNT); struct list_head list; + struct sgx_encl *encl; }; struct sgx_backing { diff --git a/arch/x86/kernel/cpu/sgx/ioctl.c b/arch/x86/kernel/cpu/sgx/ioctl.c index f0ce96bd462a..da82abbb81b4 100644 --- a/arch/x86/kernel/cpu/sgx/ioctl.c +++ b/arch/x86/kernel/cpu/sgx/ioctl.c @@ -30,6 +30,7 @@ static struct sgx_va_page *sgx_encl_grow(struct sgx_encl *encl) if (!va_page) return ERR_PTR(-ENOMEM); + va_page->encl = encl; va_page->epc_page = sgx_alloc_va_page(va_page); if (IS_ERR(va_page->epc_page)) { err = ERR_CAST(va_page->epc_page); From patchwork Fri Apr 1 14:24:03 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, Cathy" X-Patchwork-Id: 12798385 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6350BC433EF for ; Fri, 1 Apr 2022 14:24:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S245438AbiDAO0S (ORCPT ); Fri, 1 Apr 2022 10:26:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56738 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241890AbiDAO0R (ORCPT ); Fri, 1 Apr 2022 10:26:17 -0400 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4364C1168D0 for ; Fri, 1 Apr 2022 07:24:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1648823068; x=1680359068; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=OABL+vNPmI76N669MBfQX2xF2C1qkZswib1x5YU269I=; b=TPXEDyaU1Xd53Jx3aq1p9bKjUti66Hu7/wv1SXMrsK1FV/a6OLjRaRTy a5F5IC+jzx7FYX7K02rJLVV3mgbpDKUx9S5ZuhP2btI3CxXhZYEK99udi NzPkPvP8/U6FtQChWgWtJrnA1HtKOwDyTgNxyI2DFxlmBp3JmhpZpuq78 9WtyED6b4uNks6A4W/WIToYwTwiseNHMUw7LoPmazffaJR4ua7RXFwf3i C67vX8GgHSjE9jViHwZt01+cag+nA2e2FyDpNAhM0WagPkYFUKl9CIF4+ j7o/z6VAC3ZjMiv2HmDazqoZ7ZULCyqSkY6c8h5LwjPKP+gCqiLfe6UEB w==; X-IronPort-AV: E=McAfee;i="6200,9189,10304"; a="240739879" X-IronPort-AV: E=Sophos;i="5.90,227,1643702400"; d="scan'208";a="240739879" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Apr 2022 07:24:28 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,227,1643702400"; d="scan'208";a="695908348" Received: from cathy-vostro-3670.bj.intel.com ([10.238.156.128]) by fmsmga001.fm.intel.com with ESMTP; 01 Apr 2022 07:24:25 -0700 From: Cathy Zhang To: linux-sgx@vger.kernel.org, x86@kernel.org Cc: jarkko@kernel.org, reinette.chatre@intel.com, dave.hansen@intel.com, ashok.raj@intel.com, cathy.zhang@intel.com Subject: [RFC PATCH v3 04/10] x86/sgx: Keep record for SGX VA and Guest page type Date: Fri, 1 Apr 2022 22:24:03 +0800 Message-Id: <20220401142409.26215-5-cathy.zhang@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220401142409.26215-1-cathy.zhang@intel.com> References: <20220401142409.26215-1-cathy.zhang@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-sgx@vger.kernel.org Regular enclave EPC pages have sgx_encl_page as their owner, but SGX VA page and KVM guest EPC page are maintained by different owner structures. SGX CPUSVN update requires to know the EPC page owner's status and then decide how to handle the page. Keep a record of page type for SGX VA and KVM guest page while the other EPC pages already have their type tracked, so that CPUSVN update can get EPC page's owner by type and handle it then. Signed-off-by: Cathy Zhang --- arch/x86/kernel/cpu/sgx/sgx.h | 4 ++++ arch/x86/kernel/cpu/sgx/encl.c | 2 ++ arch/x86/kernel/cpu/sgx/virt.c | 2 ++ 3 files changed, 8 insertions(+) diff --git a/arch/x86/kernel/cpu/sgx/sgx.h b/arch/x86/kernel/cpu/sgx/sgx.h index f8ed9deac18b..0b036f19cca1 100644 --- a/arch/x86/kernel/cpu/sgx/sgx.h +++ b/arch/x86/kernel/cpu/sgx/sgx.h @@ -28,6 +28,10 @@ /* Pages on free list */ #define SGX_EPC_PAGE_IS_FREE BIT(1) +/* VA page */ +#define SGX_EPC_PAGE_VA BIT(2) +/* Pages allocated for KVM guest */ +#define SGX_EPC_PAGE_GUEST BIT(3) struct sgx_epc_page { unsigned int section; diff --git a/arch/x86/kernel/cpu/sgx/encl.c b/arch/x86/kernel/cpu/sgx/encl.c index c0725111cc25..a01a72637e2e 100644 --- a/arch/x86/kernel/cpu/sgx/encl.c +++ b/arch/x86/kernel/cpu/sgx/encl.c @@ -777,6 +777,8 @@ struct sgx_epc_page *sgx_alloc_va_page(struct sgx_va_page *va_page) return ERR_PTR(-EFAULT); } + epc_page->flags |= SGX_EPC_PAGE_VA; + return epc_page; } diff --git a/arch/x86/kernel/cpu/sgx/virt.c b/arch/x86/kernel/cpu/sgx/virt.c index e953816d7c8b..acdf72769a39 100644 --- a/arch/x86/kernel/cpu/sgx/virt.c +++ b/arch/x86/kernel/cpu/sgx/virt.c @@ -50,6 +50,8 @@ static int __sgx_vepc_fault(struct sgx_vepc *vepc, if (IS_ERR(epc_page)) return PTR_ERR(epc_page); + epc_page->flags |= SGX_EPC_PAGE_GUEST; + ret = xa_err(xa_store(&vepc->page_array, index, epc_page, GFP_KERNEL)); if (ret) goto err_free; From patchwork Fri Apr 1 14:24:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, Cathy" X-Patchwork-Id: 12798386 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C635EC43217 for ; Fri, 1 Apr 2022 14:24:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346814AbiDAO0U (ORCPT ); Fri, 1 Apr 2022 10:26:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56898 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346813AbiDAO0T (ORCPT ); Fri, 1 Apr 2022 10:26:19 -0400 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2F6591179A7 for ; Fri, 1 Apr 2022 07:24:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1648823070; x=1680359070; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=WN/krY8rJ7X5+9TGOsMytyTsU1nkS4gKTLDejKKaG3M=; b=hf8ofM3SERkswtycOaIO2PfJe6E/gCSfWzTVz352HhkSTY4xqUtFYs6C O7RRPLEZkiM9grD5DXWFbPZFCJEXIDsOG64tdxvaGPinfeR11c3ddiLjA gvsgnVLgKsIPIoGowMhmvrA+WrhTuN4FT91vjWXJuOBLHeT8fRnZdl4bL XEGgMSGZNJFoJGilv6C1Lrp54l23rHrfFndivehjoLQc7N2vfElfBRNgI qCAly6SJYReiwc84m/WsDPK2P3SoohbFxCLvvxxm7BO0/DQs365+Pui6Z kmOBOw6tGwo5+W9ysYf+kT3MkYv81EHiDjMxGacfeOQlVmhbU1Xy1xVs3 g==; X-IronPort-AV: E=McAfee;i="6200,9189,10304"; a="240739889" X-IronPort-AV: E=Sophos;i="5.90,227,1643702400"; d="scan'208";a="240739889" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Apr 2022 07:24:30 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,227,1643702400"; d="scan'208";a="695908362" Received: from cathy-vostro-3670.bj.intel.com ([10.238.156.128]) by fmsmga001.fm.intel.com with ESMTP; 01 Apr 2022 07:24:27 -0700 From: Cathy Zhang To: linux-sgx@vger.kernel.org, x86@kernel.org Cc: jarkko@kernel.org, reinette.chatre@intel.com, dave.hansen@intel.com, ashok.raj@intel.com, cathy.zhang@intel.com Subject: [RFC PATCH v3 05/10] x86/sgx: Save the size of each EPC section Date: Fri, 1 Apr 2022 22:24:04 +0800 Message-Id: <20220401142409.26215-6-cathy.zhang@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220401142409.26215-1-cathy.zhang@intel.com> References: <20220401142409.26215-1-cathy.zhang@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-sgx@vger.kernel.org For SGX CPUSVN update process will check all EPC pages in each section to ensure they will be marked as unused, it requires to know the size of each EPC section to end the loop. Signed-off-by: Cathy Zhang --- arch/x86/kernel/cpu/sgx/sgx.h | 1 + arch/x86/kernel/cpu/sgx/main.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/x86/kernel/cpu/sgx/sgx.h b/arch/x86/kernel/cpu/sgx/sgx.h index 0b036f19cca1..45ba6fcabfda 100644 --- a/arch/x86/kernel/cpu/sgx/sgx.h +++ b/arch/x86/kernel/cpu/sgx/sgx.h @@ -63,6 +63,7 @@ struct sgx_epc_section { void *virt_addr; struct sgx_epc_page *pages; struct sgx_numa_node *node; + u64 size; }; extern struct sgx_epc_section sgx_epc_sections[SGX_MAX_EPC_SECTIONS]; diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c index 10360f06c0df..031c1402cd7e 100644 --- a/arch/x86/kernel/cpu/sgx/main.c +++ b/arch/x86/kernel/cpu/sgx/main.c @@ -665,6 +665,7 @@ static bool __init sgx_setup_epc_section(u64 phys_addr, u64 size, } section->phys_addr = phys_addr; + section->size = size; xa_store_range(&sgx_epc_address_space, section->phys_addr, phys_addr + size - 1, section, GFP_KERNEL); From patchwork Fri Apr 1 14:24:05 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, Cathy" X-Patchwork-Id: 12798387 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 65B32C4332F for ; Fri, 1 Apr 2022 14:24:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346816AbiDAO0X (ORCPT ); Fri, 1 Apr 2022 10:26:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57130 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346813AbiDAO0W (ORCPT ); Fri, 1 Apr 2022 10:26:22 -0400 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B6D0011861C for ; Fri, 1 Apr 2022 07:24:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1648823072; x=1680359072; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=Ie2CuBNMHkCRvf3n3OaAKbvqWxD1i/ReFKsHYpDrNys=; b=eEVzjs9u2FqTC76FV5aoffqVZIXvM91DSb56UuRUkS+ZbYM86lombg+I pqRAHl/lud8AAQJlNOLqREhkpV1MAh3nGN0YPgerHvXvpCIE/QqOGNRXS CgPh7jQn28gjam127eLUClI4AqjEw0R3kAyr7lDWA0U1mEEf50d2NUULP VXiK11CDMXca0viW0aMeJEqPJ/drfL94DT1zJ3jVp2PfOoFffSYaOBZRY fgxZWWu32F8zPaWavCTcMfzK3xfaKvq+fo9iVQdOnUkmoE2wsCkAgIjpW 6yWl8Yh9hjk8g88Sm6b0gpLfhCIK40TfvjYnNkrl7w47Flh1mLRZw4PsO w==; X-IronPort-AV: E=McAfee;i="6200,9189,10304"; a="240739899" X-IronPort-AV: E=Sophos;i="5.90,227,1643702400"; d="scan'208";a="240739899" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Apr 2022 07:24:32 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,227,1643702400"; d="scan'208";a="695908382" Received: from cathy-vostro-3670.bj.intel.com ([10.238.156.128]) by fmsmga001.fm.intel.com with ESMTP; 01 Apr 2022 07:24:30 -0700 From: Cathy Zhang To: linux-sgx@vger.kernel.org, x86@kernel.org Cc: jarkko@kernel.org, reinette.chatre@intel.com, dave.hansen@intel.com, ashok.raj@intel.com, cathy.zhang@intel.com Subject: [RFC PATCH v3 06/10] x86/sgx: Forced EPC page zapping for EUPDATESVN Date: Fri, 1 Apr 2022 22:24:05 +0800 Message-Id: <20220401142409.26215-7-cathy.zhang@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220401142409.26215-1-cathy.zhang@intel.com> References: <20220401142409.26215-1-cathy.zhang@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-sgx@vger.kernel.org Before an EUPDATESVN instruction can be successful, all enclave pages (EPC) must be marked as unused in the SGX hardware metadata (EPCM). A page becomes unused when an issued EREMOVE instruction succeeds. To prepare for EUPDATESVN, loop over all SGX pages and attempt to EREMOVE them. This is fatal to running enclaves and destroys all enclave state and memory contents. This destruction is by design and mitigates any compromise of enclaves or the SGX hardware itself which occurred before the microcode update. An EREMOVE operation on a page may fail for a few reasons. Each has its own mitigations. First, EREMOVE will fail if an enclave that uses the page is executing. Send an IPI to all CPUs that might be running the enclave to force it out of the enclave long enough to EREMOVE the page. Other CPUs might enter the enclave in the meantime, so this is not a rock-solid guarantee. Second, EREMOVE can fail on special SGX metadata pages, such as SECS and VA. EREMOVE will work on them only after the normal SGX pages that depend on them have been EREMOVE'd. Defer handling those pages and repeat EREMOVE after the dependency has been addressed. Signed-off-by: Cathy Zhang --- arch/x86/kernel/cpu/sgx/sgx.h | 13 ++ arch/x86/kernel/cpu/sgx/encl.c | 14 +- arch/x86/kernel/cpu/sgx/main.c | 347 +++++++++++++++++++++++++++++++++ 3 files changed, 373 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/sgx/sgx.h b/arch/x86/kernel/cpu/sgx/sgx.h index 45ba6fcabfda..33d66473986f 100644 --- a/arch/x86/kernel/cpu/sgx/sgx.h +++ b/arch/x86/kernel/cpu/sgx/sgx.h @@ -32,6 +32,17 @@ #define SGX_EPC_PAGE_VA BIT(2) /* Pages allocated for KVM guest */ #define SGX_EPC_PAGE_GUEST BIT(3) +/* + * Pages, failed to be zapped (EREMOVED) + * by SGX CPUSVN update process. + */ +#define SGX_EPC_PAGE_ZAP_TRACKED BIT(4) +/* + * Pages, the associated enclave is being + * released while SGX CPUSVN update is + * running. + */ +#define SGX_EPC_PAGE_IN_RELEASE BIT(5) struct sgx_epc_page { unsigned int section; @@ -110,5 +121,7 @@ void sgx_update_lepubkeyhash(u64 *lepubkeyhash); extern struct srcu_struct sgx_lock_epc_srcu; bool sgx_epc_is_locked(void); +void sgx_zap_wakeup(void); +void sgx_zap_abort(void); #endif /* _X86_SGX_H */ diff --git a/arch/x86/kernel/cpu/sgx/encl.c b/arch/x86/kernel/cpu/sgx/encl.c index a01a72637e2e..be177a5e3292 100644 --- a/arch/x86/kernel/cpu/sgx/encl.c +++ b/arch/x86/kernel/cpu/sgx/encl.c @@ -457,6 +457,12 @@ void sgx_encl_release(struct kref *ref) WARN_ON_ONCE(encl->secs_child_cnt); WARN_ON_ONCE(encl->secs.epc_page); + /* + * EPC pages were freed and EREMOVE was executed. Wake + * up any zappers which were waiting for this. + */ + sgx_zap_wakeup(); + kfree(encl); } @@ -840,8 +846,14 @@ void sgx_encl_free_epc_page(struct sgx_epc_page *page) WARN_ON_ONCE(page->flags & SGX_EPC_PAGE_RECLAIMER_TRACKED); ret = __eremove(sgx_get_epc_virt_addr(page)); - if (WARN_ONCE(ret, EREMOVE_ERROR_MESSAGE, ret, ret)) + if (WARN_ONCE(ret, EREMOVE_ERROR_MESSAGE, ret, ret)) { + /* + * The EREMOVE failed. If a CPUSVN is in progress, + * it is now expected to fail. Notify it. + */ + sgx_zap_abort(); return; + } sgx_free_epc_page(page); } diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c index 031c1402cd7e..2a456aa1ad1f 100644 --- a/arch/x86/kernel/cpu/sgx/main.c +++ b/arch/x86/kernel/cpu/sgx/main.c @@ -34,6 +34,16 @@ static bool __rcu sgx_epc_locked; * will be prevented from starting during an SVN update. */ DEFINE_SRCU(sgx_lock_epc_srcu); +static DECLARE_WAIT_QUEUE_HEAD(sgx_zap_waitq); + +/* The flag means to abort the SGX CPUSVN update process */ +static bool sgx_zap_abort_wait; +/* + * Track the number of SECS and VA pages associated with enclaves + * in releasing. SGX CPUSVN update will wait for them EREMOVEd by + * enclave exiting process. + */ +static atomic_t zap_waiting_count; /* * These variables are part of the state of the reclaimer, and must be accessed @@ -636,6 +646,24 @@ void sgx_free_epc_page(struct sgx_epc_page *page) spin_lock(&node->lock); + /* + * The page is EREMOVEd, stop tracking it + * as a deferred target for CPUSVN update + * process. + */ + if ((page->flags & SGX_EPC_PAGE_ZAP_TRACKED) && + (!list_empty(&page->list))) + list_del(&page->list); + + /* + * The page is EREMOVEd, decrease + * "zap_waiting_count" to stop counting it + * as a waiting target for CPUSVN update + * process. + */ + if (page->flags & SGX_EPC_PAGE_IN_RELEASE) + atomic_dec_if_positive(&zap_waiting_count); + page->owner = NULL; if (page->poison) list_add(&page->list, &node->sgx_poison_page_list); @@ -1010,3 +1038,322 @@ bool sgx_epc_is_locked(void) lockdep_assert_held(&sgx_lock_epc_srcu); return sgx_epc_locked; } + +/** + * sgx_zap_encl_page - unuse one EPC page + * @section: EPC section + * @epc_page: EPC page + * @secs_pages_list: list to trac SECS pages failed to be EREMOVEd + * + * Zap an EPC page if it's used by an enclave. + * + * Returns: + * 0: EPC page is unused or EREMOVE succeeds. + * -EBUSY: EREMOVE failed for other threads executing + * in enclave. + * -EIO: Other EREMOVE failures, like EPC leaks. + */ +static int sgx_zap_encl_page(struct sgx_epc_section *section, + struct sgx_epc_page *epc_page, + struct list_head *secs_pages_list) +{ + struct sgx_encl *encl; + struct sgx_encl_page *encl_page; + struct sgx_va_page *va_page; + int retry_count = 10; + int ret = 0; + + /* + * Holding the per-section lock to ensure the + * "owner" field will not be cleared while + * checking. + */ + spin_lock(§ion->node->lock); + + /* + * The "owner" field is NULL, it means the page + * is unused. + */ + if (!epc_page->owner) { + spin_unlock(§ion->node->lock); + return 0; + } + + if (epc_page->flags & SGX_EPC_PAGE_VA) { + va_page = epc_page->owner; + encl = va_page->encl; + } else { + encl_page = epc_page->owner; + encl = encl_page->encl; + } + + if (!encl) { + spin_unlock(§ion->node->lock); + /* + * The page has owner, but without an Enclave + * associated with. This might be caused by + * EPC leaks happen in enclave's release path. + */ + ret = __eremove(sgx_get_epc_virt_addr(epc_page)); + if (WARN_ONCE(ret, EREMOVE_ERROR_MESSAGE, ret, ret)) + ret = -EIO; + else + sgx_free_epc_page(epc_page); + return ret; + } + + /* + * Wait for any enclave already being released to complete + * but prevent any additional enclave from starting release + * while we operate on it. + */ + if (!kref_get_unless_zero(&encl->refcount)) { + + /* + * The enclave is exiting. The EUPDATESVN + * procedure needs to wait for the EREMOVE + * operation which happens as a part of + * the enclave exit operation. Use + * "zap_waiting_count" to indicate to the + * EUPDATESVN code when it needs to wait. + */ + if (((epc_page->flags & SGX_EPC_PAGE_VA) || + (encl_page->type == SGX_PAGE_TYPE_SECS)) && + !(epc_page->flags & SGX_EPC_PAGE_IN_RELEASE)) { + atomic_inc(&zap_waiting_count); + epc_page->flags |= SGX_EPC_PAGE_IN_RELEASE; + } + + spin_unlock(§ion->node->lock); + return 0; + } + + spin_unlock(§ion->node->lock); + + /* + * This EREMOVE has two main purposes: + * 1. Getting EPC pages into the "unused" state. + * Every EPC page must be unused before an + * EUPDATESVN can be succeed. + * 2. Forcing enclaves to exit more frequently. + * EREMOVE will not succeed while any thread is + * running in the enclave. Every successful + * EREMOVE increases the chance that an enclave + * will trip over this page, fault, and exit. + * This, in turn, increases the likelihood of + * success for every future EREMOVE attempt. + */ + ret = __eremove(sgx_get_epc_virt_addr(epc_page)); + + if (!ret) { + /* + * The SECS page is EREMOVEd successfully this time. + * Remove it from the list to stop tracking it. + */ + if ((epc_page->flags & SGX_EPC_PAGE_ZAP_TRACKED) && + !list_empty(&epc_page->list)) { + list_del_init(&epc_page->list); + epc_page->flags &= ~SGX_EPC_PAGE_ZAP_TRACKED; + } + goto out; + } + + if (ret == SGX_CHILD_PRESENT) { + /* + * The SECS page is failed to be EREMOVEd due + * to associations. Add it to "secs_pages_list" + * for deferred handling. + */ + if (!(epc_page->flags & SGX_EPC_PAGE_ZAP_TRACKED) && + secs_pages_list) { + epc_page->flags |= SGX_EPC_PAGE_ZAP_TRACKED; + list_add_tail(&epc_page->list, secs_pages_list); + } + ret = 0; + goto out; + } + + if (ret) { + /* + * EREMOVE will fail on a page if the owning + * enclave is executing. An IPI will cause the + * enclave to exit, providing an opportunity to + * EREMOVE the page, but it does not guarantee + * the page will be EREMOVEd successfully. Retry + * for several times, if it keeps on failing, + * return -EBUSY to notify userspace for retry. + */ + do { + on_each_cpu_mask(sgx_encl_cpumask(encl), sgx_ipi_cb, NULL, true); + ret = __eremove(sgx_get_epc_virt_addr(epc_page)); + if (!ret) + break; + retry_count--; + } while (retry_count); + + if (ret) + ret = -EBUSY; + } + +out: + kref_put(&encl->refcount, sgx_encl_release); + return ret; +} + +/** + * sgx_zap_section_pages - unuse one EPC section's pages + * @section: EPC section + * @secs_pages_list: list to track SECS pages failed to be EREMOVEd + * + * Iterate through pages in one EPC section, unuse the pages + * initialized for enclaves on bare metal. + * + * TODO: EPC pages for KVM guest will be handled in future. + * + * Returns: + * 0: EPC page is unused. + * -EBUSY: EREMOVE failed for other threads executing + * in enclave. + * -EIO: Other EREMOVE failures, like EPC leaks. + */ +static int sgx_zap_section_pages(struct sgx_epc_section *section, + struct list_head *secs_pages_list) +{ + struct sgx_epc_page *epc_page; + int i, ret = 0; + unsigned long nr_pages = section->size >> PAGE_SHIFT; + + for (i = 0; i < nr_pages; i++) { + epc_page = §ion->pages[i]; + + /* + * EPC page has "NULL" owner, indicating + * it's unused. No action required for + * this case. + * + * No new owner can be assigned when SGX + * is "frozen". + */ + if (!epc_page->owner) + continue; + + /* + * Try to "unuse" all SGX memory used by enclaves + * on bare-metal. + * + * Failures might be caused by the following reasons: + * 1. EREMOVE failure due to other threads executing + * in enclave. Return -EBUSY to notify userspace + * for a later retry. + * 2. Other EREMOVE failures. For example, a bug in + * SGX memory management like a leak that lost + * track of an SGX EPC page. Upon these failures, + * do not even attempt EUPDATESVN. + */ + if (!(epc_page->flags & SGX_EPC_PAGE_GUEST)) { + ret = sgx_zap_encl_page(section, epc_page, secs_pages_list); + if (ret) + return ret; + } + } + + return ret; +} + +/** + * sgx_zap_pages - unuse all EPC sections' pages + * + * Context: This function is called while microcode_mutex lock + * is held by the caller, it ensures that the update + * process will not run concurrently. + * + * Returns: + * 0: All enclaves have been torn down and + * all EPC pages are unused. + * -ERESTARTSYS: Interrupted by a signal. + * -EBUSY: EREMOVE failed for other threads executing + * in enclave. + * -EIO: Other EREMOVE failures, like EPC leaks. + */ +static int sgx_zap_pages(void) +{ + struct sgx_epc_page *epc_page, *tmp; + struct sgx_epc_section *section; + int i, ret = 0; + + LIST_HEAD(secs_pages_list); + + for (i = 0; i < ARRAY_SIZE(sgx_epc_sections); i++) { + section = &sgx_epc_sections[i]; + if (!section->pages) + break; + /* + * Go through the section's pages and try to EREMOVE + * each one, except the ones associated with enclaves + * in releasing. + */ + ret = sgx_zap_section_pages(section, &secs_pages_list); + if (WARN_ON_ONCE(ret)) + goto out; + } + + /* + * The SECS page should have no associations now, try + * EREMOVE them again. + */ + list_for_each_entry_safe(epc_page, tmp, &secs_pages_list, list) { + section = &sgx_epc_sections[epc_page->section]; + ret = sgx_zap_encl_page(section, epc_page, NULL); + if (ret) + goto out; + } + + /* + * There might be pages in the process of being freed + * by exiting enclaves. Wait for the exiting process + * to succeed or fail. + */ + ret = wait_event_interruptible(sgx_zap_waitq, + (!atomic_read(&zap_waiting_count) || + sgx_zap_abort_wait)); + if (ret == -ERESTARTSYS) { + pr_err("CPUSVN update is not finished yet, but killed by userspace\n"); + goto out; + } + + if (sgx_zap_abort_wait) { + ret = -EIO; + pr_err("exit-side EREMOVE failure. Aborting CPUSVN update\n"); + goto out; + } + +out: + return ret; +} + +/** + * sgx_zap_wakeup - wake up CPUSVN update process + * + * Whenever enclave is freed, this function will + * be called to check if all EPC pages are unused. + * Wake up the CPUSVN update process if it's true. + */ +void sgx_zap_wakeup(void) +{ + if (wq_has_sleeper(&sgx_zap_waitq) && + !atomic_read(&zap_waiting_count)) + wake_up(&sgx_zap_waitq); +} + +/** + * sgx_zap_abort - abort SGX CPUSVN update process + * + * When EPC leaks happen in enclave release process, + * it will set flag sgx_zap_abort_wait as true to + * abort the CPUSVN update process. + */ +void sgx_zap_abort(void) +{ + sgx_zap_abort_wait = true; + wake_up(&sgx_zap_waitq); +} From patchwork Fri Apr 1 14:24:06 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, Cathy" X-Patchwork-Id: 12798388 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 04937C433FE for ; Fri, 1 Apr 2022 14:24:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346815AbiDAO0Z (ORCPT ); Fri, 1 Apr 2022 10:26:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57308 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346817AbiDAO0Y (ORCPT ); Fri, 1 Apr 2022 10:26:24 -0400 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 034D6119850 for ; Fri, 1 Apr 2022 07:24:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1648823074; x=1680359074; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=+3y6DxvsctMxXZh/+jol0SmDk7ld6S7QJDcag3c4+r0=; b=SDLUR/LeBcan71u7GszQcfh3QhRht6EAsQBpPNzRgHfaULTkEi0mfgz3 BXR6nosdI40lB6C3Pm1rqy9jzig0skFPg0qBIIciXurgw+Y4CyntjkZew afViauDM8lI8wdq5CGQMRvp4n7I14Krb9xWXIquq9f2fug+31UY72RSi+ wz8zTCnkFUVPLN6xmLsL66oGapQGpJrO04dh9zBn/hJe7i0P1NS2/qi4z E8TdOx8Npo3TdVSsVJRZmCjuhgT5OfCSy0goyjfvrZoyCIWHosoDrH3aN bzG+6IORlBH3tiMvrKbkFz5VINoX9mxdBrfTp1vqL7QYoCnw6tuWhHXG6 w==; X-IronPort-AV: E=McAfee;i="6200,9189,10304"; a="240739907" X-IronPort-AV: E=Sophos;i="5.90,227,1643702400"; d="scan'208";a="240739907" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Apr 2022 07:24:34 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,227,1643702400"; d="scan'208";a="695908391" Received: from cathy-vostro-3670.bj.intel.com ([10.238.156.128]) by fmsmga001.fm.intel.com with ESMTP; 01 Apr 2022 07:24:32 -0700 From: Cathy Zhang To: linux-sgx@vger.kernel.org, x86@kernel.org Cc: jarkko@kernel.org, reinette.chatre@intel.com, dave.hansen@intel.com, ashok.raj@intel.com, cathy.zhang@intel.com Subject: [RFC PATCH v3 07/10] x86/sgx: Define error codes for ENCLS[EUPDATESVN] Date: Fri, 1 Apr 2022 22:24:06 +0800 Message-Id: <20220401142409.26215-8-cathy.zhang@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220401142409.26215-1-cathy.zhang@intel.com> References: <20220401142409.26215-1-cathy.zhang@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-sgx@vger.kernel.org Add error codes for ENCLS[EUPDATESVN], then SGX CPUSVN update process can know the execution state of EUPDATESVN and notify userspace. Signed-off-by: Cathy Zhang --- arch/x86/include/asm/sgx.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/x86/include/asm/sgx.h b/arch/x86/include/asm/sgx.h index 03ec7e32659c..4a8ca7281229 100644 --- a/arch/x86/include/asm/sgx.h +++ b/arch/x86/include/asm/sgx.h @@ -65,17 +65,27 @@ enum sgx_encls_function { /** * enum sgx_return_code - The return code type for ENCLS, ENCLU and ENCLV + * %SGX_EPC_PAGE_CONFLICT Page is being written by other ENCLS function. * %SGX_NOT_TRACKED: Previous ETRACK's shootdown sequence has not * been completed yet. * %SGX_CHILD_PRESENT SECS has child pages present in the EPC. * %SGX_INVALID_EINITTOKEN: EINITTOKEN is invalid and enclave signer's * public key does not match IA32_SGXLEPUBKEYHASH. + * %SGX_INSUFFICIENT_ENTROPY: Insufficient entropy in RNG. + * %SGX_EPC_NOT_READY: EPC is not ready for SVN update. + * %SGX_NO_UPDATE: EUPDATESVN was successful, but CPUSVN was not + * updated because current SVN was not newer than + * CPUSVN. * %SGX_UNMASKED_EVENT: An unmasked event, e.g. INTR, was received */ enum sgx_return_code { + SGX_EPC_PAGE_CONFLICT = 7, SGX_NOT_TRACKED = 11, SGX_CHILD_PRESENT = 13, SGX_INVALID_EINITTOKEN = 16, + SGX_INSUFFICIENT_ENTROPY = 29, + SGX_EPC_NOT_READY = 30, + SGX_NO_UPDATE = 31, SGX_UNMASKED_EVENT = 128, }; From patchwork Fri Apr 1 14:24:07 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, Cathy" X-Patchwork-Id: 12798389 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 26B93C433EF for ; Fri, 1 Apr 2022 14:24:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346821AbiDAO02 (ORCPT ); Fri, 1 Apr 2022 10:26:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57586 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346824AbiDAO01 (ORCPT ); Fri, 1 Apr 2022 10:26:27 -0400 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7922E11BE52 for ; Fri, 1 Apr 2022 07:24:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1648823077; x=1680359077; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=pTOU/xDDoX/227GqRS+7Jx/f5aZB2kDWOTRzYArLbdM=; b=ObvEGXddmKxjaYS2FzSo2Os/Pgz+isavlmyEQH0p7Hbkdlik41NDuABF Me1yPA1+DWSpFic+3JAnZjAktbBw9k+AO9LxMA0PwJCzgK38Ms9TRb3UH v7o1jOA5x3svHys4EON4TjA2FQ47O1XXAhWVgblxhfUf/PG9kjez8/gRS lxMiYYGCfETy6kruCy111qvT4ez+DCySlqgKEg5fAbVBJDYmd9cpxqJPu Z+owQVR6RMwvE6tfGqLkQNHqZ5iXVpFUIFyYCIHb/iMHJGSu8ima0XvsY 2Ur9gd9/6QQ1rbFLkLygnwCmJQGMMAR4lUW8F0Q4PJWz0J05aREFJoRNy w==; X-IronPort-AV: E=McAfee;i="6200,9189,10304"; a="240739916" X-IronPort-AV: E=Sophos;i="5.90,227,1643702400"; d="scan'208";a="240739916" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Apr 2022 07:24:37 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,227,1643702400"; d="scan'208";a="695908406" Received: from cathy-vostro-3670.bj.intel.com ([10.238.156.128]) by fmsmga001.fm.intel.com with ESMTP; 01 Apr 2022 07:24:35 -0700 From: Cathy Zhang To: linux-sgx@vger.kernel.org, x86@kernel.org Cc: jarkko@kernel.org, reinette.chatre@intel.com, dave.hansen@intel.com, ashok.raj@intel.com, cathy.zhang@intel.com Subject: [RFC PATCH v3 08/10] x86/sgx: Implement ENCLS[EUPDATESVN] Date: Fri, 1 Apr 2022 22:24:07 +0800 Message-Id: <20220401142409.26215-9-cathy.zhang@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220401142409.26215-1-cathy.zhang@intel.com> References: <20220401142409.26215-1-cathy.zhang@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-sgx@vger.kernel.org The SGX attestation architecture assumes a compromise of all running enclaves and cryptographic assets (like internal SGX encryption keys) whenever a microcode update affects SGX. To mitigate the impact of this presumed compromise, a new supervisor SGX instruction: ENCLS[EUPDATESVN], is introduced to update SGX microcode version and generate new cryptographic assets in runtime after SGX microcode update. EUPDATESVN requires that SGX memory to be marked as "unused" before it will succeed. This ensures that no compromised enclave can survive the process and provides an opportunity to generate new cryptographic assets. Signed-off-by: Cathy Zhang --- Changes since v1: - Print message for each return code to notify userspace the ENCLS[EUPDATESVN] execution status. --- arch/x86/include/asm/sgx.h | 33 +++++++++++---------- arch/x86/kernel/cpu/sgx/encls.h | 6 ++++ arch/x86/kernel/cpu/sgx/main.c | 52 +++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 15 deletions(-) diff --git a/arch/x86/include/asm/sgx.h b/arch/x86/include/asm/sgx.h index 4a8ca7281229..74bcb6841a4b 100644 --- a/arch/x86/include/asm/sgx.h +++ b/arch/x86/include/asm/sgx.h @@ -26,23 +26,26 @@ #define SGX_CPUID_EPC_SECTION 0x1 /* The bitmask for the EPC section type. */ #define SGX_CPUID_EPC_MASK GENMASK(3, 0) +/* EUPDATESVN presence indication */ +#define SGX_CPUID_EUPDATESVN BIT(10) enum sgx_encls_function { - ECREATE = 0x00, - EADD = 0x01, - EINIT = 0x02, - EREMOVE = 0x03, - EDGBRD = 0x04, - EDGBWR = 0x05, - EEXTEND = 0x06, - ELDU = 0x08, - EBLOCK = 0x09, - EPA = 0x0A, - EWB = 0x0B, - ETRACK = 0x0C, - EAUG = 0x0D, - EMODPR = 0x0E, - EMODT = 0x0F, + ECREATE = 0x00, + EADD = 0x01, + EINIT = 0x02, + EREMOVE = 0x03, + EDGBRD = 0x04, + EDGBWR = 0x05, + EEXTEND = 0x06, + ELDU = 0x08, + EBLOCK = 0x09, + EPA = 0x0A, + EWB = 0x0B, + ETRACK = 0x0C, + EAUG = 0x0D, + EMODPR = 0x0E, + EMODT = 0x0F, + EUPDATESVN = 0x18, }; /** diff --git a/arch/x86/kernel/cpu/sgx/encls.h b/arch/x86/kernel/cpu/sgx/encls.h index 60321c5f5718..8455f385e817 100644 --- a/arch/x86/kernel/cpu/sgx/encls.h +++ b/arch/x86/kernel/cpu/sgx/encls.h @@ -208,4 +208,10 @@ static inline int __ewb(struct sgx_pageinfo *pginfo, void *addr, return __encls_ret_3(EWB, pginfo, addr, va); } +/* Update CPUSVN at runtime. */ +static inline int __eupdatesvn(void) +{ + return __encls_ret_1(EUPDATESVN, ""); +} + #endif /* _X86_ENCLS_H */ diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c index 2a456aa1ad1f..784780314762 100644 --- a/arch/x86/kernel/cpu/sgx/main.c +++ b/arch/x86/kernel/cpu/sgx/main.c @@ -1357,3 +1357,55 @@ void sgx_zap_abort(void) sgx_zap_abort_wait = true; wake_up(&sgx_zap_waitq); } + +/** + * sgx_updatesvn() - Issue ENCLS[EUPDATESVN] + * If EPC is ready, this instruction will update CPUSVN to the currently + * loaded microcode update SVN and generate new cryptographic assets. + * + * Return: + * 0: CPUSVN is update successfully. + * %SGX_LOCKFAIL: An instruction concurrency rule was violated. + * %SGX_INSUFFICIENT_ENTROPY: Insufficient entropy in RNG. + * %SGX_EPC_NOT_READY: EPC is not ready for SVN update. + * %SGX_NO_UPDATE: EUPDATESVN was successful, but CPUSVN was not + * updated because current SVN was not newer than + * CPUSVN. + */ +static int sgx_updatesvn(void) +{ + int ret; + int retry = 10; + + do { + ret = __eupdatesvn(); + if (ret != SGX_INSUFFICIENT_ENTROPY) + break; + + } while (--retry); + + switch (ret) { + case 0: + pr_info("EUPDATESVN was successful!\n"); + break; + case SGX_NO_UPDATE: + pr_info("EUPDATESVN was successful, but CPUSVN was not updated, " + "because current SVN was not newer than CPUSVN.\n"); + break; + case SGX_EPC_NOT_READY: + pr_info("EPC is not ready for SVN update."); + break; + case SGX_INSUFFICIENT_ENTROPY: + pr_info("CPUSVN update is failed due to Insufficient entropy in RNG, " + "please try it later.\n"); + break; + case SGX_EPC_PAGE_CONFLICT: + pr_info("CPUSVN update is failed due to concurrency violation, please " + "stop running any other ENCLS leaf and try it later.\n"); + break; + default: + break; + } + + return ret; +} From patchwork Fri Apr 1 14:24:08 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, Cathy" X-Patchwork-Id: 12798390 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E8CB1C4332F for ; Fri, 1 Apr 2022 14:24:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346813AbiDAO0a (ORCPT ); Fri, 1 Apr 2022 10:26:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57668 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241890AbiDAO03 (ORCPT ); Fri, 1 Apr 2022 10:26:29 -0400 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0013511BE4E for ; Fri, 1 Apr 2022 07:24:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1648823079; x=1680359079; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=8Ud/8FKTwZmPM06bP1l56ClVaV3l7zG/fPqY+plYj84=; b=kz2ZhikQ1PTsGquK3cnBJCqwQzQD+STndYB/b9f1zyDxSJSx4obNknmg AP5V+ryFt5qEp6p9WjUVM7snvIpO/ilhozwlwyaTSUIbe+KHk92Bh78zD gcRMHZDKm5z2rJjd7LzzVz6xr6WtOqiwSPLGS+/7tUXd3oMlu8z7uytKf kawqO5KfDFogjw56MGBKZ7AtcQnrimY8sS8UX9uBh6FKlvXGiDe++43Zg C7hxCBdgXEa8ySvPK9gwpCQcj8SiaoIGpKZinIfO/DOx5GqKhZdK760ee MtW79PlXF832KaNGDt9VdYlfY51Wpd/sH1gxQDJ/6gIRQo9jESZ9pCw/b Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10304"; a="240739919" X-IronPort-AV: E=Sophos;i="5.90,227,1643702400"; d="scan'208";a="240739919" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Apr 2022 07:24:39 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,227,1643702400"; d="scan'208";a="695908415" Received: from cathy-vostro-3670.bj.intel.com ([10.238.156.128]) by fmsmga001.fm.intel.com with ESMTP; 01 Apr 2022 07:24:37 -0700 From: Cathy Zhang To: linux-sgx@vger.kernel.org, x86@kernel.org Cc: jarkko@kernel.org, reinette.chatre@intel.com, dave.hansen@intel.com, ashok.raj@intel.com, cathy.zhang@intel.com Subject: [RFC PATCH v3 09/10] x86/cpu: Call ENCLS[EUPDATESVN] procedure in microcode update Date: Fri, 1 Apr 2022 22:24:08 +0800 Message-Id: <20220401142409.26215-10-cathy.zhang@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220401142409.26215-1-cathy.zhang@intel.com> References: <20220401142409.26215-1-cathy.zhang@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-sgx@vger.kernel.org EUPDATESVN is the SGX instruction which allows enclave attestation to include information about updated microcode without a reboot. Microcode updates which affect SGX require two phases: 1. Do the main microcode update 2. Make the new CPUSVN available for enclave attestation via EUPDATESVN. Before a EUPDATESVN can succeed, all enclave pages (EPC) must be marked as unused in the SGX metadata (EPCM). This operation destroys all preexisting SGX enclave data and metadata. This is by design and mitigates the impact of vulnerabilities that may have compromised enclaves or the SGX hardware itself prior to the update. Signed-off-by: Cathy Zhang --- Changes since v1: - Remove the sysfs file svnupdate. (Thomas Gleixner, Dave Hansen) - Let late microcode load path call ENCLS[EUPDATESVN] procedure directly. (Borislav Petkov) - Redefine update_cpusvn_intel() to return void instead of int. --- arch/x86/include/asm/microcode.h | 5 +++++ arch/x86/include/asm/sgx.h | 5 +++++ arch/x86/kernel/cpu/common.c | 9 +++++++++ arch/x86/kernel/cpu/sgx/main.c | 12 ++++++++++++ 4 files changed, 31 insertions(+) diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h index d6bfdfb0f0af..1ba66b9fe198 100644 --- a/arch/x86/include/asm/microcode.h +++ b/arch/x86/include/asm/microcode.h @@ -3,6 +3,7 @@ #define _ASM_X86_MICROCODE_H #include +#include #include #include @@ -137,4 +138,8 @@ static inline void load_ucode_ap(void) { } static inline void reload_early_microcode(void) { } #endif +#ifndef update_cpusvn_intel +static inline void update_cpusvn_intel(void) {} +#endif + #endif /* _ASM_X86_MICROCODE_H */ diff --git a/arch/x86/include/asm/sgx.h b/arch/x86/include/asm/sgx.h index 74bcb6841a4b..5867f5a78d13 100644 --- a/arch/x86/include/asm/sgx.h +++ b/arch/x86/include/asm/sgx.h @@ -409,4 +409,9 @@ int sgx_virt_einit(void __user *sigstruct, void __user *token, int sgx_set_attribute(unsigned long *allowed_attributes, unsigned int attribute_fd); +#ifdef CONFIG_X86_SGX +void update_cpusvn_intel(void); +#define update_cpusvn_intel update_cpusvn_intel +#endif + #endif /* _ASM_X86_SGX_H */ diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 7b8382c11788..f53fd877ba0d 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -59,6 +59,7 @@ #include #include #include +#include #include "cpu.h" @@ -2086,6 +2087,14 @@ void microcode_check(void) perf_check_microcode(); + /* + * SGX related microcode update requires EUPDATESVN to update CPUSVN, which + * will destroy all enclaves to ensure EPC is not in use. If SGX is configured + * and EUPDATESVN is supported, call the EUPDATESVN procecure. + */ + if (IS_ENABLED(CONFIG_X86_SGX) && (cpuid_eax(SGX_CPUID) & SGX_CPUID_EUPDATESVN)) + update_cpusvn_intel(); + /* Reload CPUID max function as it might've changed. */ info.cpuid_level = cpuid_eax(0); diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c index 784780314762..20800c543110 100644 --- a/arch/x86/kernel/cpu/sgx/main.c +++ b/arch/x86/kernel/cpu/sgx/main.c @@ -1409,3 +1409,15 @@ static int sgx_updatesvn(void) return ret; } + +void update_cpusvn_intel(void) +{ + sgx_lock_epc(); + if (sgx_zap_pages()) + goto out; + + sgx_updatesvn(); + +out: + sgx_unlock_epc(); +} From patchwork Fri Apr 1 14:24:09 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, Cathy" X-Patchwork-Id: 12798391 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5285FC433F5 for ; Fri, 1 Apr 2022 14:24:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346817AbiDAO0c (ORCPT ); Fri, 1 Apr 2022 10:26:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57826 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346822AbiDAO0b (ORCPT ); Fri, 1 Apr 2022 10:26:31 -0400 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6F69C11CF73 for ; Fri, 1 Apr 2022 07:24:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1648823082; x=1680359082; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=T+hPy5K8MWlAG6yHiHd9+gI34P/tcc20T14oNHvLIhY=; b=Im7q0TO5LSBv+UgVLEt+SDR4G+QAFqf/S+yHMtPWfp7Ze5T2qGUI1e/v 1LKl75uzT5YFG8SxkZg+s9V02noIulqt/IWgBO6Nm0XLMdiB5SSyIss8y 1ze7xZpld6JdRGjF/L2RKdDohasPhhvMpsvTczcAZ5Z1Esx+xY9h/pxu8 DqvH/mArRV/ya4NFEd3FFbT+ohB5tfW41iBo08iscWAQaGNDWYtQkRlUF f4GAR/TNLeGR5xnqmdoTWLSwy5XM+5iVJ1Ppa3a8Pw/kF3eThsaFZik71 ilDJ40AogEpFJkZSqexfZpkt/GXWCotYFkraeoj/hv4RQmw6Q+zFL/EUP Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10304"; a="240739929" X-IronPort-AV: E=Sophos;i="5.90,227,1643702400"; d="scan'208";a="240739929" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Apr 2022 07:24:42 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,227,1643702400"; d="scan'208";a="695908419" Received: from cathy-vostro-3670.bj.intel.com ([10.238.156.128]) by fmsmga001.fm.intel.com with ESMTP; 01 Apr 2022 07:24:40 -0700 From: Cathy Zhang To: linux-sgx@vger.kernel.org, x86@kernel.org Cc: jarkko@kernel.org, reinette.chatre@intel.com, dave.hansen@intel.com, ashok.raj@intel.com, cathy.zhang@intel.com Subject: [RFC PATCH v3 10/10] x86/sgx: Call ENCLS[EUPDATESVN] during SGX initialization Date: Fri, 1 Apr 2022 22:24:09 +0800 Message-Id: <20220401142409.26215-11-cathy.zhang@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220401142409.26215-1-cathy.zhang@intel.com> References: <20220401142409.26215-1-cathy.zhang@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-sgx@vger.kernel.org A snapshot of the processor microcode SVN is taken each boot cycle at the time when Intel SGX is first used. This results in microcode updates being loadable at any time, fixing microcode issues. However, if system boot up through kexec() from error recovery, no hardware reset happens, any SGX leaf execution during boot up is not assumed as the first use in such case, and no snapshot of SVN is taken. So, it's necessary to call ENCLS[EUPDATESVN] to update SVN automatically, rather than waiting for the admin to do it when he/she is even not aware of that. Call ENCLS[EUPDATESVN] after sanitizing pages will increase the chance of success, for it requires that EPC is empty. Signed-off-by: Cathy Zhang --- Changes since v1: - Update accordingly for update_cpusvn_intel() return *void*. --- arch/x86/kernel/cpu/sgx/main.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c index 20800c543110..48eb10f6c6fc 100644 --- a/arch/x86/kernel/cpu/sgx/main.c +++ b/arch/x86/kernel/cpu/sgx/main.c @@ -426,6 +426,7 @@ static bool sgx_should_reclaim(unsigned long watermark) !list_empty(&sgx_active_page_list); } +void update_cpusvn_intel(void); static int ksgxd(void *p) { int srcu_idx; @@ -440,7 +441,14 @@ static int ksgxd(void *p) __sgx_sanitize_pages(&sgx_dirty_page_list); /* sanity check: */ - WARN_ON(!list_empty(&sgx_dirty_page_list)); + if (!WARN_ON(!list_empty(&sgx_dirty_page_list))) { + /* + * Do SVN update for kexec(). It should complete without error, for + * all EPC pages are unused at this point. + */ + if (cpuid_eax(SGX_CPUID) & SGX_CPUID_EUPDATESVN) + update_cpusvn_intel(); + } while (!kthread_should_stop()) { if (try_to_freeze())