/* * Copyright (c) 2021, Liav A. * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include namespace Kernel { class ProcFS; class ProcFSExposedComponent; class ProcFSExposedFolder; class ProcFSRootFolder; class ProcFSBusDirectory; class ProcFSSystemBoolean; class ProcFSComponentsRegistrar { friend class ProcFS; friend class ProcFSExposedComponent; friend class ProcFSExposedFolder; friend class ProcFSRootFolder; public: static ProcFSComponentsRegistrar& the(); static void initialize(); InodeIndex allocate_inode_index() const; ProcFSComponentsRegistrar(); void register_new_bus_folder(ProcFSExposedFolder&); const ProcFSBusDirectory& buses_folder() const; void register_new_process(Process&); void unregister_process(Process&); ProcFSRootFolder& root_folder() { return *m_root_folder; } private: Lock m_lock; NonnullRefPtr m_root_folder; }; class ProcFSExposedComponent : public RefCounted { public: virtual KResultOr entries_count() const { VERIFY_NOT_REACHED(); }; StringView name() const { return m_name->view(); } virtual KResultOr read_bytes(off_t, size_t, UserOrKernelBuffer&, FileDescription*) const { VERIFY_NOT_REACHED(); } virtual KResult traverse_as_directory(unsigned, Function) const { VERIFY_NOT_REACHED(); } virtual RefPtr lookup(StringView) { VERIFY_NOT_REACHED(); }; virtual KResultOr write_bytes(off_t, size_t, const UserOrKernelBuffer&, FileDescription*) { return KResult(EROFS); } virtual size_t size() const { return 0; } virtual mode_t required_mode() const { return 0444; } virtual uid_t owner_user() const { return 0; } virtual gid_t owner_group() const { return 0; } time_t modified_time() const { return TimeManagement::now().to_timeval().tv_sec; } virtual void prepare_for_deletion() { } virtual KResult refresh_data(FileDescription&) const { return KSuccess; } virtual NonnullRefPtr to_inode(const ProcFS& procfs_instance) const; InodeIndex component_index() const { return m_component_index; }; virtual ~ProcFSExposedComponent() = default; protected: explicit ProcFSExposedComponent(StringView name); ProcFSExposedComponent(StringView name, InodeIndex preallocated_index); private: OwnPtr m_name; InodeIndex m_component_index {}; }; class ProcFSExposedFolder : public ProcFSExposedComponent { friend class ProcFSProcessFolder; friend class ProcFSComponentsRegistrar; public: virtual KResultOr entries_count() const override { return m_components.size(); }; virtual KResult traverse_as_directory(unsigned, Function) const override; virtual RefPtr lookup(StringView name) override; void add_component(const ProcFSExposedComponent&); virtual void prepare_for_deletion() override { m_components.clear(); m_parent_folder.clear(); } virtual mode_t required_mode() const override { return 0555; } virtual NonnullRefPtr to_inode(const ProcFS& procfs_instance) const override final; protected: explicit ProcFSExposedFolder(StringView name); ProcFSExposedFolder(StringView name, const ProcFSExposedFolder& parent_folder); NonnullRefPtrVector m_components; RefPtr m_parent_folder; }; class ProcFSExposedLink : public ProcFSExposedComponent { public: virtual NonnullRefPtr to_inode(const ProcFS& procfs_instance) const override final; virtual KResultOr read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, FileDescription* description) const override; protected: virtual bool acquire_link(KBufferBuilder& builder) = 0; explicit ProcFSExposedLink(StringView name); ProcFSExposedLink(StringView name, InodeIndex preallocated_index); mutable Lock m_lock { "ProcFSLink" }; }; class ProcFSRootFolder; class ProcFSProcessInformation; class ProcFSProcessFolder final : public ProcFSExposedFolder { friend class ProcFSComponentsRegistrar; friend class ProcFSRootFolder; friend class ProcFSProcessInformation; friend class ProcFSProcessUnveil; friend class ProcFSProcessPerformanceEvents; friend class ProcFSProcessFileDescription; friend class ProcFSProcessFileDescriptions; friend class ProcFSProcessOverallFileDescriptions; friend class ProcFSProcessRoot; friend class ProcFSProcessVirtualMemory; friend class ProcFSProcessCurrentWorkDirectory; friend class ProcFSProcessBinary; friend class ProcFSProcessStacks; public: static NonnullRefPtr create(const Process&); NonnullRefPtr associated_process() { return m_associated_process; } virtual uid_t owner_user() const override { return m_associated_process->uid(); } virtual gid_t owner_group() const override { return m_associated_process->gid(); } private: IntrusiveListNode> m_list_node; explicit ProcFSProcessFolder(const Process&); NonnullRefPtr m_associated_process; }; class ProcFSRootFolder; class ProcFSBusDirectory : public ProcFSExposedFolder { friend class ProcFSComponentsRegistrar; public: static NonnullRefPtr must_create(const ProcFSRootFolder& parent_folder); private: ProcFSBusDirectory(const ProcFSRootFolder& parent_folder); }; class ProcFSRootFolder final : public ProcFSExposedFolder { friend class ProcFSComponentsRegistrar; public: virtual RefPtr lookup(StringView name) override; RefPtr process_folder_for(Process&); static NonnullRefPtr must_create(); virtual ~ProcFSRootFolder(); private: virtual KResult traverse_as_directory(unsigned, Function) const override; ProcFSRootFolder(); RefPtr m_buses_folder; IntrusiveList, &ProcFSProcessFolder::m_list_node> m_process_folders; }; class ProcFSGlobalInformation : public ProcFSExposedComponent { public: virtual ~ProcFSGlobalInformation() override {}; virtual KResultOr read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, FileDescription* description) const override; virtual mode_t required_mode() const override { return 0444; } protected: explicit ProcFSGlobalInformation(StringView name) : ProcFSExposedComponent(name) { } virtual KResult refresh_data(FileDescription&) const override; virtual bool output(KBufferBuilder& builder) = 0; mutable SpinLock m_refresh_lock; }; class ProcFSSystemBoolean : public ProcFSGlobalInformation { public: virtual bool value() const = 0; virtual void set_value(bool new_value) = 0; protected: explicit ProcFSSystemBoolean(StringView name) : ProcFSGlobalInformation(name) { } virtual bool output(KBufferBuilder& builder) override { builder.appendff("{}\n", value()); return true; } }; class ProcFSProcessInformation : public ProcFSExposedComponent { public: virtual ~ProcFSProcessInformation() override {}; virtual KResultOr read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, FileDescription* description) const override; virtual uid_t owner_user() const override { return m_parent_folder->m_associated_process->uid(); } virtual gid_t owner_group() const override { return m_parent_folder->m_associated_process->gid(); } protected: ProcFSProcessInformation(StringView name, const ProcFSProcessFolder& process_folder) : ProcFSExposedComponent(name) , m_parent_folder(process_folder) { } virtual KResult refresh_data(FileDescription&) const override; virtual bool output(KBufferBuilder& builder) = 0; NonnullRefPtr m_parent_folder; mutable SpinLock m_refresh_lock; }; }