Bläddra i källkod

Kernel: Make VirtualFileSystem functions take credentials as input

Instead of getting credentials from Process::current(), we now require
that they be provided as input to the various VFS functions.

This ensures that an atomic set of credentials is used throughout an
entire VFS operation.
Andreas Kling 2 år sedan
förälder
incheckning
c3351d4b9f

+ 5 - 3
Kernel/Coredump.cpp

@@ -62,19 +62,21 @@ Coredump::Coredump(NonnullLockRefPtr<Process> process, NonnullLockRefPtr<OpenFil
 ErrorOr<NonnullLockRefPtr<OpenFileDescription>> Coredump::try_create_target_file(Process const& process, StringView output_path)
 {
     auto output_directory = KLexicalPath::dirname(output_path);
-    auto dump_directory = TRY(VirtualFileSystem::the().open_directory(output_directory, VirtualFileSystem::the().root_custody()));
+    auto dump_directory = TRY(VirtualFileSystem::the().open_directory(Process::current().credentials(), output_directory, VirtualFileSystem::the().root_custody()));
     auto dump_directory_metadata = dump_directory->inode().metadata();
     if (dump_directory_metadata.uid != 0 || dump_directory_metadata.gid != 0 || dump_directory_metadata.mode != 040777) {
         dbgln("Refusing to put coredump in sketchy directory '{}'", output_directory);
         return EINVAL;
     }
-    auto credentials = process.credentials();
+
+    auto process_credentials = process.credentials();
     return TRY(VirtualFileSystem::the().open(
+        Process::current().credentials(),
         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,
-        UidAndGid { credentials->uid(), credentials->gid() }));
+        UidAndGid { process_credentials->uid(), process_credentials->gid() }));
 }
 
 ErrorOr<void> Coredump::write_elf_header()

+ 5 - 0
Kernel/Credentials.cpp

@@ -29,4 +29,9 @@ Credentials::Credentials(UserID uid, GroupID gid, UserID euid, GroupID egid, Use
 
 Credentials::~Credentials() = default;
 
+bool Credentials::in_group(Kernel::GroupID gid) const
+{
+    return m_gid == gid || m_extra_gids.contains_slow(gid);
+}
+
 }

+ 2 - 0
Kernel/Credentials.h

@@ -27,6 +27,8 @@ public:
     GroupID sgid() const { return m_sgid; }
     Span<GroupID const> extra_gids() const { return m_extra_gids.span(); }
 
+    bool in_group(GroupID) const;
+
 private:
     Credentials(UserID uid, GroupID gid, UserID euid, GroupID egid, UserID suid, GroupID sgid, FixedArray<GroupID> extra_gids);
 

+ 1 - 1
Kernel/FileSystem/Inode.cpp

@@ -82,7 +82,7 @@ ErrorOr<NonnullRefPtr<Custody>> Inode::resolve_as_link(Custody& base, RefPtr<Cus
     // contents as a path and resolves that. That is, it
     // behaves exactly how you would expect a symlink to work.
     auto contents = TRY(read_entire());
-    return VirtualFileSystem::the().resolve_path(StringView { contents->bytes() }, base, out_parent, options, symlink_recursion_level);
+    return VirtualFileSystem::the().resolve_path(Process::current().credentials(), StringView { contents->bytes() }, base, out_parent, options, symlink_recursion_level);
 }
 
 Inode::Inode(FileSystem& fs, InodeIndex index)

+ 2 - 2
Kernel/FileSystem/InodeFile.cpp

@@ -119,14 +119,14 @@ ErrorOr<void> InodeFile::chown(OpenFileDescription& description, UserID uid, Gro
 {
     VERIFY(description.inode() == m_inode);
     VERIFY(description.custody());
-    return VirtualFileSystem::the().chown(*description.custody(), uid, gid);
+    return VirtualFileSystem::the().chown(Process::current().credentials(), *description.custody(), uid, gid);
 }
 
 ErrorOr<void> InodeFile::chmod(OpenFileDescription& description, mode_t mode)
 {
     VERIFY(description.inode() == m_inode);
     VERIFY(description.custody());
-    return VirtualFileSystem::the().chmod(*description.custody(), mode);
+    return VirtualFileSystem::the().chmod(Process::current().credentials(), *description.custody(), mode);
 }
 
 }

+ 6 - 9
Kernel/FileSystem/InodeMetadata.cpp

@@ -9,22 +9,19 @@
 
 namespace Kernel {
 
-bool InodeMetadata::may_read(Process const& process) const
+bool InodeMetadata::may_read(Credentials const& credentials) const
 {
-    auto credentials = process.credentials();
-    return may_read(credentials->euid(), credentials->egid(), credentials->extra_gids());
+    return may_read(credentials.euid(), credentials.egid(), credentials.extra_gids());
 }
 
-bool InodeMetadata::may_write(Process const& process) const
+bool InodeMetadata::may_write(Credentials const& credentials) const
 {
-    auto credentials = process.credentials();
-    return may_write(credentials->euid(), credentials->egid(), credentials->extra_gids());
+    return may_write(credentials.euid(), credentials.egid(), credentials.extra_gids());
 }
 
-bool InodeMetadata::may_execute(Process const& process) const
+bool InodeMetadata::may_execute(Credentials const& credentials) const
 {
-    auto credentials = process.credentials();
-    return may_execute(credentials->euid(), credentials->egid(), credentials->extra_gids());
+    return may_execute(credentials.euid(), credentials.egid(), credentials.extra_gids());
 }
 
 }

+ 4 - 0
Kernel/FileSystem/InodeMetadata.h

@@ -42,6 +42,10 @@ struct InodeMetadata {
     bool may_write(Process const&) const;
     bool may_execute(Process const&) const;
 
+    bool may_read(Credentials const&) const;
+    bool may_write(Credentials const&) const;
+    bool may_execute(Credentials const&) const;
+
     bool may_read(UserID u, GroupID g, Span<GroupID const> eg) const
     {
         if (u == 0)

+ 81 - 99
Kernel/FileSystem/VirtualFileSystem.cpp

@@ -204,12 +204,11 @@ ErrorOr<void> VirtualFileSystem::traverse_directory_inode(Inode& dir_inode, Func
     });
 }
 
-ErrorOr<void> VirtualFileSystem::utime(StringView path, Custody& base, time_t atime, time_t mtime)
+ErrorOr<void> VirtualFileSystem::utime(Credentials const& credentials, StringView path, Custody& base, time_t atime, time_t mtime)
 {
-    auto custody = TRY(resolve_path(path, base));
+    auto custody = TRY(resolve_path(credentials, path, base));
     auto& inode = custody->inode();
-    auto& current_process = Process::current();
-    if (!current_process.is_superuser() && inode.metadata().uid != current_process.euid())
+    if (!credentials.is_superuser() && inode.metadata().uid != credentials.euid())
         return EACCES;
     if (custody->is_readonly())
         return EROFS;
@@ -219,12 +218,11 @@ ErrorOr<void> VirtualFileSystem::utime(StringView path, Custody& base, time_t at
     return {};
 }
 
-ErrorOr<void> VirtualFileSystem::utimensat(StringView path, Custody& base, timespec const& atime, timespec const& mtime, int options)
+ErrorOr<void> VirtualFileSystem::utimensat(Credentials const& credentials, StringView path, Custody& base, timespec const& atime, timespec const& mtime, int options)
 {
-    auto custody = TRY(resolve_path(path, base, nullptr, options));
+    auto custody = TRY(resolve_path(credentials, path, base, nullptr, options));
     auto& inode = custody->inode();
-    auto& current_process = Process::current();
-    if (!current_process.is_superuser() && inode.metadata().uid != current_process.euid())
+    if (!credentials.is_superuser() && inode.metadata().uid != credentials.euid())
         return EACCES;
     if (custody->is_readonly())
         return EROFS;
@@ -238,24 +236,24 @@ ErrorOr<void> VirtualFileSystem::utimensat(StringView path, Custody& base, times
     return {};
 }
 
-ErrorOr<InodeMetadata> VirtualFileSystem::lookup_metadata(StringView path, Custody& base, int options)
+ErrorOr<InodeMetadata> VirtualFileSystem::lookup_metadata(Credentials const& credentials, StringView path, Custody& base, int options)
 {
-    auto custody = TRY(resolve_path(path, base, nullptr, options));
+    auto custody = TRY(resolve_path(credentials, path, base, nullptr, options));
     return custody->inode().metadata();
 }
 
-ErrorOr<NonnullLockRefPtr<OpenFileDescription>> VirtualFileSystem::open(StringView path, int options, mode_t mode, Custody& base, Optional<UidAndGid> owner)
+ErrorOr<NonnullLockRefPtr<OpenFileDescription>> VirtualFileSystem::open(Credentials const& credentials, StringView path, int options, mode_t mode, Custody& base, Optional<UidAndGid> owner)
 {
     if ((options & O_CREAT) && (options & O_DIRECTORY))
         return EINVAL;
 
     RefPtr<Custody> parent_custody;
-    auto custody_or_error = resolve_path(path, base, &parent_custody, options);
+    auto custody_or_error = resolve_path(credentials, path, base, &parent_custody, options);
     if (custody_or_error.is_error()) {
         // NOTE: ENOENT with a non-null parent custody signals us that the immediate parent
         //       of the file exists, but the file itself does not.
         if ((options & O_CREAT) && custody_or_error.error().code() == ENOENT && parent_custody)
-            return create(path, options, mode, *parent_custody, move(owner));
+            return create(credentials, path, options, mode, *parent_custody, move(owner));
         return custody_or_error.release_error();
     }
 
@@ -271,19 +269,18 @@ ErrorOr<NonnullLockRefPtr<OpenFileDescription>> VirtualFileSystem::open(StringVi
 
     bool should_truncate_file = false;
 
-    auto& current_process = Process::current();
-    if ((options & O_RDONLY) && !metadata.may_read(current_process))
+    if ((options & O_RDONLY) && !metadata.may_read(credentials))
         return EACCES;
 
     if (options & O_WRONLY) {
-        if (!metadata.may_write(current_process))
+        if (!metadata.may_write(credentials))
             return EACCES;
         if (metadata.is_directory())
             return EISDIR;
         should_truncate_file = options & O_TRUNC;
     }
     if (options & O_EXEC) {
-        if (!metadata.may_execute(current_process) || (custody.mount_flags() & MS_NOEXEC))
+        if (!metadata.may_execute(credentials) || (custody.mount_flags() & MS_NOEXEC))
             return EACCES;
     }
 
@@ -332,13 +329,13 @@ ErrorOr<NonnullLockRefPtr<OpenFileDescription>> VirtualFileSystem::open(StringVi
     return description;
 }
 
-ErrorOr<void> VirtualFileSystem::mknod(StringView path, mode_t mode, dev_t dev, Custody& base)
+ErrorOr<void> VirtualFileSystem::mknod(Credentials const& credentials, StringView path, mode_t mode, dev_t dev, Custody& base)
 {
     if (!is_regular_file(mode) && !is_block_device(mode) && !is_character_device(mode) && !is_fifo(mode) && !is_socket(mode))
         return EINVAL;
 
     RefPtr<Custody> parent_custody;
-    auto existing_file_or_error = resolve_path(path, base, &parent_custody);
+    auto existing_file_or_error = resolve_path(credentials, path, base, &parent_custody);
     if (!existing_file_or_error.is_error())
         return EEXIST;
     if (!parent_custody)
@@ -346,20 +343,18 @@ ErrorOr<void> VirtualFileSystem::mknod(StringView path, mode_t mode, dev_t dev,
     if (existing_file_or_error.error().code() != ENOENT)
         return existing_file_or_error.release_error();
     auto& parent_inode = parent_custody->inode();
-    auto& current_process = Process::current();
-    auto current_process_credentials = current_process.credentials();
-    if (!parent_inode.metadata().may_write(current_process))
+    if (!parent_inode.metadata().may_write(credentials))
         return EACCES;
     if (parent_custody->is_readonly())
         return EROFS;
 
     auto basename = KLexicalPath::basename(path);
     dbgln_if(VFS_DEBUG, "VirtualFileSystem::mknod: '{}' mode={} dev={} in {}", basename, mode, dev, parent_inode.identifier());
-    (void)TRY(parent_inode.create_child(basename, mode, dev, current_process_credentials->euid(), current_process_credentials->egid()));
+    (void)TRY(parent_inode.create_child(basename, mode, dev, credentials.euid(), credentials.egid()));
     return {};
 }
 
-ErrorOr<NonnullLockRefPtr<OpenFileDescription>> VirtualFileSystem::create(StringView path, int options, mode_t mode, Custody& parent_custody, Optional<UidAndGid> owner)
+ErrorOr<NonnullLockRefPtr<OpenFileDescription>> VirtualFileSystem::create(Credentials const& credentials, StringView path, int options, mode_t mode, Custody& parent_custody, Optional<UidAndGid> owner)
 {
     auto basename = KLexicalPath::basename(path);
     auto parent_path = TRY(parent_custody.try_serialize_absolute_path());
@@ -372,16 +367,14 @@ ErrorOr<NonnullLockRefPtr<OpenFileDescription>> VirtualFileSystem::create(String
     }
 
     auto& parent_inode = parent_custody.inode();
-    auto& current_process = Process::current();
-    auto current_process_credentials = current_process.credentials();
-    if (!parent_inode.metadata().may_write(current_process))
+    if (!parent_inode.metadata().may_write(credentials))
         return EACCES;
     if (parent_custody.is_readonly())
         return EROFS;
 
     dbgln_if(VFS_DEBUG, "VirtualFileSystem::create: '{}' in {}", basename, parent_inode.identifier());
-    auto uid = owner.has_value() ? owner.value().uid : current_process_credentials->euid();
-    auto gid = owner.has_value() ? owner.value().gid : current_process_credentials->egid();
+    auto uid = owner.has_value() ? owner.value().uid : credentials.euid();
+    auto gid = owner.has_value() ? owner.value().gid : credentials.egid();
 
     auto inode = TRY(parent_inode.create_child(basename, mode, 0, uid, gid));
     auto custody = TRY(Custody::try_create(&parent_custody, basename, inode, parent_custody.mount_flags()));
@@ -392,7 +385,7 @@ ErrorOr<NonnullLockRefPtr<OpenFileDescription>> VirtualFileSystem::create(String
     return description;
 }
 
-ErrorOr<void> VirtualFileSystem::mkdir(StringView path, mode_t mode, Custody& base)
+ErrorOr<void> VirtualFileSystem::mkdir(Credentials const& credentials, StringView path, mode_t mode, Custody& base)
 {
     // Unlike in basically every other case, where it's only the last
     // path component (the one being created) that is allowed not to
@@ -407,7 +400,7 @@ ErrorOr<void> VirtualFileSystem::mkdir(StringView path, mode_t mode, Custody& ba
     RefPtr<Custody> 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(path, base, &parent_custody);
+    auto result = resolve_path_without_veil(credentials, path, base, &parent_custody);
     if (!result.is_error())
         return EEXIST;
     else if (!parent_custody)
@@ -417,60 +410,56 @@ ErrorOr<void> VirtualFileSystem::mkdir(StringView path, mode_t mode, Custody& ba
 
     TRY(validate_path_against_process_veil(*parent_custody, O_CREAT));
     auto& parent_inode = parent_custody->inode();
-    auto& current_process = Process::current();
-    auto current_process_credentials = current_process.credentials();
-    if (!parent_inode.metadata().may_write(current_process))
+    if (!parent_inode.metadata().may_write(credentials))
         return EACCES;
     if (parent_custody->is_readonly())
         return EROFS;
 
     auto basename = KLexicalPath::basename(path);
     dbgln_if(VFS_DEBUG, "VirtualFileSystem::mkdir: '{}' in {}", basename, parent_inode.identifier());
-    (void)TRY(parent_inode.create_child(basename, S_IFDIR | mode, 0, current_process_credentials->euid(), current_process_credentials->egid()));
+    (void)TRY(parent_inode.create_child(basename, S_IFDIR | mode, 0, credentials.euid(), credentials.egid()));
     return {};
 }
 
-ErrorOr<void> VirtualFileSystem::access(StringView path, int mode, Custody& base)
+ErrorOr<void> VirtualFileSystem::access(Credentials const& credentials, StringView path, int mode, Custody& base)
 {
-    auto custody = TRY(resolve_path(path, base));
+    auto custody = TRY(resolve_path(credentials, path, base));
 
     auto& inode = custody->inode();
     auto metadata = inode.metadata();
-    auto& current_process = Process::current();
     if (mode & R_OK) {
-        if (!metadata.may_read(current_process))
+        if (!metadata.may_read(credentials))
             return EACCES;
     }
     if (mode & W_OK) {
-        if (!metadata.may_write(current_process))
+        if (!metadata.may_write(credentials))
             return EACCES;
         if (custody->is_readonly())
             return EROFS;
     }
     if (mode & X_OK) {
-        if (!metadata.may_execute(current_process))
+        if (!metadata.may_execute(credentials))
             return EACCES;
     }
     return {};
 }
 
-ErrorOr<NonnullRefPtr<Custody>> VirtualFileSystem::open_directory(StringView path, Custody& base)
+ErrorOr<NonnullRefPtr<Custody>> VirtualFileSystem::open_directory(Credentials const& credentials, StringView path, Custody& base)
 {
-    auto custody = TRY(resolve_path(path, base));
+    auto custody = TRY(resolve_path(credentials, path, base));
     auto& inode = custody->inode();
     if (!inode.is_directory())
         return ENOTDIR;
-    if (!inode.metadata().may_execute(Process::current()))
+    if (!inode.metadata().may_execute(credentials))
         return EACCES;
     return custody;
 }
 
-ErrorOr<void> VirtualFileSystem::chmod(Custody& custody, mode_t mode)
+ErrorOr<void> VirtualFileSystem::chmod(Credentials const& credentials, Custody& custody, mode_t mode)
 {
     auto& inode = custody.inode();
 
-    auto& current_process = Process::current();
-    if (current_process.euid() != inode.metadata().uid && !current_process.is_superuser())
+    if (credentials.euid() != inode.metadata().uid && !credentials.is_superuser())
         return EPERM;
     if (custody.is_readonly())
         return EROFS;
@@ -480,20 +469,20 @@ ErrorOr<void> VirtualFileSystem::chmod(Custody& custody, mode_t mode)
     return inode.chmod(mode);
 }
 
-ErrorOr<void> VirtualFileSystem::chmod(StringView path, mode_t mode, Custody& base, int options)
+ErrorOr<void> VirtualFileSystem::chmod(Credentials const& credentials, StringView path, mode_t mode, Custody& base, int options)
 {
-    auto custody = TRY(resolve_path(path, base, nullptr, options));
-    return chmod(custody, mode);
+    auto custody = TRY(resolve_path(credentials, path, base, nullptr, options));
+    return chmod(credentials, custody, mode);
 }
 
-ErrorOr<void> VirtualFileSystem::rename(StringView old_path, StringView new_path, Custody& base)
+ErrorOr<void> VirtualFileSystem::rename(Credentials const& credentials, StringView old_path, StringView new_path, Custody& base)
 {
     RefPtr<Custody> old_parent_custody;
-    auto old_custody = TRY(resolve_path(old_path, base, &old_parent_custody, O_NOFOLLOW_NOERROR));
+    auto old_custody = TRY(resolve_path(credentials, old_path, base, &old_parent_custody, O_NOFOLLOW_NOERROR));
     auto& old_inode = old_custody->inode();
 
     RefPtr<Custody> new_parent_custody;
-    auto new_custody_or_error = resolve_path(new_path, base, &new_parent_custody);
+    auto new_custody_or_error = resolve_path(credentials, new_path, base, &new_parent_custody);
     if (new_custody_or_error.is_error()) {
         if (new_custody_or_error.error().code() != ENOENT || !new_parent_custody)
             return new_custody_or_error.release_error();
@@ -528,15 +517,14 @@ ErrorOr<void> VirtualFileSystem::rename(StringView old_path, StringView new_path
             return EDIRINTOSELF;
     }
 
-    auto& current_process = Process::current();
-    if (!new_parent_inode.metadata().may_write(current_process))
+    if (!new_parent_inode.metadata().may_write(credentials))
         return EACCES;
 
-    if (!old_parent_inode.metadata().may_write(current_process))
+    if (!old_parent_inode.metadata().may_write(credentials))
         return EACCES;
 
     if (old_parent_inode.metadata().is_sticky()) {
-        if (!current_process.is_superuser() && old_inode.metadata().uid != current_process.euid())
+        if (!credentials.is_superuser() && old_inode.metadata().uid != credentials.euid())
             return EACCES;
     }
 
@@ -561,7 +549,7 @@ ErrorOr<void> VirtualFileSystem::rename(StringView old_path, StringView new_path
         if (&new_inode == &old_inode)
             return {};
         if (new_parent_inode.metadata().is_sticky()) {
-            if (!current_process.is_superuser() && new_inode.metadata().uid != current_process.euid())
+            if (!credentials.is_superuser() && new_inode.metadata().uid != credentials.euid())
                 return EACCES;
         }
         if (new_inode.is_directory() && !old_inode.is_directory())
@@ -574,25 +562,24 @@ ErrorOr<void> VirtualFileSystem::rename(StringView old_path, StringView new_path
     return {};
 }
 
-ErrorOr<void> VirtualFileSystem::chown(Custody& custody, UserID a_uid, GroupID a_gid)
+ErrorOr<void> VirtualFileSystem::chown(Credentials const& credentials, Custody& custody, UserID a_uid, GroupID a_gid)
 {
     auto& inode = custody.inode();
     auto metadata = inode.metadata();
 
-    auto& current_process = Process::current();
-    if (current_process.euid() != metadata.uid && !current_process.is_superuser())
+    if (credentials.euid() != metadata.uid && !credentials.is_superuser())
         return EPERM;
 
     UserID new_uid = metadata.uid;
     GroupID new_gid = metadata.gid;
 
     if (a_uid != (uid_t)-1) {
-        if (current_process.euid() != a_uid && !current_process.is_superuser())
+        if (credentials.euid() != a_uid && !credentials.is_superuser())
             return EPERM;
         new_uid = a_uid;
     }
     if (a_gid != (gid_t)-1) {
-        if (!current_process.in_group(a_gid) && !current_process.is_superuser())
+        if (!credentials.in_group(a_gid) && !credentials.is_superuser())
             return EPERM;
         new_gid = a_gid;
     }
@@ -610,36 +597,36 @@ ErrorOr<void> VirtualFileSystem::chown(Custody& custody, UserID a_uid, GroupID a
     return inode.chown(new_uid, new_gid);
 }
 
-ErrorOr<void> VirtualFileSystem::chown(StringView path, UserID a_uid, GroupID a_gid, Custody& base, int options)
+ErrorOr<void> VirtualFileSystem::chown(Credentials const& credentials, StringView path, UserID a_uid, GroupID a_gid, Custody& base, int options)
 {
-    auto custody = TRY(resolve_path(path, base, nullptr, options));
-    return chown(custody, a_uid, a_gid);
+    auto custody = TRY(resolve_path(credentials, path, base, nullptr, options));
+    return chown(credentials, custody, a_uid, a_gid);
 }
 
-static bool hard_link_allowed(Inode const& inode)
+static bool hard_link_allowed(Credentials const& credentials, Inode const& inode)
 {
     auto metadata = inode.metadata();
 
-    if (Process::current().euid() == metadata.uid)
+    if (credentials.euid() == metadata.uid)
         return true;
 
     if (metadata.is_regular_file()
         && !metadata.is_setuid()
         && !(metadata.is_setgid() && metadata.mode & S_IXGRP)
-        && metadata.may_write(Process::current())) {
+        && metadata.may_write(credentials)) {
         return true;
     }
 
     return false;
 }
 
-ErrorOr<void> VirtualFileSystem::link(StringView old_path, StringView new_path, Custody& base)
+ErrorOr<void> VirtualFileSystem::link(Credentials const& credentials, StringView old_path, StringView new_path, Custody& base)
 {
-    auto old_custody = TRY(resolve_path(old_path, base));
+    auto old_custody = TRY(resolve_path(credentials, old_path, base));
     auto& old_inode = old_custody->inode();
 
     RefPtr<Custody> parent_custody;
-    auto new_custody_or_error = resolve_path(new_path, base, &parent_custody);
+    auto new_custody_or_error = resolve_path(credentials, new_path, base, &parent_custody);
     if (!new_custody_or_error.is_error())
         return EEXIST;
 
@@ -651,7 +638,7 @@ ErrorOr<void> VirtualFileSystem::link(StringView old_path, StringView new_path,
     if (parent_inode.fsid() != old_inode.fsid())
         return EXDEV;
 
-    if (!parent_inode.metadata().may_write(Process::current()))
+    if (!parent_inode.metadata().may_write(credentials))
         return EACCES;
 
     if (old_inode.is_directory())
@@ -660,16 +647,16 @@ ErrorOr<void> VirtualFileSystem::link(StringView old_path, StringView new_path,
     if (parent_custody->is_readonly())
         return EROFS;
 
-    if (!hard_link_allowed(old_inode))
+    if (!hard_link_allowed(credentials, old_inode))
         return EPERM;
 
     return parent_inode.add_child(old_inode, KLexicalPath::basename(new_path), old_inode.mode());
 }
 
-ErrorOr<void> VirtualFileSystem::unlink(StringView path, Custody& base)
+ErrorOr<void> VirtualFileSystem::unlink(Credentials const& credentials, StringView path, Custody& base)
 {
     RefPtr<Custody> parent_custody;
-    auto custody = TRY(resolve_path(path, base, &parent_custody, O_NOFOLLOW_NOERROR | O_UNLINK_INTERNAL));
+    auto custody = TRY(resolve_path(credentials, path, base, &parent_custody, O_NOFOLLOW_NOERROR | O_UNLINK_INTERNAL));
     auto& inode = custody->inode();
 
     if (inode.is_directory())
@@ -681,12 +668,11 @@ ErrorOr<void> VirtualFileSystem::unlink(StringView path, Custody& base)
     VERIFY(parent_custody);
 
     auto& parent_inode = parent_custody->inode();
-    auto& current_process = Process::current();
-    if (!parent_inode.metadata().may_write(current_process))
+    if (!parent_inode.metadata().may_write(credentials))
         return EACCES;
 
     if (parent_inode.metadata().is_sticky()) {
-        if (!current_process.is_superuser() && inode.metadata().uid != current_process.euid())
+        if (!credentials.is_superuser() && inode.metadata().uid != credentials.euid())
             return EACCES;
     }
 
@@ -696,10 +682,10 @@ ErrorOr<void> VirtualFileSystem::unlink(StringView path, Custody& base)
     return parent_inode.remove_child(KLexicalPath::basename(path));
 }
 
-ErrorOr<void> VirtualFileSystem::symlink(StringView target, StringView linkpath, Custody& base)
+ErrorOr<void> VirtualFileSystem::symlink(Credentials const& credentials, StringView target, StringView linkpath, Custody& base)
 {
     RefPtr<Custody> parent_custody;
-    auto existing_custody_or_error = resolve_path(linkpath, base, &parent_custody);
+    auto existing_custody_or_error = resolve_path(credentials, linkpath, base, &parent_custody);
     if (!existing_custody_or_error.is_error())
         return EEXIST;
     if (!parent_custody)
@@ -707,9 +693,7 @@ ErrorOr<void> VirtualFileSystem::symlink(StringView target, StringView linkpath,
     if (existing_custody_or_error.is_error() && existing_custody_or_error.error().code() != ENOENT)
         return existing_custody_or_error.release_error();
     auto& parent_inode = parent_custody->inode();
-    auto& current_process = Process::current();
-    auto current_process_credentials = current_process.credentials();
-    if (!parent_inode.metadata().may_write(current_process))
+    if (!parent_inode.metadata().may_write(credentials))
         return EACCES;
     if (parent_custody->is_readonly())
         return EROFS;
@@ -717,7 +701,7 @@ ErrorOr<void> VirtualFileSystem::symlink(StringView target, StringView linkpath,
     auto basename = KLexicalPath::basename(linkpath);
     dbgln_if(VFS_DEBUG, "VirtualFileSystem::symlink: '{}' (-> '{}') in {}", basename, target, parent_inode.identifier());
 
-    auto inode = TRY(parent_inode.create_child(basename, S_IFLNK | 0644, 0, current_process_credentials->euid(), current_process_credentials->egid()));
+    auto inode = TRY(parent_inode.create_child(basename, S_IFLNK | 0644, 0, credentials.euid(), credentials.egid()));
 
     auto target_buffer = UserOrKernelBuffer::for_kernel_buffer(const_cast<u8*>((u8 const*)target.characters_without_null_termination()));
     MutexLocker locker(inode->m_inode_lock);
@@ -726,10 +710,10 @@ ErrorOr<void> VirtualFileSystem::symlink(StringView target, StringView linkpath,
     return {};
 }
 
-ErrorOr<void> VirtualFileSystem::rmdir(StringView path, Custody& base)
+ErrorOr<void> VirtualFileSystem::rmdir(Credentials const& credentials, StringView path, Custody& base)
 {
     RefPtr<Custody> parent_custody;
-    auto custody = TRY(resolve_path(path, base, &parent_custody));
+    auto custody = TRY(resolve_path(credentials, path, base, &parent_custody));
     auto& inode = custody->inode();
 
     // FIXME: We should return EINVAL if the last component of the path is "."
@@ -744,12 +728,11 @@ ErrorOr<void> VirtualFileSystem::rmdir(StringView path, Custody& base)
     auto& parent_inode = parent_custody->inode();
     auto parent_metadata = parent_inode.metadata();
 
-    auto& current_process = Process::current();
-    if (!parent_metadata.may_write(current_process))
+    if (!parent_metadata.may_write(credentials))
         return EACCES;
 
     if (parent_metadata.is_sticky()) {
-        if (!current_process.is_superuser() && inode.metadata().uid != current_process.euid())
+        if (!credentials.is_superuser() && inode.metadata().uid != credentials.euid())
             return EACCES;
     }
 
@@ -880,11 +863,11 @@ ErrorOr<void> VirtualFileSystem::validate_path_against_process_veil(StringView p
     return {};
 }
 
-ErrorOr<NonnullRefPtr<Custody>> VirtualFileSystem::resolve_path(StringView path, NonnullRefPtr<Custody> base, RefPtr<Custody>* out_parent, int options, int symlink_recursion_level)
+ErrorOr<NonnullRefPtr<Custody>> VirtualFileSystem::resolve_path(Credentials const& credentials, StringView path, NonnullRefPtr<Custody> base, RefPtr<Custody>* out_parent, int options, int symlink_recursion_level)
 {
     // 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(path, base, out_parent, options, symlink_recursion_level));
+    auto custody = TRY(resolve_path_without_veil(credentials, path, base, out_parent, options, symlink_recursion_level));
     if (auto result = validate_path_against_process_veil(*custody, options); result.is_error()) {
         if (out_parent)
             out_parent->clear();
@@ -893,10 +876,10 @@ ErrorOr<NonnullRefPtr<Custody>> VirtualFileSystem::resolve_path(StringView path,
     return custody;
 }
 
-static bool safe_to_follow_symlink(Inode const& inode, InodeMetadata const& parent_metadata)
+static bool safe_to_follow_symlink(Credentials const& credentials, Inode const& inode, InodeMetadata const& parent_metadata)
 {
     auto metadata = inode.metadata();
-    if (Process::current().euid() == metadata.uid)
+    if (credentials.euid() == metadata.uid)
         return true;
 
     if (!(parent_metadata.is_sticky() && parent_metadata.mode & S_IWOTH))
@@ -908,7 +891,7 @@ static bool safe_to_follow_symlink(Inode const& inode, InodeMetadata const& pare
     return false;
 }
 
-ErrorOr<NonnullRefPtr<Custody>> VirtualFileSystem::resolve_path_without_veil(StringView path, NonnullRefPtr<Custody> base, RefPtr<Custody>* out_parent, int options, int symlink_recursion_level)
+ErrorOr<NonnullRefPtr<Custody>> VirtualFileSystem::resolve_path_without_veil(Credentials const& credentials, StringView path, NonnullRefPtr<Custody> base, RefPtr<Custody>* out_parent, int options, int symlink_recursion_level)
 {
     if (symlink_recursion_level >= symlink_recursion_limit)
         return ELOOP;
@@ -917,7 +900,6 @@ ErrorOr<NonnullRefPtr<Custody>> VirtualFileSystem::resolve_path_without_veil(Str
         return EINVAL;
 
     GenericLexer path_lexer(path);
-    auto& current_process = Process::current();
 
     NonnullRefPtr<Custody> custody = path[0] == '/' ? root_custody() : base;
     bool extra_iteration = path[path.length() - 1] == '/';
@@ -933,7 +915,7 @@ ErrorOr<NonnullRefPtr<Custody>> VirtualFileSystem::resolve_path_without_veil(Str
         if (!parent_metadata.is_directory())
             return ENOTDIR;
         // Ensure the current user is allowed to resolve paths inside this directory.
-        if (!parent_metadata.may_execute(current_process))
+        if (!parent_metadata.may_execute(credentials))
             return EACCES;
 
         bool have_more_parts = !path_lexer.is_eof() || extra_iteration;
@@ -979,7 +961,7 @@ ErrorOr<NonnullRefPtr<Custody>> VirtualFileSystem::resolve_path_without_veil(Str
                     break;
             }
 
-            if (!safe_to_follow_symlink(*child_inode, parent_metadata))
+            if (!safe_to_follow_symlink(credentials, *child_inode, parent_metadata))
                 return EACCES;
 
             TRY(validate_path_against_process_veil(*custody, options));
@@ -995,7 +977,7 @@ ErrorOr<NonnullRefPtr<Custody>> VirtualFileSystem::resolve_path_without_veil(Str
             TRY(remaining_path.try_append('.'));
             TRY(remaining_path.try_append(path.substring_view_starting_after_substring(part)));
 
-            return resolve_path_without_veil(remaining_path.string_view(), symlink_target, out_parent, options, symlink_recursion_level + 1);
+            return resolve_path_without_veil(credentials, remaining_path.string_view(), symlink_target, out_parent, options, symlink_recursion_level + 1);
         }
     }
 

+ 20 - 20
Kernel/FileSystem/VirtualFileSystem.h

@@ -50,24 +50,24 @@ public:
     ErrorOr<void> remount(Custody& mount_point, int new_flags);
     ErrorOr<void> unmount(Inode& guest_inode);
 
-    ErrorOr<NonnullLockRefPtr<OpenFileDescription>> open(StringView path, int options, mode_t mode, Custody& base, Optional<UidAndGid> = {});
-    ErrorOr<NonnullLockRefPtr<OpenFileDescription>> create(StringView path, int options, mode_t mode, Custody& parent_custody, Optional<UidAndGid> = {});
-    ErrorOr<void> mkdir(StringView path, mode_t mode, Custody& base);
-    ErrorOr<void> link(StringView old_path, StringView new_path, Custody& base);
-    ErrorOr<void> unlink(StringView path, Custody& base);
-    ErrorOr<void> symlink(StringView target, StringView linkpath, Custody& base);
-    ErrorOr<void> rmdir(StringView path, Custody& base);
-    ErrorOr<void> chmod(StringView path, mode_t, Custody& base, int options = 0);
-    ErrorOr<void> chmod(Custody&, mode_t);
-    ErrorOr<void> chown(StringView path, UserID, GroupID, Custody& base, int options);
-    ErrorOr<void> chown(Custody&, UserID, GroupID);
-    ErrorOr<void> access(StringView path, int mode, Custody& base);
-    ErrorOr<InodeMetadata> lookup_metadata(StringView path, Custody& base, int options = 0);
-    ErrorOr<void> utime(StringView path, Custody& base, time_t atime, time_t mtime);
-    ErrorOr<void> utimensat(StringView path, Custody& base, timespec const& atime, timespec const& mtime, int options = 0);
-    ErrorOr<void> rename(StringView oldpath, StringView newpath, Custody& base);
-    ErrorOr<void> mknod(StringView path, mode_t, dev_t, Custody& base);
-    ErrorOr<NonnullRefPtr<Custody>> open_directory(StringView path, Custody& base);
+    ErrorOr<NonnullLockRefPtr<OpenFileDescription>> open(Credentials const&, StringView path, int options, mode_t mode, Custody& base, Optional<UidAndGid> = {});
+    ErrorOr<NonnullLockRefPtr<OpenFileDescription>> create(Credentials const&, StringView path, int options, mode_t mode, Custody& parent_custody, Optional<UidAndGid> = {});
+    ErrorOr<void> mkdir(Credentials const&, StringView path, mode_t mode, Custody& base);
+    ErrorOr<void> link(Credentials const&, StringView old_path, StringView new_path, Custody& base);
+    ErrorOr<void> unlink(Credentials const&, StringView path, Custody& base);
+    ErrorOr<void> symlink(Credentials const&, StringView target, StringView linkpath, Custody& base);
+    ErrorOr<void> rmdir(Credentials const&, StringView path, Custody& base);
+    ErrorOr<void> chmod(Credentials const&, StringView path, mode_t, Custody& base, int options = 0);
+    ErrorOr<void> chmod(Credentials const&, Custody&, mode_t);
+    ErrorOr<void> chown(Credentials const&, StringView path, UserID, GroupID, Custody& base, int options);
+    ErrorOr<void> chown(Credentials const&, Custody&, UserID, GroupID);
+    ErrorOr<void> access(Credentials const&, StringView path, int mode, Custody& base);
+    ErrorOr<InodeMetadata> lookup_metadata(Credentials const&, StringView path, Custody& base, int options = 0);
+    ErrorOr<void> utime(Credentials const&, StringView path, Custody& base, time_t atime, time_t mtime);
+    ErrorOr<void> utimensat(Credentials const&, StringView path, Custody& base, timespec const& atime, timespec const& mtime, int options = 0);
+    ErrorOr<void> rename(Credentials const&, StringView oldpath, StringView newpath, Custody& base);
+    ErrorOr<void> mknod(Credentials const&, StringView path, mode_t, dev_t, Custody& base);
+    ErrorOr<NonnullRefPtr<Custody>> open_directory(Credentials const&, StringView path, Custody& base);
 
     ErrorOr<void> for_each_mount(Function<ErrorOr<void>(Mount const&)>) const;
 
@@ -76,8 +76,8 @@ public:
     static void sync();
 
     NonnullRefPtr<Custody> root_custody();
-    ErrorOr<NonnullRefPtr<Custody>> resolve_path(StringView path, NonnullRefPtr<Custody> base, RefPtr<Custody>* out_parent = nullptr, int options = 0, int symlink_recursion_level = 0);
-    ErrorOr<NonnullRefPtr<Custody>> resolve_path_without_veil(StringView path, NonnullRefPtr<Custody> base, RefPtr<Custody>* out_parent = nullptr, int options = 0, int symlink_recursion_level = 0);
+    ErrorOr<NonnullRefPtr<Custody>> resolve_path(Credentials const&, StringView path, NonnullRefPtr<Custody> base, RefPtr<Custody>* out_parent = nullptr, int options = 0, int symlink_recursion_level = 0);
+    ErrorOr<NonnullRefPtr<Custody>> resolve_path_without_veil(Credentials const&, StringView path, NonnullRefPtr<Custody> base, RefPtr<Custody>* out_parent = nullptr, int options = 0, int symlink_recursion_level = 0);
 
 private:
     friend class OpenFileDescription;

+ 2 - 2
Kernel/Net/LocalSocket.cpp

@@ -139,7 +139,7 @@ ErrorOr<void> LocalSocket::bind(Userspace<sockaddr const*> user_address, socklen
 
     mode_t mode = S_IFSOCK | (m_prebind_mode & 0777);
     UidAndGid owner { m_prebind_uid, m_prebind_gid };
-    auto result = VirtualFileSystem::the().open(path->view(), O_CREAT | O_EXCL | O_NOFOLLOW_NOERROR, mode, Process::current().current_directory(), owner);
+    auto result = VirtualFileSystem::the().open(Process::current().credentials(), path->view(), O_CREAT | O_EXCL | O_NOFOLLOW_NOERROR, mode, Process::current().current_directory(), owner);
     if (result.is_error()) {
         if (result.error().code() == EEXIST)
             return set_so_error(EADDRINUSE);
@@ -179,7 +179,7 @@ ErrorOr<void> LocalSocket::connect(OpenFileDescription& description, Userspace<s
     auto path = SOCKET_TRY(KString::try_create(StringView { address.sun_path, strnlen(address.sun_path, sizeof(address.sun_path)) }));
     dbgln_if(LOCAL_SOCKET_DEBUG, "LocalSocket({}) connect({})", this, *path);
 
-    auto file = SOCKET_TRY(VirtualFileSystem::the().open(path->view(), O_RDWR, 0, Process::current().current_directory()));
+    auto file = SOCKET_TRY(VirtualFileSystem::the().open(Process::current().credentials(), path->view(), O_RDWR, 0, Process::current().current_directory()));
     auto inode = file->inode();
     m_inode = inode;
 

+ 2 - 1
Kernel/Process.cpp

@@ -583,8 +583,9 @@ ErrorOr<void> Process::dump_perfcore()
     auto base_filename = TRY(KString::formatted("{}_{}", name(), pid().value()));
     auto perfcore_filename = TRY(KString::formatted("{}.profile", base_filename));
     LockRefPtr<OpenFileDescription> description;
+    auto credentials = this->credentials();
     for (size_t attempt = 1; attempt <= 10; ++attempt) {
-        auto description_or_error = VirtualFileSystem::the().open(perfcore_filename->view(), O_CREAT | O_EXCL, 0400, current_directory(), UidAndGid { 0, 0 });
+        auto description_or_error = VirtualFileSystem::the().open(credentials, perfcore_filename->view(), O_CREAT | O_EXCL, 0400, current_directory(), UidAndGid { 0, 0 });
         if (!description_or_error.is_error()) {
             description = description_or_error.release_value();
             break;

+ 1 - 1
Kernel/Syscalls/access.cpp

@@ -15,7 +15,7 @@ ErrorOr<FlatPtr> Process::sys$access(Userspace<char const*> user_path, size_t pa
     VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this);
     TRY(require_promise(Pledge::rpath));
     auto path = TRY(get_syscall_path_argument(user_path, path_length));
-    TRY(VirtualFileSystem::the().access(path->view(), mode, current_directory()));
+    TRY(VirtualFileSystem::the().access(credentials(), path->view(), mode, current_directory()));
     return 0;
 }
 

+ 2 - 2
Kernel/Syscalls/chdir.cpp

@@ -19,7 +19,7 @@ ErrorOr<FlatPtr> Process::sys$chdir(Userspace<char const*> user_path, size_t pat
     auto current_directory = m_current_directory.with([](auto& current_directory) -> NonnullRefPtr<Custody> {
         return *current_directory;
     });
-    RefPtr<Custody> new_directory = TRY(VirtualFileSystem::the().open_directory(path->view(), *current_directory));
+    RefPtr<Custody> 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);
@@ -34,7 +34,7 @@ ErrorOr<FlatPtr> Process::sys$fchdir(int fd)
     auto description = TRY(open_file_description(fd));
     if (!description->is_directory())
         return ENOTDIR;
-    if (!description->metadata().may_execute(*this))
+    if (!description->metadata().may_execute(credentials()))
         return EACCES;
     m_current_directory.with([&](auto& current_directory) {
         current_directory = description->custody();

+ 1 - 1
Kernel/Syscalls/chmod.cpp

@@ -28,7 +28,7 @@ ErrorOr<FlatPtr> Process::sys$chmod(Userspace<Syscall::SC_chmod_params const*> u
         base = base_description->custody();
     }
 
-    TRY(VirtualFileSystem::the().chmod(path->view(), params.mode, *base, params.follow_symlinks ? 0 : O_NOFOLLOW_NOERROR));
+    TRY(VirtualFileSystem::the().chmod(credentials(), path->view(), params.mode, *base, params.follow_symlinks ? 0 : O_NOFOLLOW_NOERROR));
     return 0;
 }
 

+ 1 - 1
Kernel/Syscalls/chown.cpp

@@ -38,7 +38,7 @@ ErrorOr<FlatPtr> Process::sys$chown(Userspace<Syscall::SC_chown_params const*> u
         base = base_description->custody();
     }
 
-    TRY(VirtualFileSystem::the().chown(path->view(), params.uid, params.gid, *base, params.follow_symlinks ? 0 : O_NOFOLLOW_NOERROR));
+    TRY(VirtualFileSystem::the().chown(credentials(), path->view(), params.uid, params.gid, *base, params.follow_symlinks ? 0 : O_NOFOLLOW_NOERROR));
     return 0;
 }
 

+ 2 - 2
Kernel/Syscalls/execve.cpp

@@ -758,7 +758,7 @@ ErrorOr<LockRefPtr<OpenFileDescription>> Process::find_elf_interpreter_for_execu
 
     if (!interpreter_path.is_empty()) {
         dbgln_if(EXEC_DEBUG, "exec({}): Using program interpreter {}", path, interpreter_path);
-        auto interpreter_description = TRY(VirtualFileSystem::the().open(interpreter_path, O_EXEC, 0, current_directory()));
+        auto interpreter_description = TRY(VirtualFileSystem::the().open(credentials(), interpreter_path, O_EXEC, 0, current_directory()));
         auto interp_metadata = interpreter_description->metadata();
 
         VERIFY(interpreter_description->inode());
@@ -827,7 +827,7 @@ ErrorOr<void> Process::exec(NonnullOwnPtr<KString> path, NonnullOwnPtrVector<KSt
     //        * ET_EXEC binary that just gets loaded
     //        * ET_DYN binary that requires a program interpreter
     //
-    auto description = TRY(VirtualFileSystem::the().open(path->view(), O_EXEC, 0, current_directory()));
+    auto description = TRY(VirtualFileSystem::the().open(credentials(), path->view(), O_EXEC, 0, current_directory()));
     auto metadata = description->metadata();
 
     if (!metadata.is_regular_file())

+ 1 - 1
Kernel/Syscalls/inode_watcher.cpp

@@ -47,7 +47,7 @@ ErrorOr<FlatPtr> Process::sys$inode_watcher_add_watch(Userspace<Syscall::SC_inod
         return EBADF;
     auto* inode_watcher = description->inode_watcher();
     auto path = TRY(get_syscall_path_argument(params.user_path));
-    auto custody = TRY(VirtualFileSystem::the().resolve_path(path->view(), current_directory()));
+    auto custody = TRY(VirtualFileSystem::the().resolve_path(credentials(), path->view(), current_directory()));
     if (!custody->inode().fs().supports_watchers())
         return ENOTSUP;
 

+ 2 - 2
Kernel/Syscalls/link.cpp

@@ -17,7 +17,7 @@ ErrorOr<FlatPtr> Process::sys$link(Userspace<Syscall::SC_link_params const*> 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(old_path->view(), new_path->view(), current_directory()));
+    TRY(VirtualFileSystem::the().link(credentials(), old_path->view(), new_path->view(), current_directory()));
     return 0;
 }
 
@@ -29,7 +29,7 @@ ErrorOr<FlatPtr> Process::sys$symlink(Userspace<Syscall::SC_symlink_params const
 
     auto target = TRY(get_syscall_path_argument(params.target));
     auto linkpath = TRY(get_syscall_path_argument(params.linkpath));
-    TRY(VirtualFileSystem::the().symlink(target->view(), linkpath->view(), current_directory()));
+    TRY(VirtualFileSystem::the().symlink(credentials(), target->view(), linkpath->view(), current_directory()));
     return 0;
 }
 

+ 1 - 1
Kernel/Syscalls/mkdir.cpp

@@ -15,7 +15,7 @@ ErrorOr<FlatPtr> Process::sys$mkdir(Userspace<char const*> user_path, size_t pat
     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(path->view(), mode & ~umask(), current_directory()));
+    TRY(VirtualFileSystem::the().mkdir(credentials(), path->view(), mode & ~umask(), current_directory()));
     return 0;
 }
 }

+ 1 - 1
Kernel/Syscalls/mknod.cpp

@@ -19,7 +19,7 @@ ErrorOr<FlatPtr> Process::sys$mknod(Userspace<Syscall::SC_mknod_params const*> u
     if (!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(path->view(), params.mode & ~umask(), params.dev, current_directory()));
+    TRY(VirtualFileSystem::the().mknod(credentials(), path->view(), params.mode & ~umask(), params.dev, current_directory()));
     return 0;
 }
 

+ 3 - 2
Kernel/Syscalls/mmap.cpp

@@ -105,15 +105,16 @@ ErrorOr<void> Process::validate_mmap_prot(int prot, bool map_stack, bool map_ano
 
 ErrorOr<void> Process::validate_inode_mmap_prot(int prot, Inode const& inode, bool map_shared) const
 {
+    auto credentials = this->credentials();
     auto metadata = inode.metadata();
-    if ((prot & PROT_READ) && !metadata.may_read(*this))
+    if ((prot & PROT_READ) && !metadata.may_read(credentials))
         return EACCES;
 
     if (map_shared) {
         // FIXME: What about readonly filesystem mounts? We cannot make a
         // decision here without knowing the mount flags, so we would need to
         // keep a Custody or something from mmap time.
-        if ((prot & PROT_WRITE) && !metadata.may_write(*this))
+        if ((prot & PROT_WRITE) && !metadata.may_write(credentials))
             return EACCES;
         if (auto shared_vmobject = inode.shared_vmobject()) {
             if ((prot & PROT_EXEC) && shared_vmobject->writable_mappings())

+ 2 - 2
Kernel/Syscalls/mount.cpp

@@ -86,7 +86,7 @@ ErrorOr<FlatPtr> Process::sys$mount(Userspace<Syscall::SC_mount_params const*> u
     else
         dbgln("mount {} @ {}", fs_type, target);
 
-    auto target_custody = TRY(VirtualFileSystem::the().resolve_path(target->view(), current_directory()));
+    auto target_custody = TRY(VirtualFileSystem::the().resolve_path(credentials(), target->view(), current_directory()));
 
     if (params.flags & MS_REMOUNT) {
         // We're not creating a new mount, we're updating an existing one!
@@ -132,7 +132,7 @@ ErrorOr<FlatPtr> Process::sys$umount(Userspace<char const*> user_mountpoint, siz
     TRY(require_no_promises());
 
     auto mountpoint = TRY(get_syscall_path_argument(user_mountpoint, mountpoint_length));
-    auto custody = TRY(VirtualFileSystem::the().resolve_path(mountpoint->view(), current_directory()));
+    auto custody = TRY(VirtualFileSystem::the().resolve_path(credentials(), mountpoint->view(), current_directory()));
     auto& guest_inode = custody->inode();
     TRY(VirtualFileSystem::the().unmount(guest_inode));
     return 0;

+ 1 - 1
Kernel/Syscalls/open.cpp

@@ -67,7 +67,7 @@ ErrorOr<FlatPtr> Process::sys$open(Userspace<Syscall::SC_open_params const*> use
         base = base_description->custody();
     }
 
-    auto description = TRY(VirtualFileSystem::the().open(path->view(), options, mode & ~umask(), *base));
+    auto description = TRY(VirtualFileSystem::the().open(credentials(), path->view(), options, mode & ~umask(), *base));
 
     if (description->inode() && description->inode()->bound_socket())
         return ENXIO;

+ 1 - 1
Kernel/Syscalls/readlink.cpp

@@ -17,7 +17,7 @@ ErrorOr<FlatPtr> Process::sys$readlink(Userspace<Syscall::SC_readlink_params con
     auto params = TRY(copy_typed_from_user(user_params));
 
     auto path = TRY(get_syscall_path_argument(params.path));
-    auto description = TRY(VirtualFileSystem::the().open(path->view(), O_RDONLY | O_NOFOLLOW_NOERROR, 0, current_directory()));
+    auto description = TRY(VirtualFileSystem::the().open(credentials(), path->view(), O_RDONLY | O_NOFOLLOW_NOERROR, 0, current_directory()));
 
     if (!description->metadata().is_symlink())
         return EINVAL;

+ 1 - 1
Kernel/Syscalls/realpath.cpp

@@ -18,7 +18,7 @@ ErrorOr<FlatPtr> Process::sys$realpath(Userspace<Syscall::SC_realpath_params con
     auto params = TRY(copy_typed_from_user(user_params));
 
     auto path = TRY(get_syscall_path_argument(params.path));
-    auto custody = TRY(VirtualFileSystem::the().resolve_path(path->view(), current_directory()));
+    auto custody = TRY(VirtualFileSystem::the().resolve_path(credentials(), path->view(), current_directory()));
     auto absolute_path = TRY(custody->try_serialize_absolute_path());
 
     size_t ideal_size = absolute_path->length() + 1;

+ 1 - 1
Kernel/Syscalls/rename.cpp

@@ -17,7 +17,7 @@ ErrorOr<FlatPtr> Process::sys$rename(Userspace<Syscall::SC_rename_params const*>
     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(old_path->view(), new_path->view(), current_directory()));
+    TRY(VirtualFileSystem::the().rename(credentials(), old_path->view(), new_path->view(), current_directory()));
     return 0;
 }
 

+ 1 - 1
Kernel/Syscalls/rmdir.cpp

@@ -15,7 +15,7 @@ ErrorOr<FlatPtr> Process::sys$rmdir(Userspace<char const*> user_path, size_t pat
     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().rmdir(path->view(), current_directory()));
+    TRY(VirtualFileSystem::the().rmdir(credentials(), path->view(), current_directory()));
     return 0;
 }
 

+ 1 - 1
Kernel/Syscalls/stat.cpp

@@ -41,7 +41,7 @@ ErrorOr<FlatPtr> Process::sys$stat(Userspace<Syscall::SC_stat_params const*> use
             return EINVAL;
         base = base_description->custody();
     }
-    auto metadata = TRY(VirtualFileSystem::the().lookup_metadata(path->view(), *base, params.follow_symlinks ? 0 : O_NOFOLLOW_NOERROR));
+    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;

+ 1 - 1
Kernel/Syscalls/statvfs.cpp

@@ -47,7 +47,7 @@ ErrorOr<FlatPtr> Process::sys$statvfs(Userspace<Syscall::SC_statvfs_params const
 
     auto path = TRY(get_syscall_path_argument(params.path));
 
-    auto custody = TRY(VirtualFileSystem::the().resolve_path(path->view(), current_directory(), nullptr, 0));
+    auto custody = TRY(VirtualFileSystem::the().resolve_path(credentials(), path->view(), current_directory(), nullptr, 0));
     auto& inode = custody->inode();
     auto const& fs = inode.fs();
 

+ 2 - 2
Kernel/Syscalls/unlink.cpp

@@ -30,9 +30,9 @@ ErrorOr<FlatPtr> Process::sys$unlink(int dirfd, Userspace<char const*> user_path
     }
 
     if (flags & AT_REMOVEDIR)
-        TRY(VirtualFileSystem::the().rmdir(path->view(), *base));
+        TRY(VirtualFileSystem::the().rmdir(credentials(), path->view(), *base));
     else
-        TRY(VirtualFileSystem::the().unlink(path->view(), *base));
+        TRY(VirtualFileSystem::the().unlink(credentials(), path->view(), *base));
     return 0;
 }
 

+ 1 - 1
Kernel/Syscalls/unveil.cpp

@@ -82,7 +82,7 @@ ErrorOr<FlatPtr> Process::sys$unveil(Userspace<Syscall::SC_unveil_params const*>
     // If this case is encountered, the parent node of the path is returned and the custody of that inode is used instead.
     RefPtr<Custody> parent_custody; // Parent inode in case of ENOENT
     OwnPtr<KString> new_unveiled_path;
-    auto custody_or_error = VirtualFileSystem::the().resolve_path_without_veil(path->view(), VirtualFileSystem::the().root_custody(), &parent_custody);
+    auto custody_or_error = VirtualFileSystem::the().resolve_path_without_veil(credentials(), path->view(), VirtualFileSystem::the().root_custody(), &parent_custody);
     if (!custody_or_error.is_error()) {
         new_unveiled_path = TRY(custody_or_error.value()->try_serialize_absolute_path());
     } else if (custody_or_error.error().code() == ENOENT && parent_custody && (new_permissions & UnveilAccess::CreateOrRemove)) {

+ 1 - 1
Kernel/Syscalls/utime.cpp

@@ -23,7 +23,7 @@ ErrorOr<FlatPtr> Process::sys$utime(Userspace<char const*> user_path, size_t pat
         // Not a bug!
         buf = { now, now };
     }
-    TRY(VirtualFileSystem::the().utime(path->view(), current_directory(), buf.actime, buf.modtime));
+    TRY(VirtualFileSystem::the().utime(credentials(), path->view(), current_directory(), buf.actime, buf.modtime));
     return 0;
 }
 

+ 1 - 1
Kernel/Syscalls/utimensat.cpp

@@ -71,7 +71,7 @@ ErrorOr<FlatPtr> Process::sys$utimensat(Userspace<Syscall::SC_utimensat_params c
 
     auto& atime = times[0];
     auto& mtime = times[1];
-    TRY(VirtualFileSystem::the().utimensat(path->view(), *base, atime, mtime, follow_symlink));
+    TRY(VirtualFileSystem::the().utimensat(credentials(), path->view(), *base, atime, mtime, follow_symlink));
     return 0;
 }