1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-14 20:24:57 +00:00

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.
This commit is contained in:
Andreas Kling 2022-08-21 16:02:24 +02:00
parent 9744dedb50
commit c3351d4b9f
33 changed files with 159 additions and 165 deletions

View file

@ -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);
}
}