@@ -130,12 +130,13 @@ enum sgx_encl_flags {
SGX_ENCL_DEBUG = BIT(1),
SGX_ENCL_SECS_EVICTED = BIT(2),
SGX_ENCL_SUSPEND = BIT(3),
+ SGX_ENCL_PAGES_ADDED = BIT(4),
+ SGX_ENCL_INVALIDATED = BIT(5),
};
struct sgx_encl {
- unsigned int flags;
+ unsigned long flags;
unsigned int secs_child_cnt;
- unsigned int vma_cnt;
struct mutex lock;
struct task_struct *owner;
struct mm_struct *mm;
@@ -255,7 +255,10 @@ static bool sgx_process_add_page_req(struct sgx_add_page_req *req)
mutex_lock(&encl->lock);
- if (!encl->vma_cnt || sgx_find_encl(encl->mm, encl_page->addr, &vma))
+ if (encl->flags & SGX_ENCL_INVALIDATED)
+ goto out;
+
+ if (sgx_find_encl(encl->mm, encl_page->addr, &vma))
goto out;
backing = sgx_get_backing(encl, encl_page);
@@ -578,7 +581,6 @@ static long sgx_ioc_enclave_create(struct file *filep, unsigned int cmd,
up_read(¤t->mm->mmap_sem);
goto out;
}
- encl->vma_cnt++;
vma->vm_private_data = encl;
up_read(¤t->mm->mmap_sem);
@@ -682,7 +684,7 @@ static int __encl_add_page(struct sgx_encl *encl,
mutex_lock(&encl->lock);
- if (encl->flags & SGX_ENCL_INITIALIZED) {
+ if (encl->flags & (SGX_ENCL_INITIALIZED | SGX_ENCL_INVALIDATED)) {
ret = -EINVAL;
goto out;
}
@@ -734,6 +736,7 @@ out:
} else {
ret = encl_rb_insert(&encl->encl_rb, encl_page);
WARN_ON(ret);
+ encl->flags |= SGX_ENCL_PAGES_ADDED;
}
mutex_unlock(&encl->lock);
@@ -139,7 +139,7 @@ bool sgx_pin_mm(struct sgx_encl *encl)
return false;
mutex_lock(&encl->lock);
- if (encl->vma_cnt) {
+ if (!(encl->flags & SGX_ENCL_INVALIDATED)) {
atomic_inc(&encl->mm->mm_count);
} else {
mutex_unlock(&encl->lock);
@@ -149,7 +149,7 @@ bool sgx_pin_mm(struct sgx_encl *encl)
down_read(&encl->mm->mmap_sem);
- if (!encl->vma_cnt) {
+ if (encl->flags & SGX_ENCL_INVALIDATED) {
sgx_unpin_mm(encl);
return false;
}
@@ -175,7 +175,7 @@ void sgx_invalidate(struct sgx_encl *encl)
sgx_zap_tcs_ptes(encl, vma);
}
- encl->vma_cnt = 0;
+ encl->flags |= SGX_ENCL_INVALIDATED;
}
int sgx_find_encl(struct mm_struct *mm, unsigned long addr,
@@ -72,21 +72,20 @@ static void sgx_vma_open(struct vm_area_struct *vma)
{
struct sgx_encl *encl;
- /* Was vm_private_data nullified as a result of the previous fork? */
+ /* fork after fork */
encl = vma->vm_private_data;
if (!encl)
goto out_fork;
- /* Was the process forked? mm_struct changes when the process is
- * forked.
- */
- mutex_lock(&encl->lock);
- if (encl->mm != vma->vm_mm) {
- mutex_unlock(&encl->lock);
+ /* mm_struct changes when the process is forked */
+ if (encl->mm != vma->vm_mm)
goto out_fork;
+
+ if (test_bit(SGX_ENCL_PAGES_ADDED, &encl->flags)) {
+ mutex_lock(&encl->lock);
+ sgx_invalidate(encl);
+ mutex_unlock(&encl->lock);
}
- encl->vma_cnt++;
- mutex_unlock(&encl->lock);
kref_get(&encl->refcount);
return;
@@ -99,21 +98,13 @@ static void sgx_vma_close(struct vm_area_struct *vma)
{
struct sgx_encl *encl = vma->vm_private_data;
- /* If process was forked, VMA is still there but
- * vm_private_data is set to NULL.
- */
+ /* fork */
if (!encl)
return;
mutex_lock(&encl->lock);
- encl->vma_cnt--;
- vma->vm_private_data = NULL;
-
- sgx_zap_tcs_ptes(encl, vma);
- zap_vma_ptes(vma, vma->vm_start, vma->vm_end - vma->vm_start);
-
+ sgx_invalidate(encl);
mutex_unlock(&encl->lock);
-
kref_put(&encl->refcount, sgx_encl_release);
}
@@ -187,7 +178,7 @@ static struct sgx_encl_page *sgx_vma_do_fault(struct vm_area_struct *vma,
mutex_lock(&encl->lock);
- if (!encl->vma_cnt) {
+ if (encl->flags & SGX_ENCL_INVALIDATED) {
entry = ERR_PTR(-EFAULT);
goto out;
}
@@ -370,6 +361,7 @@ static int sgx_vma_access(struct vm_area_struct *vma, unsigned long addr,
if (!(encl->flags & SGX_ENCL_DEBUG) ||
!(encl->flags & SGX_ENCL_INITIALIZED) ||
+ (encl->flags & SGX_ENCL_INVALIDATED) ||
(encl->flags & SGX_ENCL_SUSPEND))
return -EFAULT;
Added SGX_ENCL_INVALIDATED flag to inform when the enclave is not usable anymore. After pages have been added to the enclave it does not make sense to change the VMA config anymore because permissions of pages cannot changed with SGX1 architecture. Also if any of the VMAs are closed the whole enclave is invalidated. This makes sense for SGX1 architecture as the permissions of pages cannot be changed later on. For SGX2 we might be able to ease the requirement because of EMODP. Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> --- drivers/platform/x86/intel_sgx.h | 5 +++-- drivers/platform/x86/intel_sgx_ioctl.c | 9 ++++++--- drivers/platform/x86/intel_sgx_util.c | 6 +++--- drivers/platform/x86/intel_sgx_vma.c | 32 ++++++++++++-------------------- 4 files changed, 24 insertions(+), 28 deletions(-)