summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-12-25 16:20:26 +0100
committerAndreas Kling <kling@serenityos.org>2020-12-25 16:22:01 +0100
commit89d3b09638ea6f810b3b07d417367bc3458ce98b (patch)
tree7117ac166398820264d27808773e95d5b2e1f724
parentd55fb7b5e205c15a775b22b40d2b1d8006db4cad (diff)
downloadserenity-89d3b09638ea6f810b3b07d417367bc3458ce98b.zip
Kernel: Allocate new main thread stack before committing to exec
If the allocation fails (e.g ENOMEM) we want to simply return an error from sys$execve() and continue executing the current executable. This patch also moves make_userspace_stack_for_main_thread() out of the Thread class since it had nothing in particular to do with Thread.
-rw-r--r--Kernel/Process.h3
-rw-r--r--Kernel/Syscalls/execve.cpp77
-rw-r--r--Kernel/Thread.cpp72
-rw-r--r--Kernel/Thread.h2
4 files changed, 77 insertions, 77 deletions
diff --git a/Kernel/Process.h b/Kernel/Process.h
index 4c40ddcadb..8f0f6ecf74 100644
--- a/Kernel/Process.h
+++ b/Kernel/Process.h
@@ -426,9 +426,10 @@ public:
size_t size { 0 };
FlatPtr program_headers { 0 };
size_t num_program_headers { 0 };
- AK::WeakPtr<Region> tls_region;
+ WeakPtr<Region> tls_region;
size_t tls_size { 0 };
size_t tls_alignment { 0 };
+ WeakPtr<Region> stack_region;
};
enum class ShouldAllocateTls {
diff --git a/Kernel/Syscalls/execve.cpp b/Kernel/Syscalls/execve.cpp
index 4714905c64..e900d8e319 100644
--- a/Kernel/Syscalls/execve.cpp
+++ b/Kernel/Syscalls/execve.cpp
@@ -62,6 +62,73 @@ static bool validate_stack_size(const Vector<String>& arguments, const Vector<St
return (total_blob_size + total_meta_size) < Thread::default_userspace_stack_size;
}
+static KResultOr<FlatPtr> make_userspace_stack_for_main_thread(Region& region, Vector<String> arguments, Vector<String> environment, Vector<ELF::AuxiliaryValue> auxiliary_values)
+{
+ FlatPtr new_esp = region.vaddr().offset(Thread::default_userspace_stack_size).get();
+
+ auto push_on_new_stack = [&new_esp](u32 value) {
+ new_esp -= 4;
+ Userspace<u32*> stack_ptr = new_esp;
+ return copy_to_user(stack_ptr, &value);
+ };
+
+ auto push_aux_value_on_new_stack = [&new_esp](auxv_t value) {
+ new_esp -= sizeof(auxv_t);
+ Userspace<auxv_t*> stack_ptr = new_esp;
+ return copy_to_user(stack_ptr, &value);
+ };
+
+ auto push_string_on_new_stack = [&new_esp](const String& string) {
+ new_esp -= round_up_to_power_of_two(string.length() + 1, 4);
+ Userspace<u32*> stack_ptr = new_esp;
+ return copy_to_user(stack_ptr, string.characters(), string.length() + 1);
+ };
+
+ Vector<FlatPtr> argv_entries;
+ for (auto& argument : arguments) {
+ push_string_on_new_stack(argument);
+ argv_entries.append(new_esp);
+ }
+
+ Vector<FlatPtr> env_entries;
+ for (auto& variable : environment) {
+ push_string_on_new_stack(variable);
+ env_entries.append(new_esp);
+ }
+
+ for (auto& value : auxiliary_values) {
+ if (!value.optional_string.is_empty()) {
+ push_string_on_new_stack(value.optional_string);
+ value.auxv.a_un.a_ptr = (void*)new_esp;
+ }
+ }
+
+ for (ssize_t i = auxiliary_values.size() - 1; i >= 0; --i) {
+ auto& value = auxiliary_values[i];
+ push_aux_value_on_new_stack(value.auxv);
+ }
+
+ push_on_new_stack(0);
+ for (ssize_t i = env_entries.size() - 1; i >= 0; --i)
+ push_on_new_stack(env_entries[i]);
+ FlatPtr envp = new_esp;
+
+ push_on_new_stack(0);
+ for (ssize_t i = argv_entries.size() - 1; i >= 0; --i)
+ push_on_new_stack(argv_entries[i]);
+ FlatPtr argv = new_esp;
+
+ // NOTE: The stack needs to be 16-byte aligned.
+ new_esp -= new_esp % 16;
+
+ push_on_new_stack((FlatPtr)envp);
+ push_on_new_stack((FlatPtr)argv);
+ push_on_new_stack((FlatPtr)argv_entries.size());
+ push_on_new_stack(0);
+
+ return new_esp;
+}
+
KResultOr<Process::LoadResult> Process::load_elf_object(FileDescription& object_description, FlatPtr load_offset, ShouldAllocateTls should_allocate_tls)
{
auto& inode = *(object_description.inode());
@@ -192,6 +259,11 @@ KResultOr<Process::LoadResult> Process::load_elf_object(FileDescription& object_
return KResult(-ENOEXEC);
}
+ auto* stack_region = allocate_region(VirtualAddress(), Thread::default_userspace_stack_size, "Stack (Main thread)", PROT_READ | PROT_WRITE, false);
+ if (!stack_region)
+ return KResult(-ENOMEM);
+ stack_region->set_stack(true);
+
return LoadResult {
load_base_address,
elf_image.entry().offset(load_offset).get(),
@@ -200,7 +272,8 @@ KResultOr<Process::LoadResult> Process::load_elf_object(FileDescription& object_
elf_image.program_header_count(),
master_tls_region ? master_tls_region->make_weak_ptr() : nullptr,
master_tls_size,
- master_tls_alignment
+ master_tls_alignment,
+ stack_region->make_weak_ptr()
};
}
@@ -368,7 +441,7 @@ int Process::do_exec(NonnullRefPtr<FileDescription> main_program_description, Ve
// NOTE: We create the new stack before disabling interrupts since it will zero-fault
// and we don't want to deal with faults after this point.
- auto make_stack_result = new_main_thread->make_userspace_stack_for_main_thread(move(arguments), move(environment), move(auxv));
+ auto make_stack_result = make_userspace_stack_for_main_thread(*load_result.stack_region.unsafe_ptr(), move(arguments), move(environment), move(auxv));
if (make_stack_result.is_error())
return make_stack_result.error();
u32 new_userspace_esp = make_stack_result.value();
diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp
index 107698adcd..b89adb4a73 100644
--- a/Kernel/Thread.cpp
+++ b/Kernel/Thread.cpp
@@ -855,78 +855,6 @@ RegisterState& Thread::get_register_dump_from_stack()
return *(RegisterState*)(kernel_stack_top() - sizeof(RegisterState));
}
-KResultOr<u32> Thread::make_userspace_stack_for_main_thread(Vector<String> arguments, Vector<String> environment, Vector<ELF::AuxiliaryValue> auxiliary_values)
-{
- auto* region = m_process->allocate_region(VirtualAddress(), default_userspace_stack_size, "Stack (Main thread)", PROT_READ | PROT_WRITE, false);
- if (!region)
- return KResult(-ENOMEM);
- region->set_stack(true);
-
- FlatPtr new_esp = region->vaddr().offset(default_userspace_stack_size).get();
-
- auto push_on_new_stack = [&new_esp](u32 value) {
- new_esp -= 4;
- Userspace<u32*> stack_ptr = new_esp;
- return copy_to_user(stack_ptr, &value);
- };
-
- auto push_aux_value_on_new_stack = [&new_esp](auxv_t value) {
- new_esp -= sizeof(auxv_t);
- Userspace<auxv_t*> stack_ptr = new_esp;
- return copy_to_user(stack_ptr, &value);
- };
-
- auto push_string_on_new_stack = [&new_esp](const String& string) {
- new_esp -= round_up_to_power_of_two(string.length() + 1, 4);
- Userspace<u32*> stack_ptr = new_esp;
- return copy_to_user(stack_ptr, string.characters(), string.length() + 1);
- };
-
- Vector<FlatPtr> argv_entries;
- for (auto& argument : arguments) {
- push_string_on_new_stack(argument);
- argv_entries.append(new_esp);
- }
-
- Vector<FlatPtr> env_entries;
- for (auto& variable : environment) {
- push_string_on_new_stack(variable);
- env_entries.append(new_esp);
- }
-
- for (auto& value : auxiliary_values) {
- if (!value.optional_string.is_empty()) {
- push_string_on_new_stack(value.optional_string);
- value.auxv.a_un.a_ptr = (void*)new_esp;
- }
- }
-
- for (ssize_t i = auxiliary_values.size() - 1; i >= 0; --i) {
- auto& value = auxiliary_values[i];
- push_aux_value_on_new_stack(value.auxv);
- }
-
- push_on_new_stack(0);
- for (ssize_t i = env_entries.size() - 1; i >= 0; --i)
- push_on_new_stack(env_entries[i]);
- FlatPtr envp = new_esp;
-
- push_on_new_stack(0);
- for (ssize_t i = argv_entries.size() - 1; i >= 0; --i)
- push_on_new_stack(argv_entries[i]);
- FlatPtr argv = new_esp;
-
- // NOTE: The stack needs to be 16-byte aligned.
- new_esp -= new_esp % 16;
-
- push_on_new_stack((FlatPtr)envp);
- push_on_new_stack((FlatPtr)argv);
- push_on_new_stack((FlatPtr)argv_entries.size());
- push_on_new_stack(0);
-
- return new_esp;
-}
-
RefPtr<Thread> Thread::clone(Process& process)
{
auto clone = adopt(*new Thread(process));
diff --git a/Kernel/Thread.h b/Kernel/Thread.h
index ff5c6488a1..c0ef852248 100644
--- a/Kernel/Thread.h
+++ b/Kernel/Thread.h
@@ -975,8 +975,6 @@ public:
void set_default_signal_dispositions();
bool push_value_on_stack(FlatPtr);
- KResultOr<u32> make_userspace_stack_for_main_thread(Vector<String> arguments, Vector<String> environment, Vector<ELF::AuxiliaryValue>);
-
KResult make_thread_specific_region(Badge<Process>);
unsigned syscall_count() const { return m_syscall_count; }