summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-02-12 16:30:29 +0100
committerAndreas Kling <kling@serenityos.org>2021-02-12 16:30:29 +0100
commit1ef43ec89ae801ce91bd9b44577f6059aa84b534 (patch)
treeb208126a1adfc91f0b44d85dbc853575e37fe209
parentca1c560161397e798c2d049246d63996a8a2ab2b (diff)
downloadserenity-1ef43ec89ae801ce91bd9b44577f6059aa84b534.zip
Kernel: Move get_interpreter_load_offset() out of Process class
This is only used inside the sys$execve() implementation so just make it a execve.cpp local function.
-rw-r--r--Kernel/Process.h1
-rw-r--r--Kernel/Syscalls/execve.cpp184
2 files changed, 92 insertions, 93 deletions
diff --git a/Kernel/Process.h b/Kernel/Process.h
index bc57a6c7c4..5a0485265d 100644
--- a/Kernel/Process.h
+++ b/Kernel/Process.h
@@ -391,7 +391,6 @@ public:
int exec(String path, Vector<String> arguments, Vector<String> environment, int recusion_depth = 0);
KResultOr<LoadResult> load(NonnullRefPtr<FileDescription> main_program_description, RefPtr<FileDescription> interpreter_description, const Elf32_Ehdr& main_program_header);
- KResultOr<FlatPtr> get_interpreter_load_offset(const Elf32_Ehdr& main_program_header, FileDescription& main_program_description, FileDescription& interpreter_description);
bool is_superuser() const
{
diff --git a/Kernel/Syscalls/execve.cpp b/Kernel/Syscalls/execve.cpp
index 0c74582bef..61a0ffd11a 100644
--- a/Kernel/Syscalls/execve.cpp
+++ b/Kernel/Syscalls/execve.cpp
@@ -153,6 +153,98 @@ static KResultOr<FlatPtr> make_userspace_stack_for_main_thread(Region& region, V
return new_esp;
}
+struct RequiredLoadRange {
+ FlatPtr start { 0 };
+ FlatPtr end { 0 };
+};
+
+static KResultOr<RequiredLoadRange> get_required_load_range(FileDescription& program_description)
+{
+ auto& inode = *(program_description.inode());
+ auto vmobject = SharedInodeVMObject::create_with_inode(inode);
+
+ size_t executable_size = inode.size();
+
+ auto region = MM.allocate_kernel_region_with_vmobject(*vmobject, PAGE_ROUND_UP(executable_size), "ELF memory range calculation", Region::Access::Read);
+ if (!region) {
+ dbgln("Could not allocate memory for ELF");
+ return ENOMEM;
+ }
+
+ auto elf_image = ELF::Image(region->vaddr().as_ptr(), executable_size);
+ if (!elf_image.is_valid()) {
+ return EINVAL;
+ }
+
+ RequiredLoadRange range {};
+ elf_image.for_each_program_header([&range](const auto& pheader) {
+ if (pheader.type() != PT_LOAD)
+ return IterationDecision::Continue;
+
+ auto region_start = (FlatPtr)pheader.vaddr().as_ptr();
+ auto region_end = region_start + pheader.size_in_memory();
+ if (range.start == 0 || region_start < range.start)
+ range.start = region_start;
+ if (range.end == 0 || region_end > range.end)
+ range.end = region_end;
+ return IterationDecision::Continue;
+ });
+
+ ASSERT(range.end > range.start);
+ return range;
+};
+
+static KResultOr<FlatPtr> get_interpreter_load_offset(const Elf32_Ehdr& main_program_header, FileDescription& main_program_description, FileDescription& interpreter_description)
+{
+ constexpr FlatPtr interpreter_load_range_start = 0x08000000;
+ constexpr FlatPtr interpreter_load_range_size = 65536 * PAGE_SIZE; // 2**16 * PAGE_SIZE = 256MB
+ constexpr FlatPtr minimum_interpreter_load_offset_randomization_size = 10 * MiB;
+
+ auto random_load_offset_in_range([](auto start, auto size) {
+ return PAGE_ROUND_DOWN(start + get_good_random<FlatPtr>() % size);
+ });
+
+ if (main_program_header.e_type == ET_DYN) {
+ return random_load_offset_in_range(interpreter_load_range_start, interpreter_load_range_size);
+ }
+
+ if (main_program_header.e_type != ET_EXEC)
+ return -EINVAL;
+
+ auto main_program_load_range_result = get_required_load_range(main_program_description);
+ if (main_program_load_range_result.is_error())
+ return main_program_load_range_result.error();
+
+ auto main_program_load_range = main_program_load_range_result.value();
+
+ auto interpreter_load_range_result = get_required_load_range(interpreter_description);
+ if (interpreter_load_range_result.is_error())
+ return interpreter_load_range_result.error();
+
+ auto interpreter_size_in_memory = interpreter_load_range_result.value().end - interpreter_load_range_result.value().start;
+ auto interpreter_load_range_end = interpreter_load_range_start + interpreter_load_range_size - interpreter_size_in_memory;
+
+ // No intersection
+ if (main_program_load_range.end < interpreter_load_range_start || main_program_load_range.start > interpreter_load_range_end)
+ return random_load_offset_in_range(interpreter_load_range_start, interpreter_load_range_size);
+
+ RequiredLoadRange first_available_part = { interpreter_load_range_start, main_program_load_range.start };
+ RequiredLoadRange second_available_part = { main_program_load_range.end, interpreter_load_range_end };
+
+ RequiredLoadRange selected_range {};
+ // Select larger part
+ if (first_available_part.end - first_available_part.start > second_available_part.end - second_available_part.start)
+ selected_range = first_available_part;
+ else
+ selected_range = second_available_part;
+
+ // If main program is too big and leaves us without enough space for adequate loader randmoization
+ if (selected_range.end - selected_range.start < minimum_interpreter_load_offset_randomization_size)
+ return -E2BIG;
+
+ return random_load_offset_in_range(selected_range.start, selected_range.end - selected_range.start);
+}
+
enum class ShouldAllocateTls {
No,
Yes,
@@ -364,98 +456,6 @@ KResultOr<LoadResult> Process::load(NonnullRefPtr<FileDescription> main_program_
return interpreter_load_result;
}
-struct RequiredLoadRange {
- FlatPtr start { 0 };
- FlatPtr end { 0 };
-};
-
-static KResultOr<RequiredLoadRange> get_required_load_range(FileDescription& program_description)
-{
- auto& inode = *(program_description.inode());
- auto vmobject = SharedInodeVMObject::create_with_inode(inode);
-
- size_t executable_size = inode.size();
-
- auto region = MM.allocate_kernel_region_with_vmobject(*vmobject, PAGE_ROUND_UP(executable_size), "ELF memory range calculation", Region::Access::Read);
- if (!region) {
- dbgln("Could not allocate memory for ELF");
- return ENOMEM;
- }
-
- auto elf_image = ELF::Image(region->vaddr().as_ptr(), executable_size);
- if (!elf_image.is_valid()) {
- return EINVAL;
- }
-
- RequiredLoadRange range {};
- elf_image.for_each_program_header([&range](const auto& pheader) {
- if (pheader.type() != PT_LOAD)
- return IterationDecision::Continue;
-
- auto region_start = (FlatPtr)pheader.vaddr().as_ptr();
- auto region_end = region_start + pheader.size_in_memory();
- if (range.start == 0 || region_start < range.start)
- range.start = region_start;
- if (range.end == 0 || region_end > range.end)
- range.end = region_end;
- return IterationDecision::Continue;
- });
-
- ASSERT(range.end > range.start);
- return range;
-};
-
-KResultOr<FlatPtr> Process::get_interpreter_load_offset(const Elf32_Ehdr& main_program_header, FileDescription& main_program_description, FileDescription& interpreter_description)
-{
- constexpr FlatPtr interpreter_load_range_start = 0x08000000;
- constexpr FlatPtr interpreter_load_range_size = 65536 * PAGE_SIZE; // 2**16 * PAGE_SIZE = 256MB
- constexpr FlatPtr minimum_interpreter_load_offset_randomization_size = 10 * MiB;
-
- auto random_load_offset_in_range([](auto start, auto size) {
- return PAGE_ROUND_DOWN(start + get_good_random<FlatPtr>() % size);
- });
-
- if (main_program_header.e_type == ET_DYN) {
- return random_load_offset_in_range(interpreter_load_range_start, interpreter_load_range_size);
- }
-
- if (main_program_header.e_type != ET_EXEC)
- return -EINVAL;
-
- auto main_program_load_range_result = get_required_load_range(main_program_description);
- if (main_program_load_range_result.is_error())
- return main_program_load_range_result.error();
-
- auto main_program_load_range = main_program_load_range_result.value();
-
- auto interpreter_load_range_result = get_required_load_range(interpreter_description);
- if (interpreter_load_range_result.is_error())
- return interpreter_load_range_result.error();
-
- auto interpreter_size_in_memory = interpreter_load_range_result.value().end - interpreter_load_range_result.value().start;
- auto interpreter_load_range_end = interpreter_load_range_start + interpreter_load_range_size - interpreter_size_in_memory;
-
- // No intersection
- if (main_program_load_range.end < interpreter_load_range_start || main_program_load_range.start > interpreter_load_range_end)
- return random_load_offset_in_range(interpreter_load_range_start, interpreter_load_range_size);
-
- RequiredLoadRange first_available_part = { interpreter_load_range_start, main_program_load_range.start };
- RequiredLoadRange second_available_part = { main_program_load_range.end, interpreter_load_range_end };
-
- RequiredLoadRange selected_range {};
- // Select larger part
- if (first_available_part.end - first_available_part.start > second_available_part.end - second_available_part.start)
- selected_range = first_available_part;
- else
- selected_range = second_available_part;
-
- // If main program is too big and leaves us without enough space for adequate loader randmoization
- if (selected_range.end - selected_range.start < minimum_interpreter_load_offset_randomization_size)
- return -E2BIG;
-
- return random_load_offset_in_range(selected_range.start, selected_range.end - selected_range.start);
-}
-
int Process::do_exec(NonnullRefPtr<FileDescription> main_program_description, Vector<String> arguments, Vector<String> environment, RefPtr<FileDescription> interpreter_description, Thread*& new_main_thread, u32& prev_flags, const Elf32_Ehdr& main_program_header)
{
ASSERT(is_user_process());