1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045 |
- /*
- * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
- * Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
- #include <AK/JsonObjectSerializer.h>
- #include <AK/Try.h>
- #include <AK/UBSanitizer.h>
- #include <Kernel/Arch/InterruptDisabler.h>
- #include <Kernel/Arch/InterruptManagement.h>
- #include <Kernel/Arch/x86/ProcessorInfo.h>
- #include <Kernel/Bus/PCI/API.h>
- #include <Kernel/Bus/PCI/Access.h>
- #include <Kernel/CommandLine.h>
- #include <Kernel/Devices/DeviceManagement.h>
- #include <Kernel/Devices/HID/HIDManagement.h>
- #include <Kernel/FileSystem/Custody.h>
- #include <Kernel/FileSystem/FileBackedFileSystem.h>
- #include <Kernel/FileSystem/OpenFileDescription.h>
- #include <Kernel/Heap/kmalloc.h>
- #include <Kernel/Interrupts/GenericInterruptHandler.h>
- #include <Kernel/KBufferBuilder.h>
- #include <Kernel/Net/LocalSocket.h>
- #include <Kernel/Net/NetworkingManagement.h>
- #include <Kernel/Net/Routing.h>
- #include <Kernel/Net/TCPSocket.h>
- #include <Kernel/Net/UDPSocket.h>
- #include <Kernel/Process.h>
- #include <Kernel/ProcessExposed.h>
- #include <Kernel/Scheduler.h>
- #include <Kernel/Sections.h>
- #include <Kernel/TTY/TTY.h>
- namespace Kernel {
- class ProcFSAdapters final : public ProcFSGlobalInformation {
- public:
- static NonnullRefPtr<ProcFSAdapters> must_create();
- private:
- ProcFSAdapters();
- virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
- {
- auto array = TRY(JsonArraySerializer<>::try_create(builder));
- TRY(NetworkingManagement::the().try_for_each([&array](auto& adapter) -> ErrorOr<void> {
- auto obj = TRY(array.add_object());
- TRY(obj.add("name"sv, adapter.name()));
- TRY(obj.add("class_name"sv, adapter.class_name()));
- auto mac_address = TRY(adapter.mac_address().to_string());
- TRY(obj.add("mac_address"sv, mac_address->view()));
- if (!adapter.ipv4_address().is_zero()) {
- auto ipv4_address = TRY(adapter.ipv4_address().to_string());
- TRY(obj.add("ipv4_address"sv, ipv4_address->view()));
- auto ipv4_netmask = TRY(adapter.ipv4_netmask().to_string());
- TRY(obj.add("ipv4_netmask"sv, ipv4_netmask->view()));
- }
- TRY(obj.add("packets_in"sv, adapter.packets_in()));
- TRY(obj.add("bytes_in"sv, adapter.bytes_in()));
- TRY(obj.add("packets_out"sv, adapter.packets_out()));
- TRY(obj.add("bytes_out"sv, adapter.bytes_out()));
- TRY(obj.add("link_up"sv, adapter.link_up()));
- TRY(obj.add("link_speed"sv, adapter.link_speed()));
- TRY(obj.add("link_full_duplex"sv, adapter.link_full_duplex()));
- TRY(obj.add("mtu"sv, adapter.mtu()));
- TRY(obj.finish());
- return {};
- }));
- TRY(array.finish());
- return {};
- }
- };
- class ProcFSARP final : public ProcFSGlobalInformation {
- public:
- static NonnullRefPtr<ProcFSARP> must_create();
- private:
- ProcFSARP();
- virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
- {
- auto array = TRY(JsonArraySerializer<>::try_create(builder));
- TRY(arp_table().with([&](auto const& table) -> ErrorOr<void> {
- for (auto& it : table) {
- auto obj = TRY(array.add_object());
- auto mac_address = TRY(it.value.to_string());
- TRY(obj.add("mac_address"sv, mac_address->view()));
- auto ip_address = TRY(it.key.to_string());
- TRY(obj.add("ip_address"sv, ip_address->view()));
- TRY(obj.finish());
- }
- return {};
- }));
- TRY(array.finish());
- return {};
- }
- };
- class ProcFSRoute final : public ProcFSGlobalInformation {
- public:
- static NonnullRefPtr<ProcFSRoute> must_create();
- private:
- ProcFSRoute();
- virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
- {
- auto array = TRY(JsonArraySerializer<>::try_create(builder));
- TRY(routing_table().with([&](auto const& table) -> ErrorOr<void> {
- for (auto& it : table) {
- auto obj = TRY(array.add_object());
- auto destination = TRY(it.destination.to_string());
- TRY(obj.add("destination"sv, destination->view()));
- auto gateway = TRY(it.gateway.to_string());
- TRY(obj.add("gateway"sv, gateway->view()));
- auto netmask = TRY(it.netmask.to_string());
- TRY(obj.add("genmask"sv, netmask->view()));
- TRY(obj.add("flags"sv, it.flags));
- TRY(obj.add("interface"sv, it.adapter->name()));
- TRY(obj.finish());
- }
- return {};
- }));
- TRY(array.finish());
- return {};
- }
- };
- class ProcFSTCP final : public ProcFSGlobalInformation {
- public:
- static NonnullRefPtr<ProcFSTCP> must_create();
- private:
- ProcFSTCP();
- virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
- {
- auto array = TRY(JsonArraySerializer<>::try_create(builder));
- TRY(TCPSocket::try_for_each([&array](auto& socket) -> ErrorOr<void> {
- auto obj = TRY(array.add_object());
- auto local_address = TRY(socket.local_address().to_string());
- TRY(obj.add("local_address"sv, local_address->view()));
- TRY(obj.add("local_port"sv, socket.local_port()));
- auto peer_address = TRY(socket.peer_address().to_string());
- TRY(obj.add("peer_address"sv, peer_address->view()));
- TRY(obj.add("peer_port"sv, socket.peer_port()));
- TRY(obj.add("state"sv, TCPSocket::to_string(socket.state())));
- TRY(obj.add("ack_number"sv, socket.ack_number()));
- TRY(obj.add("sequence_number"sv, socket.sequence_number()));
- TRY(obj.add("packets_in"sv, socket.packets_in()));
- TRY(obj.add("bytes_in"sv, socket.bytes_in()));
- TRY(obj.add("packets_out"sv, socket.packets_out()));
- TRY(obj.add("bytes_out"sv, socket.bytes_out()));
- if (Process::current().is_superuser() || Process::current().uid() == socket.origin_uid()) {
- TRY(obj.add("origin_pid"sv, socket.origin_pid().value()));
- TRY(obj.add("origin_uid"sv, socket.origin_uid().value()));
- TRY(obj.add("origin_gid"sv, socket.origin_gid().value()));
- }
- TRY(obj.finish());
- return {};
- }));
- TRY(array.finish());
- return {};
- }
- };
- class ProcFSLocalNet final : public ProcFSGlobalInformation {
- public:
- static NonnullRefPtr<ProcFSLocalNet> must_create();
- private:
- ProcFSLocalNet();
- virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
- {
- auto array = TRY(JsonArraySerializer<>::try_create(builder));
- TRY(LocalSocket::try_for_each([&array](auto& socket) -> ErrorOr<void> {
- auto obj = TRY(array.add_object());
- TRY(obj.add("path"sv, socket.socket_path()));
- TRY(obj.add("origin_pid"sv, socket.origin_pid().value()));
- TRY(obj.add("origin_uid"sv, socket.origin_uid().value()));
- TRY(obj.add("origin_gid"sv, socket.origin_gid().value()));
- TRY(obj.add("acceptor_pid"sv, socket.acceptor_pid().value()));
- TRY(obj.add("acceptor_uid"sv, socket.acceptor_uid().value()));
- TRY(obj.add("acceptor_gid"sv, socket.acceptor_gid().value()));
- TRY(obj.finish());
- return {};
- }));
- TRY(array.finish());
- return {};
- }
- };
- class ProcFSUDP final : public ProcFSGlobalInformation {
- public:
- static NonnullRefPtr<ProcFSUDP> must_create();
- private:
- ProcFSUDP();
- virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
- {
- auto array = TRY(JsonArraySerializer<>::try_create(builder));
- TRY(UDPSocket::try_for_each([&array](auto& socket) -> ErrorOr<void> {
- auto obj = TRY(array.add_object());
- auto local_address = TRY(socket.local_address().to_string());
- TRY(obj.add("local_address"sv, local_address->view()));
- TRY(obj.add("local_port"sv, socket.local_port()));
- auto peer_address = TRY(socket.peer_address().to_string());
- TRY(obj.add("peer_address"sv, peer_address->view()));
- TRY(obj.add("peer_port"sv, socket.peer_port()));
- if (Process::current().is_superuser() || Process::current().uid() == socket.origin_uid()) {
- TRY(obj.add("origin_pid"sv, socket.origin_pid().value()));
- TRY(obj.add("origin_uid"sv, socket.origin_uid().value()));
- TRY(obj.add("origin_gid"sv, socket.origin_gid().value()));
- }
- TRY(obj.finish());
- return {};
- }));
- TRY(array.finish());
- return {};
- }
- };
- class ProcFSNetworkDirectory : public ProcFSExposedDirectory {
- public:
- static NonnullRefPtr<ProcFSNetworkDirectory> must_create(ProcFSRootDirectory const& parent_directory);
- private:
- ProcFSNetworkDirectory(ProcFSRootDirectory const& parent_directory);
- };
- class ProcFSSystemDirectory : public ProcFSExposedDirectory {
- public:
- static NonnullRefPtr<ProcFSSystemDirectory> must_create(ProcFSRootDirectory const& parent_directory);
- private:
- ProcFSSystemDirectory(ProcFSRootDirectory const& parent_directory);
- };
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSAdapters> ProcFSAdapters::must_create()
- {
- return adopt_ref_if_nonnull(new (nothrow) ProcFSAdapters).release_nonnull();
- }
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSARP> ProcFSARP::must_create()
- {
- return adopt_ref_if_nonnull(new (nothrow) ProcFSARP).release_nonnull();
- }
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSRoute> ProcFSRoute::must_create()
- {
- return adopt_ref_if_nonnull(new (nothrow) ProcFSRoute).release_nonnull();
- }
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSTCP> ProcFSTCP::must_create()
- {
- return adopt_ref_if_nonnull(new (nothrow) ProcFSTCP).release_nonnull();
- }
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSLocalNet> ProcFSLocalNet::must_create()
- {
- return adopt_ref_if_nonnull(new (nothrow) ProcFSLocalNet).release_nonnull();
- }
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSUDP> ProcFSUDP::must_create()
- {
- return adopt_ref_if_nonnull(new (nothrow) ProcFSUDP).release_nonnull();
- }
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSNetworkDirectory> ProcFSNetworkDirectory::must_create(ProcFSRootDirectory const& parent_directory)
- {
- auto directory = adopt_ref(*new (nothrow) ProcFSNetworkDirectory(parent_directory));
- directory->m_components.append(ProcFSAdapters::must_create());
- directory->m_components.append(ProcFSARP::must_create());
- directory->m_components.append(ProcFSRoute::must_create());
- directory->m_components.append(ProcFSTCP::must_create());
- directory->m_components.append(ProcFSLocalNet::must_create());
- directory->m_components.append(ProcFSUDP::must_create());
- return directory;
- }
- UNMAP_AFTER_INIT ProcFSAdapters::ProcFSAdapters()
- : ProcFSGlobalInformation("adapters"sv)
- {
- }
- UNMAP_AFTER_INIT ProcFSARP::ProcFSARP()
- : ProcFSGlobalInformation("arp"sv)
- {
- }
- UNMAP_AFTER_INIT ProcFSRoute::ProcFSRoute()
- : ProcFSGlobalInformation("route"sv)
- {
- }
- UNMAP_AFTER_INIT ProcFSTCP::ProcFSTCP()
- : ProcFSGlobalInformation("tcp"sv)
- {
- }
- UNMAP_AFTER_INIT ProcFSLocalNet::ProcFSLocalNet()
- : ProcFSGlobalInformation("local"sv)
- {
- }
- UNMAP_AFTER_INIT ProcFSUDP::ProcFSUDP()
- : ProcFSGlobalInformation("udp"sv)
- {
- }
- UNMAP_AFTER_INIT ProcFSNetworkDirectory::ProcFSNetworkDirectory(ProcFSRootDirectory const& parent_directory)
- : ProcFSExposedDirectory("net"sv, parent_directory)
- {
- }
- class ProcFSDumpKmallocStacks : public ProcFSSystemBoolean {
- public:
- static NonnullRefPtr<ProcFSDumpKmallocStacks> must_create(ProcFSSystemDirectory const&);
- virtual bool value() const override
- {
- MutexLocker locker(m_lock);
- return g_dump_kmalloc_stacks;
- }
- virtual void set_value(bool new_value) override
- {
- MutexLocker locker(m_lock);
- g_dump_kmalloc_stacks = new_value;
- }
- private:
- ProcFSDumpKmallocStacks();
- mutable Mutex m_lock;
- };
- class ProcFSUBSanDeadly : public ProcFSSystemBoolean {
- public:
- static NonnullRefPtr<ProcFSUBSanDeadly> must_create(ProcFSSystemDirectory const&);
- virtual bool value() const override { return AK::UBSanitizer::g_ubsan_is_deadly; }
- virtual void set_value(bool new_value) override { AK::UBSanitizer::g_ubsan_is_deadly = new_value; }
- private:
- ProcFSUBSanDeadly();
- };
- class ProcFSCapsLockRemap : public ProcFSSystemBoolean {
- public:
- static NonnullRefPtr<ProcFSCapsLockRemap> must_create(ProcFSSystemDirectory const&);
- virtual bool value() const override
- {
- MutexLocker locker(m_lock);
- return g_caps_lock_remapped_to_ctrl.load();
- }
- virtual void set_value(bool new_value) override
- {
- MutexLocker locker(m_lock);
- g_caps_lock_remapped_to_ctrl.exchange(new_value);
- }
- private:
- ProcFSCapsLockRemap();
- mutable Mutex m_lock;
- };
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSDumpKmallocStacks> ProcFSDumpKmallocStacks::must_create(ProcFSSystemDirectory const&)
- {
- return adopt_ref_if_nonnull(new (nothrow) ProcFSDumpKmallocStacks).release_nonnull();
- }
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSUBSanDeadly> ProcFSUBSanDeadly::must_create(ProcFSSystemDirectory const&)
- {
- return adopt_ref_if_nonnull(new (nothrow) ProcFSUBSanDeadly).release_nonnull();
- }
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSCapsLockRemap> ProcFSCapsLockRemap::must_create(ProcFSSystemDirectory const&)
- {
- return adopt_ref_if_nonnull(new (nothrow) ProcFSCapsLockRemap).release_nonnull();
- }
- UNMAP_AFTER_INIT ProcFSDumpKmallocStacks::ProcFSDumpKmallocStacks()
- : ProcFSSystemBoolean("kmalloc_stacks"sv)
- {
- }
- UNMAP_AFTER_INIT ProcFSUBSanDeadly::ProcFSUBSanDeadly()
- : ProcFSSystemBoolean("ubsan_is_deadly"sv)
- {
- }
- UNMAP_AFTER_INIT ProcFSCapsLockRemap::ProcFSCapsLockRemap()
- : ProcFSSystemBoolean("caps_lock_to_ctrl"sv)
- {
- }
- class ProcFSSelfProcessDirectory final : public ProcFSExposedLink {
- public:
- static NonnullRefPtr<ProcFSSelfProcessDirectory> must_create();
- private:
- ProcFSSelfProcessDirectory();
- virtual bool acquire_link(KBufferBuilder& builder) override
- {
- return !builder.appendff("{}", Process::current().pid().value()).is_error();
- }
- };
- class ProcFSDiskUsage final : public ProcFSGlobalInformation {
- public:
- static NonnullRefPtr<ProcFSDiskUsage> must_create();
- private:
- ProcFSDiskUsage();
- virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
- {
- auto array = TRY(JsonArraySerializer<>::try_create(builder));
- TRY(VirtualFileSystem::the().for_each_mount([&array](auto& mount) -> ErrorOr<void> {
- auto& fs = mount.guest_fs();
- auto fs_object = TRY(array.add_object());
- TRY(fs_object.add("class_name"sv, fs.class_name()));
- TRY(fs_object.add("total_block_count"sv, fs.total_block_count()));
- TRY(fs_object.add("free_block_count"sv, fs.free_block_count()));
- TRY(fs_object.add("total_inode_count"sv, fs.total_inode_count()));
- TRY(fs_object.add("free_inode_count"sv, fs.free_inode_count()));
- auto mount_point = TRY(mount.absolute_path());
- TRY(fs_object.add("mount_point"sv, mount_point->view()));
- TRY(fs_object.add("block_size"sv, static_cast<u64>(fs.block_size())));
- TRY(fs_object.add("readonly"sv, fs.is_readonly()));
- TRY(fs_object.add("mount_flags"sv, mount.flags()));
- if (fs.is_file_backed()) {
- auto pseudo_path = TRY(static_cast<const FileBackedFileSystem&>(fs).file_description().pseudo_path());
- TRY(fs_object.add("source"sv, pseudo_path->view()));
- } else {
- TRY(fs_object.add("source"sv, "none"));
- }
- TRY(fs_object.finish());
- return {};
- }));
- TRY(array.finish());
- return {};
- }
- };
- class ProcFSMemoryStatus final : public ProcFSGlobalInformation {
- public:
- static NonnullRefPtr<ProcFSMemoryStatus> must_create();
- private:
- ProcFSMemoryStatus();
- virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
- {
- InterruptDisabler disabler;
- kmalloc_stats stats;
- get_kmalloc_stats(stats);
- auto system_memory = MM.get_system_memory_info();
- auto json = TRY(JsonObjectSerializer<>::try_create(builder));
- TRY(json.add("kmalloc_allocated"sv, stats.bytes_allocated));
- TRY(json.add("kmalloc_available"sv, stats.bytes_free));
- TRY(json.add("physical_allocated"sv, system_memory.physical_pages_used));
- TRY(json.add("physical_available"sv, system_memory.physical_pages - system_memory.physical_pages_used));
- TRY(json.add("physical_committed"sv, system_memory.physical_pages_committed));
- TRY(json.add("physical_uncommitted"sv, system_memory.physical_pages_uncommitted));
- TRY(json.add("kmalloc_call_count"sv, stats.kmalloc_call_count));
- TRY(json.add("kfree_call_count"sv, stats.kfree_call_count));
- TRY(json.finish());
- return {};
- }
- };
- class ProcFSSystemStatistics final : public ProcFSGlobalInformation {
- public:
- static NonnullRefPtr<ProcFSSystemStatistics> must_create();
- private:
- ProcFSSystemStatistics();
- virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
- {
- auto json = TRY(JsonObjectSerializer<>::try_create(builder));
- auto total_time_scheduled = Scheduler::get_total_time_scheduled();
- TRY(json.add("total_time"sv, total_time_scheduled.total));
- TRY(json.add("kernel_time"sv, total_time_scheduled.total_kernel));
- TRY(json.add("user_time"sv, total_time_scheduled.total - total_time_scheduled.total_kernel));
- u64 idle_time = 0;
- Processor::for_each([&](Processor& processor) {
- idle_time += processor.time_spent_idle();
- });
- TRY(json.add("idle_time"sv, idle_time));
- TRY(json.finish());
- return {};
- }
- };
- class ProcFSOverallProcesses final : public ProcFSGlobalInformation {
- public:
- static NonnullRefPtr<ProcFSOverallProcesses> must_create();
- private:
- ProcFSOverallProcesses();
- virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
- {
- auto json = TRY(JsonObjectSerializer<>::try_create(builder));
- // Keep this in sync with CProcessStatistics.
- auto build_process = [&](JsonArraySerializer<KBufferBuilder>& array, Process const& process) -> ErrorOr<void> {
- auto process_object = TRY(array.add_object());
- if (process.is_user_process()) {
- StringBuilder pledge_builder;
- #define __ENUMERATE_PLEDGE_PROMISE(promise) \
- if (process.has_promised(Pledge::promise)) \
- TRY(pledge_builder.try_append(#promise " "sv));
- ENUMERATE_PLEDGE_PROMISES
- #undef __ENUMERATE_PLEDGE_PROMISE
- TRY(process_object.add("pledge"sv, pledge_builder.string_view()));
- switch (process.veil_state()) {
- case VeilState::None:
- TRY(process_object.add("veil"sv, "None"));
- break;
- case VeilState::Dropped:
- TRY(process_object.add("veil"sv, "Dropped"));
- break;
- case VeilState::Locked:
- TRY(process_object.add("veil"sv, "Locked"));
- break;
- }
- } else {
- TRY(process_object.add("pledge"sv, ""sv));
- TRY(process_object.add("veil"sv, ""sv));
- }
- TRY(process_object.add("pid"sv, process.pid().value()));
- TRY(process_object.add("pgid"sv, process.tty() ? process.tty()->pgid().value() : 0));
- TRY(process_object.add("pgp"sv, process.pgid().value()));
- TRY(process_object.add("sid"sv, process.sid().value()));
- TRY(process_object.add("uid"sv, process.uid().value()));
- TRY(process_object.add("gid"sv, process.gid().value()));
- TRY(process_object.add("ppid"sv, process.ppid().value()));
- if (process.tty()) {
- auto tty_pseudo_name = TRY(process.tty()->pseudo_name());
- TRY(process_object.add("tty"sv, tty_pseudo_name->view()));
- } else {
- TRY(process_object.add("tty"sv, ""));
- }
- TRY(process_object.add("nfds"sv, process.fds().with_shared([](auto& fds) { return fds.open_count(); })));
- TRY(process_object.add("name"sv, process.name()));
- TRY(process_object.add("executable"sv, process.executable() ? TRY(process.executable()->try_serialize_absolute_path())->view() : ""sv));
- TRY(process_object.add("amount_virtual"sv, process.address_space().amount_virtual()));
- TRY(process_object.add("amount_resident"sv, process.address_space().amount_resident()));
- TRY(process_object.add("amount_dirty_private"sv, process.address_space().amount_dirty_private()));
- TRY(process_object.add("amount_clean_inode"sv, TRY(process.address_space().amount_clean_inode())));
- TRY(process_object.add("amount_shared"sv, process.address_space().amount_shared()));
- TRY(process_object.add("amount_purgeable_volatile"sv, process.address_space().amount_purgeable_volatile()));
- TRY(process_object.add("amount_purgeable_nonvolatile"sv, process.address_space().amount_purgeable_nonvolatile()));
- TRY(process_object.add("dumpable"sv, process.is_dumpable()));
- TRY(process_object.add("kernel"sv, process.is_kernel_process()));
- auto thread_array = TRY(process_object.add_array("threads"sv));
- TRY(process.try_for_each_thread([&](const Thread& thread) -> ErrorOr<void> {
- SpinlockLocker locker(thread.get_lock());
- auto thread_object = TRY(thread_array.add_object());
- #if LOCK_DEBUG
- TRY(thread_object.add("lock_count"sv, thread.lock_count()));
- #endif
- TRY(thread_object.add("tid"sv, thread.tid().value()));
- TRY(thread_object.add("name"sv, thread.name()));
- TRY(thread_object.add("times_scheduled"sv, thread.times_scheduled()));
- TRY(thread_object.add("time_user"sv, thread.time_in_user()));
- TRY(thread_object.add("time_kernel"sv, thread.time_in_kernel()));
- TRY(thread_object.add("state"sv, thread.state_string()));
- TRY(thread_object.add("cpu"sv, thread.cpu()));
- TRY(thread_object.add("priority"sv, thread.priority()));
- TRY(thread_object.add("syscall_count"sv, thread.syscall_count()));
- TRY(thread_object.add("inode_faults"sv, thread.inode_faults()));
- TRY(thread_object.add("zero_faults"sv, thread.zero_faults()));
- TRY(thread_object.add("cow_faults"sv, thread.cow_faults()));
- TRY(thread_object.add("file_read_bytes"sv, thread.file_read_bytes()));
- TRY(thread_object.add("file_write_bytes"sv, thread.file_write_bytes()));
- TRY(thread_object.add("unix_socket_read_bytes"sv, thread.unix_socket_read_bytes()));
- TRY(thread_object.add("unix_socket_write_bytes"sv, thread.unix_socket_write_bytes()));
- TRY(thread_object.add("ipv4_socket_read_bytes"sv, thread.ipv4_socket_read_bytes()));
- TRY(thread_object.add("ipv4_socket_write_bytes"sv, thread.ipv4_socket_write_bytes()));
- TRY(thread_object.finish());
- return {};
- }));
- TRY(thread_array.finish());
- TRY(process_object.finish());
- return {};
- };
- {
- auto array = TRY(json.add_array("processes"sv));
- TRY(build_process(array, *Scheduler::colonel()));
- TRY(Process::all_instances().with([&](auto& processes) -> ErrorOr<void> {
- for (auto& process : processes)
- TRY(build_process(array, process));
- return {};
- }));
- TRY(array.finish());
- }
- auto total_time_scheduled = Scheduler::get_total_time_scheduled();
- TRY(json.add("total_time"sv, total_time_scheduled.total));
- TRY(json.add("total_time_kernel"sv, total_time_scheduled.total_kernel));
- TRY(json.finish());
- return {};
- }
- };
- class ProcFSCPUInformation final : public ProcFSGlobalInformation {
- public:
- static NonnullRefPtr<ProcFSCPUInformation> must_create();
- private:
- ProcFSCPUInformation();
- virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
- {
- auto array = TRY(JsonArraySerializer<>::try_create(builder));
- TRY(Processor::try_for_each(
- [&](Processor& proc) -> ErrorOr<void> {
- auto& info = proc.info();
- auto obj = TRY(array.add_object());
- TRY(obj.add("processor"sv, proc.id()));
- TRY(obj.add("vendor_id"sv, info.vendor_id_string()));
- TRY(obj.add("family"sv, info.display_family()));
- if (!info.hypervisor_vendor_id_string().is_null())
- TRY(obj.add("hypervisor_vendor_id"sv, info.hypervisor_vendor_id_string()));
- auto features_array = TRY(obj.add_array("features"sv));
- auto keep_empty = false;
- ErrorOr<void> result; // FIXME: Make this nicer
- info.features_string().for_each_split_view(' ', keep_empty, [&](StringView feature) {
- if (result.is_error())
- return;
- result = features_array.add(feature);
- });
- TRY(result);
- TRY(features_array.finish());
- TRY(obj.add("model"sv, info.display_model()));
- TRY(obj.add("stepping"sv, info.stepping()));
- TRY(obj.add("type"sv, info.type()));
- TRY(obj.add("brand"sv, info.brand_string()));
- auto caches = TRY(obj.add_object("caches"sv));
- auto add_cache_info = [&](StringView name, ProcessorInfo::Cache const& cache) -> ErrorOr<void> {
- auto cache_object = TRY(caches.add_object(name));
- TRY(cache_object.add("size"sv, cache.size));
- TRY(cache_object.add("line_size"sv, cache.line_size));
- TRY(cache_object.finish());
- return {};
- };
- if (info.l1_data_cache().has_value())
- TRY(add_cache_info("l1_data"sv, *info.l1_data_cache()));
- if (info.l1_instruction_cache().has_value())
- TRY(add_cache_info("l1_instruction"sv, *info.l1_instruction_cache()));
- if (info.l2_cache().has_value())
- TRY(add_cache_info("l2"sv, *info.l2_cache()));
- if (info.l3_cache().has_value())
- TRY(add_cache_info("l3"sv, *info.l3_cache()));
- TRY(caches.finish());
- TRY(obj.finish());
- return {};
- }));
- TRY(array.finish());
- return {};
- }
- };
- class ProcFSDmesg final : public ProcFSGlobalInformation {
- public:
- static NonnullRefPtr<ProcFSDmesg> must_create();
- virtual mode_t required_mode() const override { return 0400; }
- private:
- ProcFSDmesg();
- virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
- {
- VERIFY(DeviceManagement::the().is_console_device_attached());
- InterruptDisabler disabler;
- for (char ch : DeviceManagement::the().console_device().logbuffer()) {
- TRY(builder.append(ch));
- }
- return {};
- }
- };
- class ProcFSInterrupts final : public ProcFSGlobalInformation {
- public:
- static NonnullRefPtr<ProcFSInterrupts> must_create();
- private:
- ProcFSInterrupts();
- virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
- {
- auto array = TRY(JsonArraySerializer<>::try_create(builder));
- ErrorOr<void> result; // FIXME: Make this nicer
- InterruptManagement::the().enumerate_interrupt_handlers([&array, &result](GenericInterruptHandler& handler) {
- if (result.is_error())
- return;
- result = ([&]() -> ErrorOr<void> {
- auto obj = TRY(array.add_object());
- TRY(obj.add("purpose"sv, handler.purpose()));
- TRY(obj.add("interrupt_line"sv, handler.interrupt_number()));
- TRY(obj.add("controller"sv, handler.controller()));
- TRY(obj.add("cpu_handler"sv, 0)); // FIXME: Determine the responsible CPU for each interrupt handler.
- TRY(obj.add("device_sharing"sv, (unsigned)handler.sharing_devices_count()));
- TRY(obj.add("call_count"sv, (unsigned)handler.get_invoking_count()));
- TRY(obj.finish());
- return {};
- })();
- });
- TRY(result);
- TRY(array.finish());
- return {};
- }
- };
- class ProcFSKeymap final : public ProcFSGlobalInformation {
- public:
- static NonnullRefPtr<ProcFSKeymap> must_create();
- private:
- ProcFSKeymap();
- virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
- {
- auto json = TRY(JsonObjectSerializer<>::try_create(builder));
- TRY(HIDManagement::the().keymap_data().with([&](auto const& keymap_data) {
- return json.add("keymap"sv, keymap_data.character_map_name->view());
- }));
- TRY(json.finish());
- return {};
- }
- };
- class ProcFSDevices final : public ProcFSGlobalInformation {
- public:
- static NonnullRefPtr<ProcFSDevices> must_create();
- private:
- ProcFSDevices();
- virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
- {
- auto array = TRY(JsonArraySerializer<>::try_create(builder));
- TRY(DeviceManagement::the().try_for_each([&array](auto& device) -> ErrorOr<void> {
- auto obj = TRY(array.add_object());
- TRY(obj.add("major"sv, device.major().value()));
- TRY(obj.add("minor"sv, device.minor().value()));
- TRY(obj.add("class_name"sv, device.class_name()));
- if (device.is_block_device())
- TRY(obj.add("type"sv, "block"));
- else if (device.is_character_device())
- TRY(obj.add("type"sv, "character"));
- else
- VERIFY_NOT_REACHED();
- TRY(obj.finish());
- return {};
- }));
- TRY(array.finish());
- return {};
- }
- };
- class ProcFSUptime final : public ProcFSGlobalInformation {
- public:
- static NonnullRefPtr<ProcFSUptime> must_create();
- private:
- ProcFSUptime();
- virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
- {
- return builder.appendff("{}\n", TimeManagement::the().uptime_ms() / 1000);
- }
- };
- class ProcFSCommandLine final : public ProcFSGlobalInformation {
- public:
- static NonnullRefPtr<ProcFSCommandLine> must_create();
- private:
- ProcFSCommandLine();
- virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
- {
- TRY(builder.append(kernel_command_line().string()));
- TRY(builder.append('\n'));
- return {};
- }
- };
- class ProcFSSystemMode final : public ProcFSGlobalInformation {
- public:
- static NonnullRefPtr<ProcFSSystemMode> must_create();
- private:
- ProcFSSystemMode();
- virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
- {
- TRY(builder.append(kernel_command_line().system_mode()));
- TRY(builder.append('\n'));
- return {};
- }
- };
- class ProcFSProfile final : public ProcFSGlobalInformation {
- public:
- static NonnullRefPtr<ProcFSProfile> must_create();
- virtual mode_t required_mode() const override { return 0400; }
- private:
- ProcFSProfile();
- virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
- {
- if (!g_global_perf_events)
- return ENOENT;
- TRY(g_global_perf_events->to_json(builder));
- return {};
- }
- };
- class ProcFSKernelBase final : public ProcFSGlobalInformation {
- public:
- static NonnullRefPtr<ProcFSKernelBase> must_create();
- private:
- ProcFSKernelBase();
- virtual mode_t required_mode() const override { return 0400; }
- virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
- {
- if (!Process::current().is_superuser())
- return EPERM;
- return builder.appendff("{}", kernel_load_base);
- }
- };
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSSelfProcessDirectory> ProcFSSelfProcessDirectory::must_create()
- {
- return adopt_ref_if_nonnull(new (nothrow) ProcFSSelfProcessDirectory()).release_nonnull();
- }
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSDiskUsage> ProcFSDiskUsage::must_create()
- {
- return adopt_ref_if_nonnull(new (nothrow) ProcFSDiskUsage).release_nonnull();
- }
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSMemoryStatus> ProcFSMemoryStatus::must_create()
- {
- return adopt_ref_if_nonnull(new (nothrow) ProcFSMemoryStatus).release_nonnull();
- }
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSSystemStatistics> ProcFSSystemStatistics::must_create()
- {
- return adopt_ref_if_nonnull(new (nothrow) ProcFSSystemStatistics).release_nonnull();
- }
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSOverallProcesses> ProcFSOverallProcesses::must_create()
- {
- return adopt_ref_if_nonnull(new (nothrow) ProcFSOverallProcesses).release_nonnull();
- }
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSCPUInformation> ProcFSCPUInformation::must_create()
- {
- return adopt_ref_if_nonnull(new (nothrow) ProcFSCPUInformation).release_nonnull();
- }
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSDmesg> ProcFSDmesg::must_create()
- {
- return adopt_ref_if_nonnull(new (nothrow) ProcFSDmesg).release_nonnull();
- }
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSInterrupts> ProcFSInterrupts::must_create()
- {
- return adopt_ref_if_nonnull(new (nothrow) ProcFSInterrupts).release_nonnull();
- }
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSKeymap> ProcFSKeymap::must_create()
- {
- return adopt_ref_if_nonnull(new (nothrow) ProcFSKeymap).release_nonnull();
- }
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSDevices> ProcFSDevices::must_create()
- {
- return adopt_ref_if_nonnull(new (nothrow) ProcFSDevices).release_nonnull();
- }
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSUptime> ProcFSUptime::must_create()
- {
- return adopt_ref_if_nonnull(new (nothrow) ProcFSUptime).release_nonnull();
- }
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSCommandLine> ProcFSCommandLine::must_create()
- {
- return adopt_ref_if_nonnull(new (nothrow) ProcFSCommandLine).release_nonnull();
- }
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSSystemMode> ProcFSSystemMode::must_create()
- {
- return adopt_ref_if_nonnull(new (nothrow) ProcFSSystemMode).release_nonnull();
- }
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSProfile> ProcFSProfile::must_create()
- {
- return adopt_ref_if_nonnull(new (nothrow) ProcFSProfile).release_nonnull();
- }
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSKernelBase> ProcFSKernelBase::must_create()
- {
- return adopt_ref_if_nonnull(new (nothrow) ProcFSKernelBase).release_nonnull();
- }
- UNMAP_AFTER_INIT ProcFSSelfProcessDirectory::ProcFSSelfProcessDirectory()
- : ProcFSExposedLink("self"sv)
- {
- }
- UNMAP_AFTER_INIT ProcFSDiskUsage::ProcFSDiskUsage()
- : ProcFSGlobalInformation("df"sv)
- {
- }
- UNMAP_AFTER_INIT ProcFSMemoryStatus::ProcFSMemoryStatus()
- : ProcFSGlobalInformation("memstat"sv)
- {
- }
- UNMAP_AFTER_INIT ProcFSSystemStatistics::ProcFSSystemStatistics()
- : ProcFSGlobalInformation("stat"sv)
- {
- }
- UNMAP_AFTER_INIT ProcFSOverallProcesses::ProcFSOverallProcesses()
- : ProcFSGlobalInformation("all"sv)
- {
- }
- UNMAP_AFTER_INIT ProcFSCPUInformation::ProcFSCPUInformation()
- : ProcFSGlobalInformation("cpuinfo"sv)
- {
- }
- UNMAP_AFTER_INIT ProcFSDmesg::ProcFSDmesg()
- : ProcFSGlobalInformation("dmesg"sv)
- {
- }
- UNMAP_AFTER_INIT ProcFSInterrupts::ProcFSInterrupts()
- : ProcFSGlobalInformation("interrupts"sv)
- {
- }
- UNMAP_AFTER_INIT ProcFSKeymap::ProcFSKeymap()
- : ProcFSGlobalInformation("keymap"sv)
- {
- }
- UNMAP_AFTER_INIT ProcFSDevices::ProcFSDevices()
- : ProcFSGlobalInformation("devices"sv)
- {
- }
- UNMAP_AFTER_INIT ProcFSUptime::ProcFSUptime()
- : ProcFSGlobalInformation("uptime"sv)
- {
- }
- UNMAP_AFTER_INIT ProcFSCommandLine::ProcFSCommandLine()
- : ProcFSGlobalInformation("cmdline"sv)
- {
- }
- UNMAP_AFTER_INIT ProcFSSystemMode::ProcFSSystemMode()
- : ProcFSGlobalInformation("system_mode"sv)
- {
- }
- UNMAP_AFTER_INIT ProcFSProfile::ProcFSProfile()
- : ProcFSGlobalInformation("profile"sv)
- {
- }
- UNMAP_AFTER_INIT ProcFSKernelBase::ProcFSKernelBase()
- : ProcFSGlobalInformation("kernel_base"sv)
- {
- }
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSSystemDirectory> ProcFSSystemDirectory::must_create(ProcFSRootDirectory const& parent_directory)
- {
- auto directory = adopt_ref(*new (nothrow) ProcFSSystemDirectory(parent_directory));
- directory->m_components.append(ProcFSDumpKmallocStacks::must_create(directory));
- directory->m_components.append(ProcFSUBSanDeadly::must_create(directory));
- directory->m_components.append(ProcFSCapsLockRemap::must_create(directory));
- return directory;
- }
- UNMAP_AFTER_INIT ProcFSSystemDirectory::ProcFSSystemDirectory(ProcFSRootDirectory const& parent_directory)
- : ProcFSExposedDirectory("sys"sv, parent_directory)
- {
- }
- UNMAP_AFTER_INIT NonnullRefPtr<ProcFSRootDirectory> ProcFSRootDirectory::must_create()
- {
- auto directory = adopt_ref(*new (nothrow) ProcFSRootDirectory);
- directory->m_components.append(ProcFSSelfProcessDirectory::must_create());
- directory->m_components.append(ProcFSDiskUsage::must_create());
- directory->m_components.append(ProcFSMemoryStatus::must_create());
- directory->m_components.append(ProcFSSystemStatistics::must_create());
- directory->m_components.append(ProcFSOverallProcesses::must_create());
- directory->m_components.append(ProcFSCPUInformation::must_create());
- directory->m_components.append(ProcFSDmesg::must_create());
- directory->m_components.append(ProcFSInterrupts::must_create());
- directory->m_components.append(ProcFSKeymap::must_create());
- directory->m_components.append(ProcFSDevices::must_create());
- directory->m_components.append(ProcFSUptime::must_create());
- directory->m_components.append(ProcFSCommandLine::must_create());
- directory->m_components.append(ProcFSSystemMode::must_create());
- directory->m_components.append(ProcFSProfile::must_create());
- directory->m_components.append(ProcFSKernelBase::must_create());
- directory->m_components.append(ProcFSNetworkDirectory::must_create(*directory));
- directory->m_components.append(ProcFSSystemDirectory::must_create(*directory));
- return directory;
- }
- ErrorOr<void> ProcFSRootDirectory::traverse_as_directory(FileSystemID fsid, Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)> callback) const
- {
- MutexLocker locker(ProcFSComponentRegistry::the().get_lock());
- TRY(callback({ "."sv, { fsid, component_index() }, 0 }));
- TRY(callback({ ".."sv, { fsid, 0 }, 0 }));
- for (auto const& component : m_components) {
- InodeIdentifier identifier = { fsid, component.component_index() };
- TRY(callback({ component.name(), identifier, 0 }));
- }
- return Process::all_instances().with([&](auto& list) -> ErrorOr<void> {
- for (auto& process : list) {
- VERIFY(!(process.pid() < 0));
- u64 process_id = (u64)process.pid().value();
- InodeIdentifier identifier = { fsid, static_cast<InodeIndex>(process_id << 36) };
- auto process_id_string = TRY(KString::formatted("{:d}", process_id));
- TRY(callback({ process_id_string->view(), identifier, 0 }));
- }
- return {};
- });
- }
- ErrorOr<NonnullRefPtr<ProcFSExposedComponent>> ProcFSRootDirectory::lookup(StringView name)
- {
- auto maybe_candidate = ProcFSExposedDirectory::lookup(name);
- if (maybe_candidate.is_error()) {
- if (maybe_candidate.error().code() != ENOENT) {
- return maybe_candidate.release_error();
- }
- } else {
- return maybe_candidate.release_value();
- }
- auto pid = name.to_uint<unsigned>();
- if (!pid.has_value())
- return ESRCH;
- auto actual_pid = pid.value();
- if (auto maybe_process = Process::from_pid(actual_pid))
- return maybe_process->procfs_traits();
- return ENOENT;
- }
- UNMAP_AFTER_INIT ProcFSRootDirectory::ProcFSRootDirectory()
- : ProcFSExposedDirectory("."sv)
- {
- }
- UNMAP_AFTER_INIT ProcFSRootDirectory::~ProcFSRootDirectory() = default;
- }
|