[init] Randomize load address of dynamic ELF modules

Update init to use the new xoroshiro RNG to create a random load address for dynamic executables.
Also pass an address past the end of the loader in the loader_arg to use when loading dynamic
dependencies.
This commit is contained in:
Justin C. Miller
2024-02-19 15:00:42 -08:00
parent 0bf709a339
commit dff9e53658
3 changed files with 12 additions and 4 deletions

View File

@@ -42,6 +42,8 @@ struct j6_arg_loader
uintptr_t image_base; uintptr_t image_base;
uintptr_t *got; uintptr_t *got;
uintptr_t entrypoint; uintptr_t entrypoint;
uintptr_t start_addr;
uintptr_t other;
}; };
struct j6_arg_driver struct j6_arg_driver

View File

@@ -37,7 +37,6 @@ ldso_init(j6_arg_header *stack_args, uintptr_t *got)
} }
if (!arg_loader) { if (!arg_loader) {
j6::syslog("ld.so: error: did not get j6_arg_loader");
exit(127); exit(127);
} }
@@ -71,7 +70,7 @@ ldso_init(j6_arg_header *stack_args, uintptr_t *got)
reinterpret_cast<const dyn_entry*>(arg_loader->got[0] + arg_loader->image_base)); reinterpret_cast<const dyn_entry*>(arg_loader->got[0] + arg_loader->image_base));
all_images.push_back(&target_image); all_images.push_back(&target_image);
all_images.load(vfs, 0xb00'0000); all_images.load(vfs, arg_loader->start_addr);
return arg_loader->entrypoint + arg_loader->image_base; return arg_loader->entrypoint + arg_loader->image_base;
} }

View File

@@ -10,6 +10,7 @@
#include <j6/protocols.h> #include <j6/protocols.h>
#include <j6/syscalls.h> #include <j6/syscalls.h>
#include <j6/syslog.hh> #include <j6/syslog.hh>
#include <util/xoroshiro.h>
#include "j6romfs.h" #include "j6romfs.h"
#include "loader.h" #include "loader.h"
@@ -20,6 +21,8 @@ static constexpr size_t MiB = 0x10'0000ull;
static constexpr size_t stack_size = 16 * MiB; static constexpr size_t stack_size = 16 * MiB;
static constexpr uintptr_t stack_top = 0x7f0'0000'0000; static constexpr uintptr_t stack_top = 0x7f0'0000'0000;
static util::xoroshiro256pp rng {0x123456};
inline uintptr_t align_up(uintptr_t a) { return ((a-1) & ~(MiB-1)) + MiB; } inline uintptr_t align_up(uintptr_t a) { return ((a-1) & ~(MiB-1)) + MiB; }
j6_handle_t j6_handle_t
@@ -180,7 +183,9 @@ load_program(
elf::file program_elf {program_data}; elf::file program_elf {program_data};
bool dyn = program_elf.type() == elf::filetype::shared; bool dyn = program_elf.type() == elf::filetype::shared;
uintptr_t program_image_base = dyn ? 0xa00'0000 : 0; uintptr_t program_image_base = 0;
if (dyn)
program_image_base = (rng.next() & 0xffe0 + 16) << 20;
if (!program_elf.valid(dyn ? elf::filetype::shared : elf::filetype::executable)) { if (!program_elf.valid(dyn ? elf::filetype::shared : elf::filetype::executable)) {
j6::syslog(" ** error loading program '%s': ELF is invalid", path); j6::syslog(" ** error loading program '%s': ELF is invalid", path);
@@ -250,8 +255,10 @@ load_program(
return false; return false;
} }
load_program_into(proc, ldso_elf, ldso_image_base, ldso_path); uintptr_t eop = load_program_into(proc, ldso_elf, ldso_image_base, ldso_path);
eop = (eop & ~0xfffffull) + 0x100000;
loader_arg->loader_base = ldso_image_base; loader_arg->loader_base = ldso_image_base;
loader_arg->start_addr = eop;
entrypoint = ldso_elf.entrypoint() + ldso_image_base; entrypoint = ldso_elf.entrypoint() + ldso_image_base;
delete [] reinterpret_cast<uint8_t*>(ldso_data.pointer); delete [] reinterpret_cast<uint8_t*>(ldso_data.pointer);
break; break;