Skip to content

Commit

Permalink
Kernel: Make VirtualFileSystem functions take credentials as input
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
awesomekling committed Aug 21, 2022
1 parent 9744ded commit c3351d4
Show file tree
Hide file tree
Showing 33 changed files with 159 additions and 165 deletions.
8 changes: 5 additions & 3 deletions Kernel/Coredump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
5 changes: 5 additions & 0 deletions Kernel/Credentials.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 2 additions & 0 deletions Kernel/Credentials.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ class Credentials final : public AtomicRefCounted<Credentials> {
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);

Expand Down
2 changes: 1 addition & 1 deletion Kernel/FileSystem/Inode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions Kernel/FileSystem/InodeFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

}
15 changes: 6 additions & 9 deletions Kernel/FileSystem/InodeMetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 4 additions & 0 deletions Kernel/FileSystem/InodeMetadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading

0 comments on commit c3351d4

Please sign in to comment.