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:
+67
-20
@@ -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 **)®ionAddress,
|
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,
|
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 **)®ionAddress,
|
id = vm_map_file(team->id, regionName, (void **)®ionAddress,
|
||||||
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;
|
||||||
|
|
||||||
|
|||||||
@@ -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) }
|
||||||
|
|||||||
@@ -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) ;
|
||||||
|
|||||||
Reference in New Issue
Block a user