@@ -1031,6 +1031,7 @@ config INTEL_SGX
tristate "Intel(R) SGX Driver"
default n
depends on X86
+ select MMU_NOTIFIER
---help---
Intel(R) SGX is a set of CPU instructions that can be used by
applications to set aside private regions of code and data. The code
@@ -67,6 +67,7 @@
#include <linux/rwsem.h>
#include <linux/sched.h>
#include <linux/workqueue.h>
+#include <linux/mmu_notifier.h>
#define SGX_EINIT_SPIN_COUNT 20
#define SGX_EINIT_SLEEP_COUNT 50
@@ -152,6 +153,7 @@ struct sgx_encl {
struct sgx_encl_page secs_page;
struct sgx_tgid_ctx *tgid_ctx;
struct list_head encl_list;
+ struct mmu_notifier mmu_notifier;
};
extern struct workqueue_struct *sgx_add_page_wq;
@@ -471,6 +471,21 @@ static int sgx_init_page(struct sgx_encl *encl,
return 0;
}
+static void sgx_mmu_notifier_release(struct mmu_notifier *mn,
+ struct mm_struct *mm)
+{
+ struct sgx_encl *encl =
+ container_of(mn, struct sgx_encl, mmu_notifier);
+
+ mutex_lock(&encl->lock);
+ encl->flags |= SGX_ENCL_INVALIDATED;
+ mutex_unlock(&encl->lock);
+}
+
+static const struct mmu_notifier_ops sgx_mmu_notifier_ops = {
+ .release = sgx_mmu_notifier_release,
+};
+
/**
* sgx_ioc_enclave_create - handler for SGX_IOC_ENCLAVE_CREATE
*
@@ -572,6 +587,12 @@ static long sgx_ioc_enclave_create(struct file *filep, unsigned int cmd,
if (secs->flags & SGX_SECS_A_DEBUG)
encl->flags |= SGX_ENCL_DEBUG;
+ ret = mmu_notifier_register(&encl->mmu_notifier, encl->mm);
+ if (ret)
+ goto out;
+
+ encl->mmu_notifier.ops = &sgx_mmu_notifier_ops;
+
down_read(¤t->mm->mmap_sem);
vma = find_vma(current->mm, secs->base);
if (!vma || vma->vm_ops != &sgx_vm_ops ||
@@ -237,6 +237,10 @@ void sgx_encl_release(struct kref *ref)
mutex_unlock(&sgx_tgid_ctx_mutex);
+ if (encl->mmu_notifier.ops)
+ mmu_notifier_unregister_no_release(&encl->mmu_notifier,
+ encl->mm);
+
rb1 = rb_first(&encl->encl_rb);
while (rb1) {
entry = container_of(rb1, struct sgx_encl_page, node);
Page table should not be manipulated after all user processes cease to exist. This can result page table inconsistency errors: BUG: non-zero nr_ptes on freeing mm: 1 This commit fixes the issue by invalidating the enclave after all user processes have been died. Reported-by: Sean Christopherson <sean.j.christopherson@intel.com> Suggested-by: Sean Christopherson <sean.j.christopherson@intel.com> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> --- drivers/platform/x86/Kconfig | 1 + drivers/platform/x86/intel_sgx.h | 2 ++ drivers/platform/x86/intel_sgx_ioctl.c | 21 +++++++++++++++++++++ drivers/platform/x86/intel_sgx_util.c | 4 ++++ 4 files changed, 28 insertions(+)