diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index e361a58aec9..81771e9f85d 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -135,6 +135,7 @@ set(KERNEL_SOURCES FileSystem/AnonymousFile.cpp FileSystem/BlockBasedFileSystem.cpp FileSystem/Custody.cpp + FileSystem/CustodyBase.cpp FileSystem/DevLoopFS/FileSystem.cpp FileSystem/DevLoopFS/Inode.cpp FileSystem/DevPtsFS/FileSystem.cpp diff --git a/Kernel/FileSystem/CustodyBase.cpp b/Kernel/FileSystem/CustodyBase.cpp new file mode 100644 index 00000000000..03fc8c3f4c3 --- /dev/null +++ b/Kernel/FileSystem/CustodyBase.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include + +namespace Kernel { + +ErrorOr> CustodyBase::resolve() const +{ + if (m_base) + return *m_base; + if (KLexicalPath::is_absolute(m_path)) + return VirtualFileSystem::the().root_custody(); + return Process::current().custody_for_dirfd({}, m_dirfd); +} + +} diff --git a/Kernel/FileSystem/CustodyBase.h b/Kernel/FileSystem/CustodyBase.h new file mode 100644 index 00000000000..3fd12262ed4 --- /dev/null +++ b/Kernel/FileSystem/CustodyBase.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include + +namespace Kernel { + +class CustodyBase { +public: + CustodyBase(int dirfd, StringView path) + : m_path(path) + , m_dirfd(dirfd) + { + } + + CustodyBase(NonnullRefPtr base) + : m_base(base) + { + } + + CustodyBase(Custody& base) + : m_base(base) + { + } + + CustodyBase(Custody const& base) + : m_base(base) + { + } + + ErrorOr> resolve() const; + +private: + RefPtr const m_base; + StringView m_path; + int m_dirfd { -1 }; +}; + +} diff --git a/Kernel/FileSystem/Inode.cpp b/Kernel/FileSystem/Inode.cpp index 83250141310..2918fa41a5a 100644 --- a/Kernel/FileSystem/Inode.cpp +++ b/Kernel/FileSystem/Inode.cpp @@ -52,7 +52,7 @@ void Inode::sync() } } -ErrorOr> Inode::resolve_as_link(Credentials const& credentials, Custody& base, RefPtr* out_parent, int options, int symlink_recursion_level) const +ErrorOr> Inode::resolve_as_link(Credentials const& credentials, CustodyBase const& base, RefPtr* out_parent, int options, int symlink_recursion_level) const { // The default implementation simply treats the stored // contents as a path and resolves that. That is, it diff --git a/Kernel/FileSystem/Inode.h b/Kernel/FileSystem/Inode.h index dfd1aa17ee5..da0e1ad91e0 100644 --- a/Kernel/FileSystem/Inode.h +++ b/Kernel/FileSystem/Inode.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -72,7 +73,7 @@ public: virtual ErrorOr chmod(mode_t) = 0; virtual ErrorOr chown(UserID, GroupID) = 0; - ErrorOr> resolve_as_link(Credentials const&, Custody& base, RefPtr* out_parent, int options, int symlink_recursion_level) const; + ErrorOr> resolve_as_link(Credentials const&, CustodyBase const& base, RefPtr* out_parent, int options, int symlink_recursion_level) const; virtual ErrorOr get_block_address(int) { return ENOTSUP; } diff --git a/Kernel/FileSystem/VirtualFileSystem.cpp b/Kernel/FileSystem/VirtualFileSystem.cpp index e62c83f80b3..32243f78e62 100644 --- a/Kernel/FileSystem/VirtualFileSystem.cpp +++ b/Kernel/FileSystem/VirtualFileSystem.cpp @@ -418,7 +418,7 @@ ErrorOr VirtualFileSystem::traverse_directory_inode(Inode& dir_inode, Func }); } -ErrorOr VirtualFileSystem::utime(Credentials const& credentials, StringView path, Custody& base, time_t atime, time_t mtime) +ErrorOr VirtualFileSystem::utime(Credentials const& credentials, StringView path, CustodyBase const& base, time_t atime, time_t mtime) { auto custody = TRY(resolve_path(credentials, path, base)); auto& inode = custody->inode(); @@ -431,7 +431,7 @@ ErrorOr VirtualFileSystem::utime(Credentials const& credentials, StringVie return {}; } -ErrorOr VirtualFileSystem::utimensat(Credentials const& credentials, StringView path, Custody& base, timespec const& atime, timespec const& mtime, int options) +ErrorOr VirtualFileSystem::utimensat(Credentials const& credentials, StringView path, CustodyBase const& base, timespec const& atime, timespec const& mtime, int options) { auto custody = TRY(resolve_path(credentials, path, base, nullptr, options)); return do_utimens(credentials, custody, atime, mtime); @@ -454,18 +454,18 @@ ErrorOr VirtualFileSystem::do_utimens(Credentials const& credentials, Cust return {}; } -ErrorOr VirtualFileSystem::lookup_metadata(Credentials const& credentials, StringView path, Custody& base, int options) +ErrorOr VirtualFileSystem::lookup_metadata(Credentials const& credentials, StringView path, CustodyBase const& base, int options) { auto custody = TRY(resolve_path(credentials, path, base, nullptr, options)); return custody->inode().metadata(); } -ErrorOr> VirtualFileSystem::open(Credentials const& credentials, StringView path, int options, mode_t mode, Custody& base, Optional owner) +ErrorOr> VirtualFileSystem::open(Credentials const& credentials, StringView path, int options, mode_t mode, CustodyBase const& base, Optional owner) { return open(Process::current(), credentials, path, options, mode, base, owner); } -ErrorOr> VirtualFileSystem::open(Process const& process, Credentials const& credentials, StringView path, int options, mode_t mode, Custody& base, Optional owner) +ErrorOr> VirtualFileSystem::open(Process const& process, Credentials const& credentials, StringView path, int options, mode_t mode, CustodyBase const& base, Optional owner) { if ((options & O_CREAT) && (options & O_DIRECTORY)) return EINVAL; @@ -555,7 +555,7 @@ ErrorOr> VirtualFileSystem::open(Process cons return description; } -ErrorOr VirtualFileSystem::mknod(Credentials const& credentials, StringView path, mode_t mode, dev_t dev, Custody& base) +ErrorOr VirtualFileSystem::mknod(Credentials const& credentials, StringView path, mode_t mode, dev_t dev, CustodyBase const& base) { if (!is_regular_file(mode) && !is_block_device(mode) && !is_character_device(mode) && !is_fifo(mode) && !is_socket(mode)) return EINVAL; @@ -618,7 +618,7 @@ ErrorOr> VirtualFileSystem::create(Process co return description; } -ErrorOr VirtualFileSystem::mkdir(Credentials const& credentials, StringView path, mode_t mode, Custody& base) +ErrorOr VirtualFileSystem::mkdir(Credentials const& credentials, StringView path, mode_t mode, CustodyBase const& base) { // Unlike in basically every other case, where it's only the last // path component (the one being created) that is allowed not to @@ -633,7 +633,8 @@ ErrorOr VirtualFileSystem::mkdir(Credentials const& credentials, StringVie RefPtr parent_custody; // FIXME: The errors returned by resolve_path_without_veil can leak information about paths that are not unveiled, // e.g. when the error is EACCESS or similar. - auto result = resolve_path_without_veil(credentials, path, base, &parent_custody); + auto base_custody = TRY(base.resolve()); + auto result = resolve_path_without_veil(credentials, path, base_custody, &parent_custody); if (!result.is_error()) return EEXIST; else if (!parent_custody) @@ -654,7 +655,7 @@ ErrorOr VirtualFileSystem::mkdir(Credentials const& credentials, StringVie return {}; } -ErrorOr VirtualFileSystem::access(Credentials const& credentials, StringView path, int mode, Custody& base, AccessFlags access_flags) +ErrorOr VirtualFileSystem::access(Credentials const& credentials, StringView path, int mode, CustodyBase const& base, AccessFlags access_flags) { auto should_follow_symlinks = !has_flag(access_flags, AccessFlags::DoNotFollowSymlinks); auto custody = TRY(resolve_path(credentials, path, base, nullptr, should_follow_symlinks ? 0 : O_NOFOLLOW_NOERROR)); @@ -679,7 +680,7 @@ ErrorOr VirtualFileSystem::access(Credentials const& credentials, StringVi return {}; } -ErrorOr> VirtualFileSystem::open_directory(Credentials const& credentials, StringView path, Custody& base) +ErrorOr> VirtualFileSystem::open_directory(Credentials const& credentials, StringView path, CustodyBase const& base) { auto custody = TRY(resolve_path(credentials, path, base)); auto& inode = custody->inode(); @@ -704,13 +705,13 @@ ErrorOr VirtualFileSystem::chmod(Credentials const& credentials, Custody& return inode.chmod(mode); } -ErrorOr VirtualFileSystem::chmod(Credentials const& credentials, StringView path, mode_t mode, Custody& base, int options) +ErrorOr VirtualFileSystem::chmod(Credentials const& credentials, StringView path, mode_t mode, CustodyBase const& base, int options) { auto custody = TRY(resolve_path(credentials, path, base, nullptr, options)); return chmod(credentials, custody, mode); } -ErrorOr VirtualFileSystem::rename(Credentials const& credentials, Custody& old_base, StringView old_path, Custody& new_base, StringView new_path) +ErrorOr VirtualFileSystem::rename(Credentials const& credentials, CustodyBase const& old_base, StringView old_path, CustodyBase const& new_base, StringView new_path) { RefPtr old_parent_custody; auto old_custody = TRY(resolve_path(credentials, old_path, old_base, &old_parent_custody, O_NOFOLLOW_NOERROR)); @@ -844,7 +845,7 @@ ErrorOr VirtualFileSystem::chown(Credentials const& credentials, Custody& return inode.chown(new_uid, new_gid); } -ErrorOr VirtualFileSystem::chown(Credentials const& credentials, StringView path, UserID a_uid, GroupID a_gid, Custody& base, int options) +ErrorOr VirtualFileSystem::chown(Credentials const& credentials, StringView path, UserID a_uid, GroupID a_gid, CustodyBase const& base, int options) { auto custody = TRY(resolve_path(credentials, path, base, nullptr, options)); return chown(credentials, custody, a_uid, a_gid); @@ -867,7 +868,7 @@ static bool hard_link_allowed(Credentials const& credentials, Inode const& inode return false; } -ErrorOr VirtualFileSystem::link(Credentials const& credentials, StringView old_path, StringView new_path, Custody& base) +ErrorOr VirtualFileSystem::link(Credentials const& credentials, StringView old_path, StringView new_path, CustodyBase const& base) { // NOTE: To prevent unveil bypass by creating an hardlink after unveiling a path as read-only, // check that if write permission is allowed by the veil info on the old_path. @@ -902,7 +903,7 @@ ErrorOr VirtualFileSystem::link(Credentials const& credentials, StringView return parent_inode.add_child(old_inode, KLexicalPath::basename(new_path), old_inode.mode()); } -ErrorOr VirtualFileSystem::unlink(Credentials const& credentials, StringView path, Custody& base) +ErrorOr VirtualFileSystem::unlink(Credentials const& credentials, StringView path, CustodyBase const& base) { RefPtr parent_custody; auto custody = TRY(resolve_path(credentials, path, base, &parent_custody, O_WRONLY | O_NOFOLLOW_NOERROR | O_UNLINK_INTERNAL)); @@ -931,10 +932,11 @@ ErrorOr VirtualFileSystem::unlink(Credentials const& credentials, StringVi return parent_inode.remove_child(KLexicalPath::basename(path)); } -ErrorOr VirtualFileSystem::symlink(Credentials const& credentials, StringView target, StringView linkpath, Custody& base) +ErrorOr VirtualFileSystem::symlink(Credentials const& credentials, StringView target, StringView linkpath, CustodyBase const& base) { + auto base_custody = TRY(base.resolve()); // NOTE: Check that the actual target (if it exists right now) is unveiled and prevent creating symlinks on veiled paths! - if (auto target_custody_or_error = resolve_path_without_veil(credentials, target, base, nullptr, O_RDWR, 0); !target_custody_or_error.is_error()) { + if (auto target_custody_or_error = resolve_path_without_veil(credentials, target, base_custody, nullptr, O_RDWR, 0); !target_custody_or_error.is_error()) { auto target_custody = target_custody_or_error.release_value(); TRY(validate_path_against_process_veil(*target_custody, O_RDWR)); } @@ -971,7 +973,7 @@ ErrorOr VirtualFileSystem::symlink(Credentials const& credentials, StringV } // https://pubs.opengroup.org/onlinepubs/9699919799/functions/rmdir.html -ErrorOr VirtualFileSystem::rmdir(Credentials const& credentials, StringView path, Custody& base) +ErrorOr VirtualFileSystem::rmdir(Credentials const& credentials, StringView path, CustodyBase const& base) { RefPtr parent_custody; auto custody = TRY(resolve_path(credentials, path, base, &parent_custody, O_CREAT)); @@ -1151,16 +1153,17 @@ ErrorOr VirtualFileSystem::validate_path_against_process_veil(StringView p return validate_path_against_process_veil(Process::current(), path, options); } -ErrorOr> VirtualFileSystem::resolve_path(Credentials const& credentials, StringView path, NonnullRefPtr base, RefPtr* out_parent, int options, int symlink_recursion_level) +ErrorOr> VirtualFileSystem::resolve_path(Credentials const& credentials, StringView path, CustodyBase const& base, RefPtr* out_parent, int options, int symlink_recursion_level) { return resolve_path(Process::current(), credentials, path, base, out_parent, options, symlink_recursion_level); } -ErrorOr> VirtualFileSystem::resolve_path(Process const& process, Credentials const& credentials, StringView path, NonnullRefPtr base, RefPtr* out_parent, int options, int symlink_recursion_level) +ErrorOr> VirtualFileSystem::resolve_path(Process const& process, Credentials const& credentials, StringView path, CustodyBase const& base, RefPtr* out_parent, int options, int symlink_recursion_level) { + auto base_custody = TRY(base.resolve()); // FIXME: The errors returned by resolve_path_without_veil can leak information about paths that are not unveiled, // e.g. when the error is EACCESS or similar. - auto custody = TRY(resolve_path_without_veil(credentials, path, base, out_parent, options, symlink_recursion_level)); + auto custody = TRY(resolve_path_without_veil(credentials, path, base_custody, out_parent, options, symlink_recursion_level)); if (auto result = validate_path_against_process_veil(process, *custody, options); result.is_error()) { if (out_parent) out_parent->clear(); diff --git a/Kernel/FileSystem/VirtualFileSystem.h b/Kernel/FileSystem/VirtualFileSystem.h index 464b721da6a..b577f9fd6f5 100644 --- a/Kernel/FileSystem/VirtualFileSystem.h +++ b/Kernel/FileSystem/VirtualFileSystem.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -64,27 +65,27 @@ public: ErrorOr unmount(Custody& mount_point); ErrorOr unmount(Inode& guest_inode, StringView custody_path); - ErrorOr> open(Credentials const&, StringView path, int options, mode_t mode, Custody& base, Optional = {}); - ErrorOr> open(Process const&, Credentials const&, StringView path, int options, mode_t mode, Custody& base, Optional = {}); + ErrorOr> open(Credentials const&, StringView path, int options, mode_t mode, CustodyBase const& base, Optional = {}); + ErrorOr> open(Process const&, Credentials const&, StringView path, int options, mode_t mode, CustodyBase const& base, Optional = {}); ErrorOr> create(Credentials const&, StringView path, int options, mode_t mode, Custody& parent_custody, Optional = {}); ErrorOr> create(Process const&, Credentials const&, StringView path, int options, mode_t mode, Custody& parent_custody, Optional = {}); - ErrorOr mkdir(Credentials const&, StringView path, mode_t mode, Custody& base); - ErrorOr link(Credentials const&, StringView old_path, StringView new_path, Custody& base); - ErrorOr unlink(Credentials const&, StringView path, Custody& base); - ErrorOr symlink(Credentials const&, StringView target, StringView linkpath, Custody& base); - ErrorOr rmdir(Credentials const&, StringView path, Custody& base); - ErrorOr chmod(Credentials const&, StringView path, mode_t, Custody& base, int options = 0); + ErrorOr mkdir(Credentials const&, StringView path, mode_t mode, CustodyBase const& base); + ErrorOr link(Credentials const&, StringView old_path, StringView new_path, CustodyBase const& base); + ErrorOr unlink(Credentials const&, StringView path, CustodyBase const& base); + ErrorOr symlink(Credentials const&, StringView target, StringView linkpath, CustodyBase const& base); + ErrorOr rmdir(Credentials const&, StringView path, CustodyBase const& base); + ErrorOr chmod(Credentials const&, StringView path, mode_t, CustodyBase const& base, int options = 0); ErrorOr chmod(Credentials const&, Custody&, mode_t); - ErrorOr chown(Credentials const&, StringView path, UserID, GroupID, Custody& base, int options); + ErrorOr chown(Credentials const&, StringView path, UserID, GroupID, CustodyBase const& base, int options); ErrorOr chown(Credentials const&, Custody&, UserID, GroupID); - ErrorOr access(Credentials const&, StringView path, int mode, Custody& base, AccessFlags); - ErrorOr lookup_metadata(Credentials const&, StringView path, Custody& base, int options = 0); - ErrorOr utime(Credentials const&, StringView path, Custody& base, time_t atime, time_t mtime); - ErrorOr utimensat(Credentials const&, StringView path, Custody& base, timespec const& atime, timespec const& mtime, int options = 0); + ErrorOr access(Credentials const&, StringView path, int mode, CustodyBase const& base, AccessFlags); + ErrorOr lookup_metadata(Credentials const&, StringView path, CustodyBase const& base, int options = 0); + ErrorOr utime(Credentials const&, StringView path, CustodyBase const& base, time_t atime, time_t mtime); + ErrorOr utimensat(Credentials const&, StringView path, CustodyBase const& base, timespec const& atime, timespec const& mtime, int options = 0); ErrorOr do_utimens(Credentials const& credentials, Custody& custody, timespec const& atime, timespec const& mtime); - ErrorOr rename(Credentials const&, Custody& old_base, StringView oldpath, Custody& new_base, StringView newpath); - ErrorOr mknod(Credentials const&, StringView path, mode_t, dev_t, Custody& base); - ErrorOr> open_directory(Credentials const&, StringView path, Custody& base); + ErrorOr rename(Credentials const&, CustodyBase const& old_base, StringView oldpath, CustodyBase const& new_base, StringView newpath); + ErrorOr mknod(Credentials const&, StringView path, mode_t, dev_t, CustodyBase const& base); + ErrorOr> open_directory(Credentials const&, StringView path, CustodyBase const& base); ErrorOr for_each_mount(Function(Mount const&)>) const; @@ -94,8 +95,8 @@ public: static void sync(); NonnullRefPtr root_custody(); - ErrorOr> resolve_path(Credentials const&, StringView path, NonnullRefPtr base, RefPtr* out_parent = nullptr, int options = 0, int symlink_recursion_level = 0); - ErrorOr> resolve_path(Process const&, Credentials const&, StringView path, NonnullRefPtr base, RefPtr* out_parent = nullptr, int options = 0, int symlink_recursion_level = 0); + ErrorOr> resolve_path(Credentials const&, StringView path, CustodyBase const& base, RefPtr* out_parent = nullptr, int options = 0, int symlink_recursion_level = 0); + ErrorOr> resolve_path(Process const&, Credentials const&, StringView path, CustodyBase const& base, RefPtr* out_parent = nullptr, int options = 0, int symlink_recursion_level = 0); ErrorOr> resolve_path_without_veil(Credentials const&, StringView path, NonnullRefPtr base, RefPtr* out_parent = nullptr, int options = 0, int symlink_recursion_level = 0); private: diff --git a/Kernel/Forward.h b/Kernel/Forward.h index 6fbc35db183..81d990ed93d 100644 --- a/Kernel/Forward.h +++ b/Kernel/Forward.h @@ -17,6 +17,7 @@ class BlockDevice; class CharacterDevice; class Coredump; class Credentials; +class CustodyBase; class Custody; class Device; class DeviceControlDevice; diff --git a/Kernel/Syscalls/chdir.cpp b/Kernel/Syscalls/chdir.cpp index 47625d050c0..3cec0525802 100644 --- a/Kernel/Syscalls/chdir.cpp +++ b/Kernel/Syscalls/chdir.cpp @@ -16,10 +16,8 @@ ErrorOr Process::sys$chdir(Userspace user_path, size_t pat VERIFY_NO_PROCESS_BIG_LOCK(this); TRY(require_promise(Pledge::rpath)); auto path = TRY(get_syscall_path_argument(user_path, path_length)); - auto current_directory = m_current_directory.with([](auto& current_directory) -> NonnullRefPtr { - return *current_directory; - }); - RefPtr new_directory = TRY(VirtualFileSystem::the().open_directory(credentials(), path->view(), *current_directory)); + + RefPtr new_directory = TRY(VirtualFileSystem::the().open_directory(credentials(), path->view(), current_directory())); m_current_directory.with([&](auto& current_directory) { // NOTE: We use swap() here to avoid manipulating the ref counts while holding the lock. swap(current_directory, new_directory); diff --git a/Kernel/Syscalls/chmod.cpp b/Kernel/Syscalls/chmod.cpp index a6eeae4e3a1..2105aea6580 100644 --- a/Kernel/Syscalls/chmod.cpp +++ b/Kernel/Syscalls/chmod.cpp @@ -17,8 +17,8 @@ ErrorOr Process::sys$chmod(Userspace u TRY(require_promise(Pledge::fattr)); auto params = TRY(copy_typed_from_user(user_params)); auto path = TRY(get_syscall_path_argument(params.path)); - auto base = TRY(custody_for_dirfd(params.dirfd)); - TRY(VirtualFileSystem::the().chmod(credentials(), path->view(), params.mode, *base, params.follow_symlinks ? 0 : O_NOFOLLOW_NOERROR)); + CustodyBase base(params.dirfd, path->view()); + TRY(VirtualFileSystem::the().chmod(credentials(), path->view(), params.mode, base, params.follow_symlinks ? 0 : O_NOFOLLOW_NOERROR)); return 0; } diff --git a/Kernel/Syscalls/chown.cpp b/Kernel/Syscalls/chown.cpp index 7e8ea355f27..563390a0765 100644 --- a/Kernel/Syscalls/chown.cpp +++ b/Kernel/Syscalls/chown.cpp @@ -27,8 +27,8 @@ ErrorOr Process::sys$chown(Userspace u TRY(require_promise(Pledge::chown)); auto params = TRY(copy_typed_from_user(user_params)); auto path = TRY(get_syscall_path_argument(params.path)); - auto base = TRY(custody_for_dirfd(params.dirfd)); - TRY(VirtualFileSystem::the().chown(credentials(), path->view(), params.uid, params.gid, *base, params.follow_symlinks ? 0 : O_NOFOLLOW_NOERROR)); + CustodyBase base(params.dirfd, path->view()); + TRY(VirtualFileSystem::the().chown(credentials(), path->view(), params.uid, params.gid, base, params.follow_symlinks ? 0 : O_NOFOLLOW_NOERROR)); return 0; } diff --git a/Kernel/Syscalls/faccessat.cpp b/Kernel/Syscalls/faccessat.cpp index 32918ecde59..023e22b80d5 100644 --- a/Kernel/Syscalls/faccessat.cpp +++ b/Kernel/Syscalls/faccessat.cpp @@ -26,7 +26,8 @@ ErrorOr Process::sys$faccessat(Userspaceview(), params.mode, TRY(custody_for_dirfd(params.dirfd)), flags)); + CustodyBase base(params.dirfd, pathname->view()); + TRY(VirtualFileSystem::the().access(credentials(), pathname->view(), params.mode, base, flags)); return 0; } diff --git a/Kernel/Syscalls/link.cpp b/Kernel/Syscalls/link.cpp index a9abe884d00..1c206aa54e7 100644 --- a/Kernel/Syscalls/link.cpp +++ b/Kernel/Syscalls/link.cpp @@ -17,6 +17,7 @@ ErrorOr Process::sys$link(Userspace use auto params = TRY(copy_typed_from_user(user_params)); auto old_path = TRY(try_copy_kstring_from_user(params.old_path)); auto new_path = TRY(try_copy_kstring_from_user(params.new_path)); + TRY(VirtualFileSystem::the().link(credentials(), old_path->view(), new_path->view(), current_directory())); return 0; } @@ -29,7 +30,8 @@ ErrorOr Process::sys$symlink(Userspaceview(), linkpath->view(), TRY(custody_for_dirfd(params.dirfd)))); + CustodyBase base(params.dirfd, target->view()); + TRY(VirtualFileSystem::the().symlink(credentials(), target->view(), linkpath->view(), base)); return 0; } diff --git a/Kernel/Syscalls/mkdir.cpp b/Kernel/Syscalls/mkdir.cpp index 59067c148cc..aef932e5e41 100644 --- a/Kernel/Syscalls/mkdir.cpp +++ b/Kernel/Syscalls/mkdir.cpp @@ -15,7 +15,9 @@ ErrorOr Process::sys$mkdir(int dirfd, Userspace user_path, VERIFY_NO_PROCESS_BIG_LOCK(this); TRY(require_promise(Pledge::cpath)); auto path = TRY(get_syscall_path_argument(user_path, path_length)); - TRY(VirtualFileSystem::the().mkdir(credentials(), path->view(), mode & ~umask(), TRY(custody_for_dirfd(dirfd)))); + + CustodyBase base(dirfd, path->view()); + TRY(VirtualFileSystem::the().mkdir(credentials(), path->view(), mode & ~umask(), base)); return 0; } } diff --git a/Kernel/Syscalls/mknod.cpp b/Kernel/Syscalls/mknod.cpp index 1870c6cde89..353fbe6cc29 100644 --- a/Kernel/Syscalls/mknod.cpp +++ b/Kernel/Syscalls/mknod.cpp @@ -20,7 +20,9 @@ ErrorOr Process::sys$mknod(Userspace u if (!credentials->is_superuser() && !is_regular_file(params.mode) && !is_fifo(params.mode) && !is_socket(params.mode)) return EPERM; auto path = TRY(get_syscall_path_argument(params.path)); - TRY(VirtualFileSystem::the().mknod(credentials, path->view(), params.mode & ~umask(), params.dev, TRY(custody_for_dirfd(params.dirfd)))); + + CustodyBase base(params.dirfd, path->view()); + TRY(VirtualFileSystem::the().mknod(credentials, path->view(), params.mode & ~umask(), params.dev, base)); return 0; } diff --git a/Kernel/Syscalls/open.cpp b/Kernel/Syscalls/open.cpp index f67fd30423a..644808f93cd 100644 --- a/Kernel/Syscalls/open.cpp +++ b/Kernel/Syscalls/open.cpp @@ -55,8 +55,8 @@ ErrorOr Process::open_impl(Userspace us dbgln_if(IO_DEBUG, "sys$open(dirfd={}, path='{}', options={}, mode={})", dirfd, path->view(), options, mode); auto fd_allocation = TRY(allocate_fd()); - auto base = TRY(custody_for_dirfd(dirfd)); - auto description = TRY(VirtualFileSystem::the().open(credentials(), path->view(), options, mode & ~umask(), *base)); + CustodyBase base(dirfd, path->view()); + auto description = TRY(VirtualFileSystem::the().open(credentials(), path->view(), options, mode & ~umask(), base)); if (description->inode() && description->inode()->bound_socket()) return ENXIO; diff --git a/Kernel/Syscalls/rename.cpp b/Kernel/Syscalls/rename.cpp index 48745df2c30..e9426b80375 100644 --- a/Kernel/Syscalls/rename.cpp +++ b/Kernel/Syscalls/rename.cpp @@ -17,7 +17,9 @@ ErrorOr Process::sys$rename(Userspace auto params = TRY(copy_typed_from_user(user_params)); auto old_path = TRY(get_syscall_path_argument(params.old_path)); auto new_path = TRY(get_syscall_path_argument(params.new_path)); - TRY(VirtualFileSystem::the().rename(credentials(), TRY(custody_for_dirfd(params.olddirfd)), old_path->view(), TRY(custody_for_dirfd(params.newdirfd)), new_path->view())); + CustodyBase old_base(params.olddirfd, old_path->view()); + CustodyBase new_base(params.newdirfd, new_path->view()); + TRY(VirtualFileSystem::the().rename(credentials(), old_base, old_path->view(), new_base, new_path->view())); return 0; } diff --git a/Kernel/Syscalls/stat.cpp b/Kernel/Syscalls/stat.cpp index 409b440c76e..800e0899e34 100644 --- a/Kernel/Syscalls/stat.cpp +++ b/Kernel/Syscalls/stat.cpp @@ -28,8 +28,9 @@ ErrorOr Process::sys$stat(Userspace use auto params = TRY(copy_typed_from_user(user_params)); auto path = TRY(get_syscall_path_argument(params.path)); - auto base = TRY(custody_for_dirfd(params.dirfd)); - auto metadata = TRY(VirtualFileSystem::the().lookup_metadata(credentials(), path->view(), *base, params.follow_symlinks ? 0 : O_NOFOLLOW_NOERROR)); + + CustodyBase base(params.dirfd, path->view()); + auto metadata = TRY(VirtualFileSystem::the().lookup_metadata(credentials(), path->view(), base, params.follow_symlinks ? 0 : O_NOFOLLOW_NOERROR)); auto statbuf = TRY(metadata.stat()); TRY(copy_to_user(params.statbuf, &statbuf)); return 0; diff --git a/Kernel/Syscalls/unlink.cpp b/Kernel/Syscalls/unlink.cpp index 0dc0ed77114..00851918d9f 100644 --- a/Kernel/Syscalls/unlink.cpp +++ b/Kernel/Syscalls/unlink.cpp @@ -19,12 +19,12 @@ ErrorOr Process::sys$unlink(int dirfd, Userspace user_path if (flags & ~AT_REMOVEDIR) return Error::from_errno(EINVAL); - auto base = TRY(custody_for_dirfd(dirfd)); + CustodyBase base(dirfd, path->view()); if (flags & AT_REMOVEDIR) - TRY(VirtualFileSystem::the().rmdir(credentials(), path->view(), *base)); + TRY(VirtualFileSystem::the().rmdir(credentials(), path->view(), base)); else - TRY(VirtualFileSystem::the().unlink(credentials(), path->view(), *base)); + TRY(VirtualFileSystem::the().unlink(credentials(), path->view(), base)); return 0; } diff --git a/Kernel/Syscalls/utimensat.cpp b/Kernel/Syscalls/utimensat.cpp index 6128be1277f..d34bd3aca61 100644 --- a/Kernel/Syscalls/utimensat.cpp +++ b/Kernel/Syscalls/utimensat.cpp @@ -69,18 +69,12 @@ ErrorOr Process::sys$utimensat(Userspace ErrorOr> { - if (!path.is_empty() && path[0] == '/') - return VirtualFileSystem::the().root_custody(); - else - return custody_for_dirfd(params.dirfd); - }; - auto path = TRY(get_syscall_path_argument(params.path)); - auto base = TRY(resolve_base(path->view())); auto& atime = times[0]; auto& mtime = times[1]; - TRY(VirtualFileSystem::the().utimensat(credentials(), path->view(), *base, atime, mtime, follow_symlink)); + + CustodyBase base(params.dirfd, path->view()); + TRY(VirtualFileSystem::the().utimensat(credentials(), path->view(), base, atime, mtime, follow_symlink)); return 0; } diff --git a/Kernel/Tasks/Coredump.cpp b/Kernel/Tasks/Coredump.cpp index 46bfda95363..401f8064a6e 100644 --- a/Kernel/Tasks/Coredump.cpp +++ b/Kernel/Tasks/Coredump.cpp @@ -109,7 +109,7 @@ ErrorOr> Coredump::try_create_target_file(Pro KLexicalPath::basename(output_path), O_CREAT | O_WRONLY | O_EXCL, S_IFREG, // We will enable reading from userspace when we finish generating the coredump file - *dump_directory, + dump_directory, UidAndGid { process_credentials->uid(), process_credentials->gid() })); } diff --git a/Kernel/Tasks/Process.cpp b/Kernel/Tasks/Process.cpp index 3baf3bcc538..4e87124ca68 100644 --- a/Kernel/Tasks/Process.cpp +++ b/Kernel/Tasks/Process.cpp @@ -1195,6 +1195,11 @@ RefPtr Process::executable() const return m_executable.with([](auto& executable) { return executable; }); } +ErrorOr> Process::custody_for_dirfd(Badge, int dirfd) +{ + return custody_for_dirfd(dirfd); +} + ErrorOr> Process::custody_for_dirfd(int dirfd) { if (dirfd == AT_FDCWD) diff --git a/Kernel/Tasks/Process.h b/Kernel/Tasks/Process.h index f83b429b664..bdee0a7438d 100644 --- a/Kernel/Tasks/Process.h +++ b/Kernel/Tasks/Process.h @@ -919,6 +919,8 @@ public: return m_fds.with_exclusive([](auto& fds) { return fds.allocate(); }); } + ErrorOr> custody_for_dirfd(Badge, int dirfd); + private: ErrorOr> custody_for_dirfd(int dirfd);