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
This commit is contained in:
Pawel Dziepak
2013-04-16 02:29:05 +02:00
parent cf35dcc5bc
commit db1ca60528
4 changed files with 70 additions and 23 deletions
+67 -20
View File
@@ -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 */ /*! Until we have shared library support, just this links against the kernel */
static int 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; int status = B_NO_ERROR;
@@ -1079,7 +1079,7 @@ elf_relocate(struct elf_image_info *image)
if (image->rel) { if (image->rel) {
TRACE(("total %i rel relocs\n", image->rel_len / (int)sizeof(elf_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); image->rel_len);
if (status < B_OK) if (status < B_OK)
return status; return status;
@@ -1089,12 +1089,12 @@ elf_relocate(struct elf_image_info *image)
if (image->pltrel_type == DT_REL) { if (image->pltrel_type == DT_REL) {
TRACE(("total %i plt-relocs\n", TRACE(("total %i plt-relocs\n",
image->pltrel_len / (int)sizeof(elf_rel))); 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); image->pltrel_len);
} else { } else {
TRACE(("total %i plt-relocs\n", TRACE(("total %i plt-relocs\n",
image->pltrel_len / (int)sizeof(elf_rela))); 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); (elf_rela *)image->pltrel, image->pltrel_len);
} }
if (status < B_OK) if (status < B_OK)
@@ -1105,7 +1105,7 @@ elf_relocate(struct elf_image_info *image)
TRACE(("total %i rel relocs\n", TRACE(("total %i rel relocs\n",
image->rela_len / (int)sizeof(elf_rela))); 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); image->rela_len);
if (status < B_OK) if (status < B_OK)
return status; return status;
@@ -1288,7 +1288,7 @@ insert_preloaded_image(preloaded_elf_image *preloadedImage, bool kernel)
if (status != B_OK) if (status != B_OK)
goto error1; goto error1;
status = elf_relocate(image); status = elf_relocate(image, sKernelImage);
if (status != B_OK) if (status != B_OK)
goto error1; goto error1;
} else } else
@@ -1825,6 +1825,8 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry)
ssize_t length; ssize_t length;
int fd; int fd;
int i; int i;
addr_t delta = 0;
uint32 addressSpec = B_RANDOMIZED_BASE_ADDRESS;
TRACE(("elf_load: entry path '%s', team %p\n", path, team)); 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) if (status < B_OK)
goto error; 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 // read program header
programHeaders = (elf_phdr *)malloc( 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) { if (programHeaders == NULL) {
dprintf("error allocating space for program headers\n"); dprintf("error allocating space for program headers\n");
status = B_NO_MEMORY; status = B_NO_MEMORY;
goto error; goto error2;
} }
TRACE(("reading in program headers at 0x%lx, length 0x%x\n", 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) { if (length < B_OK) {
status = length; status = length;
dprintf("error reading in program headers\n"); dprintf("error reading in program headers\n");
goto error; goto error2;
} }
if (length != elfHeader.e_phnum * elfHeader.e_phentsize) { if (length != elfHeader.e_phnum * elfHeader.e_phentsize) {
dprintf("short read while reading in program headers\n"); dprintf("short read while reading in program headers\n");
status = -1; status = -1;
goto error; goto error2;
} }
// construct a nice name for the region we have to create below // 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++) { for (i = 0; i < elfHeader.e_phnum; i++) {
char regionName[B_OS_NAME_LENGTH]; char regionName[B_OS_NAME_LENGTH];
char *regionAddress; char *regionAddress;
char *originalRegionAddress;
area_id id; 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) if (programHeaders[i].p_type != PT_LOAD)
continue; continue;
regionAddress = (char *)ROUNDDOWN(programHeaders[i].p_vaddr, regionAddress = (char *)(ROUNDDOWN(programHeaders[i].p_vaddr,
B_PAGE_SIZE); B_PAGE_SIZE) + delta);
originalRegionAddress = regionAddress;
if (programHeaders[i].p_flags & PF_WRITE) { if (programHeaders[i].p_flags & PF_WRITE) {
// rw/data segment // rw/data segment
size_t memUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE) 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); sprintf(regionName, "%s_seg%drw", baseName, i);
id = vm_map_file(team->id, regionName, (void **)&regionAddress, id = vm_map_file(team->id, regionName, (void **)&regionAddress,
B_EXACT_ADDRESS, fileUpperBound, addressSpec, fileUpperBound,
B_READ_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP, false, B_READ_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP, false,
fd, ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE)); fd, ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
if (id < B_OK) { if (id < B_OK) {
dprintf("error mapping file data: %s!\n", strerror(id)); dprintf("error mapping file data: %s!\n", strerror(id));
status = B_NOT_AN_EXECUTABLE; status = B_NOT_AN_EXECUTABLE;
goto error; goto error2;
} }
imageInfo.data = regionAddress; imageInfo.data = regionAddress;
imageInfo.data_size = memUpperBound; 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, // clean garbage brought by mmap (the region behind the file,
// at least parts of it are the bss and have to be zeroed) // at least parts of it are the bss and have to be zeroed)
addr_t start = (addr_t)regionAddress 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) { if (id < B_OK) {
dprintf("error allocating bss area: %s!\n", strerror(id)); dprintf("error allocating bss area: %s!\n", strerror(id));
status = B_NOT_AN_EXECUTABLE; status = B_NOT_AN_EXECUTABLE;
goto error; goto error2;
} }
} }
} else { } 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); + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
id = vm_map_file(team->id, regionName, (void **)&regionAddress, id = vm_map_file(team->id, regionName, (void **)&regionAddress,
B_EXACT_ADDRESS, segmentSize, addressSpec, segmentSize,
B_READ_AREA | B_EXECUTE_AREA, REGION_PRIVATE_MAP, false, B_READ_AREA | B_EXECUTE_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP,
fd, ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE)); false, fd, ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
if (id < B_OK) { if (id < B_OK) {
dprintf("error mapping file text: %s!\n", strerror(id)); dprintf("error mapping file text: %s!\n", strerror(id));
status = B_NOT_AN_EXECUTABLE; status = B_NOT_AN_EXECUTABLE;
goto error; goto error2;
} }
imageInfo.text = regionAddress; imageInfo.text = regionAddress;
imageInfo.text_size = segmentSize; 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 // register the loaded image
imageInfo.type = B_LIBRARY_IMAGE; imageInfo.type = B_LIBRARY_IMAGE;
imageInfo.device = st.st_dev; 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")); TRACE(("elf_load: done!\n"));
*entry = elfHeader.e_entry; *entry = elfHeader.e_entry + delta;
status = B_OK; status = B_OK;
error2:
image->elf_header = NULL;
delete_elf_image(image);
error: error:
free(programHeaders); free(programHeaders);
_kern_close(fd); _kern_close(fd);
@@ -2258,7 +2305,7 @@ load_kernel_add_on(const char *path)
if (status != B_OK) if (status != B_OK)
goto error5; goto error5;
status = elf_relocate(image); status = elf_relocate(image, sKernelImage);
if (status < B_OK) if (status < B_OK)
goto error5; goto error5;
+1 -1
View File
@@ -5,7 +5,7 @@ ENTRY(runtime_loader)
SEARCH_DIR("libgcc"); SEARCH_DIR("libgcc");
SECTIONS SECTIONS
{ {
. = 0x00100000 + SIZEOF_HEADERS; . = 0x00000000 + SIZEOF_HEADERS;
.interp : { *(.interp) } .interp : { *(.interp) }
.hash : { *(.hash) } .hash : { *(.hash) }
@@ -5,7 +5,7 @@ ENTRY(runtime_loader)
SEARCH_DIR("libgcc"); SEARCH_DIR("libgcc");
SECTIONS SECTIONS
{ {
. = 0x00200000 + SIZEOF_HEADERS; . = 0x00000000 + SIZEOF_HEADERS;
.interp : { *(.interp) } .interp : { *(.interp) }
.hash : { *(.hash) } .hash : { *(.hash) }
+1 -1
View File
@@ -91,7 +91,7 @@ Ld runtime_loader :
$(TARGET_STATIC_LIBSUPC++) $(TARGET_STATIC_LIBSUPC++)
$(TARGET_GCC_LIBGCC) $(TARGET_GCC_LIBGCC)
: $(HAIKU_TOP)/src/system/ldscripts/$(TARGET_ARCH)/runtime_loader.ld : $(HAIKU_TOP)/src/system/ldscripts/$(TARGET_ARCH)/runtime_loader.ld
: --no-undefined : --no-undefined -shared -soname=runtime_loader
; ;
HaikuSubInclude arch $(TARGET_ARCH) ; HaikuSubInclude arch $(TARGET_ARCH) ;