@@ -484,7 +484,11 @@ void sgx_encl_destroy(struct sgx_encl *encl)
encl->secs.epc_page = NULL;
}
-
+ /*
+ * The reclaimer is responsible for checking SGX_ENCL_DEAD before doing
+ * EWB, thus it's safe to free VA pages even if the reclaimer holds a
+ * reference to the enclave.
+ */
while (!list_empty(&encl->va_pages)) {
va_page = list_first_entry(&encl->va_pages, struct sgx_va_page,
list);
@@ -321,16 +321,19 @@ static void sgx_reclaimer_write(struct sgx_epc_page *epc_page,
encl_page->epc_page = NULL;
encl->secs_child_cnt--;
- if (!encl->secs_child_cnt &&
- (atomic_read(&encl->flags) &
- (SGX_ENCL_DEAD | SGX_ENCL_INITIALIZED))) {
- ret = sgx_encl_get_backing(encl, PFN_DOWN(encl->size),
- &secs_backing);
- if (!ret) {
- sgx_encl_ewb(encl->secs.epc_page, &secs_backing);
+ if (!encl->secs_child_cnt) {
+ if (atomic_read(&encl->flags) & SGX_ENCL_DEAD) {
sgx_free_page(encl->secs.epc_page);
-
encl->secs.epc_page = NULL;
+ } else if (atomic_read(&encl->flags) & SGX_ENCL_INITIALIZED) {
+ ret = sgx_encl_get_backing(encl, PFN_DOWN(encl->size),
+ &secs_backing);
+ if (!ret) {
+ sgx_encl_ewb(encl->secs.epc_page, &secs_backing);
+
+ sgx_free_page(encl->secs.epc_page);
+ encl->secs.epc_page = NULL;
+ }
sgx_encl_put_backing(&secs_backing, true);
}
Don't EWB if the enclave is dead when opportunistically zapping the SECS during reclaim as VA pages are freed by sgx_encl_destroy(), i.e. sgx_encl_ewb() will consume a bad encl->va_pages if the enclave has been destroyed. Add a comment in sgx_encl_destroy() to explicit call out that it's ok to free VA pages. Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com> --- arch/x86/kernel/cpu/sgx/encl.c | 6 +++++- arch/x86/kernel/cpu/sgx/reclaim.c | 19 +++++++++++-------- 2 files changed, 16 insertions(+), 9 deletions(-)