added 2 changesets to branch 'refs/remotes/pdziepak-github/aslr' old head: d0a8e6ef2bc88d776c0e6f167bbd4ac9b8c262dd new head: db1ca60528285ea0c6620a5acac93c083fbbca6a overview: https://github.com/pdziepak/Haiku/compare/d0a8e6e...db1ca60 ---------------------------------------------------------------------------- cf35dcc: vm: make aslr use more secure PRNG db1ca60: runtime_loader: randomize position of runtime_loader * make runtime_loader a dynammically linked object * add kernel support for loading user images that need to be relocated * load runtime_loader at random address [ Pawel Dziepak <pdziepak@xxxxxxxxxxx> ] ---------------------------------------------------------------------------- 5 files changed, 71 insertions(+), 24 deletions(-) src/system/kernel/elf.cpp | 87 +++++++++++++++++------ src/system/kernel/vm/VMUserAddressSpace.cpp | 2 +- src/system/ldscripts/x86/runtime_loader.ld | 2 +- src/system/ldscripts/x86_64/runtime_loader.ld | 2 +- src/system/runtime_loader/Jamfile | 2 +- ############################################################################ Commit: cf35dcc5bc7827e242b5322fb6a06550c9395896 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Thu Apr 11 15:16:49 2013 UTC vm: make aslr use more secure PRNG ---------------------------------------------------------------------------- diff --git a/src/system/kernel/vm/VMUserAddressSpace.cpp b/src/system/kernel/vm/VMUserAddressSpace.cpp index a366cf7..71d48a6 100644 --- a/src/system/kernel/vm/VMUserAddressSpace.cpp +++ b/src/system/kernel/vm/VMUserAddressSpace.cpp @@ -407,7 +407,7 @@ VMUserAddressSpace::_RandomizeAddress(addr_t start, addr_t end, else range = min_c(range, kMaxRandomize); - addr_t random = get_random<addr_t>(); + addr_t random = secure_get_random<addr_t>(); random %= range; random &= ~addr_t(alignment - 1); ############################################################################ Commit: db1ca60528285ea0c6620a5acac93c083fbbca6a Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Tue Apr 16 00:29:05 2013 UTC runtime_loader: randomize position of runtime_loader * make runtime_loader a dynammically linked object * add kernel support for loading user images that need to be relocated * load runtime_loader at random address ---------------------------------------------------------------------------- diff --git a/src/system/kernel/elf.cpp b/src/system/kernel/elf.cpp index 307b55b..d937d8a 100644 --- a/src/system/kernel/elf.cpp +++ b/src/system/kernel/elf.cpp @@ -1069,7 +1069,7 @@ elf_resolve_symbol(struct elf_image_info *image, elf_sym *symbol, /*! Until we have shared library support, just this links against the kernel */ static int -elf_relocate(struct elf_image_info *image) +elf_relocate(struct elf_image_info* image, struct elf_image_info* resolveImage) { int status = B_NO_ERROR; @@ -1079,7 +1079,7 @@ elf_relocate(struct elf_image_info *image) if (image->rel) { TRACE(("total %i rel relocs\n", image->rel_len / (int)sizeof(elf_rel))); - status = arch_elf_relocate_rel(image, sKernelImage, image->rel, + status = arch_elf_relocate_rel(image, resolveImage, image->rel, image->rel_len); if (status < B_OK) return status; @@ -1089,12 +1089,12 @@ elf_relocate(struct elf_image_info *image) if (image->pltrel_type == DT_REL) { TRACE(("total %i plt-relocs\n", image->pltrel_len / (int)sizeof(elf_rel))); - status = arch_elf_relocate_rel(image, sKernelImage, image->pltrel, + status = arch_elf_relocate_rel(image, resolveImage, image->pltrel, image->pltrel_len); } else { TRACE(("total %i plt-relocs\n", image->pltrel_len / (int)sizeof(elf_rela))); - status = arch_elf_relocate_rela(image, sKernelImage, + status = arch_elf_relocate_rela(image, resolveImage, (elf_rela *)image->pltrel, image->pltrel_len); } if (status < B_OK) @@ -1105,7 +1105,7 @@ elf_relocate(struct elf_image_info *image) TRACE(("total %i rel relocs\n", image->rela_len / (int)sizeof(elf_rela))); - status = arch_elf_relocate_rela(image, sKernelImage, image->rela, + status = arch_elf_relocate_rela(image, resolveImage, image->rela, image->rela_len); if (status < B_OK) return status; @@ -1288,7 +1288,7 @@ insert_preloaded_image(preloaded_elf_image *preloadedImage, bool kernel) if (status != B_OK) goto error1; - status = elf_relocate(image); + status = elf_relocate(image, sKernelImage); if (status != B_OK) goto error1; } else @@ -1825,6 +1825,8 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry) ssize_t length; int fd; int i; + addr_t delta = 0; + uint32 addressSpec = B_RANDOMIZED_BASE_ADDRESS; TRACE(("elf_load: entry path '%s', team %p\n", path, team)); @@ -1854,6 +1856,14 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry) if (status < B_OK) goto error; + struct elf_image_info* image; + image = create_image_struct(); + if (image == NULL) { + status = B_NO_MEMORY; + goto error; + } + image->elf_header = &elfHeader; + // read program header programHeaders = (elf_phdr *)malloc( @@ -1861,7 +1871,7 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry) if (programHeaders == NULL) { dprintf("error allocating space for program headers\n"); status = B_NO_MEMORY; - goto error; + goto error2; } TRACE(("reading in program headers at 0x%lx, length 0x%x\n", @@ -1871,12 +1881,12 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry) if (length < B_OK) { status = length; dprintf("error reading in program headers\n"); - goto error; + goto error2; } if (length != elfHeader.e_phnum * elfHeader.e_phentsize) { dprintf("short read while reading in program headers\n"); status = -1; - goto error; + goto error2; } // construct a nice name for the region we have to create below @@ -1904,13 +1914,21 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry) for (i = 0; i < elfHeader.e_phnum; i++) { char regionName[B_OS_NAME_LENGTH]; char *regionAddress; + char *originalRegionAddress; area_id id; + if (programHeaders[i].p_type == PT_DYNAMIC) { + image->dynamic_section = programHeaders[i].p_vaddr; + continue; + } + if (programHeaders[i].p_type != PT_LOAD) continue; - regionAddress = (char *)ROUNDDOWN(programHeaders[i].p_vaddr, - B_PAGE_SIZE); + regionAddress = (char *)(ROUNDDOWN(programHeaders[i].p_vaddr, + B_PAGE_SIZE) + delta); + originalRegionAddress = regionAddress; + if (programHeaders[i].p_flags & PF_WRITE) { // rw/data segment size_t memUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE) @@ -1924,18 +1942,21 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry) sprintf(regionName, "%s_seg%drw", baseName, i); id = vm_map_file(team->id, regionName, (void **)®ionAddress, - B_EXACT_ADDRESS, fileUpperBound, + addressSpec, fileUpperBound, B_READ_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP, false, fd, ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE)); if (id < B_OK) { dprintf("error mapping file data: %s!\n", strerror(id)); status = B_NOT_AN_EXECUTABLE; - goto error; + goto error2; } imageInfo.data = regionAddress; imageInfo.data_size = memUpperBound; + image->data_region.start = (addr_t)regionAddress; + image->data_region.size = memUpperBound; + // clean garbage brought by mmap (the region behind the file, // at least parts of it are the bss and have to be zeroed) addr_t start = (addr_t)regionAddress @@ -1965,7 +1986,7 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry) if (id < B_OK) { dprintf("error allocating bss area: %s!\n", strerror(id)); status = B_NOT_AN_EXECUTABLE; - goto error; + goto error2; } } } else { @@ -1976,20 +1997,42 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry) + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE); id = vm_map_file(team->id, regionName, (void **)®ionAddress, - B_EXACT_ADDRESS, segmentSize, - B_READ_AREA | B_EXECUTE_AREA, REGION_PRIVATE_MAP, false, - fd, ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE)); + addressSpec, segmentSize, + B_READ_AREA | B_EXECUTE_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP, + false, fd, ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE)); if (id < B_OK) { dprintf("error mapping file text: %s!\n", strerror(id)); status = B_NOT_AN_EXECUTABLE; - goto error; + goto error2; } imageInfo.text = regionAddress; imageInfo.text_size = segmentSize; + + image->text_region.start = (addr_t)regionAddress; + image->text_region.size = segmentSize; + } + + if (addressSpec != B_EXACT_ADDRESS) { + addressSpec = B_EXACT_ADDRESS; + delta = regionAddress - originalRegionAddress; } } + image->data_region.delta = delta; + image->text_region.delta = delta; + + // modify the dynamic ptr by the delta of the regions + image->dynamic_section += image->text_region.delta; + + status = elf_parse_dynamic_section(image); + if (status != B_OK) + goto error2; + + status = elf_relocate(image, image); + if (status != B_OK) + goto error2; + // register the loaded image imageInfo.type = B_LIBRARY_IMAGE; imageInfo.device = st.st_dev; @@ -2009,9 +2052,13 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry) TRACE(("elf_load: done!\n")); - *entry = elfHeader.e_entry; + *entry = elfHeader.e_entry + delta; status = B_OK; +error2: + image->elf_header = NULL; + delete_elf_image(image); + error: free(programHeaders); _kern_close(fd); @@ -2258,7 +2305,7 @@ load_kernel_add_on(const char *path) if (status != B_OK) goto error5; - status = elf_relocate(image); + status = elf_relocate(image, sKernelImage); if (status < B_OK) goto error5; diff --git a/src/system/ldscripts/x86/runtime_loader.ld b/src/system/ldscripts/x86/runtime_loader.ld index 2bc53c6..ae1062f 100644 --- a/src/system/ldscripts/x86/runtime_loader.ld +++ b/src/system/ldscripts/x86/runtime_loader.ld @@ -5,7 +5,7 @@ ENTRY(runtime_loader) SEARCH_DIR("libgcc"); SECTIONS { - . = 0x00100000 + SIZEOF_HEADERS; + . = 0x00000000 + SIZEOF_HEADERS; .interp : { *(.interp) } .hash : { *(.hash) } diff --git a/src/system/ldscripts/x86_64/runtime_loader.ld b/src/system/ldscripts/x86_64/runtime_loader.ld index a83a6de..ee0b42f 100644 --- a/src/system/ldscripts/x86_64/runtime_loader.ld +++ b/src/system/ldscripts/x86_64/runtime_loader.ld @@ -5,7 +5,7 @@ ENTRY(runtime_loader) SEARCH_DIR("libgcc"); SECTIONS { - . = 0x00200000 + SIZEOF_HEADERS; + . = 0x00000000 + SIZEOF_HEADERS; .interp : { *(.interp) } .hash : { *(.hash) } diff --git a/src/system/runtime_loader/Jamfile b/src/system/runtime_loader/Jamfile index d687912..11bc811 100644 --- a/src/system/runtime_loader/Jamfile +++ b/src/system/runtime_loader/Jamfile @@ -91,7 +91,7 @@ Ld runtime_loader : $(TARGET_STATIC_LIBSUPC++) $(TARGET_GCC_LIBGCC) : $(HAIKU_TOP)/src/system/ldscripts/$(TARGET_ARCH)/runtime_loader.ld - : --no-undefined + : --no-undefined -shared -soname=runtime_loader ; HaikuSubInclude arch $(TARGET_ARCH) ;