diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 5f8d2c69f70..30ffbe74216 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -215,20 +215,20 @@ void Process::unprotect_data() }); } -ErrorOr> Process::try_create(RefPtr& first_thread, NonnullOwnPtr name, UserID uid, GroupID gid, ProcessID ppid, bool is_kernel_process, RefPtr cwd, RefPtr executable, TTY* tty, Process* fork_parent) +ErrorOr> Process::try_create(RefPtr& first_thread, NonnullOwnPtr name, UserID uid, GroupID gid, ProcessID ppid, bool is_kernel_process, RefPtr current_directory, RefPtr executable, TTY* tty, Process* fork_parent) { auto space = TRY(Memory::AddressSpace::try_create(fork_parent ? &fork_parent->address_space() : nullptr)); auto unveil_tree = UnveilNode { TRY(KString::try_create("/"sv)), UnveilMetadata(TRY(KString::try_create("/"sv))) }; - auto process = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) Process(move(name), uid, gid, ppid, is_kernel_process, move(cwd), move(executable), tty, move(unveil_tree)))); + auto process = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) Process(move(name), uid, gid, ppid, is_kernel_process, move(current_directory), move(executable), tty, move(unveil_tree)))); TRY(process->attach_resources(move(space), first_thread, fork_parent)); return process; } -Process::Process(NonnullOwnPtr name, UserID uid, GroupID gid, ProcessID ppid, bool is_kernel_process, RefPtr cwd, RefPtr executable, TTY* tty, UnveilNode unveil_tree) +Process::Process(NonnullOwnPtr name, UserID uid, GroupID gid, ProcessID ppid, bool is_kernel_process, NonnullRefPtr current_directory, RefPtr executable, TTY* tty, UnveilNode unveil_tree) : m_name(move(name)) , m_is_kernel_process(is_kernel_process) , m_executable(move(executable)) - , m_cwd(move(cwd)) + , m_current_directory(move(current_directory)) , m_tty(tty) , m_unveiled_paths(move(unveil_tree)) , m_wait_blocker_set(*this) @@ -528,11 +528,13 @@ siginfo_t Process::wait_info() const return siginfo; } -Custody& Process::current_directory() +NonnullRefPtr Process::current_directory() { - if (!m_cwd) - m_cwd = VirtualFileSystem::the().root_custody(); - return *m_cwd; + return m_current_directory.with([&](auto& current_directory) -> NonnullRefPtr { + if (!current_directory) + current_directory = VirtualFileSystem::the().root_custody(); + return *current_directory; + }); } ErrorOr> Process::get_syscall_path_argument(Userspace user_path, size_t path_length) @@ -629,7 +631,6 @@ void Process::finalize() m_fds.with_exclusive([](auto& fds) { fds.clear(); }); m_tty = nullptr; m_executable = nullptr; - m_cwd = nullptr; m_arguments.clear(); m_environment.clear(); diff --git a/Kernel/Process.h b/Kernel/Process.h index 560e7064b34..8c59d0d11b1 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -432,7 +432,7 @@ public: u32 m_ticks_in_user_for_dead_children { 0 }; u32 m_ticks_in_kernel_for_dead_children { 0 }; - Custody& current_directory(); + NonnullRefPtr current_directory(); Custody* executable() { return m_executable.ptr(); } const Custody* executable() const { return m_executable.ptr(); } @@ -525,8 +525,8 @@ private: bool add_thread(Thread&); bool remove_thread(Thread&); - Process(NonnullOwnPtr name, UserID, GroupID, ProcessID ppid, bool is_kernel_process, RefPtr cwd, RefPtr executable, TTY* tty, UnveilNode unveil_tree); - static ErrorOr> try_create(RefPtr& first_thread, NonnullOwnPtr name, UserID, GroupID, ProcessID ppid, bool is_kernel_process, RefPtr cwd = nullptr, RefPtr executable = nullptr, TTY* = nullptr, Process* fork_parent = nullptr); + Process(NonnullOwnPtr name, UserID, GroupID, ProcessID ppid, bool is_kernel_process, RefPtr current_directory, RefPtr executable, TTY* tty, UnveilNode unveil_tree); + static ErrorOr> try_create(RefPtr& first_thread, NonnullOwnPtr name, UserID, GroupID, ProcessID ppid, bool is_kernel_process, RefPtr current_directory = nullptr, RefPtr executable = nullptr, TTY* = nullptr, Process* fork_parent = nullptr); ErrorOr attach_resources(NonnullOwnPtr&&, RefPtr& first_thread, Process* fork_parent); static ProcessID allocate_pid(); @@ -788,7 +788,8 @@ private: bool m_should_generate_coredump { false }; RefPtr m_executable; - RefPtr m_cwd; + + SpinlockProtected> m_current_directory; NonnullOwnPtrVector m_arguments; NonnullOwnPtrVector m_environment; diff --git a/Kernel/ProcessSpecificExposed.cpp b/Kernel/ProcessSpecificExposed.cpp index c0db187b189..a8b1e0ecbb5 100644 --- a/Kernel/ProcessSpecificExposed.cpp +++ b/Kernel/ProcessSpecificExposed.cpp @@ -274,7 +274,7 @@ ErrorOr Process::procfs_get_virtual_memory_stats(KBufferBuilder& builder) ErrorOr Process::procfs_get_current_work_directory_link(KBufferBuilder& builder) const { - return builder.append(TRY(const_cast(*this).current_directory().try_serialize_absolute_path())->view()); + return builder.append(TRY(const_cast(*this).current_directory()->try_serialize_absolute_path())->view()); } mode_t Process::binary_link_required_mode() const diff --git a/Kernel/Syscalls/chdir.cpp b/Kernel/Syscalls/chdir.cpp index fa64c694879..c60183a4473 100644 --- a/Kernel/Syscalls/chdir.cpp +++ b/Kernel/Syscalls/chdir.cpp @@ -15,8 +15,10 @@ ErrorOr Process::sys$chdir(Userspace user_path, size_t pat VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this); TRY(require_promise(Pledge::rpath)); auto path = TRY(get_syscall_path_argument(user_path, path_length)); - m_cwd = TRY(VirtualFileSystem::the().open_directory(path->view(), current_directory())); - return 0; + return m_current_directory.with([&](auto& current_directory) -> ErrorOr { + current_directory = TRY(VirtualFileSystem::the().open_directory(path->view(), *current_directory)); + return 0; + }); } ErrorOr Process::sys$fchdir(int fd) @@ -28,7 +30,9 @@ ErrorOr Process::sys$fchdir(int fd) return ENOTDIR; if (!description->metadata().may_execute(*this)) return EACCES; - m_cwd = description->custody(); + m_current_directory.with([&](auto& current_directory) { + current_directory = description->custody(); + }); return 0; } @@ -40,7 +44,7 @@ ErrorOr Process::sys$getcwd(Userspace buffer, size_t size) if (size > NumericLimits::max()) return EINVAL; - auto path = TRY(current_directory().try_serialize_absolute_path()); + auto path = TRY(current_directory()->try_serialize_absolute_path()); size_t ideal_size = path->length() + 1; auto size_to_copy = min(ideal_size, size); TRY(copy_to_user(buffer, path->characters(), size_to_copy)); diff --git a/Kernel/Syscalls/fork.cpp b/Kernel/Syscalls/fork.cpp index a9890025cd3..2872b947371 100644 --- a/Kernel/Syscalls/fork.cpp +++ b/Kernel/Syscalls/fork.cpp @@ -19,7 +19,7 @@ ErrorOr Process::sys$fork(RegisterState& regs) TRY(require_promise(Pledge::proc)); RefPtr child_first_thread; auto child_name = TRY(m_name->try_clone()); - auto child = TRY(Process::try_create(child_first_thread, move(child_name), uid(), gid(), pid(), m_is_kernel_process, m_cwd, m_executable, m_tty, this)); + auto child = TRY(Process::try_create(child_first_thread, move(child_name), uid(), gid(), pid(), m_is_kernel_process, current_directory(), m_executable, m_tty, this)); child->m_veil_state = m_veil_state; child->m_unveiled_paths = TRY(m_unveiled_paths.deep_copy());