]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
x86/sgx: Move PTE zap code to new sgx_zap_enclave_ptes()
authorReinette Chatre <reinette.chatre@intel.com>
Tue, 10 May 2022 18:08:44 +0000 (11:08 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 13 Mar 2025 11:51:06 +0000 (12:51 +0100)
[ Upstream commit f89c2f9bf5a64f619de06ded4349dff5a35da860 ]

The SGX reclaimer removes page table entries pointing to pages that are
moved to swap.

SGX2 enables changes to pages belonging to an initialized enclave, thus
enclave pages may have their permission or type changed while the page
is being accessed by an enclave. Supporting SGX2 requires page table
entries to be removed so that any cached mappings to changed pages
are removed. For example, with the ability to change enclave page types
a regular enclave page may be changed to a Thread Control Structure
(TCS) page that may not be accessed by an enclave.

Factor out the code removing page table entries to a separate function
sgx_zap_enclave_ptes(), fixing accuracy of comments in the process,
and make it available to the upcoming SGX2 code.

Place sgx_zap_enclave_ptes() with the rest of the enclave code in
encl.c interacting with the page table since this code is no longer
unique to the reclaimer.

Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Link: https://lkml.kernel.org/r/b010cdf01d7ce55dd0f00e883b7ccbd9db57160a.1652137848.git.reinette.chatre@intel.com
Stable-dep-of: 0d3e0dfd68fb ("x86/sgx: Fix size overflows in sgx_encl_create()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
arch/x86/kernel/cpu/sgx/encl.c
arch/x86/kernel/cpu/sgx/encl.h
arch/x86/kernel/cpu/sgx/main.c

index 70fd9aa47c68d77bef132b5bcc7e85b33f42e6a9..7cb9f89ee7365d1a9540d41ad4f8543ec11fa5d6 100644 (file)
@@ -721,7 +721,7 @@ int sgx_encl_mm_add(struct sgx_encl *encl, struct mm_struct *mm)
 
        spin_lock(&encl->mm_lock);
        list_add_rcu(&encl_mm->list, &encl->mm_list);
-       /* Pairs with smp_rmb() in sgx_reclaimer_block(). */
+       /* Pairs with smp_rmb() in sgx_zap_enclave_ptes(). */
        smp_wmb();
        encl->mm_list_version++;
        spin_unlock(&encl->mm_lock);
@@ -936,6 +936,49 @@ int sgx_encl_test_and_clear_young(struct mm_struct *mm,
        return ret;
 }
 
+/**
+ * sgx_zap_enclave_ptes() - remove PTEs mapping the address from enclave
+ * @encl: the enclave
+ * @addr: page aligned pointer to single page for which PTEs will be removed
+ *
+ * Multiple VMAs may have an enclave page mapped. Remove the PTE mapping
+ * @addr from each VMA. Ensure that page fault handler is ready to handle
+ * new mappings of @addr before calling this function.
+ */
+void sgx_zap_enclave_ptes(struct sgx_encl *encl, unsigned long addr)
+{
+       unsigned long mm_list_version;
+       struct sgx_encl_mm *encl_mm;
+       struct vm_area_struct *vma;
+       int idx, ret;
+
+       do {
+               mm_list_version = encl->mm_list_version;
+
+               /* Pairs with smp_wmb() in sgx_encl_mm_add(). */
+               smp_rmb();
+
+               idx = srcu_read_lock(&encl->srcu);
+
+               list_for_each_entry_rcu(encl_mm, &encl->mm_list, list) {
+                       if (!mmget_not_zero(encl_mm->mm))
+                               continue;
+
+                       mmap_read_lock(encl_mm->mm);
+
+                       ret = sgx_encl_find(encl_mm->mm, addr, &vma);
+                       if (!ret && encl == vma->vm_private_data)
+                               zap_vma_ptes(vma, addr, PAGE_SIZE);
+
+                       mmap_read_unlock(encl_mm->mm);
+
+                       mmput_async(encl_mm->mm);
+               }
+
+               srcu_read_unlock(&encl->srcu, idx);
+       } while (unlikely(encl->mm_list_version != mm_list_version));
+}
+
 /**
  * sgx_alloc_va_page() - Allocate a Version Array (VA) page
  *
index a4894cf3f56a2874633d770aaecee48feabf9633..ed5ced8ccd2c83bfc0631803798f933e6928223c 100644 (file)
@@ -113,7 +113,7 @@ int sgx_encl_alloc_backing(struct sgx_encl *encl, unsigned long page_index,
 void sgx_encl_put_backing(struct sgx_backing *backing);
 int sgx_encl_test_and_clear_young(struct mm_struct *mm,
                                  struct sgx_encl_page *page);
-
+void sgx_zap_enclave_ptes(struct sgx_encl *encl, unsigned long addr);
 struct sgx_epc_page *sgx_alloc_va_page(void);
 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);
index ad453b4387a443317a2cb1feba2264759a437294..fd786f1bc4e8717fff718699634251d21f39c43f 100644 (file)
@@ -122,36 +122,9 @@ static void sgx_reclaimer_block(struct sgx_epc_page *epc_page)
        struct sgx_encl_page *page = epc_page->owner;
        unsigned long addr = page->desc & PAGE_MASK;
        struct sgx_encl *encl = page->encl;
-       unsigned long mm_list_version;
-       struct sgx_encl_mm *encl_mm;
-       struct vm_area_struct *vma;
-       int idx, ret;
-
-       do {
-               mm_list_version = encl->mm_list_version;
-
-               /* Pairs with smp_rmb() in sgx_encl_mm_add(). */
-               smp_rmb();
-
-               idx = srcu_read_lock(&encl->srcu);
-
-               list_for_each_entry_rcu(encl_mm, &encl->mm_list, list) {
-                       if (!mmget_not_zero(encl_mm->mm))
-                               continue;
-
-                       mmap_read_lock(encl_mm->mm);
-
-                       ret = sgx_encl_find(encl_mm->mm, addr, &vma);
-                       if (!ret && encl == vma->vm_private_data)
-                               zap_vma_ptes(vma, addr, PAGE_SIZE);
-
-                       mmap_read_unlock(encl_mm->mm);
-
-                       mmput_async(encl_mm->mm);
-               }
+       int ret;
 
-               srcu_read_unlock(&encl->srcu, idx);
-       } while (unlikely(encl->mm_list_version != mm_list_version));
+       sgx_zap_enclave_ptes(encl, addr);
 
        mutex_lock(&encl->lock);