mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 04:27:44 +00:00
Kernel: Add the auxiliary vector to the stack size validation
This patch validates that the size of the auxiliary vector does not exceed `Process::max_auxiliary_size`. The auxiliary vector is a range of memory in userspace stack where the kernel can pass information to the process that will be created via `Process:do_exec`. The reason the kernel needs to validate its size is that the about to be created process needs to have remaining space on the stack. Previously only `argv` and `envp` were taken into account for the size validation, with this patch, the size of `auxv` is also checked. All three elements contain values that a user (or an attacker) can specify. This patch adds the constant `Process::max_auxiliary_size` which is defined to be one eight of the user-space stack size. This is the approach taken by `Process:max_arguments_size` and `Process::max_environment_size` which are used to check the sizes of `argv` and `envp`.
This commit is contained in:
parent
e6a8bd1058
commit
ac40090583
2 changed files with 18 additions and 6 deletions
|
@ -466,6 +466,7 @@ public:
|
||||||
|
|
||||||
static constexpr size_t max_arguments_size = Thread::default_userspace_stack_size / 8;
|
static constexpr size_t max_arguments_size = Thread::default_userspace_stack_size / 8;
|
||||||
static constexpr size_t max_environment_size = Thread::default_userspace_stack_size / 8;
|
static constexpr size_t max_environment_size = Thread::default_userspace_stack_size / 8;
|
||||||
|
static constexpr size_t max_auxiliary_size = Thread::default_userspace_stack_size / 8;
|
||||||
NonnullOwnPtrVector<KString> const& arguments() const { return m_arguments; };
|
NonnullOwnPtrVector<KString> const& arguments() const { return m_arguments; };
|
||||||
NonnullOwnPtrVector<KString> const& environment() const { return m_environment; };
|
NonnullOwnPtrVector<KString> const& environment() const { return m_environment; };
|
||||||
|
|
||||||
|
|
|
@ -43,18 +43,27 @@ struct LoadResult {
|
||||||
static constexpr size_t auxiliary_vector_size = 15;
|
static constexpr size_t auxiliary_vector_size = 15;
|
||||||
static Array<ELF::AuxiliaryValue, auxiliary_vector_size> generate_auxiliary_vector(FlatPtr load_base, FlatPtr entry_eip, UserID uid, UserID euid, GroupID gid, GroupID egid, StringView executable_path, Optional<Process::ScopedDescriptionAllocation> const& main_program_fd_allocation);
|
static Array<ELF::AuxiliaryValue, auxiliary_vector_size> generate_auxiliary_vector(FlatPtr load_base, FlatPtr entry_eip, UserID uid, UserID euid, GroupID gid, GroupID egid, StringView executable_path, Optional<Process::ScopedDescriptionAllocation> const& main_program_fd_allocation);
|
||||||
|
|
||||||
static bool validate_stack_size(NonnullOwnPtrVector<KString> const& arguments, NonnullOwnPtrVector<KString>& environment)
|
static bool validate_stack_size(NonnullOwnPtrVector<KString> const& arguments, NonnullOwnPtrVector<KString>& environment, Array<ELF::AuxiliaryValue, auxiliary_vector_size> const& auxiliary)
|
||||||
{
|
{
|
||||||
size_t total_arguments_size = 0;
|
size_t total_arguments_size = 0;
|
||||||
size_t total_environment_size = 0;
|
size_t total_environment_size = 0;
|
||||||
|
size_t total_auxiliary_size = 0;
|
||||||
|
|
||||||
for (auto const& a : arguments)
|
for (auto const& a : arguments)
|
||||||
total_arguments_size += a.length() + 1;
|
total_arguments_size += a.length() + 1;
|
||||||
for (auto const& e : environment)
|
for (auto const& e : environment)
|
||||||
total_environment_size += e.length() + 1;
|
total_environment_size += e.length() + 1;
|
||||||
|
for (auto const& v : auxiliary) {
|
||||||
|
if (!v.optional_string.is_empty())
|
||||||
|
total_auxiliary_size += round_up_to_power_of_two(v.optional_string.length() + 1, sizeof(FlatPtr));
|
||||||
|
|
||||||
|
if (v.auxv.a_type == ELF::AuxiliaryValue::Random)
|
||||||
|
total_auxiliary_size += round_up_to_power_of_two(16, sizeof(FlatPtr));
|
||||||
|
}
|
||||||
|
|
||||||
total_arguments_size += sizeof(char*) * (arguments.size() + 1);
|
total_arguments_size += sizeof(char*) * (arguments.size() + 1);
|
||||||
total_environment_size += sizeof(char*) * (environment.size() + 1);
|
total_environment_size += sizeof(char*) * (environment.size() + 1);
|
||||||
|
total_auxiliary_size += sizeof(auxv_t) * auxiliary.size();
|
||||||
|
|
||||||
if (total_arguments_size > Process::max_arguments_size)
|
if (total_arguments_size > Process::max_arguments_size)
|
||||||
return false;
|
return false;
|
||||||
|
@ -62,7 +71,9 @@ static bool validate_stack_size(NonnullOwnPtrVector<KString> const& arguments, N
|
||||||
if (total_environment_size > Process::max_environment_size)
|
if (total_environment_size > Process::max_environment_size)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// FIXME: This doesn't account for the size of the auxiliary vector
|
if (total_auxiliary_size > Process::max_auxiliary_size)
|
||||||
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,10 +487,6 @@ ErrorOr<void> Process::do_exec(NonnullLockRefPtr<OpenFileDescription> main_progr
|
||||||
|
|
||||||
dbgln_if(EXEC_DEBUG, "do_exec: {}", path);
|
dbgln_if(EXEC_DEBUG, "do_exec: {}", path);
|
||||||
|
|
||||||
// FIXME: How much stack space does process startup need?
|
|
||||||
if (!validate_stack_size(arguments, environment))
|
|
||||||
return E2BIG;
|
|
||||||
|
|
||||||
auto last_part = path->view().find_last_split_view('/');
|
auto last_part = path->view().find_last_split_view('/');
|
||||||
|
|
||||||
auto new_process_name = TRY(KString::try_create(last_part));
|
auto new_process_name = TRY(KString::try_create(last_part));
|
||||||
|
@ -627,6 +634,10 @@ ErrorOr<void> Process::do_exec(NonnullLockRefPtr<OpenFileDescription> main_progr
|
||||||
auto credentials = this->credentials();
|
auto credentials = this->credentials();
|
||||||
auto auxv = generate_auxiliary_vector(load_result.load_base, load_result.entry_eip, credentials->uid(), credentials->euid(), credentials->gid(), credentials->egid(), path->view(), main_program_fd_allocation);
|
auto auxv = generate_auxiliary_vector(load_result.load_base, load_result.entry_eip, credentials->uid(), credentials->euid(), credentials->gid(), credentials->egid(), path->view(), main_program_fd_allocation);
|
||||||
|
|
||||||
|
// FIXME: How much stack space does process startup need?
|
||||||
|
if (!validate_stack_size(m_arguments, m_environment, auxv))
|
||||||
|
return E2BIG;
|
||||||
|
|
||||||
// NOTE: We create the new stack before disabling interrupts since it will zero-fault
|
// 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.
|
// and we don't want to deal with faults after this point.
|
||||||
auto new_userspace_sp = TRY(make_userspace_context_for_main_thread(new_main_thread->regs(), *load_result.stack_region.unsafe_ptr(), m_arguments, m_environment, move(auxv)));
|
auto new_userspace_sp = TRY(make_userspace_context_for_main_thread(new_main_thread->regs(), *load_result.stack_region.unsafe_ptr(), m_arguments, m_environment, move(auxv)));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue