keystone-enclave / keystone-sdk

SDK for Keystone Enclave - ABI/SBI libraries and sample apps
Other
44 stars 22 forks source link

PhysicalEnclaveMemory::WriteMem segfaults with glibc-2.28 #48

Closed kazkojima closed 3 years ago

kazkojima commented 4 years ago

I've tried a bit newer version of glibc 2.28 during building keystone. Everything are built without failure, but tests fail a bit randomly. Those tests fail with segfault at memcpy in the host library function:

void PhysicalEnclaveMemory::WriteMem(vaddr_t src, vaddr_t dst, size_t size){
  vaddr_t va_dst = (vaddr_t) mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, keystone_fd, dst - start_phys_addr);
  memcpy((void *) va_dst, (void *) src, size);
}

Looking into details, mmap returns MAP_FAILED==-1 for the problematic case and memcpy of riscv-glibc 2.26 does nothing for this destination address 0xffffffffffffffff, though 2.28's memcpy segfaults with it. This WriteMem is called by Keystone::allocPage() with

    case UTM_FULL: {
       *pte = pte_create(page_addr, PTE_D | PTE_A | PTE_R | PTE_W |PTE_V);
       pMemory->WriteMem(src, (vaddr_t) page_addr << PAGE_BITS, PAGE_SIZE);
       break;

and ((vaddr_t) page_addr << PAGE_BITS) is less than start_phys_addr when the issue happens. I guess that WriteMem won't work well for UTM, because it computes the offset from start_phys_addr which may not be the base address of utm pages. It seems that the above WriteMem isn't required in the first place, because UTM is cleared already by SM with clean_enclave_memory in create_enclave().

dayeol commented 3 years ago

Hi, thank you for the detailed report. I noticed that this was reported a long time ago. I think Alex missed it somehow. I was able to reproduce the issue and started to debug it.

dayeol commented 3 years ago

@alexthomas1 Could you take a look at this issue? Also, see if buildroot is related https://github.com/buildroot/buildroot/commit/acc1330d4a838193eb276e02e6642cf297c0e9c1#diff-593cf9bfa15cf7394701eb5b03826f794da95490e8a28a6f8d85199723f63112