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

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 */
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 **)&regionAddress,
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 **)&regionAddress,
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;

View File

@ -5,7 +5,7 @@ ENTRY(runtime_loader)
SEARCH_DIR("libgcc");
SECTIONS
{
. = 0x00100000 + SIZEOF_HEADERS;
. = 0x00000000 + SIZEOF_HEADERS;
.interp : { *(.interp) }
.hash : { *(.hash) }

View File

@ -5,7 +5,7 @@ ENTRY(runtime_loader)
SEARCH_DIR("libgcc");
SECTIONS
{
. = 0x00200000 + SIZEOF_HEADERS;
. = 0x00000000 + SIZEOF_HEADERS;
.interp : { *(.interp) }
.hash : { *(.hash) }

View File

@ -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) ;