Detect the SECS in paging related flows by explicitly checking the page against the enclave's SECS page. Assuming a page with VA=0 is the SECS will break enclaves that actually use VA=0, which is extremely unlikely but theoretically possible. Signed-off-by: Sean Christopherson <sean.j.christopherson@xxxxxxxxx> --- arch/x86/kernel/cpu/sgx/encl.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/cpu/sgx/encl.c b/arch/x86/kernel/cpu/sgx/encl.c index 909af9a664f0..6da1c36a01e6 100644 --- a/arch/x86/kernel/cpu/sgx/encl.c +++ b/arch/x86/kernel/cpu/sgx/encl.c @@ -12,10 +12,14 @@ #include "encls.h" #include "sgx.h" +static bool sgx_encl_is_secs(struct sgx_encl *encl, struct sgx_encl_page *page) +{ + return page == &encl->secs; +} + static int __sgx_encl_eldu(struct sgx_encl_page *encl_page, struct sgx_epc_page *epc_page) { - unsigned long addr = SGX_ENCL_PAGE_ADDR(encl_page); unsigned long va_offset = SGX_ENCL_PAGE_VA_OFFSET(encl_page); struct sgx_encl *encl = encl_page->encl; pgoff_t page_index = sgx_encl_get_index(encl, encl_page); @@ -38,11 +42,11 @@ static int __sgx_encl_eldu(struct sgx_encl_page *encl_page, goto err_pcmd; } - pginfo.addr = addr; + pginfo.addr = SGX_ENCL_PAGE_ADDR(encl_page); pginfo.contents = (unsigned long)kmap_atomic(backing); pginfo.metadata = (unsigned long)kmap_atomic(pcmd) + pcmd_offset; - pginfo.secs = addr ? (unsigned long)sgx_epc_addr(encl->secs.epc_page) : - 0; + pginfo.secs = sgx_encl_is_secs(encl, encl_page) ? 0 : + (unsigned long)sgx_epc_addr(encl->secs.epc_page); ret = __eldu(&pginfo, sgx_epc_addr(epc_page), sgx_epc_addr(encl_page->va_page->epc_page) + va_offset); @@ -546,7 +550,7 @@ void sgx_encl_release(struct kref *ref) */ pgoff_t sgx_encl_get_index(struct sgx_encl *encl, struct sgx_encl_page *page) { - if (!PFN_DOWN(page->desc)) + if (sgx_encl_is_secs(encl, page)) return PFN_DOWN(encl->size); return PFN_DOWN(page->desc - encl->base); -- 2.22.0