diff --git a/Kernel/Arch/x86/ISABus/IDEController.cpp b/Kernel/Arch/x86/ISABus/IDEController.cpp index 190c1ddca8..af22874137 100644 --- a/Kernel/Arch/x86/ISABus/IDEController.cpp +++ b/Kernel/Arch/x86/ISABus/IDEController.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include diff --git a/Kernel/Arch/x86/PCI/IDELegacyModeController.cpp b/Kernel/Arch/x86/PCI/IDELegacyModeController.cpp index 5f445e9682..c89df06cce 100644 --- a/Kernel/Arch/x86/PCI/IDELegacyModeController.cpp +++ b/Kernel/Arch/x86/PCI/IDELegacyModeController.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index 1ec6cdb26c..c1adf0c0e5 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -125,7 +125,16 @@ set(KERNEL_SOURCES FileSystem/Mount.cpp FileSystem/OpenFileDescription.cpp FileSystem/Plan9FileSystem.cpp - FileSystem/ProcFS.cpp + FileSystem/ProcFS/ComponentRegistry.cpp + FileSystem/ProcFS/DirectoryInode.cpp + FileSystem/ProcFS/FileSystem.cpp + FileSystem/ProcFS/GlobalInode.cpp + FileSystem/ProcFS/Inode.cpp + FileSystem/ProcFS/LinkInode.cpp + FileSystem/ProcFS/ProcessAssociatedInode.cpp + FileSystem/ProcFS/ProcessDirectoryInode.cpp + FileSystem/ProcFS/ProcessPropertyInode.cpp + FileSystem/ProcFS/ProcessSubDirectoryInode.cpp FileSystem/SysFS/Component.cpp FileSystem/SysFS/DirectoryInode.cpp FileSystem/SysFS/FileSystem.cpp diff --git a/Kernel/FileSystem/ProcFS.cpp b/Kernel/FileSystem/ProcFS.cpp deleted file mode 100644 index 6eb4ad3771..0000000000 --- a/Kernel/FileSystem/ProcFS.cpp +++ /dev/null @@ -1,610 +0,0 @@ -/* - * Copyright (c) 2018-2021, Andreas Kling - * Copyright (c) 2021, Spencer Dixon - * Copyright (c) 2021, Liav A. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Kernel { - -static Singleton s_the; - -ProcFSComponentRegistry& ProcFSComponentRegistry::the() -{ - return *s_the; -} - -UNMAP_AFTER_INIT void ProcFSComponentRegistry::initialize() -{ - VERIFY(!s_the.is_initialized()); - s_the.ensure_instance(); -} - -UNMAP_AFTER_INIT ProcFSComponentRegistry::ProcFSComponentRegistry() - : m_root_directory(ProcFSRootDirectory::must_create()) -{ -} - -ErrorOr> ProcFS::try_create() -{ - return TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFS)); -} - -ProcFS::ProcFS() = default; -ProcFS::~ProcFS() = default; - -ErrorOr ProcFS::initialize() -{ - m_root_inode = static_ptr_cast(TRY(ProcFSComponentRegistry::the().root_directory().to_inode(*this))); - return {}; -} - -Inode& ProcFS::root_inode() -{ - return *m_root_inode; -} - -ProcFSInode::ProcFSInode(ProcFS const& fs, InodeIndex index) - : Inode(const_cast(fs), index) -{ -} - -ProcFSInode::~ProcFSInode() = default; - -ErrorOr ProcFSInode::flush_metadata() -{ - return {}; -} - -ErrorOr ProcFSInode::add_child(Inode&, StringView, mode_t) -{ - return EROFS; -} - -ErrorOr> ProcFSInode::create_child(StringView, mode_t, dev_t, UserID, GroupID) -{ - return EROFS; -} - -ErrorOr ProcFSInode::remove_child(StringView) -{ - return EROFS; -} - -ErrorOr ProcFSInode::chmod(mode_t) -{ - return EPERM; -} - -ErrorOr ProcFSInode::chown(UserID, GroupID) -{ - return EPERM; -} - -ErrorOr> ProcFSGlobalInode::try_create(ProcFS const& fs, ProcFSExposedComponent const& component) -{ - return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSGlobalInode(fs, component)); -} - -ProcFSGlobalInode::ProcFSGlobalInode(ProcFS const& fs, ProcFSExposedComponent const& component) - : ProcFSInode(fs, component.component_index()) - , m_associated_component(component) -{ -} - -void ProcFSGlobalInode::did_seek(OpenFileDescription& description, off_t new_offset) -{ - if (new_offset != 0) - return; - auto result = m_associated_component->refresh_data(description); - if (result.is_error()) { - // Subsequent calls to read will return EIO! - dbgln("ProcFS: Could not refresh contents: {}", result.error()); - } -} - -ErrorOr ProcFSGlobalInode::attach(OpenFileDescription& description) -{ - return m_associated_component->refresh_data(description); -} - -ErrorOr ProcFSGlobalInode::read_bytes_locked(off_t offset, size_t count, UserOrKernelBuffer& buffer, OpenFileDescription* fd) const -{ - return m_associated_component->read_bytes(offset, count, buffer, fd); -} - -StringView ProcFSGlobalInode::name() const -{ - return m_associated_component->name(); -} - -ErrorOr ProcFSGlobalInode::traverse_as_directory(Function(FileSystem::DirectoryEntryView const&)>) const -{ - VERIFY_NOT_REACHED(); -} - -ErrorOr> ProcFSGlobalInode::lookup(StringView) -{ - VERIFY_NOT_REACHED(); -} - -ErrorOr ProcFSGlobalInode::truncate(u64 size) -{ - return m_associated_component->truncate(size); -} - -ErrorOr ProcFSGlobalInode::update_timestamps(Optional, Optional, Optional) -{ - return {}; -} - -InodeMetadata ProcFSGlobalInode::metadata() const -{ - MutexLocker locker(m_inode_lock); - InodeMetadata metadata; - metadata.inode = { fsid(), m_associated_component->component_index() }; - metadata.mode = S_IFREG | m_associated_component->required_mode(); - metadata.uid = m_associated_component->owner_user(); - metadata.gid = m_associated_component->owner_group(); - metadata.size = 0; - metadata.mtime = m_associated_component->modified_time(); - return metadata; -} - -ErrorOr ProcFSGlobalInode::write_bytes_locked(off_t offset, size_t count, UserOrKernelBuffer const& buffer, OpenFileDescription* fd) -{ - return m_associated_component->write_bytes(offset, count, buffer, fd); -} - -ErrorOr> ProcFSDirectoryInode::try_create(ProcFS const& procfs, ProcFSExposedComponent const& component) -{ - return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSDirectoryInode(procfs, component)); -} - -ProcFSDirectoryInode::ProcFSDirectoryInode(ProcFS const& fs, ProcFSExposedComponent const& component) - : ProcFSGlobalInode(fs, component) -{ -} - -ProcFSDirectoryInode::~ProcFSDirectoryInode() = default; -InodeMetadata ProcFSDirectoryInode::metadata() const -{ - MutexLocker locker(m_inode_lock); - InodeMetadata metadata; - metadata.inode = { fsid(), m_associated_component->component_index() }; - metadata.mode = S_IFDIR | m_associated_component->required_mode(); - metadata.uid = m_associated_component->owner_user(); - metadata.gid = m_associated_component->owner_group(); - metadata.size = 0; - metadata.mtime = m_associated_component->modified_time(); - return metadata; -} -ErrorOr ProcFSDirectoryInode::traverse_as_directory(Function(FileSystem::DirectoryEntryView const&)> callback) const -{ - MutexLocker locker(procfs().m_lock); - return m_associated_component->traverse_as_directory(procfs().fsid(), move(callback)); -} - -ErrorOr> ProcFSDirectoryInode::lookup(StringView name) -{ - MutexLocker locker(procfs().m_lock); - auto component = TRY(m_associated_component->lookup(name)); - return component->to_inode(procfs()); -} - -ErrorOr> ProcFSLinkInode::try_create(ProcFS const& procfs, ProcFSExposedComponent const& component) -{ - return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSLinkInode(procfs, component)); -} - -ProcFSLinkInode::ProcFSLinkInode(ProcFS const& fs, ProcFSExposedComponent const& component) - : ProcFSGlobalInode(fs, component) -{ -} - -InodeMetadata ProcFSLinkInode::metadata() const -{ - MutexLocker locker(m_inode_lock); - InodeMetadata metadata; - metadata.inode = { fsid(), m_associated_component->component_index() }; - metadata.mode = S_IFLNK | m_associated_component->required_mode(); - metadata.uid = m_associated_component->owner_user(); - metadata.gid = m_associated_component->owner_group(); - metadata.size = 0; - metadata.mtime = m_associated_component->modified_time(); - return metadata; -} - -ProcFSProcessAssociatedInode::ProcFSProcessAssociatedInode(ProcFS const& fs, ProcessID associated_pid, InodeIndex determined_index) - : ProcFSInode(fs, determined_index) - , m_pid(associated_pid) -{ -} - -ErrorOr ProcFSProcessAssociatedInode::write_bytes_locked(off_t, size_t, UserOrKernelBuffer const&, OpenFileDescription*) -{ - return ENOTSUP; -} - -ErrorOr> ProcFSProcessDirectoryInode::try_create(ProcFS const& procfs, ProcessID pid) -{ - return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSProcessDirectoryInode(procfs, pid)); -} - -ProcFSProcessDirectoryInode::ProcFSProcessDirectoryInode(ProcFS const& procfs, ProcessID pid) - : ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_pid_directory(pid)) -{ -} - -ErrorOr ProcFSProcessDirectoryInode::attach(OpenFileDescription&) -{ - return {}; -} - -InodeMetadata ProcFSProcessDirectoryInode::metadata() const -{ - MutexLocker locker(m_inode_lock); - auto process = Process::from_pid_in_same_jail(associated_pid()); - if (!process) - return {}; - - auto traits = process->procfs_traits(); - InodeMetadata metadata; - metadata.inode = { fsid(), traits->component_index() }; - metadata.mode = S_IFDIR | traits->required_mode(); - metadata.uid = traits->owner_user(); - metadata.gid = traits->owner_group(); - metadata.size = 0; - metadata.mtime = traits->modified_time(); - return metadata; -} - -ErrorOr ProcFSProcessDirectoryInode::read_bytes_locked(off_t, size_t, UserOrKernelBuffer&, OpenFileDescription*) const -{ - VERIFY_NOT_REACHED(); -} - -ErrorOr ProcFSProcessDirectoryInode::traverse_as_directory(Function(FileSystem::DirectoryEntryView const&)> callback) const -{ - MutexLocker locker(procfs().m_lock); - auto process = Process::from_pid_in_same_jail(associated_pid()); - if (!process) - return EINVAL; - return process->procfs_traits()->traverse_as_directory(procfs().fsid(), move(callback)); -} - -ErrorOr> ProcFSProcessDirectoryInode::lookup(StringView name) -{ - MutexLocker locker(procfs().m_lock); - auto process = Process::from_pid_in_same_jail(associated_pid()); - if (!process) - return ESRCH; - if (name == "fd"sv) - return TRY(ProcFSProcessSubDirectoryInode::try_create(procfs(), SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions, associated_pid())); - if (name == "stacks"sv) - return TRY(ProcFSProcessSubDirectoryInode::try_create(procfs(), SegmentedProcFSIndex::ProcessSubDirectory::Stacks, associated_pid())); - if (name == "children"sv) - return TRY(ProcFSProcessSubDirectoryInode::try_create(procfs(), SegmentedProcFSIndex::ProcessSubDirectory::Children, associated_pid())); - if (name == "unveil"sv) - return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::Unveil, associated_pid())); - if (name == "pledge"sv) - return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::Pledge, associated_pid())); - if (name == "fds"sv) - return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::OpenFileDescriptions, associated_pid())); - if (name == "exe"sv) - return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::BinaryLink, associated_pid())); - if (name == "cwd"sv) - return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::CurrentWorkDirectoryLink, associated_pid())); - if (name == "perf_events"sv) - return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::PerformanceEvents, associated_pid())); - if (name == "vm"sv) - return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::VirtualMemoryStats, associated_pid())); - if (name == "cmdline"sv) - return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::CommandLine, associated_pid())); - return ENOENT; -} - -ErrorOr> ProcFSProcessSubDirectoryInode::try_create(ProcFS const& procfs, SegmentedProcFSIndex::ProcessSubDirectory sub_directory_type, ProcessID pid) -{ - return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSProcessSubDirectoryInode(procfs, sub_directory_type, pid)); -} - -ProcFSProcessSubDirectoryInode::ProcFSProcessSubDirectoryInode(ProcFS const& procfs, SegmentedProcFSIndex::ProcessSubDirectory sub_directory_type, ProcessID pid) - : ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_sub_directory(pid, sub_directory_type)) - , m_sub_directory_type(sub_directory_type) -{ -} - -ErrorOr ProcFSProcessSubDirectoryInode::read_bytes_locked(off_t, size_t, UserOrKernelBuffer&, OpenFileDescription*) const -{ - VERIFY_NOT_REACHED(); -} - -ErrorOr ProcFSProcessSubDirectoryInode::attach(OpenFileDescription&) -{ - return {}; -} - -void ProcFSProcessSubDirectoryInode::did_seek(OpenFileDescription&, off_t) -{ - VERIFY_NOT_REACHED(); -} - -InodeMetadata ProcFSProcessSubDirectoryInode::metadata() const -{ - MutexLocker locker(m_inode_lock); - auto process = Process::from_pid_in_same_jail(associated_pid()); - if (!process) - return {}; - - auto traits = process->procfs_traits(); - InodeMetadata metadata; - metadata.inode = { fsid(), traits->component_index() }; - metadata.mode = S_IFDIR | traits->required_mode(); - metadata.uid = traits->owner_user(); - metadata.gid = traits->owner_group(); - metadata.size = 0; - metadata.mtime = traits->modified_time(); - return metadata; -} - -ErrorOr ProcFSProcessSubDirectoryInode::traverse_as_directory(Function(FileSystem::DirectoryEntryView const&)> callback) const -{ - MutexLocker locker(procfs().m_lock); - auto process = Process::from_pid_in_same_jail(associated_pid()); - if (!process) - return EINVAL; - switch (m_sub_directory_type) { - case SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions: - return process->traverse_file_descriptions_directory(procfs().fsid(), move(callback)); - case SegmentedProcFSIndex::ProcessSubDirectory::Stacks: - return process->traverse_stacks_directory(procfs().fsid(), move(callback)); - case SegmentedProcFSIndex::ProcessSubDirectory::Children: - return process->traverse_children_directory(procfs().fsid(), move(callback)); - default: - VERIFY_NOT_REACHED(); - } - VERIFY_NOT_REACHED(); -} - -ErrorOr> ProcFSProcessSubDirectoryInode::lookup(StringView name) -{ - MutexLocker locker(procfs().m_lock); - auto process = Process::from_pid_in_same_jail(associated_pid()); - if (!process) - return ESRCH; - switch (m_sub_directory_type) { - case SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions: - return process->lookup_file_descriptions_directory(procfs(), name); - case SegmentedProcFSIndex::ProcessSubDirectory::Stacks: - return process->lookup_stacks_directory(procfs(), name); - case SegmentedProcFSIndex::ProcessSubDirectory::Children: - return process->lookup_children_directory(procfs(), name); - default: - VERIFY_NOT_REACHED(); - } -} - -ErrorOr> ProcFSProcessPropertyInode::try_create_for_file_description_link(ProcFS const& procfs, unsigned file_description_index, ProcessID pid) -{ - return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSProcessPropertyInode(procfs, file_description_index, pid)); -} -ErrorOr> ProcFSProcessPropertyInode::try_create_for_thread_stack(ProcFS const& procfs, ThreadID stack_thread_index, ProcessID pid) -{ - return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSProcessPropertyInode(procfs, stack_thread_index, pid)); -} -ErrorOr> ProcFSProcessPropertyInode::try_create_for_pid_property(ProcFS const& procfs, SegmentedProcFSIndex::MainProcessProperty main_property_type, ProcessID pid) -{ - return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSProcessPropertyInode(procfs, main_property_type, pid)); -} -ErrorOr> ProcFSProcessPropertyInode::try_create_for_child_process_link(ProcFS const& procfs, ProcessID child_pid, ProcessID pid) -{ - return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSProcessPropertyInode(procfs, child_pid, pid)); -} - -ProcFSProcessPropertyInode::ProcFSProcessPropertyInode(ProcFS const& procfs, SegmentedProcFSIndex::MainProcessProperty main_property_type, ProcessID pid) - : ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_main_property_in_pid_directory(pid, main_property_type)) - , m_parent_sub_directory_type(SegmentedProcFSIndex::ProcessSubDirectory::Reserved) -{ - m_possible_data.property_type = main_property_type; -} - -ProcFSProcessPropertyInode::ProcFSProcessPropertyInode(ProcFS const& procfs, unsigned file_description_index, ProcessID pid) - : ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_file_description(pid, file_description_index)) - , m_parent_sub_directory_type(SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions) -{ - m_possible_data.property_index = file_description_index; -} - -ProcFSProcessPropertyInode::ProcFSProcessPropertyInode(ProcFS const& procfs, ThreadID thread_stack_index, ProcessID pid) - : ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_thread_stack(pid, thread_stack_index)) - , m_parent_sub_directory_type(SegmentedProcFSIndex::ProcessSubDirectory::Stacks) -{ - m_possible_data.property_index = thread_stack_index.value(); -} - -ProcFSProcessPropertyInode::ProcFSProcessPropertyInode(ProcFS const& procfs, ProcessID child_pid, ProcessID pid) - : ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_children(pid, child_pid)) - , m_parent_sub_directory_type(SegmentedProcFSIndex::ProcessSubDirectory::Children) -{ - m_possible_data.property_index = child_pid.value(); -} - -ErrorOr ProcFSProcessPropertyInode::attach(OpenFileDescription& description) -{ - return refresh_data(description); -} -void ProcFSProcessPropertyInode::did_seek(OpenFileDescription& description, off_t offset) -{ - if (offset != 0) - return; - (void)refresh_data(description); -} - -static mode_t determine_procfs_process_inode_mode(SegmentedProcFSIndex::ProcessSubDirectory parent_sub_directory_type, SegmentedProcFSIndex::MainProcessProperty main_property) -{ - if (parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions) - return S_IFLNK | 0400; - if (parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Stacks) - return S_IFREG | 0400; - if (parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Children) - return S_IFLNK | 0400; - VERIFY(parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Reserved); - if (main_property == SegmentedProcFSIndex::MainProcessProperty::BinaryLink) - return S_IFLNK | 0777; - if (main_property == SegmentedProcFSIndex::MainProcessProperty::CurrentWorkDirectoryLink) - return S_IFLNK | 0777; - return S_IFREG | 0400; -} - -InodeMetadata ProcFSProcessPropertyInode::metadata() const -{ - MutexLocker locker(m_inode_lock); - auto process = Process::from_pid_in_same_jail(associated_pid()); - if (!process) - return {}; - - auto traits = process->procfs_traits(); - InodeMetadata metadata; - metadata.inode = { fsid(), traits->component_index() }; - metadata.mode = determine_procfs_process_inode_mode(m_parent_sub_directory_type, m_possible_data.property_type); - metadata.uid = traits->owner_user(); - metadata.gid = traits->owner_group(); - metadata.size = 0; - metadata.mtime = traits->modified_time(); - return metadata; -} -ErrorOr ProcFSProcessPropertyInode::traverse_as_directory(Function(FileSystem::DirectoryEntryView const&)>) const -{ - VERIFY_NOT_REACHED(); -} -ErrorOr ProcFSProcessPropertyInode::read_bytes_locked(off_t offset, size_t count, UserOrKernelBuffer& buffer, OpenFileDescription* description) const -{ - dbgln_if(PROCFS_DEBUG, "ProcFS ProcessInformation: read_bytes_locked offset: {} count: {}", offset, count); - - VERIFY(offset >= 0); - VERIFY(buffer.user_or_kernel_ptr()); - - if (!description) { - auto builder = TRY(KBufferBuilder::try_create()); - auto process = Process::from_pid_in_same_jail(associated_pid()); - if (!process) - return Error::from_errno(ESRCH); - TRY(try_to_acquire_data(*process, builder)); - auto data_buffer = builder.build(); - if (!data_buffer) - return Error::from_errno(EFAULT); - ssize_t nread = min(static_cast(data_buffer->size() - offset), static_cast(count)); - TRY(buffer.write(data_buffer->data() + offset, nread)); - return nread; - } - if (!description->data()) { - dbgln("ProcFS Process Information: Do not have cached data!"); - return Error::from_errno(EIO); - } - - MutexLocker locker(m_refresh_lock); - - auto& typed_cached_data = static_cast(*description->data()); - auto& data_buffer = typed_cached_data.buffer; - - if (!data_buffer || (size_t)offset >= data_buffer->size()) - return 0; - - ssize_t nread = min(static_cast(data_buffer->size() - offset), static_cast(count)); - TRY(buffer.write(data_buffer->data() + offset, nread)); - - return nread; -} -ErrorOr> ProcFSProcessPropertyInode::lookup(StringView) -{ - return EINVAL; -} - -static ErrorOr build_from_cached_data(KBufferBuilder& builder, ProcFSInodeData& cached_data) -{ - cached_data.buffer = builder.build(); - if (!cached_data.buffer) - return ENOMEM; - return {}; -} - -ErrorOr ProcFSProcessPropertyInode::try_to_acquire_data(Process& process, KBufferBuilder& builder) const -{ - // FIXME: Verify process is already ref-counted - if (m_parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions) { - TRY(process.procfs_get_file_description_link(m_possible_data.property_index, builder)); - return {}; - } - if (m_parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Stacks) { - TRY(process.procfs_get_thread_stack(m_possible_data.property_index, builder)); - return {}; - } - if (m_parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Children) { - TRY(process.procfs_get_child_proccess_link(m_possible_data.property_index, builder)); - return {}; - } - - VERIFY(m_parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Reserved); - switch (m_possible_data.property_type) { - case SegmentedProcFSIndex::MainProcessProperty::Unveil: - return process.procfs_get_unveil_stats(builder); - case SegmentedProcFSIndex::MainProcessProperty::Pledge: - return process.procfs_get_pledge_stats(builder); - case SegmentedProcFSIndex::MainProcessProperty::OpenFileDescriptions: - return process.procfs_get_fds_stats(builder); - case SegmentedProcFSIndex::MainProcessProperty::BinaryLink: - return process.procfs_get_binary_link(builder); - case SegmentedProcFSIndex::MainProcessProperty::CurrentWorkDirectoryLink: - return process.procfs_get_current_work_directory_link(builder); - case SegmentedProcFSIndex::MainProcessProperty::PerformanceEvents: - return process.procfs_get_perf_events(builder); - case SegmentedProcFSIndex::MainProcessProperty::VirtualMemoryStats: - return process.procfs_get_virtual_memory_stats(builder); - case SegmentedProcFSIndex::MainProcessProperty::CommandLine: - return process.procfs_get_command_line(builder); - default: - VERIFY_NOT_REACHED(); - } -} - -ErrorOr ProcFSProcessPropertyInode::refresh_data(OpenFileDescription& description) -{ - // For process-specific inodes, hold the process's ptrace lock across refresh - // and refuse to load data if the process is not dumpable. - // Without this, files opened before a process went non-dumpable could still be used for dumping. - auto process = Process::from_pid_in_same_jail(associated_pid()); - if (!process) - return Error::from_errno(ESRCH); - process->ptrace_lock().lock(); - if (!process->is_dumpable()) { - process->ptrace_lock().unlock(); - return EPERM; - } - ScopeGuard guard = [&] { - process->ptrace_lock().unlock(); - }; - MutexLocker locker(m_refresh_lock); - auto& cached_data = description.data(); - if (!cached_data) { - cached_data = adopt_own_if_nonnull(new (nothrow) ProcFSInodeData); - if (!cached_data) - return ENOMEM; - } - auto builder = TRY(KBufferBuilder::try_create()); - TRY(try_to_acquire_data(*process, builder)); - return build_from_cached_data(builder, static_cast(*cached_data)); -} -} diff --git a/Kernel/FileSystem/ProcFS.h b/Kernel/FileSystem/ProcFS.h deleted file mode 100644 index 58e384709b..0000000000 --- a/Kernel/FileSystem/ProcFS.h +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Kernel { - -class ProcFS final : public FileSystem { - friend class ProcFSInode; - friend class ProcFSDirectoryInode; - friend class ProcFSProcessDirectoryInode; - friend class ProcFSGlobalInode; - friend class ProcFSAssociatedProcessInode; - friend class ProcFSProcessSubDirectoryInode; - -public: - virtual ~ProcFS() override; - static ErrorOr> try_create(); - - virtual ErrorOr initialize() override; - virtual StringView class_name() const override { return "ProcFS"sv; } - - virtual Inode& root_inode() override; - -private: - ProcFS(); - - LockRefPtr m_root_inode; -}; - -class ProcFSInode : public Inode { - friend class ProcFS; - -public: - virtual ~ProcFSInode() override; - -protected: - ProcFSInode(ProcFS const&, InodeIndex); - - ProcFS& procfs() { return static_cast(Inode::fs()); } - ProcFS const& procfs() const { return static_cast(Inode::fs()); } - - // ^Inode - virtual ErrorOr attach(OpenFileDescription& description) override = 0; - virtual void did_seek(OpenFileDescription&, off_t) override = 0; - virtual ErrorOr flush_metadata() override final; - virtual ErrorOr> create_child(StringView name, mode_t, dev_t, UserID, GroupID) override final; - virtual ErrorOr add_child(Inode&, StringView name, mode_t) override final; - virtual ErrorOr remove_child(StringView name) override final; - virtual ErrorOr chmod(mode_t) override final; - virtual ErrorOr chown(UserID, GroupID) override final; -}; - -class ProcFSGlobalInode : public ProcFSInode { - friend class ProcFS; - -public: - static ErrorOr> try_create(ProcFS const&, ProcFSExposedComponent const&); - virtual ~ProcFSGlobalInode() override {}; - StringView name() const; - -protected: - ProcFSGlobalInode(ProcFS const&, ProcFSExposedComponent const&); - - // ^Inode - virtual ErrorOr attach(OpenFileDescription& description) override final; - virtual ErrorOr read_bytes_locked(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const override final; - virtual ErrorOr write_bytes_locked(off_t, size_t, UserOrKernelBuffer const& buffer, OpenFileDescription*) override final; - virtual void did_seek(OpenFileDescription&, off_t) override final; - virtual InodeMetadata metadata() const override; - virtual ErrorOr traverse_as_directory(Function(FileSystem::DirectoryEntryView const&)>) const override; - virtual ErrorOr> lookup(StringView) override; - virtual ErrorOr truncate(u64) override final; - virtual ErrorOr update_timestamps(Optional atime, Optional ctime, Optional mtime) override; - - NonnullLockRefPtr m_associated_component; -}; - -class ProcFSLinkInode : public ProcFSGlobalInode { - friend class ProcFS; - -public: - static ErrorOr> try_create(ProcFS const&, ProcFSExposedComponent const&); - -protected: - ProcFSLinkInode(ProcFS const&, ProcFSExposedComponent const&); - virtual InodeMetadata metadata() const override; -}; - -class ProcFSDirectoryInode final : public ProcFSGlobalInode { - friend class ProcFS; - -public: - static ErrorOr> try_create(ProcFS const&, ProcFSExposedComponent const&); - virtual ~ProcFSDirectoryInode() override; - -protected: - ProcFSDirectoryInode(ProcFS const&, ProcFSExposedComponent const&); - // ^Inode - virtual InodeMetadata metadata() const override; - virtual ErrorOr traverse_as_directory(Function(FileSystem::DirectoryEntryView const&)>) const override; - virtual ErrorOr> lookup(StringView name) override; -}; - -class ProcFSProcessAssociatedInode : public ProcFSInode { - friend class ProcFS; - -protected: - ProcFSProcessAssociatedInode(ProcFS const&, ProcessID, InodeIndex); - ProcessID associated_pid() const { return m_pid; } - - // ^Inode - virtual ErrorOr write_bytes_locked(off_t, size_t, UserOrKernelBuffer const& buffer, OpenFileDescription*) override final; - -private: - const ProcessID m_pid; -}; - -class ProcFSProcessDirectoryInode final : public ProcFSProcessAssociatedInode { - friend class ProcFS; - -public: - static ErrorOr> try_create(ProcFS const&, ProcessID); - -private: - ProcFSProcessDirectoryInode(ProcFS const&, ProcessID); - // ^Inode - virtual ErrorOr attach(OpenFileDescription& description) override; - virtual void did_seek(OpenFileDescription&, off_t) override { } - virtual InodeMetadata metadata() const override; - virtual ErrorOr traverse_as_directory(Function(FileSystem::DirectoryEntryView const&)>) const override; - virtual ErrorOr read_bytes_locked(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const override final; - virtual ErrorOr> lookup(StringView name) override; -}; - -class ProcFSProcessSubDirectoryInode final : public ProcFSProcessAssociatedInode { - friend class ProcFS; - -public: - static ErrorOr> try_create(ProcFS const&, SegmentedProcFSIndex::ProcessSubDirectory, ProcessID); - -private: - ProcFSProcessSubDirectoryInode(ProcFS const&, SegmentedProcFSIndex::ProcessSubDirectory, ProcessID); - // ^Inode - virtual ErrorOr attach(OpenFileDescription& description) override; - virtual void did_seek(OpenFileDescription&, off_t) override; - virtual InodeMetadata metadata() const override; - virtual ErrorOr traverse_as_directory(Function(FileSystem::DirectoryEntryView const&)>) const override; - virtual ErrorOr read_bytes_locked(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const override final; - virtual ErrorOr> lookup(StringView name) override; - - const SegmentedProcFSIndex::ProcessSubDirectory m_sub_directory_type; -}; - -class ProcFSProcessPropertyInode final : public ProcFSProcessAssociatedInode { - friend class ProcFS; - -public: - static ErrorOr> try_create_for_file_description_link(ProcFS const&, unsigned, ProcessID); - static ErrorOr> try_create_for_thread_stack(ProcFS const&, ThreadID, ProcessID); - static ErrorOr> try_create_for_pid_property(ProcFS const&, SegmentedProcFSIndex::MainProcessProperty, ProcessID); - static ErrorOr> try_create_for_child_process_link(ProcFS const&, ProcessID, ProcessID); - -private: - ProcFSProcessPropertyInode(ProcFS const&, SegmentedProcFSIndex::MainProcessProperty, ProcessID); - ProcFSProcessPropertyInode(ProcFS const&, ThreadID, ProcessID); - ProcFSProcessPropertyInode(ProcFS const&, unsigned, ProcessID); - ProcFSProcessPropertyInode(ProcFS const&, ProcessID, ProcessID); - - // ^Inode - virtual ErrorOr attach(OpenFileDescription& description) override; - virtual void did_seek(OpenFileDescription&, off_t) override; - virtual InodeMetadata metadata() const override; - virtual ErrorOr traverse_as_directory(Function(FileSystem::DirectoryEntryView const&)>) const override; - virtual ErrorOr read_bytes_locked(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const override final; - virtual ErrorOr> lookup(StringView name) override final; - - ErrorOr refresh_data(OpenFileDescription& description); - ErrorOr try_to_acquire_data(Process& process, KBufferBuilder& builder) const; - - const SegmentedProcFSIndex::ProcessSubDirectory m_parent_sub_directory_type; - union { - SegmentedProcFSIndex::MainProcessProperty property_type; - unsigned property_index; - } m_possible_data; - mutable Mutex m_refresh_lock; -}; -} diff --git a/Kernel/FileSystem/ProcFS/ComponentRegistry.cpp b/Kernel/FileSystem/ProcFS/ComponentRegistry.cpp new file mode 100644 index 0000000000..d0437ad302 --- /dev/null +++ b/Kernel/FileSystem/ProcFS/ComponentRegistry.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018-2021, Andreas Kling + * Copyright (c) 2021, Spencer Dixon + * Copyright (c) 2021, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +namespace Kernel { + +static Singleton s_the; + +ProcFSComponentRegistry& ProcFSComponentRegistry::the() +{ + return *s_the; +} + +UNMAP_AFTER_INIT void ProcFSComponentRegistry::initialize() +{ + VERIFY(!s_the.is_initialized()); + s_the.ensure_instance(); +} + +UNMAP_AFTER_INIT ProcFSComponentRegistry::ProcFSComponentRegistry() + : m_root_directory(ProcFSRootDirectory::must_create()) +{ +} + +} diff --git a/Kernel/FileSystem/ProcFS/DirectoryInode.cpp b/Kernel/FileSystem/ProcFS/DirectoryInode.cpp new file mode 100644 index 0000000000..569fa480fd --- /dev/null +++ b/Kernel/FileSystem/ProcFS/DirectoryInode.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2018-2021, Andreas Kling + * Copyright (c) 2021, Spencer Dixon + * Copyright (c) 2021, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +namespace Kernel { + +ErrorOr> ProcFSDirectoryInode::try_create(ProcFS const& procfs, ProcFSExposedComponent const& component) +{ + return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSDirectoryInode(procfs, component)); +} + +ProcFSDirectoryInode::ProcFSDirectoryInode(ProcFS const& fs, ProcFSExposedComponent const& component) + : ProcFSGlobalInode(fs, component) +{ +} + +ProcFSDirectoryInode::~ProcFSDirectoryInode() = default; + +InodeMetadata ProcFSDirectoryInode::metadata() const +{ + MutexLocker locker(m_inode_lock); + InodeMetadata metadata; + metadata.inode = { fsid(), m_associated_component->component_index() }; + metadata.mode = S_IFDIR | m_associated_component->required_mode(); + metadata.uid = m_associated_component->owner_user(); + metadata.gid = m_associated_component->owner_group(); + metadata.size = 0; + metadata.mtime = m_associated_component->modified_time(); + return metadata; +} + +ErrorOr ProcFSDirectoryInode::traverse_as_directory(Function(FileSystem::DirectoryEntryView const&)> callback) const +{ + MutexLocker locker(procfs().m_lock); + return m_associated_component->traverse_as_directory(procfs().fsid(), move(callback)); +} + +ErrorOr> ProcFSDirectoryInode::lookup(StringView name) +{ + MutexLocker locker(procfs().m_lock); + auto component = TRY(m_associated_component->lookup(name)); + return component->to_inode(procfs()); +} + +} diff --git a/Kernel/FileSystem/ProcFS/DirectoryInode.h b/Kernel/FileSystem/ProcFS/DirectoryInode.h new file mode 100644 index 0000000000..173af61667 --- /dev/null +++ b/Kernel/FileSystem/ProcFS/DirectoryInode.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Kernel { + +class ProcFSDirectoryInode final : public ProcFSGlobalInode { + friend class ProcFS; + +public: + static ErrorOr> try_create(ProcFS const&, ProcFSExposedComponent const&); + virtual ~ProcFSDirectoryInode() override; + +protected: + ProcFSDirectoryInode(ProcFS const&, ProcFSExposedComponent const&); + // ^Inode + virtual InodeMetadata metadata() const override; + virtual ErrorOr traverse_as_directory(Function(FileSystem::DirectoryEntryView const&)>) const override; + virtual ErrorOr> lookup(StringView name) override; +}; + +} diff --git a/Kernel/FileSystem/ProcFS/FileSystem.cpp b/Kernel/FileSystem/ProcFS/FileSystem.cpp new file mode 100644 index 0000000000..7ea12c6344 --- /dev/null +++ b/Kernel/FileSystem/ProcFS/FileSystem.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018-2021, Andreas Kling + * Copyright (c) 2021, Spencer Dixon + * Copyright (c) 2021, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +namespace Kernel { + +ErrorOr> ProcFS::try_create() +{ + return TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFS)); +} + +ProcFS::ProcFS() = default; +ProcFS::~ProcFS() = default; + +ErrorOr ProcFS::initialize() +{ + m_root_inode = static_ptr_cast(TRY(ProcFSComponentRegistry::the().root_directory().to_inode(*this))); + return {}; +} + +Inode& ProcFS::root_inode() +{ + return *m_root_inode; +} + +} diff --git a/Kernel/FileSystem/ProcFS/FileSystem.h b/Kernel/FileSystem/ProcFS/FileSystem.h new file mode 100644 index 0000000000..f8d127e3c9 --- /dev/null +++ b/Kernel/FileSystem/ProcFS/FileSystem.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include + +namespace Kernel { + +class ProcFSInode; +class ProcFSProcessDirectoryInode; +class ProcFSGlobalInode; +class ProcFSAssociatedProcessInode; +class ProcFSProcessSubDirectoryInode; + +class ProcFS final : public FileSystem { + friend class ProcFSInode; + friend class ProcFSDirectoryInode; + friend class ProcFSProcessDirectoryInode; + friend class ProcFSGlobalInode; + friend class ProcFSAssociatedProcessInode; + friend class ProcFSProcessSubDirectoryInode; + +public: + virtual ~ProcFS() override; + static ErrorOr> try_create(); + + virtual ErrorOr initialize() override; + virtual StringView class_name() const override { return "ProcFS"sv; } + + virtual Inode& root_inode() override; + +private: + ProcFS(); + + LockRefPtr m_root_inode; +}; + +} diff --git a/Kernel/FileSystem/ProcFS/GlobalInode.cpp b/Kernel/FileSystem/ProcFS/GlobalInode.cpp new file mode 100644 index 0000000000..67fda1947e --- /dev/null +++ b/Kernel/FileSystem/ProcFS/GlobalInode.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018-2021, Andreas Kling + * Copyright (c) 2021, Spencer Dixon + * Copyright (c) 2021, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +namespace Kernel { + +ErrorOr> ProcFSGlobalInode::try_create(ProcFS const& fs, ProcFSExposedComponent const& component) +{ + return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSGlobalInode(fs, component)); +} + +ProcFSGlobalInode::ProcFSGlobalInode(ProcFS const& fs, ProcFSExposedComponent const& component) + : ProcFSInode(fs, component.component_index()) + , m_associated_component(component) +{ +} + +void ProcFSGlobalInode::did_seek(OpenFileDescription& description, off_t new_offset) +{ + if (new_offset != 0) + return; + auto result = m_associated_component->refresh_data(description); + if (result.is_error()) { + // Subsequent calls to read will return EIO! + dbgln("ProcFS: Could not refresh contents: {}", result.error()); + } +} + +ErrorOr ProcFSGlobalInode::attach(OpenFileDescription& description) +{ + return m_associated_component->refresh_data(description); +} + +ErrorOr ProcFSGlobalInode::read_bytes_locked(off_t offset, size_t count, UserOrKernelBuffer& buffer, OpenFileDescription* fd) const +{ + return m_associated_component->read_bytes(offset, count, buffer, fd); +} + +StringView ProcFSGlobalInode::name() const +{ + return m_associated_component->name(); +} + +ErrorOr ProcFSGlobalInode::traverse_as_directory(Function(FileSystem::DirectoryEntryView const&)>) const +{ + VERIFY_NOT_REACHED(); +} + +ErrorOr> ProcFSGlobalInode::lookup(StringView) +{ + VERIFY_NOT_REACHED(); +} + +ErrorOr ProcFSGlobalInode::truncate(u64 size) +{ + return m_associated_component->truncate(size); +} + +ErrorOr ProcFSGlobalInode::update_timestamps(Optional, Optional, Optional) +{ + return {}; +} + +InodeMetadata ProcFSGlobalInode::metadata() const +{ + MutexLocker locker(m_inode_lock); + InodeMetadata metadata; + metadata.inode = { fsid(), m_associated_component->component_index() }; + metadata.mode = S_IFREG | m_associated_component->required_mode(); + metadata.uid = m_associated_component->owner_user(); + metadata.gid = m_associated_component->owner_group(); + metadata.size = 0; + metadata.mtime = m_associated_component->modified_time(); + return metadata; +} + +ErrorOr ProcFSGlobalInode::write_bytes_locked(off_t offset, size_t count, UserOrKernelBuffer const& buffer, OpenFileDescription* fd) +{ + return m_associated_component->write_bytes(offset, count, buffer, fd); +} + +} diff --git a/Kernel/FileSystem/ProcFS/GlobalInode.h b/Kernel/FileSystem/ProcFS/GlobalInode.h new file mode 100644 index 0000000000..6a485cdfb8 --- /dev/null +++ b/Kernel/FileSystem/ProcFS/GlobalInode.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace Kernel { + +class ProcFSGlobalInode : public ProcFSInode { + friend class ProcFS; + +public: + static ErrorOr> try_create(ProcFS const&, ProcFSExposedComponent const&); + virtual ~ProcFSGlobalInode() override {}; + StringView name() const; + +protected: + ProcFSGlobalInode(ProcFS const&, ProcFSExposedComponent const&); + + // ^Inode + virtual ErrorOr attach(OpenFileDescription& description) override final; + virtual ErrorOr read_bytes_locked(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const override final; + virtual ErrorOr write_bytes_locked(off_t, size_t, UserOrKernelBuffer const& buffer, OpenFileDescription*) override final; + virtual void did_seek(OpenFileDescription&, off_t) override final; + virtual InodeMetadata metadata() const override; + virtual ErrorOr traverse_as_directory(Function(FileSystem::DirectoryEntryView const&)>) const override; + virtual ErrorOr> lookup(StringView) override; + virtual ErrorOr truncate(u64) override final; + virtual ErrorOr update_timestamps(Optional atime, Optional ctime, Optional mtime) override; + + NonnullLockRefPtr m_associated_component; +}; + +} diff --git a/Kernel/FileSystem/ProcFS/Inode.cpp b/Kernel/FileSystem/ProcFS/Inode.cpp new file mode 100644 index 0000000000..6c774b0998 --- /dev/null +++ b/Kernel/FileSystem/ProcFS/Inode.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018-2021, Andreas Kling + * Copyright (c) 2021, Spencer Dixon + * Copyright (c) 2021, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +namespace Kernel { + +ProcFSInode::ProcFSInode(ProcFS const& fs, InodeIndex index) + : Inode(const_cast(fs), index) +{ +} + +ProcFSInode::~ProcFSInode() = default; + +ErrorOr ProcFSInode::flush_metadata() +{ + return {}; +} + +ErrorOr ProcFSInode::add_child(Inode&, StringView, mode_t) +{ + return EROFS; +} + +ErrorOr> ProcFSInode::create_child(StringView, mode_t, dev_t, UserID, GroupID) +{ + return EROFS; +} + +ErrorOr ProcFSInode::remove_child(StringView) +{ + return EROFS; +} + +ErrorOr ProcFSInode::chmod(mode_t) +{ + return EPERM; +} + +ErrorOr ProcFSInode::chown(UserID, GroupID) +{ + return EPERM; +} + +} diff --git a/Kernel/FileSystem/ProcFS/Inode.h b/Kernel/FileSystem/ProcFS/Inode.h new file mode 100644 index 0000000000..3fcf5847c4 --- /dev/null +++ b/Kernel/FileSystem/ProcFS/Inode.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace Kernel { + +class ProcFSInode : public Inode { + friend class ProcFS; + +public: + virtual ~ProcFSInode() override; + +protected: + ProcFSInode(ProcFS const&, InodeIndex); + + ProcFS& procfs() { return static_cast(Inode::fs()); } + ProcFS const& procfs() const { return static_cast(Inode::fs()); } + + // ^Inode + virtual ErrorOr attach(OpenFileDescription& description) override = 0; + virtual void did_seek(OpenFileDescription&, off_t) override = 0; + virtual ErrorOr flush_metadata() override final; + virtual ErrorOr> create_child(StringView name, mode_t, dev_t, UserID, GroupID) override final; + virtual ErrorOr add_child(Inode&, StringView name, mode_t) override final; + virtual ErrorOr remove_child(StringView name) override final; + virtual ErrorOr chmod(mode_t) override final; + virtual ErrorOr chown(UserID, GroupID) override final; +}; + +} diff --git a/Kernel/FileSystem/ProcFS/LinkInode.cpp b/Kernel/FileSystem/ProcFS/LinkInode.cpp new file mode 100644 index 0000000000..4331d0b2a0 --- /dev/null +++ b/Kernel/FileSystem/ProcFS/LinkInode.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018-2021, Andreas Kling + * Copyright (c) 2021, Spencer Dixon + * Copyright (c) 2021, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +namespace Kernel { + +ErrorOr> ProcFSLinkInode::try_create(ProcFS const& procfs, ProcFSExposedComponent const& component) +{ + return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSLinkInode(procfs, component)); +} + +ProcFSLinkInode::ProcFSLinkInode(ProcFS const& fs, ProcFSExposedComponent const& component) + : ProcFSGlobalInode(fs, component) +{ +} + +InodeMetadata ProcFSLinkInode::metadata() const +{ + MutexLocker locker(m_inode_lock); + InodeMetadata metadata; + metadata.inode = { fsid(), m_associated_component->component_index() }; + metadata.mode = S_IFLNK | m_associated_component->required_mode(); + metadata.uid = m_associated_component->owner_user(); + metadata.gid = m_associated_component->owner_group(); + metadata.size = 0; + metadata.mtime = m_associated_component->modified_time(); + return metadata; +} + +} diff --git a/Kernel/FileSystem/ProcFS/LinkInode.h b/Kernel/FileSystem/ProcFS/LinkInode.h new file mode 100644 index 0000000000..8b80471314 --- /dev/null +++ b/Kernel/FileSystem/ProcFS/LinkInode.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Kernel { + +class ProcFSLinkInode : public ProcFSGlobalInode { + friend class ProcFS; + +public: + static ErrorOr> try_create(ProcFS const&, ProcFSExposedComponent const&); + +protected: + ProcFSLinkInode(ProcFS const&, ProcFSExposedComponent const&); + virtual InodeMetadata metadata() const override; +}; + +} diff --git a/Kernel/FileSystem/ProcFS/ProcessAssociatedInode.cpp b/Kernel/FileSystem/ProcFS/ProcessAssociatedInode.cpp new file mode 100644 index 0000000000..627a2fa980 --- /dev/null +++ b/Kernel/FileSystem/ProcFS/ProcessAssociatedInode.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018-2021, Andreas Kling + * Copyright (c) 2021, Spencer Dixon + * Copyright (c) 2021, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +namespace Kernel { + +ProcFSProcessAssociatedInode::ProcFSProcessAssociatedInode(ProcFS const& fs, ProcessID associated_pid, InodeIndex determined_index) + : ProcFSInode(fs, determined_index) + , m_pid(associated_pid) +{ +} + +ErrorOr ProcFSProcessAssociatedInode::write_bytes_locked(off_t, size_t, UserOrKernelBuffer const&, OpenFileDescription*) +{ + return ENOTSUP; +} + +} diff --git a/Kernel/FileSystem/ProcFS/ProcessAssociatedInode.h b/Kernel/FileSystem/ProcFS/ProcessAssociatedInode.h new file mode 100644 index 0000000000..34a9ca1448 --- /dev/null +++ b/Kernel/FileSystem/ProcFS/ProcessAssociatedInode.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Kernel { + +class ProcFSProcessAssociatedInode : public ProcFSInode { + friend class ProcFS; + +protected: + ProcFSProcessAssociatedInode(ProcFS const&, ProcessID, InodeIndex); + ProcessID associated_pid() const { return m_pid; } + + // ^Inode + virtual ErrorOr write_bytes_locked(off_t, size_t, UserOrKernelBuffer const& buffer, OpenFileDescription*) override final; + +private: + const ProcessID m_pid; +}; + +} diff --git a/Kernel/FileSystem/ProcFS/ProcessDirectoryInode.cpp b/Kernel/FileSystem/ProcFS/ProcessDirectoryInode.cpp new file mode 100644 index 0000000000..a8e4593c6e --- /dev/null +++ b/Kernel/FileSystem/ProcFS/ProcessDirectoryInode.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2018-2021, Andreas Kling + * Copyright (c) 2021, Spencer Dixon + * Copyright (c) 2021, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include + +namespace Kernel { + +ErrorOr> ProcFSProcessDirectoryInode::try_create(ProcFS const& procfs, ProcessID pid) +{ + return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSProcessDirectoryInode(procfs, pid)); +} + +ProcFSProcessDirectoryInode::ProcFSProcessDirectoryInode(ProcFS const& procfs, ProcessID pid) + : ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_pid_directory(pid)) +{ +} + +ErrorOr ProcFSProcessDirectoryInode::attach(OpenFileDescription&) +{ + return {}; +} + +InodeMetadata ProcFSProcessDirectoryInode::metadata() const +{ + MutexLocker locker(m_inode_lock); + auto process = Process::from_pid_in_same_jail(associated_pid()); + if (!process) + return {}; + + auto traits = process->procfs_traits(); + InodeMetadata metadata; + metadata.inode = { fsid(), traits->component_index() }; + metadata.mode = S_IFDIR | traits->required_mode(); + metadata.uid = traits->owner_user(); + metadata.gid = traits->owner_group(); + metadata.size = 0; + metadata.mtime = traits->modified_time(); + return metadata; +} + +ErrorOr ProcFSProcessDirectoryInode::read_bytes_locked(off_t, size_t, UserOrKernelBuffer&, OpenFileDescription*) const +{ + VERIFY_NOT_REACHED(); +} + +ErrorOr ProcFSProcessDirectoryInode::traverse_as_directory(Function(FileSystem::DirectoryEntryView const&)> callback) const +{ + MutexLocker locker(procfs().m_lock); + auto process = Process::from_pid_in_same_jail(associated_pid()); + if (!process) + return EINVAL; + return process->procfs_traits()->traverse_as_directory(procfs().fsid(), move(callback)); +} + +ErrorOr> ProcFSProcessDirectoryInode::lookup(StringView name) +{ + MutexLocker locker(procfs().m_lock); + auto process = Process::from_pid_in_same_jail(associated_pid()); + if (!process) + return ESRCH; + if (name == "fd"sv) + return TRY(ProcFSProcessSubDirectoryInode::try_create(procfs(), SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions, associated_pid())); + if (name == "stacks"sv) + return TRY(ProcFSProcessSubDirectoryInode::try_create(procfs(), SegmentedProcFSIndex::ProcessSubDirectory::Stacks, associated_pid())); + if (name == "children"sv) + return TRY(ProcFSProcessSubDirectoryInode::try_create(procfs(), SegmentedProcFSIndex::ProcessSubDirectory::Children, associated_pid())); + if (name == "unveil"sv) + return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::Unveil, associated_pid())); + if (name == "pledge"sv) + return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::Pledge, associated_pid())); + if (name == "fds"sv) + return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::OpenFileDescriptions, associated_pid())); + if (name == "exe"sv) + return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::BinaryLink, associated_pid())); + if (name == "cwd"sv) + return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::CurrentWorkDirectoryLink, associated_pid())); + if (name == "perf_events"sv) + return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::PerformanceEvents, associated_pid())); + if (name == "vm"sv) + return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::VirtualMemoryStats, associated_pid())); + if (name == "cmdline"sv) + return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::CommandLine, associated_pid())); + return ENOENT; +} + +} diff --git a/Kernel/FileSystem/ProcFS/ProcessDirectoryInode.h b/Kernel/FileSystem/ProcFS/ProcessDirectoryInode.h new file mode 100644 index 0000000000..e3e9fb758a --- /dev/null +++ b/Kernel/FileSystem/ProcFS/ProcessDirectoryInode.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Kernel { + +class ProcFSProcessDirectoryInode final : public ProcFSProcessAssociatedInode { + friend class ProcFS; + +public: + static ErrorOr> try_create(ProcFS const&, ProcessID); + +private: + ProcFSProcessDirectoryInode(ProcFS const&, ProcessID); + // ^Inode + virtual ErrorOr attach(OpenFileDescription& description) override; + virtual void did_seek(OpenFileDescription&, off_t) override { } + virtual InodeMetadata metadata() const override; + virtual ErrorOr traverse_as_directory(Function(FileSystem::DirectoryEntryView const&)>) const override; + virtual ErrorOr read_bytes_locked(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const override final; + virtual ErrorOr> lookup(StringView name) override; +}; + +} diff --git a/Kernel/FileSystem/ProcFS/ProcessPropertyInode.cpp b/Kernel/FileSystem/ProcFS/ProcessPropertyInode.cpp new file mode 100644 index 0000000000..5e701615b1 --- /dev/null +++ b/Kernel/FileSystem/ProcFS/ProcessPropertyInode.cpp @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2018-2021, Andreas Kling + * Copyright (c) 2021, Spencer Dixon + * Copyright (c) 2021, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include + +namespace Kernel { + +ErrorOr> ProcFSProcessPropertyInode::try_create_for_file_description_link(ProcFS const& procfs, unsigned file_description_index, ProcessID pid) +{ + return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSProcessPropertyInode(procfs, file_description_index, pid)); +} + +ErrorOr> ProcFSProcessPropertyInode::try_create_for_thread_stack(ProcFS const& procfs, ThreadID stack_thread_index, ProcessID pid) +{ + return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSProcessPropertyInode(procfs, stack_thread_index, pid)); +} + +ErrorOr> ProcFSProcessPropertyInode::try_create_for_pid_property(ProcFS const& procfs, SegmentedProcFSIndex::MainProcessProperty main_property_type, ProcessID pid) +{ + return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSProcessPropertyInode(procfs, main_property_type, pid)); +} + +ErrorOr> ProcFSProcessPropertyInode::try_create_for_child_process_link(ProcFS const& procfs, ProcessID child_pid, ProcessID pid) +{ + return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSProcessPropertyInode(procfs, child_pid, pid)); +} + +ProcFSProcessPropertyInode::ProcFSProcessPropertyInode(ProcFS const& procfs, SegmentedProcFSIndex::MainProcessProperty main_property_type, ProcessID pid) + : ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_main_property_in_pid_directory(pid, main_property_type)) + , m_parent_sub_directory_type(SegmentedProcFSIndex::ProcessSubDirectory::Reserved) +{ + m_possible_data.property_type = main_property_type; +} + +ProcFSProcessPropertyInode::ProcFSProcessPropertyInode(ProcFS const& procfs, unsigned file_description_index, ProcessID pid) + : ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_file_description(pid, file_description_index)) + , m_parent_sub_directory_type(SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions) +{ + m_possible_data.property_index = file_description_index; +} + +ProcFSProcessPropertyInode::ProcFSProcessPropertyInode(ProcFS const& procfs, ThreadID thread_stack_index, ProcessID pid) + : ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_thread_stack(pid, thread_stack_index)) + , m_parent_sub_directory_type(SegmentedProcFSIndex::ProcessSubDirectory::Stacks) +{ + m_possible_data.property_index = thread_stack_index.value(); +} + +ProcFSProcessPropertyInode::ProcFSProcessPropertyInode(ProcFS const& procfs, ProcessID child_pid, ProcessID pid) + : ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_children(pid, child_pid)) + , m_parent_sub_directory_type(SegmentedProcFSIndex::ProcessSubDirectory::Children) +{ + m_possible_data.property_index = child_pid.value(); +} + +ErrorOr ProcFSProcessPropertyInode::attach(OpenFileDescription& description) +{ + return refresh_data(description); +} + +void ProcFSProcessPropertyInode::did_seek(OpenFileDescription& description, off_t offset) +{ + if (offset != 0) + return; + (void)refresh_data(description); +} + +static mode_t determine_procfs_process_inode_mode(SegmentedProcFSIndex::ProcessSubDirectory parent_sub_directory_type, SegmentedProcFSIndex::MainProcessProperty main_property) +{ + if (parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions) + return S_IFLNK | 0400; + if (parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Stacks) + return S_IFREG | 0400; + if (parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Children) + return S_IFLNK | 0400; + VERIFY(parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Reserved); + if (main_property == SegmentedProcFSIndex::MainProcessProperty::BinaryLink) + return S_IFLNK | 0777; + if (main_property == SegmentedProcFSIndex::MainProcessProperty::CurrentWorkDirectoryLink) + return S_IFLNK | 0777; + return S_IFREG | 0400; +} + +InodeMetadata ProcFSProcessPropertyInode::metadata() const +{ + MutexLocker locker(m_inode_lock); + auto process = Process::from_pid_in_same_jail(associated_pid()); + if (!process) + return {}; + + auto traits = process->procfs_traits(); + InodeMetadata metadata; + metadata.inode = { fsid(), traits->component_index() }; + metadata.mode = determine_procfs_process_inode_mode(m_parent_sub_directory_type, m_possible_data.property_type); + metadata.uid = traits->owner_user(); + metadata.gid = traits->owner_group(); + metadata.size = 0; + metadata.mtime = traits->modified_time(); + return metadata; +} + +ErrorOr ProcFSProcessPropertyInode::traverse_as_directory(Function(FileSystem::DirectoryEntryView const&)>) const +{ + VERIFY_NOT_REACHED(); +} + +ErrorOr ProcFSProcessPropertyInode::read_bytes_locked(off_t offset, size_t count, UserOrKernelBuffer& buffer, OpenFileDescription* description) const +{ + dbgln_if(PROCFS_DEBUG, "ProcFS ProcessInformation: read_bytes_locked offset: {} count: {}", offset, count); + + VERIFY(offset >= 0); + VERIFY(buffer.user_or_kernel_ptr()); + + if (!description) { + auto builder = TRY(KBufferBuilder::try_create()); + auto process = Process::from_pid_in_same_jail(associated_pid()); + if (!process) + return Error::from_errno(ESRCH); + TRY(try_to_acquire_data(*process, builder)); + auto data_buffer = builder.build(); + if (!data_buffer) + return Error::from_errno(EFAULT); + ssize_t nread = min(static_cast(data_buffer->size() - offset), static_cast(count)); + TRY(buffer.write(data_buffer->data() + offset, nread)); + return nread; + } + if (!description->data()) { + dbgln("ProcFS Process Information: Do not have cached data!"); + return Error::from_errno(EIO); + } + + MutexLocker locker(m_refresh_lock); + + auto& typed_cached_data = static_cast(*description->data()); + auto& data_buffer = typed_cached_data.buffer; + + if (!data_buffer || (size_t)offset >= data_buffer->size()) + return 0; + + ssize_t nread = min(static_cast(data_buffer->size() - offset), static_cast(count)); + TRY(buffer.write(data_buffer->data() + offset, nread)); + + return nread; +} + +ErrorOr> ProcFSProcessPropertyInode::lookup(StringView) +{ + return EINVAL; +} + +static ErrorOr build_from_cached_data(KBufferBuilder& builder, ProcFSInodeData& cached_data) +{ + cached_data.buffer = builder.build(); + if (!cached_data.buffer) + return ENOMEM; + return {}; +} + +ErrorOr ProcFSProcessPropertyInode::try_to_acquire_data(Process& process, KBufferBuilder& builder) const +{ + // FIXME: Verify process is already ref-counted + if (m_parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions) { + TRY(process.procfs_get_file_description_link(m_possible_data.property_index, builder)); + return {}; + } + if (m_parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Stacks) { + TRY(process.procfs_get_thread_stack(m_possible_data.property_index, builder)); + return {}; + } + if (m_parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Children) { + TRY(process.procfs_get_child_proccess_link(m_possible_data.property_index, builder)); + return {}; + } + + VERIFY(m_parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Reserved); + switch (m_possible_data.property_type) { + case SegmentedProcFSIndex::MainProcessProperty::Unveil: + return process.procfs_get_unveil_stats(builder); + case SegmentedProcFSIndex::MainProcessProperty::Pledge: + return process.procfs_get_pledge_stats(builder); + case SegmentedProcFSIndex::MainProcessProperty::OpenFileDescriptions: + return process.procfs_get_fds_stats(builder); + case SegmentedProcFSIndex::MainProcessProperty::BinaryLink: + return process.procfs_get_binary_link(builder); + case SegmentedProcFSIndex::MainProcessProperty::CurrentWorkDirectoryLink: + return process.procfs_get_current_work_directory_link(builder); + case SegmentedProcFSIndex::MainProcessProperty::PerformanceEvents: + return process.procfs_get_perf_events(builder); + case SegmentedProcFSIndex::MainProcessProperty::VirtualMemoryStats: + return process.procfs_get_virtual_memory_stats(builder); + case SegmentedProcFSIndex::MainProcessProperty::CommandLine: + return process.procfs_get_command_line(builder); + default: + VERIFY_NOT_REACHED(); + } +} + +ErrorOr ProcFSProcessPropertyInode::refresh_data(OpenFileDescription& description) +{ + // For process-specific inodes, hold the process's ptrace lock across refresh + // and refuse to load data if the process is not dumpable. + // Without this, files opened before a process went non-dumpable could still be used for dumping. + auto process = Process::from_pid_in_same_jail(associated_pid()); + if (!process) + return Error::from_errno(ESRCH); + process->ptrace_lock().lock(); + if (!process->is_dumpable()) { + process->ptrace_lock().unlock(); + return EPERM; + } + ScopeGuard guard = [&] { + process->ptrace_lock().unlock(); + }; + MutexLocker locker(m_refresh_lock); + auto& cached_data = description.data(); + if (!cached_data) { + cached_data = adopt_own_if_nonnull(new (nothrow) ProcFSInodeData); + if (!cached_data) + return ENOMEM; + } + auto builder = TRY(KBufferBuilder::try_create()); + TRY(try_to_acquire_data(*process, builder)); + return build_from_cached_data(builder, static_cast(*cached_data)); +} + +} diff --git a/Kernel/FileSystem/ProcFS/ProcessPropertyInode.h b/Kernel/FileSystem/ProcFS/ProcessPropertyInode.h new file mode 100644 index 0000000000..9340d63080 --- /dev/null +++ b/Kernel/FileSystem/ProcFS/ProcessPropertyInode.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace Kernel { + +class ProcFSProcessPropertyInode final : public ProcFSProcessAssociatedInode { + friend class ProcFS; + +public: + static ErrorOr> try_create_for_file_description_link(ProcFS const&, unsigned, ProcessID); + static ErrorOr> try_create_for_thread_stack(ProcFS const&, ThreadID, ProcessID); + static ErrorOr> try_create_for_pid_property(ProcFS const&, SegmentedProcFSIndex::MainProcessProperty, ProcessID); + static ErrorOr> try_create_for_child_process_link(ProcFS const&, ProcessID, ProcessID); + +private: + ProcFSProcessPropertyInode(ProcFS const&, SegmentedProcFSIndex::MainProcessProperty, ProcessID); + ProcFSProcessPropertyInode(ProcFS const&, ThreadID, ProcessID); + ProcFSProcessPropertyInode(ProcFS const&, unsigned, ProcessID); + ProcFSProcessPropertyInode(ProcFS const&, ProcessID, ProcessID); + + // ^Inode + virtual ErrorOr attach(OpenFileDescription& description) override; + virtual void did_seek(OpenFileDescription&, off_t) override; + virtual InodeMetadata metadata() const override; + virtual ErrorOr traverse_as_directory(Function(FileSystem::DirectoryEntryView const&)>) const override; + virtual ErrorOr read_bytes_locked(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const override final; + virtual ErrorOr> lookup(StringView name) override final; + + ErrorOr refresh_data(OpenFileDescription& description); + ErrorOr try_to_acquire_data(Process& process, KBufferBuilder& builder) const; + + const SegmentedProcFSIndex::ProcessSubDirectory m_parent_sub_directory_type; + union { + SegmentedProcFSIndex::MainProcessProperty property_type; + unsigned property_index; + } m_possible_data; + mutable Mutex m_refresh_lock; +}; +} diff --git a/Kernel/FileSystem/ProcFS/ProcessSubDirectoryInode.cpp b/Kernel/FileSystem/ProcFS/ProcessSubDirectoryInode.cpp new file mode 100644 index 0000000000..843daede7d --- /dev/null +++ b/Kernel/FileSystem/ProcFS/ProcessSubDirectoryInode.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2018-2021, Andreas Kling + * Copyright (c) 2021, Spencer Dixon + * Copyright (c) 2021, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +namespace Kernel { + +ErrorOr> ProcFSProcessSubDirectoryInode::try_create(ProcFS const& procfs, SegmentedProcFSIndex::ProcessSubDirectory sub_directory_type, ProcessID pid) +{ + return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSProcessSubDirectoryInode(procfs, sub_directory_type, pid)); +} + +ProcFSProcessSubDirectoryInode::ProcFSProcessSubDirectoryInode(ProcFS const& procfs, SegmentedProcFSIndex::ProcessSubDirectory sub_directory_type, ProcessID pid) + : ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_sub_directory(pid, sub_directory_type)) + , m_sub_directory_type(sub_directory_type) +{ +} + +ErrorOr ProcFSProcessSubDirectoryInode::read_bytes_locked(off_t, size_t, UserOrKernelBuffer&, OpenFileDescription*) const +{ + VERIFY_NOT_REACHED(); +} + +ErrorOr ProcFSProcessSubDirectoryInode::attach(OpenFileDescription&) +{ + return {}; +} + +void ProcFSProcessSubDirectoryInode::did_seek(OpenFileDescription&, off_t) +{ + VERIFY_NOT_REACHED(); +} + +InodeMetadata ProcFSProcessSubDirectoryInode::metadata() const +{ + MutexLocker locker(m_inode_lock); + auto process = Process::from_pid_in_same_jail(associated_pid()); + if (!process) + return {}; + + auto traits = process->procfs_traits(); + InodeMetadata metadata; + metadata.inode = { fsid(), traits->component_index() }; + metadata.mode = S_IFDIR | traits->required_mode(); + metadata.uid = traits->owner_user(); + metadata.gid = traits->owner_group(); + metadata.size = 0; + metadata.mtime = traits->modified_time(); + return metadata; +} + +ErrorOr ProcFSProcessSubDirectoryInode::traverse_as_directory(Function(FileSystem::DirectoryEntryView const&)> callback) const +{ + MutexLocker locker(procfs().m_lock); + auto process = Process::from_pid_in_same_jail(associated_pid()); + if (!process) + return EINVAL; + switch (m_sub_directory_type) { + case SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions: + return process->traverse_file_descriptions_directory(procfs().fsid(), move(callback)); + case SegmentedProcFSIndex::ProcessSubDirectory::Stacks: + return process->traverse_stacks_directory(procfs().fsid(), move(callback)); + case SegmentedProcFSIndex::ProcessSubDirectory::Children: + return process->traverse_children_directory(procfs().fsid(), move(callback)); + default: + VERIFY_NOT_REACHED(); + } + VERIFY_NOT_REACHED(); +} + +ErrorOr> ProcFSProcessSubDirectoryInode::lookup(StringView name) +{ + MutexLocker locker(procfs().m_lock); + auto process = Process::from_pid_in_same_jail(associated_pid()); + if (!process) + return ESRCH; + switch (m_sub_directory_type) { + case SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions: + return process->lookup_file_descriptions_directory(procfs(), name); + case SegmentedProcFSIndex::ProcessSubDirectory::Stacks: + return process->lookup_stacks_directory(procfs(), name); + case SegmentedProcFSIndex::ProcessSubDirectory::Children: + return process->lookup_children_directory(procfs(), name); + default: + VERIFY_NOT_REACHED(); + } +} + +} diff --git a/Kernel/FileSystem/ProcFS/ProcessSubDirectoryInode.h b/Kernel/FileSystem/ProcFS/ProcessSubDirectoryInode.h new file mode 100644 index 0000000000..4a64281194 --- /dev/null +++ b/Kernel/FileSystem/ProcFS/ProcessSubDirectoryInode.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace Kernel { + +class ProcFSProcessSubDirectoryInode final : public ProcFSProcessAssociatedInode { + friend class ProcFS; + +public: + static ErrorOr> try_create(ProcFS const&, SegmentedProcFSIndex::ProcessSubDirectory, ProcessID); + +private: + ProcFSProcessSubDirectoryInode(ProcFS const&, SegmentedProcFSIndex::ProcessSubDirectory, ProcessID); + // ^Inode + virtual ErrorOr attach(OpenFileDescription& description) override; + virtual void did_seek(OpenFileDescription&, off_t) override; + virtual InodeMetadata metadata() const override; + virtual ErrorOr traverse_as_directory(Function(FileSystem::DirectoryEntryView const&)>) const override; + virtual ErrorOr read_bytes_locked(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const override final; + virtual ErrorOr> lookup(StringView name) override; + + const SegmentedProcFSIndex::ProcessSubDirectory m_sub_directory_type; +}; + +} diff --git a/Kernel/ProcessExposed.cpp b/Kernel/ProcessExposed.cpp index 1891dd8567..d9f9315f48 100644 --- a/Kernel/ProcessExposed.cpp +++ b/Kernel/ProcessExposed.cpp @@ -5,9 +5,8 @@ */ #include -#include -#include -#include +#include +#include #include #include #include diff --git a/Kernel/ProcessProcFSTraits.cpp b/Kernel/ProcessProcFSTraits.cpp index b664165e47..0686cb9d96 100644 --- a/Kernel/ProcessProcFSTraits.cpp +++ b/Kernel/ProcessProcFSTraits.cpp @@ -4,8 +4,9 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include +#include namespace Kernel { diff --git a/Kernel/ProcessSpecificExposed.cpp b/Kernel/ProcessSpecificExposed.cpp index 19b5b09286..df86e04943 100644 --- a/Kernel/ProcessSpecificExposed.cpp +++ b/Kernel/ProcessSpecificExposed.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Kernel/Storage/ATA/GenericIDE/Controller.cpp b/Kernel/Storage/ATA/GenericIDE/Controller.cpp index e9d73510fe..1f1aea0e8e 100644 --- a/Kernel/Storage/ATA/GenericIDE/Controller.cpp +++ b/Kernel/Storage/ATA/GenericIDE/Controller.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include diff --git a/Kernel/Storage/NVMe/NVMeController.cpp b/Kernel/Storage/NVMe/NVMeController.cpp index dab462ddb7..e03ae9e809 100644 --- a/Kernel/Storage/NVMe/NVMeController.cpp +++ b/Kernel/Storage/NVMe/NVMeController.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff --git a/Kernel/Syscalls/mount.cpp b/Kernel/Syscalls/mount.cpp index 099ece7e58..41828fd178 100644 --- a/Kernel/Syscalls/mount.cpp +++ b/Kernel/Syscalls/mount.cpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include