On Tue, Nov 17, 2020 at 06:26:50PM +0100, Borislav Petkov wrote:
On Fri, Nov 13, 2020 at 12:01:31AM +0200, Jarkko Sakkinen wrote:
+bool encl_load(const char *path, struct encl *encl) +{
- Elf64_Phdr *phdr_tbl;
- off_t src_offset;
- Elf64_Ehdr *ehdr;
- int i, j;
- int ret;
- memset(encl, 0, sizeof(*encl));
- ret = open("/dev/sgx_enclave", O_RDWR);
- if (ret < 0) {
fprintf(stderr, "Unable to open /dev/sgx_enclave\n");
goto err;
- }
- encl->fd = ret;
- if (!encl_map_bin(path, encl))
goto err;
- ehdr = encl->bin;
- phdr_tbl = encl->bin + ehdr->e_phoff;
- for (i = 0; i < ehdr->e_phnum; i++) {
Elf64_Phdr *phdr = &phdr_tbl[i];
if (phdr->p_type == PT_LOAD)
encl->nr_segments++;
- }
- encl->segment_tbl = calloc(encl->nr_segments,
sizeof(struct encl_segment));
- if (!encl->segment_tbl)
goto err;
- for (i = 0, j = 0; i < ehdr->e_phnum; i++) {
Elf64_Phdr *phdr = &phdr_tbl[i];
unsigned int flags = phdr->p_flags;
struct encl_segment *seg;
if (phdr->p_type != PT_LOAD)
continue;
seg = &encl->segment_tbl[j];
if (!!(flags & ~(PF_R | PF_W | PF_X))) {
fprintf(stderr,
"%d has invalid segment flags 0x%02x.\n", i,
phdr->p_flags);
goto err;
}
if (j == 0 && flags != (PF_R | PF_W)) {
fprintf(stderr,
"TCS has invalid segment flags 0x%02x.\n",
phdr->p_flags);
goto err;
}
if (j == 0) {
src_offset = (phdr->p_offset & PAGE_MASK) - src_offset;
seg->prot = PROT_READ | PROT_WRITE;
seg->flags = SGX_PAGE_TYPE_TCS << 8;
} else {
seg->prot = (phdr->p_flags & PF_R) ? PROT_READ : 0;
seg->prot |= (phdr->p_flags & PF_W) ? PROT_WRITE : 0;
seg->prot |= (phdr->p_flags & PF_X) ? PROT_EXEC : 0;
seg->flags = (SGX_PAGE_TYPE_REG << 8) | seg->prot;
}
seg->offset = (phdr->p_offset & PAGE_MASK) - src_offset;
seg->size = (phdr->p_filesz + PAGE_SIZE - 1) & PAGE_MASK;
printf("0x%016lx 0x%016lx 0x%02x\n", seg->offset, seg->size,
seg->prot);
j++;
- }
- assert(j == encl->nr_segments);
- encl->src = encl->bin + src_offset;
- encl->src_size = encl->segment_tbl[j - 1].offset +
encl->segment_tbl[j - 1].size;
- for (encl->encl_size = 4096; encl->encl_size < encl->src_size; )
encl->encl_size <<= 1;
Something's fishy. That selftest fails with
mmap: Cannot allocate memory
I sprinkled some printfs at this size computation above and here's what it says:
0x00007fdd3b4ca190 0x0000000000002000 0x03 0x00007fdd3b4cc190 0x0000000000001000 0x05 0x00007fdd3b4cd190 0x0000000000003000 0x03 encl_load: encl->nr_segments: 3 encl_load: seg2 offset: 0x7fdd3b4cd190, seg2 size: 12288 encl_load: encl_size: 140737488355328, src_size: 140588159402384 encl_map_area: encl_size: 140737488355328 mmap: Cannot allocate memory
src_size is computed by adding the offset and size of the last segment which is at index 2.
src_size does not look right. I'll debug.
The loop computes encl_size to 0x0000800000000000 then and mmap tries to map double that in encl_map_area(). Looks like too much to me too.
The enclave base must be naturally aligned in relative to its size.
What's up?
-- Regards/Gruss, Boris.
/Jarkko