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:
parent
9744dedb50
commit
c3351d4b9f
Notes:
sideshowbarker
2024-07-17 23:02:37 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/c3351d4b9f
33 changed files with 159 additions and 165 deletions
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue