mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-30 00:31:14 +00:00
Kernel: Make Process creation APIs OOM safe
This change looks more involved than it actually is. This simply reshuffles the previous Process constructor and splits out the parts which can fail (resource allocation) into separate methods which can be called from a factory method. The factory is then used everywhere instead of the constructor.
This commit is contained in:
parent
77868abe6a
commit
ede1483e48
Notes:
sideshowbarker
2024-07-18 18:07:29 +09:00
Author: https://github.com/bgianfo Commit: https://github.com/SerenityOS/serenity/commit/ede1483e48a Pull-request: https://github.com/SerenityOS/serenity/pull/7103 Reviewed-by: https://github.com/awesomekling
|
@ -144,7 +144,7 @@ RefPtr<Process> Process::create_user_process(RefPtr<Thread>& first_thread, const
|
|||
if (!cwd)
|
||||
cwd = VFS::the().root_custody();
|
||||
|
||||
auto process = adopt_ref(*new Process(first_thread, parts.take_last(), uid, gid, parent_pid, false, move(cwd), nullptr, tty));
|
||||
auto process = Process::create(first_thread, parts.take_last(), uid, gid, parent_pid, false, move(cwd), nullptr, tty);
|
||||
if (!first_thread)
|
||||
return {};
|
||||
if (!process->m_fds.try_resize(m_max_open_file_descriptors)) {
|
||||
|
@ -175,8 +175,8 @@ RefPtr<Process> Process::create_user_process(RefPtr<Thread>& first_thread, const
|
|||
|
||||
RefPtr<Process> Process::create_kernel_process(RefPtr<Thread>& first_thread, String&& name, void (*entry)(void*), void* entry_data, u32 affinity)
|
||||
{
|
||||
auto process = adopt_ref(*new Process(first_thread, move(name), (uid_t)0, (gid_t)0, ProcessID(0), true));
|
||||
if (!first_thread)
|
||||
auto process = Process::create(first_thread, move(name), (uid_t)0, (gid_t)0, ProcessID(0), true);
|
||||
if (!first_thread || !process)
|
||||
return {};
|
||||
first_thread->tss().eip = (FlatPtr)entry;
|
||||
first_thread->tss().esp = FlatPtr(entry_data); // entry function argument is expected to be in tss.esp
|
||||
|
@ -203,7 +203,18 @@ void Process::unprotect_data()
|
|||
MM.set_page_writable_direct(VirtualAddress { this }, true);
|
||||
}
|
||||
|
||||
Process::Process(RefPtr<Thread>& first_thread, const String& name, uid_t uid, gid_t gid, ProcessID ppid, bool is_kernel_process, RefPtr<Custody> cwd, RefPtr<Custody> executable, TTY* tty, Process* fork_parent)
|
||||
RefPtr<Process> Process::create(RefPtr<Thread>& first_thread, const String& name, uid_t uid, gid_t gid, ProcessID ppid, bool is_kernel_process, RefPtr<Custody> cwd, RefPtr<Custody> executable, TTY* tty, Process* fork_parent)
|
||||
{
|
||||
auto process = adopt_ref_if_nonnull(new Process(name, uid, gid, ppid, is_kernel_process, move(cwd), move(executable), tty));
|
||||
if (!process)
|
||||
return {};
|
||||
auto result = process->attach_resources(first_thread, fork_parent);
|
||||
if (result.is_error())
|
||||
return {};
|
||||
return process;
|
||||
}
|
||||
|
||||
Process::Process(const String& name, uid_t uid, gid_t gid, ProcessID ppid, bool is_kernel_process, RefPtr<Custody> cwd, RefPtr<Custody> executable, TTY* tty)
|
||||
: m_name(move(name))
|
||||
, m_is_kernel_process(is_kernel_process)
|
||||
, m_executable(move(executable))
|
||||
|
@ -224,19 +235,28 @@ Process::Process(RefPtr<Thread>& first_thread, const String& name, uid_t uid, gi
|
|||
m_sgid = gid;
|
||||
|
||||
dbgln_if(PROCESS_DEBUG, "Created new process {}({})", m_name, this->pid().value());
|
||||
}
|
||||
|
||||
KResult Process::attach_resources(RefPtr<Thread>& first_thread, Process* fork_parent)
|
||||
{
|
||||
m_space = Space::create(*this, fork_parent ? &fork_parent->space() : nullptr);
|
||||
if (!m_space)
|
||||
return ENOMEM;
|
||||
|
||||
if (fork_parent) {
|
||||
// NOTE: fork() doesn't clone all threads; the thread that called fork() becomes the only thread in the new process.
|
||||
first_thread = Thread::current()->clone(*this);
|
||||
if (!first_thread)
|
||||
return ENOMEM;
|
||||
} else {
|
||||
// NOTE: This non-forked code path is only taken when the kernel creates a process "manually" (at boot.)
|
||||
auto thread_or_error = Thread::try_create(*this);
|
||||
VERIFY(!thread_or_error.is_error());
|
||||
if (thread_or_error.is_error())
|
||||
return thread_or_error.error();
|
||||
first_thread = thread_or_error.release_value();
|
||||
first_thread->detach();
|
||||
}
|
||||
return KSuccess;
|
||||
}
|
||||
|
||||
Process::~Process()
|
||||
|
|
|
@ -499,7 +499,9 @@ private:
|
|||
bool add_thread(Thread&);
|
||||
bool remove_thread(Thread&);
|
||||
|
||||
Process(RefPtr<Thread>& first_thread, const String& name, uid_t, gid_t, ProcessID ppid, bool is_kernel_process, RefPtr<Custody> cwd = nullptr, RefPtr<Custody> executable = nullptr, TTY* = nullptr, Process* fork_parent = nullptr);
|
||||
Process(const String& name, uid_t uid, gid_t gid, ProcessID ppid, bool is_kernel_process, RefPtr<Custody> cwd, RefPtr<Custody> executable, TTY* tty);
|
||||
static RefPtr<Process> create(RefPtr<Thread>& first_thread, const String& name, uid_t, gid_t, ProcessID ppid, bool is_kernel_process, RefPtr<Custody> cwd = nullptr, RefPtr<Custody> executable = nullptr, TTY* = nullptr, Process* fork_parent = nullptr);
|
||||
KResult attach_resources(RefPtr<Thread>& first_thread, Process* fork_parent);
|
||||
static ProcessID allocate_pid();
|
||||
|
||||
void kill_threads_except_self();
|
||||
|
|
|
@ -17,8 +17,8 @@ KResultOr<pid_t> Process::sys$fork(RegisterState& regs)
|
|||
{
|
||||
REQUIRE_PROMISE(proc);
|
||||
RefPtr<Thread> child_first_thread;
|
||||
auto child = adopt_ref(*new Process(child_first_thread, m_name, uid(), gid(), pid(), m_is_kernel_process, m_cwd, m_executable, m_tty, this));
|
||||
if (!child_first_thread)
|
||||
auto child = Process::create(child_first_thread, m_name, uid(), gid(), pid(), m_is_kernel_process, m_cwd, m_executable, m_tty, this);
|
||||
if (!child || !child_first_thread)
|
||||
return ENOMEM;
|
||||
child->m_root_directory = m_root_directory;
|
||||
child->m_root_directory_relative_to_global_root = m_root_directory_relative_to_global_root;
|
||||
|
|
Loading…
Reference in a new issue