diff options
-rw-r--r-- | Kernel/API/POSIX/sys/limits.h | 3 | ||||
-rw-r--r-- | Kernel/API/Syscall.h | 2 | ||||
-rw-r--r-- | Kernel/API/serenity_limits.h | 9 | ||||
-rw-r--r-- | Kernel/Syscalls/execve.cpp | 11 | ||||
-rw-r--r-- | Userland/Libraries/LibC/elf.h | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibC/limits.h | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibC/pthread.cpp | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibELF/Image.cpp | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibELF/Validation.cpp | 16 |
9 files changed, 43 insertions, 7 deletions
diff --git a/Kernel/API/POSIX/sys/limits.h b/Kernel/API/POSIX/sys/limits.h index df12d14894..9afa33667c 100644 --- a/Kernel/API/POSIX/sys/limits.h +++ b/Kernel/API/POSIX/sys/limits.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2022, Andreas Kling <kling@serenityos.org> + * Copyright (c) 2022, sin-ack <sin-ack@protonmail.com> * * SPDX-License-Identifier: BSD-2-Clause */ @@ -7,3 +8,5 @@ #pragma once #define NGROUPS_MAX 32 + +#define PTHREAD_STACK_MIN (64 * 1024) // 64KiB diff --git a/Kernel/API/Syscall.h b/Kernel/API/Syscall.h index d9be71d747..a1c0f11da4 100644 --- a/Kernel/API/Syscall.h +++ b/Kernel/API/Syscall.h @@ -360,7 +360,7 @@ struct SC_create_thread_params { // ... ok, if you say so posix. Guess we get to lie to people about guard page size unsigned int guard_page_size = 0; // Rounded up to PAGE_SIZE unsigned int reported_guard_page_size = 0; // The lie we tell callers - unsigned int stack_size = 1 * MiB; // Default PTHREAD_STACK_MIN + unsigned int stack_size = 1 * MiB; // Equal to Thread::default_userspace_stack_size void* stack_location; // nullptr means any, o.w. process virtual address # if ARCH(X86_64) FlatPtr rdi; diff --git a/Kernel/API/serenity_limits.h b/Kernel/API/serenity_limits.h new file mode 100644 index 0000000000..6fe025f535 --- /dev/null +++ b/Kernel/API/serenity_limits.h @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2022, sin-ack <sin-ack@protonmail.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#define PTHREAD_STACK_MAX (8 * 1024 * 1024) // 8MiB diff --git a/Kernel/Syscalls/execve.cpp b/Kernel/Syscalls/execve.cpp index 7026f6090b..206b414582 100644 --- a/Kernel/Syscalls/execve.cpp +++ b/Kernel/Syscalls/execve.cpp @@ -279,6 +279,7 @@ static ErrorOr<LoadResult> load_elf_object(NonnullOwnPtr<Memory::AddressSpace> n size_t master_tls_size = 0; size_t master_tls_alignment = 0; FlatPtr load_base_address = 0; + size_t stack_size = 0; auto elf_name = TRY(object_description.pseudo_path()); VERIFY(!Processor::in_critical()); @@ -374,6 +375,10 @@ static ErrorOr<LoadResult> load_elf_object(NonnullOwnPtr<Memory::AddressSpace> n if (program_header.type() == PT_LOAD) return load_section(program_header); + if (program_header.type() == PT_GNU_STACK) { + stack_size = program_header.size_in_memory(); + } + // NOTE: We ignore other program header types. return {}; }; @@ -387,12 +392,16 @@ static ErrorOr<LoadResult> load_elf_object(NonnullOwnPtr<Memory::AddressSpace> n return result; }()); + if (stack_size == 0) { + stack_size = Thread::default_userspace_stack_size; + } + if (!elf_image.entry().offset(load_offset).get()) { dbgln("do_exec: Failure loading program, entry pointer is invalid! {})", elf_image.entry().offset(load_offset)); return ENOEXEC; } - auto* stack_region = TRY(new_space->allocate_region(Memory::RandomizeVirtualAddress::Yes, {}, Thread::default_userspace_stack_size, PAGE_SIZE, "Stack (Main thread)"sv, PROT_READ | PROT_WRITE, AllocationStrategy::Reserve)); + auto* stack_region = TRY(new_space->allocate_region(Memory::RandomizeVirtualAddress::Yes, {}, stack_size, PAGE_SIZE, "Stack (Main thread)"sv, PROT_READ | PROT_WRITE, AllocationStrategy::Reserve)); stack_region->set_stack(true); return LoadResult { diff --git a/Userland/Libraries/LibC/elf.h b/Userland/Libraries/LibC/elf.h index 97e0660251..9d968e59bf 100644 --- a/Userland/Libraries/LibC/elf.h +++ b/Userland/Libraries/LibC/elf.h @@ -487,7 +487,7 @@ typedef struct { #define PT_GNU_EH_FRAME 0x6474e550 /* Exception handling info */ #define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ -#define PT_GNU_STACK 0x6474e551 /* Stack permissions info */ +#define PT_GNU_STACK 0x6474e551 /* Stack permissions & size info */ #define PT_OPENBSD_RANDOMIZE 0x65a3dbe6 /* fill with random data */ #define PT_OPENBSD_WXNEEDED 0x65a3dbe7 /* program performs W^X violations */ diff --git a/Userland/Libraries/LibC/limits.h b/Userland/Libraries/LibC/limits.h index 54d288a6e4..24280767d0 100644 --- a/Userland/Libraries/LibC/limits.h +++ b/Userland/Libraries/LibC/limits.h @@ -7,6 +7,7 @@ #pragma once #include <Kernel/API/POSIX/sys/limits.h> +#include <Kernel/API/serenity_limits.h> #include <bits/posix1_lim.h> #include <bits/stdint.h> #include <bits/wchar.h> @@ -86,8 +87,6 @@ #define ARG_MAX 65536 -#define PTHREAD_STACK_MIN 65536 - #define SSIZE_MAX 2147483647 #define LINK_MAX 4096 diff --git a/Userland/Libraries/LibC/pthread.cpp b/Userland/Libraries/LibC/pthread.cpp index 0bc540991c..5af92b2c80 100644 --- a/Userland/Libraries/LibC/pthread.cpp +++ b/Userland/Libraries/LibC/pthread.cpp @@ -34,7 +34,6 @@ using PthreadAttrImpl = Syscall::SC_create_thread_params; static constexpr size_t required_stack_alignment = 4 * MiB; static constexpr size_t highest_reasonable_guard_size = 32 * PAGE_SIZE; -static constexpr size_t highest_reasonable_stack_size = 8 * MiB; // That's the default in Ubuntu? __thread void* s_stack_location; __thread size_t s_stack_size; @@ -467,7 +466,7 @@ int pthread_attr_setstacksize(pthread_attr_t* attributes, size_t stack_size) if (!attributes_impl) return EINVAL; - if ((stack_size < PTHREAD_STACK_MIN) || stack_size > highest_reasonable_stack_size) + if (stack_size < PTHREAD_STACK_MIN || stack_size > PTHREAD_STACK_MAX) return EINVAL; attributes_impl->stack_size = stack_size; diff --git a/Userland/Libraries/LibELF/Image.cpp b/Userland/Libraries/LibELF/Image.cpp index 49af2ef3eb..0a4dea5b45 100644 --- a/Userland/Libraries/LibELF/Image.cpp +++ b/Userland/Libraries/LibELF/Image.cpp @@ -12,6 +12,7 @@ #include <AK/QuickSort.h> #include <AK/StringBuilder.h> #include <AK/StringView.h> +#include <Kernel/API/serenity_limits.h> #include <LibELF/Image.h> #include <LibELF/Validation.h> #include <limits.h> diff --git a/Userland/Libraries/LibELF/Validation.cpp b/Userland/Libraries/LibELF/Validation.cpp index c3d01f8dfe..d334777fdf 100644 --- a/Userland/Libraries/LibELF/Validation.cpp +++ b/Userland/Libraries/LibELF/Validation.cpp @@ -7,6 +7,7 @@ #include <AK/Assertions.h> #include <AK/Checked.h> +#include <Kernel/API/serenity_limits.h> #include <LibC/elf.h> #include <LibELF/Validation.h> #include <limits.h> @@ -298,6 +299,21 @@ ErrorOr<bool> validate_program_headers(ElfW(Ehdr) const& elf_header, size_t file if (verbose) dbgln("Possible shenanigans! Validating an ELF with executable stack."); } + + if (program_header.p_memsz != 0) { + if (program_header.p_memsz < static_cast<unsigned>(PTHREAD_STACK_MIN) || program_header.p_memsz > static_cast<unsigned>(PTHREAD_STACK_MAX)) { + if (verbose) + dbgln("PT_GNU_STACK defines an unacceptable stack size."); + return false; + } + + if (program_header.p_memsz % PAGE_SIZE != 0) { + if (verbose) + dbgln("PT_GNU_STACK size is not page-aligned."); + return false; + } + } + break; case PT_GNU_RELRO: if ((program_header.p_flags & PF_X) && (program_header.p_flags & PF_W)) { |