diff --git a/Kernel/FileSystem/ProcFS.cpp b/Kernel/FileSystem/ProcFS.cpp index a6f3b98027..844c95d7a4 100644 --- a/Kernel/FileSystem/ProcFS.cpp +++ b/Kernel/FileSystem/ProcFS.cpp @@ -295,6 +295,8 @@ ErrorOr> ProcFSProcessDirectoryInode::lookup(StringView nam 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) @@ -367,6 +369,8 @@ ErrorOr ProcFSProcessSubDirectoryInode::traverse_as_directory(Functiontraverse_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(); } @@ -384,6 +388,8 @@ ErrorOr> ProcFSProcessSubDirectoryInode::lookup(StringView 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(); } @@ -401,6 +407,10 @@ ErrorOr> ProcFSProcessPropertyInode::t { return adopt_nonnull_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_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)) @@ -423,6 +433,13 @@ ProcFSProcessPropertyInode::ProcFSProcessPropertyInode(ProcFS const& procfs, Thr 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); @@ -440,6 +457,8 @@ static mode_t determine_procfs_process_inode_mode(SegmentedProcFSIndex::ProcessS 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; @@ -531,6 +550,10 @@ ErrorOr ProcFSProcessPropertyInode::try_to_acquire_data(Process& process, 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) { diff --git a/Kernel/FileSystem/ProcFS.h b/Kernel/FileSystem/ProcFS.h index 96c8e46237..97d5c9051b 100644 --- a/Kernel/FileSystem/ProcFS.h +++ b/Kernel/FileSystem/ProcFS.h @@ -172,11 +172,14 @@ 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; diff --git a/Kernel/Process.h b/Kernel/Process.h index 195ef0b3d9..fb460e08d1 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -591,6 +591,9 @@ public: ErrorOr procfs_get_file_description_link(unsigned fd, KBufferBuilder& builder) const; ErrorOr traverse_file_descriptions_directory(FileSystemID, Function(FileSystem::DirectoryEntryView const&)> callback) const; ErrorOr> lookup_file_descriptions_directory(ProcFS const&, StringView name) const; + ErrorOr> lookup_children_directory(ProcFS const&, StringView name) const; + ErrorOr traverse_children_directory(FileSystemID, Function(FileSystem::DirectoryEntryView const&)> callback) const; + ErrorOr procfs_get_child_proccess_link(ProcessID child_pid, KBufferBuilder& builder) const; private: inline PerformanceEventBuffer* current_perf_events_buffer() diff --git a/Kernel/ProcessExposed.cpp b/Kernel/ProcessExposed.cpp index 603e281d5e..2a37d06269 100644 --- a/Kernel/ProcessExposed.cpp +++ b/Kernel/ProcessExposed.cpp @@ -67,6 +67,11 @@ InodeIndex build_segmented_index_for_file_description(ProcessID pid, unsigned fd return build_segmented_index_with_unknown_property(pid, ProcessSubDirectory::OpenFileDescriptions, fd); } +InodeIndex build_segmented_index_for_children(ProcessID pid, ProcessID child_pid) +{ + return build_segmented_index_with_unknown_property(pid, ProcessSubDirectory::Children, child_pid.value()); +} + } static size_t s_allocate_global_inode_index() diff --git a/Kernel/ProcessExposed.h b/Kernel/ProcessExposed.h index 0f798ba166..5f8248e75a 100644 --- a/Kernel/ProcessExposed.h +++ b/Kernel/ProcessExposed.h @@ -36,6 +36,7 @@ enum class ProcessSubDirectory { Reserved = 0, OpenFileDescriptions = 1, Stacks = 2, + Children = 3 }; void read_segments(u32& primary, ProcessSubDirectory& sub_directory, MainProcessProperty& property); @@ -45,6 +46,8 @@ InodeIndex build_segmented_index_for_main_property(ProcessID, ProcessSubDirector InodeIndex build_segmented_index_for_main_property_in_pid_directory(ProcessID, MainProcessProperty property); InodeIndex build_segmented_index_for_thread_stack(ProcessID, ThreadID); InodeIndex build_segmented_index_for_file_description(ProcessID, unsigned); +InodeIndex build_segmented_index_for_children(ProcessID, ProcessID); + } class ProcFSComponentRegistry { diff --git a/Kernel/ProcessProcFSTraits.cpp b/Kernel/ProcessProcFSTraits.cpp index 97335f8891..45ff810d90 100644 --- a/Kernel/ProcessProcFSTraits.cpp +++ b/Kernel/ProcessProcFSTraits.cpp @@ -55,6 +55,7 @@ ErrorOr Process::ProcessProcFSTraits::traverse_as_directory(FileSystemID f TRY(callback({ "..", { fsid, ProcFSComponentRegistry::the().root_directory().component_index() }, DT_DIR })); TRY(callback({ "fd", { fsid, SegmentedProcFSIndex::build_segmented_index_for_sub_directory(process->pid(), SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions) }, DT_DIR })); TRY(callback({ "stacks", { fsid, SegmentedProcFSIndex::build_segmented_index_for_sub_directory(process->pid(), SegmentedProcFSIndex::ProcessSubDirectory::Stacks) }, DT_DIR })); + TRY(callback({ "children", { fsid, SegmentedProcFSIndex::build_segmented_index_for_sub_directory(process->pid(), SegmentedProcFSIndex::ProcessSubDirectory::Children) }, DT_DIR })); TRY(callback({ "unveil", { fsid, SegmentedProcFSIndex::build_segmented_index_for_main_property_in_pid_directory(process->pid(), SegmentedProcFSIndex::MainProcessProperty::Unveil) }, DT_REG })); TRY(callback({ "pledge", { fsid, SegmentedProcFSIndex::build_segmented_index_for_main_property_in_pid_directory(process->pid(), SegmentedProcFSIndex::MainProcessProperty::Pledge) }, DT_REG })); TRY(callback({ "fds", { fsid, SegmentedProcFSIndex::build_segmented_index_for_main_property_in_pid_directory(process->pid(), SegmentedProcFSIndex::MainProcessProperty::OpenFileDescriptions) }, DT_DIR })); diff --git a/Kernel/ProcessSpecificExposed.cpp b/Kernel/ProcessSpecificExposed.cpp index c43a016a41..653f1c786a 100644 --- a/Kernel/ProcessSpecificExposed.cpp +++ b/Kernel/ProcessSpecificExposed.cpp @@ -80,6 +80,41 @@ ErrorOr> Process::lookup_stacks_directory(ProcFS const& pro return thread_stack_inode.release_value(); } +ErrorOr Process::traverse_children_directory(FileSystemID fsid, Function(FileSystem::DirectoryEntryView const&)> callback) const +{ + TRY(callback({ ".", { fsid, SegmentedProcFSIndex::build_segmented_index_for_sub_directory(pid(), SegmentedProcFSIndex::ProcessSubDirectory::Children) }, 0 })); + TRY(callback({ "..", { fsid, m_procfs_traits->component_index() }, 0 })); + return Process::all_instances().with([&](auto& processes) -> ErrorOr { + for (auto& process : processes) { + if (process.ppid() == pid()) { + StringBuilder builder; + builder.appendff("{}", process.pid()); + TRY(callback({ builder.string_view(), { fsid, SegmentedProcFSIndex::build_segmented_index_for_children(pid(), process.pid()) }, DT_LNK })); + } + } + return {}; + }); +} + +ErrorOr> Process::lookup_children_directory(ProcFS const& procfs, StringView name) const +{ + auto maybe_pid = name.to_uint(); + if (!maybe_pid.has_value()) + return ENOENT; + + auto child_process = Process::from_pid(*maybe_pid); + if (!child_process || child_process->ppid() != pid()) + return ENOENT; + + return TRY(ProcFSProcessPropertyInode::try_create_for_child_process_link(procfs, *maybe_pid, pid())); +} + +ErrorOr Process::procfs_get_child_proccess_link(ProcessID child_pid, KBufferBuilder& builder) const +{ + TRY(builder.appendff("/proc/{}", child_pid.value())); + return builder.length(); +} + ErrorOr Process::procfs_get_file_description_link(unsigned fd, KBufferBuilder& builder) const { auto file_description = TRY(open_file_description(fd));