mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +00:00
Kernel: Wrap much of sys$execve() in a block scope
Since we don't return normally from this function, let's make it a little extra difficult to accidentally leak something by leaving it on the stack in this function.
This commit is contained in:
parent
0e72b04e7d
commit
0e08763483
Notes:
sideshowbarker
2024-07-17 20:55:46 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/0e08763483b
1 changed files with 38 additions and 33 deletions
|
@ -838,41 +838,46 @@ ErrorOr<FlatPtr> Process::sys$execve(Userspace<const Syscall::SC_execve_params*>
|
|||
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this);
|
||||
TRY(require_promise(Pledge::exec));
|
||||
|
||||
// NOTE: Be extremely careful with allocating any kernel memory in this function.
|
||||
// On success, the kernel stack will be lost.
|
||||
auto params = TRY(copy_typed_from_user(user_params));
|
||||
|
||||
if (params.arguments.length > ARG_MAX || params.environment.length > ARG_MAX)
|
||||
return E2BIG;
|
||||
|
||||
auto path = TRY(get_syscall_path_argument(params.path));
|
||||
|
||||
auto copy_user_strings = [](const auto& list, auto& output) -> ErrorOr<void> {
|
||||
if (!list.length)
|
||||
return {};
|
||||
Checked<size_t> size = sizeof(*list.strings);
|
||||
size *= list.length;
|
||||
if (size.has_overflow())
|
||||
return EOVERFLOW;
|
||||
Vector<Syscall::StringArgument, 32> strings;
|
||||
TRY(strings.try_resize(list.length));
|
||||
TRY(copy_from_user(strings.data(), list.strings, size.value()));
|
||||
for (size_t i = 0; i < list.length; ++i) {
|
||||
auto string = TRY(try_copy_kstring_from_user(strings[i]));
|
||||
TRY(output.try_append(move(string)));
|
||||
}
|
||||
return {};
|
||||
};
|
||||
|
||||
NonnullOwnPtrVector<KString> arguments;
|
||||
TRY(copy_user_strings(params.arguments, arguments));
|
||||
|
||||
NonnullOwnPtrVector<KString> environment;
|
||||
TRY(copy_user_strings(params.environment, environment));
|
||||
|
||||
Thread* new_main_thread = nullptr;
|
||||
u32 prev_flags = 0;
|
||||
TRY(exec(move(path), move(arguments), move(environment), new_main_thread, prev_flags));
|
||||
|
||||
// NOTE: Be extremely careful with allocating any kernel memory in this function.
|
||||
// On success, the kernel stack will be lost.
|
||||
// The explicit block scope below is specifically placed to minimize the number
|
||||
// of stack locals in this function.
|
||||
{
|
||||
auto params = TRY(copy_typed_from_user(user_params));
|
||||
|
||||
if (params.arguments.length > ARG_MAX || params.environment.length > ARG_MAX)
|
||||
return E2BIG;
|
||||
|
||||
auto path = TRY(get_syscall_path_argument(params.path));
|
||||
|
||||
auto copy_user_strings = [](const auto& list, auto& output) -> ErrorOr<void> {
|
||||
if (!list.length)
|
||||
return {};
|
||||
Checked<size_t> size = sizeof(*list.strings);
|
||||
size *= list.length;
|
||||
if (size.has_overflow())
|
||||
return EOVERFLOW;
|
||||
Vector<Syscall::StringArgument, 32> strings;
|
||||
TRY(strings.try_resize(list.length));
|
||||
TRY(copy_from_user(strings.data(), list.strings, size.value()));
|
||||
for (size_t i = 0; i < list.length; ++i) {
|
||||
auto string = TRY(try_copy_kstring_from_user(strings[i]));
|
||||
TRY(output.try_append(move(string)));
|
||||
}
|
||||
return {};
|
||||
};
|
||||
|
||||
NonnullOwnPtrVector<KString> arguments;
|
||||
TRY(copy_user_strings(params.arguments, arguments));
|
||||
|
||||
NonnullOwnPtrVector<KString> environment;
|
||||
TRY(copy_user_strings(params.environment, environment));
|
||||
|
||||
TRY(exec(move(path), move(arguments), move(environment), new_main_thread, prev_flags));
|
||||
}
|
||||
|
||||
// NOTE: If we're here, the exec has succeeded and we've got a new executable image!
|
||||
// We will not return normally from this function. Instead, the next time we
|
||||
|
|
Loading…
Reference in a new issue