diff --git a/lib/liblaunch/elf.c b/lib/liblaunch/elf.c index e3e3f18..4cd90c4 100644 --- a/lib/liblaunch/elf.c +++ b/lib/liblaunch/elf.c @@ -104,6 +104,7 @@ static enum launch_status parse_phdr(struct elf_image *image) size_t r = 0; image->e_total_size = 0; image->e_data_size = 0; + off_t vaddr, vlimit; for (size_t i = 0; i < image->e_hdr.e_phnum; i++) { off_t offset @@ -119,23 +120,24 @@ static enum launch_status parse_phdr(struct elf_image *image) return LAUNCH_ERR_INVALID_EXECUTABLE; } + vaddr = phdr.p_vaddr; + vlimit = phdr.p_vaddr + phdr.p_memsz; + if (vaddr & (PAGE_SIZE - 1)) { + vaddr &= ~(PAGE_SIZE - 1); + } + + if (vlimit & (PAGE_SIZE - 1)) { + vlimit &= ~(PAGE_SIZE - 1); + vlimit += PAGE_SIZE; + } + switch (phdr.p_type) { case PT_DYNAMIC: image->e_dynamic = phdr; break; case PT_LOAD: - if (phdr.p_vaddr & (PAGE_SIZE - 1)) { - phdr.p_vaddr &= (PAGE_SIZE - 1); - } - if (phdr.p_memsz & (PAGE_SIZE - 1)) { - phdr.p_memsz &= (PAGE_SIZE - 1); - phdr.p_memsz += PAGE_SIZE; - } - - image->e_total_size - = MAX(image->e_total_size, - phdr.p_vaddr + phdr.p_memsz); + image->e_total_size = MAX(image->e_total_size, vlimit); break; case PT_INTERP: { size_t r = 0; @@ -153,9 +155,7 @@ static enum launch_status parse_phdr(struct elf_image *image) } if (phdr.p_flags & PF_W) { - image->e_data_size - = MAX(image->e_data_size, - phdr.p_vaddr + phdr.p_memsz); + image->e_data_size = MAX(image->e_data_size, vlimit); } } @@ -164,6 +164,10 @@ static enum launch_status parse_phdr(struct elf_image *image) static kern_status_t create_exec_regions(struct elf_image *image) { + kern_tracef( + "launch: executable region size=%zu %zx", + image->e_total_size, + image->e_total_size); kern_status_t status = KERN_OK; if (image->e_local_space != KERN_HANDLE_INVALID) { status = vm_region_create( @@ -240,6 +244,7 @@ static enum launch_status map_executable(struct elf_image *image) if (phdr.p_flags & PF_W) { vmo = image->e_data; offset = data_offset; + size_t tmp = 0; status = vm_object_copy( image->e_data, @@ -247,7 +252,11 @@ static enum launch_status map_executable(struct elf_image *image) image->e_image, phdr.p_offset, phdr.p_filesz, - NULL); + &tmp); + + if (tmp != phdr.p_filesz) { + return LAUNCH_ERR_IMAGE_DATA_LOAD_FAILED; + } } if (status != KERN_OK) { @@ -383,6 +392,7 @@ static enum launch_status relocate(struct elf_image *image) size_t nr_dyn = image->e_dynamic.p_filesz / sizeof *dyn; for (size_t i = 0; i < nr_dyn; i++) { + kern_tracef("DYN:%zx", dyn[i].d_tag); switch (dyn[i].d_tag) { case DT_SYMTAB: image->e_dynsym = dyn[i].d_un.d_ptr;