From 39bc6c43dc974f3213787a3a61df676cb9ab6d17 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Sat, 30 Sep 2023 23:01:33 +0300 Subject: [PATCH] Kernel: Expose command line and environment to /proc --- kernel/include/kernel/FS/ProcFS/Inode.h | 9 +-- kernel/include/kernel/Process.h | 7 +- kernel/kernel/FS/ProcFS/Inode.cpp | 24 +++---- kernel/kernel/Process.cpp | 94 +++++++++++++++++++------ 4 files changed, 94 insertions(+), 40 deletions(-) diff --git a/kernel/include/kernel/FS/ProcFS/Inode.h b/kernel/include/kernel/FS/ProcFS/Inode.h index a71164c491..4300721e1c 100644 --- a/kernel/include/kernel/FS/ProcFS/Inode.h +++ b/kernel/include/kernel/FS/ProcFS/Inode.h @@ -20,11 +20,11 @@ namespace Kernel Process& m_process; }; - class ProcMemInode final : public RamInode + class ProcROInode final : public RamInode { public: - static BAN::ErrorOr> create(Process&, RamFileSystem&, mode_t, uid_t, gid_t); - ~ProcMemInode() = default; + static BAN::ErrorOr> create(Process&, size_t (Process::*callback)(off_t, void*, size_t) const, RamFileSystem&, mode_t, uid_t, gid_t); + ~ProcROInode() = default; protected: virtual BAN::ErrorOr read_impl(off_t, void*, size_t) override; @@ -35,10 +35,11 @@ namespace Kernel virtual bool has_data_impl() const override { return true; } private: - ProcMemInode(Process&, RamFileSystem&, const FullInodeInfo&); + ProcROInode(Process&, size_t (Process::*)(off_t, void*, size_t) const, RamFileSystem&, const FullInodeInfo&); private: Process& m_process; + size_t (Process::*m_callback)(off_t, void*, size_t) const; }; } diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index 625d34c67e..a0b23e9668 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -139,7 +139,9 @@ namespace Kernel PageTable& page_table() { return m_page_table ? *m_page_table : PageTable::kernel(); } - void get_meminfo(proc_meminfo_t*) const; + size_t proc_meminfo(off_t offset, void* buffer, size_t buffer_size) const; + size_t proc_cmdline(off_t offset, void* buffer, size_t buffer_size) const; + size_t proc_environ(off_t offset, void* buffer, size_t buffer_size) const; bool is_userspace() const { return m_is_userspace; } const userspace_info_t& userspace_info() const { return m_userspace_info; } @@ -192,6 +194,9 @@ namespace Kernel vaddr_t m_signal_handlers[_SIGMAX + 1] { }; uint64_t m_signal_pending_mask { 0 }; + BAN::Vector m_cmdline; + BAN::Vector m_environ; + bool m_is_userspace { false }; userspace_info_t m_userspace_info; ExitStatus m_exit_status; diff --git a/kernel/kernel/FS/ProcFS/Inode.cpp b/kernel/kernel/FS/ProcFS/Inode.cpp index fdba47e3f0..7bc0a3920d 100644 --- a/kernel/kernel/FS/ProcFS/Inode.cpp +++ b/kernel/kernel/FS/ProcFS/Inode.cpp @@ -12,7 +12,9 @@ namespace Kernel return BAN::Error::from_errno(ENOMEM); auto inode = BAN::RefPtr::adopt(inode_ptr); - TRY(inode->add_inode("meminfo"sv, MUST(ProcMemInode::create(process, fs, 0755, 0, 0)))); + TRY(inode->add_inode("meminfo"sv, MUST(ProcROInode::create(process, &Process::proc_meminfo, fs, 0755, 0, 0)))); + TRY(inode->add_inode("cmdline"sv, MUST(ProcROInode::create(process, &Process::proc_cmdline, fs, 0755, 0, 0)))); + TRY(inode->add_inode("environ"sv, MUST(ProcROInode::create(process, &Process::proc_environ, fs, 0755, 0, 0)))); return inode; } @@ -23,36 +25,30 @@ namespace Kernel { } - BAN::ErrorOr> ProcMemInode::create(Process& process, RamFileSystem& fs, mode_t mode, uid_t uid, gid_t gid) + BAN::ErrorOr> ProcROInode::create(Process& process, size_t (Process::*callback)(off_t, void*, size_t) const, RamFileSystem& fs, mode_t mode, uid_t uid, gid_t gid) { FullInodeInfo inode_info(fs, mode, uid, gid); - auto* inode_ptr = new ProcMemInode(process, fs, inode_info); + auto* inode_ptr = new ProcROInode(process, callback, fs, inode_info); if (inode_ptr == nullptr) return BAN::Error::from_errno(ENOMEM); - return BAN::RefPtr::adopt(inode_ptr); + return BAN::RefPtr::adopt(inode_ptr); } - ProcMemInode::ProcMemInode(Process& process, RamFileSystem& fs, const FullInodeInfo& inode_info) + ProcROInode::ProcROInode(Process& process, size_t (Process::*callback)(off_t, void*, size_t) const, RamFileSystem& fs, const FullInodeInfo& inode_info) : RamInode(fs, inode_info) , m_process(process) + , m_callback(callback) { m_inode_info.mode |= Inode::Mode::IFREG; } - BAN::ErrorOr ProcMemInode::read_impl(off_t offset, void* buffer, size_t buffer_size) + BAN::ErrorOr ProcROInode::read_impl(off_t offset, void* buffer, size_t buffer_size) { ASSERT(offset >= 0); if ((size_t)offset >= sizeof(proc_meminfo_t)) return 0; - - proc_meminfo_t meminfo; - m_process.get_meminfo(&meminfo); - - size_t bytes = BAN::Math::min(buffer_size, sizeof(meminfo) - offset); - memcpy(buffer, &meminfo, bytes); - - return bytes; + return (m_process.*m_callback)(offset, buffer, buffer_size); } } diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index cca2ee7fe8..acce6aef83 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -119,6 +119,9 @@ namespace Kernel MUST(process->m_working_directory.push_back('/')); process->m_page_table = BAN::UniqPtr::adopt(MUST(PageTable::create_userspace())); + TRY(process->m_cmdline.push_back({})); + TRY(process->m_cmdline.back().append(path)); + process->m_loadable_elf = TRY(load_elf_for_exec(credentials, path, "/"sv, process->page_table())); process->m_loadable_elf->reserve_address_space(); @@ -252,29 +255,75 @@ namespace Kernel thread->set_terminating(); } - void Process::get_meminfo(proc_meminfo_t* out) const + size_t Process::proc_meminfo(off_t offset, void* buffer, size_t buffer_size) const + { + ASSERT(offset >= 0); + if ((size_t)offset >= sizeof(proc_meminfo_t)) + return 0; + + proc_meminfo_t meminfo; + meminfo.page_size = PAGE_SIZE; + meminfo.virt_pages = 0; + meminfo.phys_pages = 0; + + { + LockGuard _(m_lock); + for (auto* thread : m_threads) + { + meminfo.virt_pages += thread->virtual_page_count(); + meminfo.phys_pages += thread->physical_page_count(); + } + for (auto& region : m_mapped_regions) + { + meminfo.virt_pages += region->virtual_page_count(); + meminfo.phys_pages += region->physical_page_count(); + } + if (m_loadable_elf) + { + meminfo.virt_pages += m_loadable_elf->virtual_page_count(); + meminfo.phys_pages += m_loadable_elf->physical_page_count(); + } + } + + size_t bytes = BAN::Math::min(sizeof(proc_meminfo_t) - offset, buffer_size); + memcpy(buffer, (uint8_t*)&meminfo + offset, bytes); + return bytes; + } + + static size_t read_from_vec_of_str(const BAN::Vector& container, size_t start, void* buffer, size_t buffer_size) + { + size_t offset = 0; + size_t written = 0; + for (const auto& elem : container) + { + if (start < offset + elem.size() + 1) + { + size_t elem_offset = 0; + if (offset < start) + elem_offset = start - offset; + + size_t bytes = BAN::Math::min(elem.size() + 1 - elem_offset, buffer_size - written); + memcpy((uint8_t*)buffer + written, elem.data() + elem_offset, bytes); + + written += bytes; + if (written >= buffer_size) + break; + } + offset += elem.size() + 1; + } + return written; + } + + size_t Process::proc_cmdline(off_t offset, void* buffer, size_t buffer_size) const { LockGuard _(m_lock); + return read_from_vec_of_str(m_cmdline, offset, buffer, buffer_size); + } - out->page_size = PAGE_SIZE; - out->virt_pages = 0; - out->phys_pages = 0; - - for (auto* thread : m_threads) - { - out->virt_pages += thread->virtual_page_count(); - out->phys_pages += thread->physical_page_count(); - } - for (auto& region : m_mapped_regions) - { - out->virt_pages += region->virtual_page_count(); - out->phys_pages += region->physical_page_count(); - } - if (m_loadable_elf) - { - out->virt_pages += m_loadable_elf->virtual_page_count(); - out->phys_pages += m_loadable_elf->physical_page_count(); - } + size_t Process::proc_environ(off_t offset, void* buffer, size_t buffer_size) const + { + LockGuard _(m_lock); + return read_from_vec_of_str(m_environ, offset, buffer, buffer_size); } BAN::ErrorOr Process::sys_exit(int status) @@ -461,9 +510,12 @@ namespace Kernel auto envp_region = MUST(create_region(str_envp.span())); m_userspace_info.envp = (char**)envp_region->vaddr(); MUST(m_mapped_regions.push_back(BAN::move(envp_region))); - + m_userspace_info.argc = str_argv.size(); + m_cmdline = BAN::move(str_argv); + m_environ = BAN::move(str_envp); + asm volatile("cli"); }