GlobalProcessExposed.cpp 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033
  1. /*
  2. * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
  3. * Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/JsonObjectSerializer.h>
  8. #include <AK/Try.h>
  9. #include <AK/UBSanitizer.h>
  10. #include <Kernel/Arch/InterruptManagement.h>
  11. #include <Kernel/Arch/x86/ProcessorInfo.h>
  12. #include <Kernel/Bus/PCI/API.h>
  13. #include <Kernel/Bus/PCI/Access.h>
  14. #include <Kernel/CommandLine.h>
  15. #include <Kernel/Devices/DeviceManagement.h>
  16. #include <Kernel/Devices/HID/HIDManagement.h>
  17. #include <Kernel/FileSystem/Custody.h>
  18. #include <Kernel/FileSystem/FileBackedFileSystem.h>
  19. #include <Kernel/FileSystem/OpenFileDescription.h>
  20. #include <Kernel/FileSystem/VirtualFileSystem.h>
  21. #include <Kernel/Heap/kmalloc.h>
  22. #include <Kernel/InterruptDisabler.h>
  23. #include <Kernel/Interrupts/GenericInterruptHandler.h>
  24. #include <Kernel/KBufferBuilder.h>
  25. #include <Kernel/Net/LocalSocket.h>
  26. #include <Kernel/Net/NetworkingManagement.h>
  27. #include <Kernel/Net/Routing.h>
  28. #include <Kernel/Net/TCPSocket.h>
  29. #include <Kernel/Net/UDPSocket.h>
  30. #include <Kernel/Process.h>
  31. #include <Kernel/ProcessExposed.h>
  32. #include <Kernel/Scheduler.h>
  33. #include <Kernel/Sections.h>
  34. #include <Kernel/TTY/TTY.h>
  35. namespace Kernel {
  36. class ProcFSAdapters final : public ProcFSGlobalInformation {
  37. public:
  38. static NonnullLockRefPtr<ProcFSAdapters> must_create();
  39. private:
  40. ProcFSAdapters();
  41. virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
  42. {
  43. auto array = TRY(JsonArraySerializer<>::try_create(builder));
  44. TRY(NetworkingManagement::the().try_for_each([&array](auto& adapter) -> ErrorOr<void> {
  45. auto obj = TRY(array.add_object());
  46. TRY(obj.add("name"sv, adapter.name()));
  47. TRY(obj.add("class_name"sv, adapter.class_name()));
  48. auto mac_address = TRY(adapter.mac_address().to_string());
  49. TRY(obj.add("mac_address"sv, mac_address->view()));
  50. if (!adapter.ipv4_address().is_zero()) {
  51. auto ipv4_address = TRY(adapter.ipv4_address().to_string());
  52. TRY(obj.add("ipv4_address"sv, ipv4_address->view()));
  53. auto ipv4_netmask = TRY(adapter.ipv4_netmask().to_string());
  54. TRY(obj.add("ipv4_netmask"sv, ipv4_netmask->view()));
  55. }
  56. TRY(obj.add("packets_in"sv, adapter.packets_in()));
  57. TRY(obj.add("bytes_in"sv, adapter.bytes_in()));
  58. TRY(obj.add("packets_out"sv, adapter.packets_out()));
  59. TRY(obj.add("bytes_out"sv, adapter.bytes_out()));
  60. TRY(obj.add("link_up"sv, adapter.link_up()));
  61. TRY(obj.add("link_speed"sv, adapter.link_speed()));
  62. TRY(obj.add("link_full_duplex"sv, adapter.link_full_duplex()));
  63. TRY(obj.add("mtu"sv, adapter.mtu()));
  64. TRY(obj.finish());
  65. return {};
  66. }));
  67. TRY(array.finish());
  68. return {};
  69. }
  70. };
  71. class ProcFSARP final : public ProcFSGlobalInformation {
  72. public:
  73. static NonnullLockRefPtr<ProcFSARP> must_create();
  74. private:
  75. ProcFSARP();
  76. virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
  77. {
  78. auto array = TRY(JsonArraySerializer<>::try_create(builder));
  79. TRY(arp_table().with([&](auto const& table) -> ErrorOr<void> {
  80. for (auto& it : table) {
  81. auto obj = TRY(array.add_object());
  82. auto mac_address = TRY(it.value.to_string());
  83. TRY(obj.add("mac_address"sv, mac_address->view()));
  84. auto ip_address = TRY(it.key.to_string());
  85. TRY(obj.add("ip_address"sv, ip_address->view()));
  86. TRY(obj.finish());
  87. }
  88. return {};
  89. }));
  90. TRY(array.finish());
  91. return {};
  92. }
  93. };
  94. class ProcFSRoute final : public ProcFSGlobalInformation {
  95. public:
  96. static NonnullLockRefPtr<ProcFSRoute> must_create();
  97. private:
  98. ProcFSRoute();
  99. virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
  100. {
  101. auto array = TRY(JsonArraySerializer<>::try_create(builder));
  102. TRY(routing_table().with([&](auto const& table) -> ErrorOr<void> {
  103. for (auto& it : table) {
  104. auto obj = TRY(array.add_object());
  105. auto destination = TRY(it.destination.to_string());
  106. TRY(obj.add("destination"sv, destination->view()));
  107. auto gateway = TRY(it.gateway.to_string());
  108. TRY(obj.add("gateway"sv, gateway->view()));
  109. auto netmask = TRY(it.netmask.to_string());
  110. TRY(obj.add("genmask"sv, netmask->view()));
  111. TRY(obj.add("flags"sv, it.flags));
  112. TRY(obj.add("interface"sv, it.adapter->name()));
  113. TRY(obj.finish());
  114. }
  115. return {};
  116. }));
  117. TRY(array.finish());
  118. return {};
  119. }
  120. };
  121. class ProcFSTCP final : public ProcFSGlobalInformation {
  122. public:
  123. static NonnullLockRefPtr<ProcFSTCP> must_create();
  124. private:
  125. ProcFSTCP();
  126. virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
  127. {
  128. auto array = TRY(JsonArraySerializer<>::try_create(builder));
  129. TRY(TCPSocket::try_for_each([&array](auto& socket) -> ErrorOr<void> {
  130. auto obj = TRY(array.add_object());
  131. auto local_address = TRY(socket.local_address().to_string());
  132. TRY(obj.add("local_address"sv, local_address->view()));
  133. TRY(obj.add("local_port"sv, socket.local_port()));
  134. auto peer_address = TRY(socket.peer_address().to_string());
  135. TRY(obj.add("peer_address"sv, peer_address->view()));
  136. TRY(obj.add("peer_port"sv, socket.peer_port()));
  137. TRY(obj.add("state"sv, TCPSocket::to_string(socket.state())));
  138. TRY(obj.add("ack_number"sv, socket.ack_number()));
  139. TRY(obj.add("sequence_number"sv, socket.sequence_number()));
  140. TRY(obj.add("packets_in"sv, socket.packets_in()));
  141. TRY(obj.add("bytes_in"sv, socket.bytes_in()));
  142. TRY(obj.add("packets_out"sv, socket.packets_out()));
  143. TRY(obj.add("bytes_out"sv, socket.bytes_out()));
  144. auto current_process_credentials = Process::current().credentials();
  145. if (current_process_credentials->is_superuser() || current_process_credentials->uid() == socket.origin_uid()) {
  146. TRY(obj.add("origin_pid"sv, socket.origin_pid().value()));
  147. TRY(obj.add("origin_uid"sv, socket.origin_uid().value()));
  148. TRY(obj.add("origin_gid"sv, socket.origin_gid().value()));
  149. }
  150. TRY(obj.finish());
  151. return {};
  152. }));
  153. TRY(array.finish());
  154. return {};
  155. }
  156. };
  157. class ProcFSLocalNet final : public ProcFSGlobalInformation {
  158. public:
  159. static NonnullLockRefPtr<ProcFSLocalNet> must_create();
  160. private:
  161. ProcFSLocalNet();
  162. virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
  163. {
  164. auto array = TRY(JsonArraySerializer<>::try_create(builder));
  165. TRY(LocalSocket::try_for_each([&array](auto& socket) -> ErrorOr<void> {
  166. auto obj = TRY(array.add_object());
  167. TRY(obj.add("path"sv, socket.socket_path()));
  168. TRY(obj.add("origin_pid"sv, socket.origin_pid().value()));
  169. TRY(obj.add("origin_uid"sv, socket.origin_uid().value()));
  170. TRY(obj.add("origin_gid"sv, socket.origin_gid().value()));
  171. TRY(obj.add("acceptor_pid"sv, socket.acceptor_pid().value()));
  172. TRY(obj.add("acceptor_uid"sv, socket.acceptor_uid().value()));
  173. TRY(obj.add("acceptor_gid"sv, socket.acceptor_gid().value()));
  174. TRY(obj.finish());
  175. return {};
  176. }));
  177. TRY(array.finish());
  178. return {};
  179. }
  180. };
  181. class ProcFSUDP final : public ProcFSGlobalInformation {
  182. public:
  183. static NonnullLockRefPtr<ProcFSUDP> must_create();
  184. private:
  185. ProcFSUDP();
  186. virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
  187. {
  188. auto array = TRY(JsonArraySerializer<>::try_create(builder));
  189. TRY(UDPSocket::try_for_each([&array](auto& socket) -> ErrorOr<void> {
  190. auto obj = TRY(array.add_object());
  191. auto local_address = TRY(socket.local_address().to_string());
  192. TRY(obj.add("local_address"sv, local_address->view()));
  193. TRY(obj.add("local_port"sv, socket.local_port()));
  194. auto peer_address = TRY(socket.peer_address().to_string());
  195. TRY(obj.add("peer_address"sv, peer_address->view()));
  196. TRY(obj.add("peer_port"sv, socket.peer_port()));
  197. auto current_process_credentials = Process::current().credentials();
  198. if (current_process_credentials->is_superuser() || current_process_credentials->uid() == socket.origin_uid()) {
  199. TRY(obj.add("origin_pid"sv, socket.origin_pid().value()));
  200. TRY(obj.add("origin_uid"sv, socket.origin_uid().value()));
  201. TRY(obj.add("origin_gid"sv, socket.origin_gid().value()));
  202. }
  203. TRY(obj.finish());
  204. return {};
  205. }));
  206. TRY(array.finish());
  207. return {};
  208. }
  209. };
  210. class ProcFSNetworkDirectory : public ProcFSExposedDirectory {
  211. public:
  212. static NonnullLockRefPtr<ProcFSNetworkDirectory> must_create(ProcFSRootDirectory const& parent_directory);
  213. private:
  214. ProcFSNetworkDirectory(ProcFSRootDirectory const& parent_directory);
  215. };
  216. class ProcFSSystemDirectory : public ProcFSExposedDirectory {
  217. public:
  218. static NonnullLockRefPtr<ProcFSSystemDirectory> must_create(ProcFSRootDirectory const& parent_directory);
  219. private:
  220. ProcFSSystemDirectory(ProcFSRootDirectory const& parent_directory);
  221. };
  222. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSAdapters> ProcFSAdapters::must_create()
  223. {
  224. return adopt_lock_ref_if_nonnull(new (nothrow) ProcFSAdapters).release_nonnull();
  225. }
  226. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSARP> ProcFSARP::must_create()
  227. {
  228. return adopt_lock_ref_if_nonnull(new (nothrow) ProcFSARP).release_nonnull();
  229. }
  230. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSRoute> ProcFSRoute::must_create()
  231. {
  232. return adopt_lock_ref_if_nonnull(new (nothrow) ProcFSRoute).release_nonnull();
  233. }
  234. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSTCP> ProcFSTCP::must_create()
  235. {
  236. return adopt_lock_ref_if_nonnull(new (nothrow) ProcFSTCP).release_nonnull();
  237. }
  238. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSLocalNet> ProcFSLocalNet::must_create()
  239. {
  240. return adopt_lock_ref_if_nonnull(new (nothrow) ProcFSLocalNet).release_nonnull();
  241. }
  242. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSUDP> ProcFSUDP::must_create()
  243. {
  244. return adopt_lock_ref_if_nonnull(new (nothrow) ProcFSUDP).release_nonnull();
  245. }
  246. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSNetworkDirectory> ProcFSNetworkDirectory::must_create(ProcFSRootDirectory const& parent_directory)
  247. {
  248. auto directory = adopt_lock_ref(*new (nothrow) ProcFSNetworkDirectory(parent_directory));
  249. directory->m_components.append(ProcFSAdapters::must_create());
  250. directory->m_components.append(ProcFSARP::must_create());
  251. directory->m_components.append(ProcFSRoute::must_create());
  252. directory->m_components.append(ProcFSTCP::must_create());
  253. directory->m_components.append(ProcFSLocalNet::must_create());
  254. directory->m_components.append(ProcFSUDP::must_create());
  255. return directory;
  256. }
  257. UNMAP_AFTER_INIT ProcFSAdapters::ProcFSAdapters()
  258. : ProcFSGlobalInformation("adapters"sv)
  259. {
  260. }
  261. UNMAP_AFTER_INIT ProcFSARP::ProcFSARP()
  262. : ProcFSGlobalInformation("arp"sv)
  263. {
  264. }
  265. UNMAP_AFTER_INIT ProcFSRoute::ProcFSRoute()
  266. : ProcFSGlobalInformation("route"sv)
  267. {
  268. }
  269. UNMAP_AFTER_INIT ProcFSTCP::ProcFSTCP()
  270. : ProcFSGlobalInformation("tcp"sv)
  271. {
  272. }
  273. UNMAP_AFTER_INIT ProcFSLocalNet::ProcFSLocalNet()
  274. : ProcFSGlobalInformation("local"sv)
  275. {
  276. }
  277. UNMAP_AFTER_INIT ProcFSUDP::ProcFSUDP()
  278. : ProcFSGlobalInformation("udp"sv)
  279. {
  280. }
  281. UNMAP_AFTER_INIT ProcFSNetworkDirectory::ProcFSNetworkDirectory(ProcFSRootDirectory const& parent_directory)
  282. : ProcFSExposedDirectory("net"sv, parent_directory)
  283. {
  284. }
  285. class ProcFSDumpKmallocStacks : public ProcFSSystemBoolean {
  286. public:
  287. static NonnullLockRefPtr<ProcFSDumpKmallocStacks> must_create(ProcFSSystemDirectory const&);
  288. virtual bool value() const override
  289. {
  290. MutexLocker locker(m_lock);
  291. return g_dump_kmalloc_stacks;
  292. }
  293. virtual void set_value(bool new_value) override
  294. {
  295. MutexLocker locker(m_lock);
  296. g_dump_kmalloc_stacks = new_value;
  297. }
  298. private:
  299. ProcFSDumpKmallocStacks();
  300. mutable Mutex m_lock;
  301. };
  302. class ProcFSUBSanDeadly : public ProcFSSystemBoolean {
  303. public:
  304. static NonnullLockRefPtr<ProcFSUBSanDeadly> must_create(ProcFSSystemDirectory const&);
  305. virtual bool value() const override { return AK::UBSanitizer::g_ubsan_is_deadly; }
  306. virtual void set_value(bool new_value) override { AK::UBSanitizer::g_ubsan_is_deadly = new_value; }
  307. private:
  308. ProcFSUBSanDeadly();
  309. };
  310. class ProcFSCapsLockRemap : public ProcFSSystemBoolean {
  311. public:
  312. static NonnullLockRefPtr<ProcFSCapsLockRemap> must_create(ProcFSSystemDirectory const&);
  313. virtual bool value() const override
  314. {
  315. MutexLocker locker(m_lock);
  316. return g_caps_lock_remapped_to_ctrl.load();
  317. }
  318. virtual void set_value(bool new_value) override
  319. {
  320. MutexLocker locker(m_lock);
  321. g_caps_lock_remapped_to_ctrl.exchange(new_value);
  322. }
  323. private:
  324. ProcFSCapsLockRemap();
  325. mutable Mutex m_lock;
  326. };
  327. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSDumpKmallocStacks> ProcFSDumpKmallocStacks::must_create(ProcFSSystemDirectory const&)
  328. {
  329. return adopt_lock_ref_if_nonnull(new (nothrow) ProcFSDumpKmallocStacks).release_nonnull();
  330. }
  331. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSUBSanDeadly> ProcFSUBSanDeadly::must_create(ProcFSSystemDirectory const&)
  332. {
  333. return adopt_lock_ref_if_nonnull(new (nothrow) ProcFSUBSanDeadly).release_nonnull();
  334. }
  335. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSCapsLockRemap> ProcFSCapsLockRemap::must_create(ProcFSSystemDirectory const&)
  336. {
  337. return adopt_lock_ref_if_nonnull(new (nothrow) ProcFSCapsLockRemap).release_nonnull();
  338. }
  339. UNMAP_AFTER_INIT ProcFSDumpKmallocStacks::ProcFSDumpKmallocStacks()
  340. : ProcFSSystemBoolean("kmalloc_stacks"sv)
  341. {
  342. }
  343. UNMAP_AFTER_INIT ProcFSUBSanDeadly::ProcFSUBSanDeadly()
  344. : ProcFSSystemBoolean("ubsan_is_deadly"sv)
  345. {
  346. }
  347. UNMAP_AFTER_INIT ProcFSCapsLockRemap::ProcFSCapsLockRemap()
  348. : ProcFSSystemBoolean("caps_lock_to_ctrl"sv)
  349. {
  350. }
  351. class ProcFSSelfProcessDirectory final : public ProcFSExposedLink {
  352. public:
  353. static NonnullLockRefPtr<ProcFSSelfProcessDirectory> must_create();
  354. private:
  355. ProcFSSelfProcessDirectory();
  356. virtual bool acquire_link(KBufferBuilder& builder) override
  357. {
  358. return !builder.appendff("{}", Process::current().pid().value()).is_error();
  359. }
  360. };
  361. class ProcFSDiskUsage final : public ProcFSGlobalInformation {
  362. public:
  363. static NonnullLockRefPtr<ProcFSDiskUsage> must_create();
  364. private:
  365. ProcFSDiskUsage();
  366. virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
  367. {
  368. auto array = TRY(JsonArraySerializer<>::try_create(builder));
  369. TRY(VirtualFileSystem::the().for_each_mount([&array](auto& mount) -> ErrorOr<void> {
  370. auto& fs = mount.guest_fs();
  371. auto fs_object = TRY(array.add_object());
  372. TRY(fs_object.add("class_name"sv, fs.class_name()));
  373. TRY(fs_object.add("total_block_count"sv, fs.total_block_count()));
  374. TRY(fs_object.add("free_block_count"sv, fs.free_block_count()));
  375. TRY(fs_object.add("total_inode_count"sv, fs.total_inode_count()));
  376. TRY(fs_object.add("free_inode_count"sv, fs.free_inode_count()));
  377. auto mount_point = TRY(mount.absolute_path());
  378. TRY(fs_object.add("mount_point"sv, mount_point->view()));
  379. TRY(fs_object.add("block_size"sv, static_cast<u64>(fs.block_size())));
  380. TRY(fs_object.add("readonly"sv, fs.is_readonly()));
  381. TRY(fs_object.add("mount_flags"sv, mount.flags()));
  382. if (fs.is_file_backed()) {
  383. auto pseudo_path = TRY(static_cast<const FileBackedFileSystem&>(fs).file_description().pseudo_path());
  384. TRY(fs_object.add("source"sv, pseudo_path->view()));
  385. } else {
  386. TRY(fs_object.add("source"sv, "none"));
  387. }
  388. TRY(fs_object.finish());
  389. return {};
  390. }));
  391. TRY(array.finish());
  392. return {};
  393. }
  394. };
  395. class ProcFSMemoryStatus final : public ProcFSGlobalInformation {
  396. public:
  397. static NonnullLockRefPtr<ProcFSMemoryStatus> must_create();
  398. private:
  399. ProcFSMemoryStatus();
  400. virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
  401. {
  402. InterruptDisabler disabler;
  403. kmalloc_stats stats;
  404. get_kmalloc_stats(stats);
  405. auto system_memory = MM.get_system_memory_info();
  406. auto json = TRY(JsonObjectSerializer<>::try_create(builder));
  407. TRY(json.add("kmalloc_allocated"sv, stats.bytes_allocated));
  408. TRY(json.add("kmalloc_available"sv, stats.bytes_free));
  409. TRY(json.add("physical_allocated"sv, system_memory.physical_pages_used));
  410. TRY(json.add("physical_available"sv, system_memory.physical_pages - system_memory.physical_pages_used));
  411. TRY(json.add("physical_committed"sv, system_memory.physical_pages_committed));
  412. TRY(json.add("physical_uncommitted"sv, system_memory.physical_pages_uncommitted));
  413. TRY(json.add("kmalloc_call_count"sv, stats.kmalloc_call_count));
  414. TRY(json.add("kfree_call_count"sv, stats.kfree_call_count));
  415. TRY(json.finish());
  416. return {};
  417. }
  418. };
  419. class ProcFSSystemStatistics final : public ProcFSGlobalInformation {
  420. public:
  421. static NonnullLockRefPtr<ProcFSSystemStatistics> must_create();
  422. private:
  423. ProcFSSystemStatistics();
  424. virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
  425. {
  426. auto json = TRY(JsonObjectSerializer<>::try_create(builder));
  427. auto total_time_scheduled = Scheduler::get_total_time_scheduled();
  428. TRY(json.add("total_time"sv, total_time_scheduled.total));
  429. TRY(json.add("kernel_time"sv, total_time_scheduled.total_kernel));
  430. TRY(json.add("user_time"sv, total_time_scheduled.total - total_time_scheduled.total_kernel));
  431. u64 idle_time = 0;
  432. Processor::for_each([&](Processor& processor) {
  433. idle_time += processor.time_spent_idle();
  434. });
  435. TRY(json.add("idle_time"sv, idle_time));
  436. TRY(json.finish());
  437. return {};
  438. }
  439. };
  440. class ProcFSOverallProcesses final : public ProcFSGlobalInformation {
  441. public:
  442. static NonnullLockRefPtr<ProcFSOverallProcesses> must_create();
  443. private:
  444. ProcFSOverallProcesses();
  445. virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
  446. {
  447. auto json = TRY(JsonObjectSerializer<>::try_create(builder));
  448. // Keep this in sync with CProcessStatistics.
  449. auto build_process = [&](JsonArraySerializer<KBufferBuilder>& array, Process const& process) -> ErrorOr<void> {
  450. auto process_object = TRY(array.add_object());
  451. if (process.is_user_process()) {
  452. StringBuilder pledge_builder;
  453. #define __ENUMERATE_PLEDGE_PROMISE(promise) \
  454. if (process.has_promised(Pledge::promise)) \
  455. TRY(pledge_builder.try_append(#promise " "sv));
  456. ENUMERATE_PLEDGE_PROMISES
  457. #undef __ENUMERATE_PLEDGE_PROMISE
  458. TRY(process_object.add("pledge"sv, pledge_builder.string_view()));
  459. switch (process.veil_state()) {
  460. case VeilState::None:
  461. TRY(process_object.add("veil"sv, "None"));
  462. break;
  463. case VeilState::Dropped:
  464. TRY(process_object.add("veil"sv, "Dropped"));
  465. break;
  466. case VeilState::Locked:
  467. TRY(process_object.add("veil"sv, "Locked"));
  468. break;
  469. }
  470. } else {
  471. TRY(process_object.add("pledge"sv, ""sv));
  472. TRY(process_object.add("veil"sv, ""sv));
  473. }
  474. TRY(process_object.add("pid"sv, process.pid().value()));
  475. TRY(process_object.add("pgid"sv, process.tty() ? process.tty()->pgid().value() : 0));
  476. TRY(process_object.add("pgp"sv, process.pgid().value()));
  477. TRY(process_object.add("sid"sv, process.sid().value()));
  478. auto credentials = process.credentials();
  479. TRY(process_object.add("uid"sv, credentials->uid().value()));
  480. TRY(process_object.add("gid"sv, credentials->gid().value()));
  481. TRY(process_object.add("ppid"sv, process.ppid().value()));
  482. if (process.tty()) {
  483. auto tty_pseudo_name = TRY(process.tty()->pseudo_name());
  484. TRY(process_object.add("tty"sv, tty_pseudo_name->view()));
  485. } else {
  486. TRY(process_object.add("tty"sv, ""));
  487. }
  488. TRY(process_object.add("nfds"sv, process.fds().with_shared([](auto& fds) { return fds.open_count(); })));
  489. TRY(process_object.add("name"sv, process.name()));
  490. TRY(process_object.add("executable"sv, process.executable() ? TRY(process.executable()->try_serialize_absolute_path())->view() : ""sv));
  491. size_t amount_virtual = 0;
  492. size_t amount_resident = 0;
  493. size_t amount_dirty_private = 0;
  494. size_t amount_clean_inode = 0;
  495. size_t amount_shared = 0;
  496. size_t amount_purgeable_volatile = 0;
  497. size_t amount_purgeable_nonvolatile = 0;
  498. TRY(process.address_space().with([&](auto& space) -> ErrorOr<void> {
  499. amount_virtual = space->amount_virtual();
  500. amount_resident = space->amount_resident();
  501. amount_dirty_private = space->amount_dirty_private();
  502. amount_clean_inode = TRY(space->amount_clean_inode());
  503. amount_shared = space->amount_shared();
  504. amount_purgeable_volatile = space->amount_purgeable_volatile();
  505. amount_purgeable_nonvolatile = space->amount_purgeable_nonvolatile();
  506. return {};
  507. }));
  508. TRY(process_object.add("amount_virtual"sv, amount_virtual));
  509. TRY(process_object.add("amount_resident"sv, amount_resident));
  510. TRY(process_object.add("amount_dirty_private"sv, amount_dirty_private));
  511. TRY(process_object.add("amount_clean_inode"sv, amount_clean_inode));
  512. TRY(process_object.add("amount_shared"sv, amount_shared));
  513. TRY(process_object.add("amount_purgeable_volatile"sv, amount_purgeable_volatile));
  514. TRY(process_object.add("amount_purgeable_nonvolatile"sv, amount_purgeable_nonvolatile));
  515. TRY(process_object.add("dumpable"sv, process.is_dumpable()));
  516. TRY(process_object.add("kernel"sv, process.is_kernel_process()));
  517. auto thread_array = TRY(process_object.add_array("threads"sv));
  518. TRY(process.try_for_each_thread([&](const Thread& thread) -> ErrorOr<void> {
  519. SpinlockLocker locker(thread.get_lock());
  520. auto thread_object = TRY(thread_array.add_object());
  521. #if LOCK_DEBUG
  522. TRY(thread_object.add("lock_count"sv, thread.lock_count()));
  523. #endif
  524. TRY(thread_object.add("tid"sv, thread.tid().value()));
  525. TRY(thread_object.add("name"sv, thread.name()));
  526. TRY(thread_object.add("times_scheduled"sv, thread.times_scheduled()));
  527. TRY(thread_object.add("time_user"sv, thread.time_in_user()));
  528. TRY(thread_object.add("time_kernel"sv, thread.time_in_kernel()));
  529. TRY(thread_object.add("state"sv, thread.state_string()));
  530. TRY(thread_object.add("cpu"sv, thread.cpu()));
  531. TRY(thread_object.add("priority"sv, thread.priority()));
  532. TRY(thread_object.add("syscall_count"sv, thread.syscall_count()));
  533. TRY(thread_object.add("inode_faults"sv, thread.inode_faults()));
  534. TRY(thread_object.add("zero_faults"sv, thread.zero_faults()));
  535. TRY(thread_object.add("cow_faults"sv, thread.cow_faults()));
  536. TRY(thread_object.add("file_read_bytes"sv, thread.file_read_bytes()));
  537. TRY(thread_object.add("file_write_bytes"sv, thread.file_write_bytes()));
  538. TRY(thread_object.add("unix_socket_read_bytes"sv, thread.unix_socket_read_bytes()));
  539. TRY(thread_object.add("unix_socket_write_bytes"sv, thread.unix_socket_write_bytes()));
  540. TRY(thread_object.add("ipv4_socket_read_bytes"sv, thread.ipv4_socket_read_bytes()));
  541. TRY(thread_object.add("ipv4_socket_write_bytes"sv, thread.ipv4_socket_write_bytes()));
  542. TRY(thread_object.finish());
  543. return {};
  544. }));
  545. TRY(thread_array.finish());
  546. TRY(process_object.finish());
  547. return {};
  548. };
  549. {
  550. auto array = TRY(json.add_array("processes"sv));
  551. TRY(build_process(array, *Scheduler::colonel()));
  552. TRY(Process::all_instances().with([&](auto& processes) -> ErrorOr<void> {
  553. for (auto& process : processes)
  554. TRY(build_process(array, process));
  555. return {};
  556. }));
  557. TRY(array.finish());
  558. }
  559. auto total_time_scheduled = Scheduler::get_total_time_scheduled();
  560. TRY(json.add("total_time"sv, total_time_scheduled.total));
  561. TRY(json.add("total_time_kernel"sv, total_time_scheduled.total_kernel));
  562. TRY(json.finish());
  563. return {};
  564. }
  565. };
  566. class ProcFSCPUInformation final : public ProcFSGlobalInformation {
  567. public:
  568. static NonnullLockRefPtr<ProcFSCPUInformation> must_create();
  569. private:
  570. ProcFSCPUInformation();
  571. virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
  572. {
  573. auto array = TRY(JsonArraySerializer<>::try_create(builder));
  574. TRY(Processor::try_for_each(
  575. [&](Processor& proc) -> ErrorOr<void> {
  576. auto& info = proc.info();
  577. auto obj = TRY(array.add_object());
  578. TRY(obj.add("processor"sv, proc.id()));
  579. TRY(obj.add("vendor_id"sv, info.vendor_id_string()));
  580. TRY(obj.add("family"sv, info.display_family()));
  581. if (!info.hypervisor_vendor_id_string().is_null())
  582. TRY(obj.add("hypervisor_vendor_id"sv, info.hypervisor_vendor_id_string()));
  583. auto features_array = TRY(obj.add_array("features"sv));
  584. auto keep_empty = SplitBehavior::KeepEmpty;
  585. ErrorOr<void> result; // FIXME: Make this nicer
  586. info.features_string().for_each_split_view(' ', keep_empty, [&](StringView feature) {
  587. if (result.is_error())
  588. return;
  589. result = features_array.add(feature);
  590. });
  591. TRY(result);
  592. TRY(features_array.finish());
  593. TRY(obj.add("model"sv, info.display_model()));
  594. TRY(obj.add("stepping"sv, info.stepping()));
  595. TRY(obj.add("type"sv, info.type()));
  596. TRY(obj.add("brand"sv, info.brand_string()));
  597. auto caches = TRY(obj.add_object("caches"sv));
  598. auto add_cache_info = [&](StringView name, ProcessorInfo::Cache const& cache) -> ErrorOr<void> {
  599. auto cache_object = TRY(caches.add_object(name));
  600. TRY(cache_object.add("size"sv, cache.size));
  601. TRY(cache_object.add("line_size"sv, cache.line_size));
  602. TRY(cache_object.finish());
  603. return {};
  604. };
  605. if (info.l1_data_cache().has_value())
  606. TRY(add_cache_info("l1_data"sv, *info.l1_data_cache()));
  607. if (info.l1_instruction_cache().has_value())
  608. TRY(add_cache_info("l1_instruction"sv, *info.l1_instruction_cache()));
  609. if (info.l2_cache().has_value())
  610. TRY(add_cache_info("l2"sv, *info.l2_cache()));
  611. if (info.l3_cache().has_value())
  612. TRY(add_cache_info("l3"sv, *info.l3_cache()));
  613. TRY(caches.finish());
  614. TRY(obj.finish());
  615. return {};
  616. }));
  617. TRY(array.finish());
  618. return {};
  619. }
  620. };
  621. class ProcFSDmesg final : public ProcFSGlobalInformation {
  622. public:
  623. static NonnullLockRefPtr<ProcFSDmesg> must_create();
  624. virtual mode_t required_mode() const override { return 0400; }
  625. private:
  626. ProcFSDmesg();
  627. virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
  628. {
  629. VERIFY(DeviceManagement::the().is_console_device_attached());
  630. InterruptDisabler disabler;
  631. for (char ch : DeviceManagement::the().console_device().logbuffer()) {
  632. TRY(builder.append(ch));
  633. }
  634. return {};
  635. }
  636. };
  637. class ProcFSInterrupts final : public ProcFSGlobalInformation {
  638. public:
  639. static NonnullLockRefPtr<ProcFSInterrupts> must_create();
  640. private:
  641. ProcFSInterrupts();
  642. virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
  643. {
  644. auto array = TRY(JsonArraySerializer<>::try_create(builder));
  645. ErrorOr<void> result; // FIXME: Make this nicer
  646. InterruptManagement::the().enumerate_interrupt_handlers([&array, &result](GenericInterruptHandler& handler) {
  647. if (result.is_error())
  648. return;
  649. result = ([&]() -> ErrorOr<void> {
  650. auto obj = TRY(array.add_object());
  651. TRY(obj.add("purpose"sv, handler.purpose()));
  652. TRY(obj.add("interrupt_line"sv, handler.interrupt_number()));
  653. TRY(obj.add("controller"sv, handler.controller()));
  654. TRY(obj.add("cpu_handler"sv, 0)); // FIXME: Determine the responsible CPU for each interrupt handler.
  655. TRY(obj.add("device_sharing"sv, (unsigned)handler.sharing_devices_count()));
  656. TRY(obj.add("call_count"sv, (unsigned)handler.get_invoking_count()));
  657. TRY(obj.finish());
  658. return {};
  659. })();
  660. });
  661. TRY(result);
  662. TRY(array.finish());
  663. return {};
  664. }
  665. };
  666. class ProcFSKeymap final : public ProcFSGlobalInformation {
  667. public:
  668. static NonnullLockRefPtr<ProcFSKeymap> must_create();
  669. private:
  670. ProcFSKeymap();
  671. virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
  672. {
  673. auto json = TRY(JsonObjectSerializer<>::try_create(builder));
  674. TRY(HIDManagement::the().keymap_data().with([&](auto const& keymap_data) {
  675. return json.add("keymap"sv, keymap_data.character_map_name->view());
  676. }));
  677. TRY(json.finish());
  678. return {};
  679. }
  680. };
  681. class ProcFSUptime final : public ProcFSGlobalInformation {
  682. public:
  683. static NonnullLockRefPtr<ProcFSUptime> must_create();
  684. private:
  685. ProcFSUptime();
  686. virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
  687. {
  688. return builder.appendff("{}\n", TimeManagement::the().uptime_ms() / 1000);
  689. }
  690. };
  691. class ProcFSCommandLine final : public ProcFSGlobalInformation {
  692. public:
  693. static NonnullLockRefPtr<ProcFSCommandLine> must_create();
  694. private:
  695. ProcFSCommandLine();
  696. virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
  697. {
  698. TRY(builder.append(kernel_command_line().string()));
  699. TRY(builder.append('\n'));
  700. return {};
  701. }
  702. };
  703. class ProcFSSystemMode final : public ProcFSGlobalInformation {
  704. public:
  705. static NonnullLockRefPtr<ProcFSSystemMode> must_create();
  706. private:
  707. ProcFSSystemMode();
  708. virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
  709. {
  710. TRY(builder.append(kernel_command_line().system_mode()));
  711. TRY(builder.append('\n'));
  712. return {};
  713. }
  714. };
  715. class ProcFSProfile final : public ProcFSGlobalInformation {
  716. public:
  717. static NonnullLockRefPtr<ProcFSProfile> must_create();
  718. virtual mode_t required_mode() const override { return 0400; }
  719. private:
  720. ProcFSProfile();
  721. virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
  722. {
  723. if (!g_global_perf_events)
  724. return ENOENT;
  725. TRY(g_global_perf_events->to_json(builder));
  726. return {};
  727. }
  728. };
  729. class ProcFSKernelBase final : public ProcFSGlobalInformation {
  730. public:
  731. static NonnullLockRefPtr<ProcFSKernelBase> must_create();
  732. private:
  733. ProcFSKernelBase();
  734. virtual mode_t required_mode() const override { return 0400; }
  735. virtual ErrorOr<void> try_generate(KBufferBuilder& builder) override
  736. {
  737. auto current_process_credentials = Process::current().credentials();
  738. if (!current_process_credentials->is_superuser())
  739. return EPERM;
  740. return builder.appendff("{}", kernel_load_base);
  741. }
  742. };
  743. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSSelfProcessDirectory> ProcFSSelfProcessDirectory::must_create()
  744. {
  745. return adopt_lock_ref_if_nonnull(new (nothrow) ProcFSSelfProcessDirectory()).release_nonnull();
  746. }
  747. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSDiskUsage> ProcFSDiskUsage::must_create()
  748. {
  749. return adopt_lock_ref_if_nonnull(new (nothrow) ProcFSDiskUsage).release_nonnull();
  750. }
  751. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSMemoryStatus> ProcFSMemoryStatus::must_create()
  752. {
  753. return adopt_lock_ref_if_nonnull(new (nothrow) ProcFSMemoryStatus).release_nonnull();
  754. }
  755. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSSystemStatistics> ProcFSSystemStatistics::must_create()
  756. {
  757. return adopt_lock_ref_if_nonnull(new (nothrow) ProcFSSystemStatistics).release_nonnull();
  758. }
  759. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSOverallProcesses> ProcFSOverallProcesses::must_create()
  760. {
  761. return adopt_lock_ref_if_nonnull(new (nothrow) ProcFSOverallProcesses).release_nonnull();
  762. }
  763. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSCPUInformation> ProcFSCPUInformation::must_create()
  764. {
  765. return adopt_lock_ref_if_nonnull(new (nothrow) ProcFSCPUInformation).release_nonnull();
  766. }
  767. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSDmesg> ProcFSDmesg::must_create()
  768. {
  769. return adopt_lock_ref_if_nonnull(new (nothrow) ProcFSDmesg).release_nonnull();
  770. }
  771. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSInterrupts> ProcFSInterrupts::must_create()
  772. {
  773. return adopt_lock_ref_if_nonnull(new (nothrow) ProcFSInterrupts).release_nonnull();
  774. }
  775. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSKeymap> ProcFSKeymap::must_create()
  776. {
  777. return adopt_lock_ref_if_nonnull(new (nothrow) ProcFSKeymap).release_nonnull();
  778. }
  779. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSUptime> ProcFSUptime::must_create()
  780. {
  781. return adopt_lock_ref_if_nonnull(new (nothrow) ProcFSUptime).release_nonnull();
  782. }
  783. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSCommandLine> ProcFSCommandLine::must_create()
  784. {
  785. return adopt_lock_ref_if_nonnull(new (nothrow) ProcFSCommandLine).release_nonnull();
  786. }
  787. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSSystemMode> ProcFSSystemMode::must_create()
  788. {
  789. return adopt_lock_ref_if_nonnull(new (nothrow) ProcFSSystemMode).release_nonnull();
  790. }
  791. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSProfile> ProcFSProfile::must_create()
  792. {
  793. return adopt_lock_ref_if_nonnull(new (nothrow) ProcFSProfile).release_nonnull();
  794. }
  795. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSKernelBase> ProcFSKernelBase::must_create()
  796. {
  797. return adopt_lock_ref_if_nonnull(new (nothrow) ProcFSKernelBase).release_nonnull();
  798. }
  799. UNMAP_AFTER_INIT ProcFSSelfProcessDirectory::ProcFSSelfProcessDirectory()
  800. : ProcFSExposedLink("self"sv)
  801. {
  802. }
  803. UNMAP_AFTER_INIT ProcFSDiskUsage::ProcFSDiskUsage()
  804. : ProcFSGlobalInformation("df"sv)
  805. {
  806. }
  807. UNMAP_AFTER_INIT ProcFSMemoryStatus::ProcFSMemoryStatus()
  808. : ProcFSGlobalInformation("memstat"sv)
  809. {
  810. }
  811. UNMAP_AFTER_INIT ProcFSSystemStatistics::ProcFSSystemStatistics()
  812. : ProcFSGlobalInformation("stat"sv)
  813. {
  814. }
  815. UNMAP_AFTER_INIT ProcFSOverallProcesses::ProcFSOverallProcesses()
  816. : ProcFSGlobalInformation("all"sv)
  817. {
  818. }
  819. UNMAP_AFTER_INIT ProcFSCPUInformation::ProcFSCPUInformation()
  820. : ProcFSGlobalInformation("cpuinfo"sv)
  821. {
  822. }
  823. UNMAP_AFTER_INIT ProcFSDmesg::ProcFSDmesg()
  824. : ProcFSGlobalInformation("dmesg"sv)
  825. {
  826. }
  827. UNMAP_AFTER_INIT ProcFSInterrupts::ProcFSInterrupts()
  828. : ProcFSGlobalInformation("interrupts"sv)
  829. {
  830. }
  831. UNMAP_AFTER_INIT ProcFSKeymap::ProcFSKeymap()
  832. : ProcFSGlobalInformation("keymap"sv)
  833. {
  834. }
  835. UNMAP_AFTER_INIT ProcFSUptime::ProcFSUptime()
  836. : ProcFSGlobalInformation("uptime"sv)
  837. {
  838. }
  839. UNMAP_AFTER_INIT ProcFSCommandLine::ProcFSCommandLine()
  840. : ProcFSGlobalInformation("cmdline"sv)
  841. {
  842. }
  843. UNMAP_AFTER_INIT ProcFSSystemMode::ProcFSSystemMode()
  844. : ProcFSGlobalInformation("system_mode"sv)
  845. {
  846. }
  847. UNMAP_AFTER_INIT ProcFSProfile::ProcFSProfile()
  848. : ProcFSGlobalInformation("profile"sv)
  849. {
  850. }
  851. UNMAP_AFTER_INIT ProcFSKernelBase::ProcFSKernelBase()
  852. : ProcFSGlobalInformation("kernel_base"sv)
  853. {
  854. }
  855. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSSystemDirectory> ProcFSSystemDirectory::must_create(ProcFSRootDirectory const& parent_directory)
  856. {
  857. auto directory = adopt_lock_ref(*new (nothrow) ProcFSSystemDirectory(parent_directory));
  858. directory->m_components.append(ProcFSDumpKmallocStacks::must_create(directory));
  859. directory->m_components.append(ProcFSUBSanDeadly::must_create(directory));
  860. directory->m_components.append(ProcFSCapsLockRemap::must_create(directory));
  861. return directory;
  862. }
  863. UNMAP_AFTER_INIT ProcFSSystemDirectory::ProcFSSystemDirectory(ProcFSRootDirectory const& parent_directory)
  864. : ProcFSExposedDirectory("sys"sv, parent_directory)
  865. {
  866. }
  867. UNMAP_AFTER_INIT NonnullLockRefPtr<ProcFSRootDirectory> ProcFSRootDirectory::must_create()
  868. {
  869. auto directory = adopt_lock_ref(*new (nothrow) ProcFSRootDirectory);
  870. directory->m_components.append(ProcFSSelfProcessDirectory::must_create());
  871. directory->m_components.append(ProcFSDiskUsage::must_create());
  872. directory->m_components.append(ProcFSMemoryStatus::must_create());
  873. directory->m_components.append(ProcFSSystemStatistics::must_create());
  874. directory->m_components.append(ProcFSOverallProcesses::must_create());
  875. directory->m_components.append(ProcFSCPUInformation::must_create());
  876. directory->m_components.append(ProcFSDmesg::must_create());
  877. directory->m_components.append(ProcFSInterrupts::must_create());
  878. directory->m_components.append(ProcFSKeymap::must_create());
  879. directory->m_components.append(ProcFSUptime::must_create());
  880. directory->m_components.append(ProcFSCommandLine::must_create());
  881. directory->m_components.append(ProcFSSystemMode::must_create());
  882. directory->m_components.append(ProcFSProfile::must_create());
  883. directory->m_components.append(ProcFSKernelBase::must_create());
  884. directory->m_components.append(ProcFSNetworkDirectory::must_create(*directory));
  885. directory->m_components.append(ProcFSSystemDirectory::must_create(*directory));
  886. return directory;
  887. }
  888. ErrorOr<void> ProcFSRootDirectory::traverse_as_directory(FileSystemID fsid, Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)> callback) const
  889. {
  890. MutexLocker locker(ProcFSComponentRegistry::the().get_lock());
  891. TRY(callback({ "."sv, { fsid, component_index() }, 0 }));
  892. TRY(callback({ ".."sv, { fsid, 0 }, 0 }));
  893. for (auto const& component : m_components) {
  894. InodeIdentifier identifier = { fsid, component.component_index() };
  895. TRY(callback({ component.name(), identifier, 0 }));
  896. }
  897. return Process::all_instances().with([&](auto& list) -> ErrorOr<void> {
  898. for (auto& process : list) {
  899. VERIFY(!(process.pid() < 0));
  900. u64 process_id = (u64)process.pid().value();
  901. InodeIdentifier identifier = { fsid, static_cast<InodeIndex>(process_id << 36) };
  902. auto process_id_string = TRY(KString::formatted("{:d}", process_id));
  903. TRY(callback({ process_id_string->view(), identifier, 0 }));
  904. }
  905. return {};
  906. });
  907. }
  908. ErrorOr<NonnullLockRefPtr<ProcFSExposedComponent>> ProcFSRootDirectory::lookup(StringView name)
  909. {
  910. auto maybe_candidate = ProcFSExposedDirectory::lookup(name);
  911. if (maybe_candidate.is_error()) {
  912. if (maybe_candidate.error().code() != ENOENT) {
  913. return maybe_candidate.release_error();
  914. }
  915. } else {
  916. return maybe_candidate.release_value();
  917. }
  918. auto pid = name.to_uint<unsigned>();
  919. if (!pid.has_value())
  920. return ESRCH;
  921. auto actual_pid = pid.value();
  922. if (auto maybe_process = Process::from_pid(actual_pid))
  923. return maybe_process->procfs_traits();
  924. return ENOENT;
  925. }
  926. UNMAP_AFTER_INIT ProcFSRootDirectory::ProcFSRootDirectory()
  927. : ProcFSExposedDirectory("."sv)
  928. {
  929. }
  930. UNMAP_AFTER_INIT ProcFSRootDirectory::~ProcFSRootDirectory() = default;
  931. }