ProcessExposed.cpp 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626
  1. /*
  2. * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/JsonArraySerializer.h>
  7. #include <AK/JsonObject.h>
  8. #include <AK/JsonObjectSerializer.h>
  9. #include <AK/JsonValue.h>
  10. #include <AK/UBSanitizer.h>
  11. #include <Kernel/Arch/x86/CPU.h>
  12. #include <Kernel/Arch/x86/InterruptDisabler.h>
  13. #include <Kernel/Arch/x86/ProcessorInfo.h>
  14. #include <Kernel/CommandLine.h>
  15. #include <Kernel/ConsoleDevice.h>
  16. #include <Kernel/Debug.h>
  17. #include <Kernel/Devices/BlockDevice.h>
  18. #include <Kernel/Devices/HID/HIDManagement.h>
  19. #include <Kernel/FileSystem/Custody.h>
  20. #include <Kernel/FileSystem/FileBackedFileSystem.h>
  21. #include <Kernel/FileSystem/FileDescription.h>
  22. #include <Kernel/FileSystem/ProcFS.h>
  23. #include <Kernel/FileSystem/VirtualFileSystem.h>
  24. #include <Kernel/Heap/kmalloc.h>
  25. #include <Kernel/Interrupts/GenericInterruptHandler.h>
  26. #include <Kernel/Interrupts/InterruptManagement.h>
  27. #include <Kernel/KBufferBuilder.h>
  28. #include <Kernel/Module.h>
  29. #include <Kernel/Net/LocalSocket.h>
  30. #include <Kernel/Net/NetworkAdapter.h>
  31. #include <Kernel/Net/NetworkingManagement.h>
  32. #include <Kernel/Net/Routing.h>
  33. #include <Kernel/Net/TCPSocket.h>
  34. #include <Kernel/Net/UDPSocket.h>
  35. #include <Kernel/PCI/Access.h>
  36. #include <Kernel/PerformanceEventBuffer.h>
  37. #include <Kernel/Process.h>
  38. #include <Kernel/ProcessExposed.h>
  39. #include <Kernel/Sections.h>
  40. #include <Kernel/VM/AnonymousVMObject.h>
  41. #include <Kernel/VM/MemoryManager.h>
  42. namespace Kernel {
  43. static SpinLock<u8> s_index_lock;
  44. static InodeIndex s_next_inode_index = 0;
  45. static size_t s_allocate_inode_index()
  46. {
  47. ScopedSpinLock lock(s_index_lock);
  48. s_next_inode_index = s_next_inode_index.value() + 1;
  49. VERIFY(s_next_inode_index > 0);
  50. return s_next_inode_index.value();
  51. }
  52. InodeIndex ProcFSComponentsRegistrar::allocate_inode_index() const
  53. {
  54. return s_allocate_inode_index();
  55. }
  56. ProcFSExposedComponent::ProcFSExposedComponent(StringView name)
  57. : m_component_index(s_allocate_inode_index())
  58. {
  59. m_name = KString::try_create(name);
  60. }
  61. // Note: This constructor is intended to be used in /proc/pid/fd/* symlinks
  62. // so we preallocated inode index for them so we just need to set it here.
  63. ProcFSExposedComponent::ProcFSExposedComponent(StringView name, InodeIndex preallocated_index)
  64. : m_component_index(preallocated_index.value())
  65. {
  66. VERIFY(preallocated_index.value() != 0);
  67. VERIFY(preallocated_index <= s_next_inode_index);
  68. m_name = KString::try_create(name);
  69. }
  70. ProcFSExposedFolder::ProcFSExposedFolder(StringView name)
  71. : ProcFSExposedComponent(name)
  72. {
  73. }
  74. ProcFSExposedFolder::ProcFSExposedFolder(StringView name, const ProcFSExposedFolder& parent_folder)
  75. : ProcFSExposedComponent(name)
  76. , m_parent_folder(parent_folder)
  77. {
  78. }
  79. ProcFSExposedLink::ProcFSExposedLink(StringView name)
  80. : ProcFSExposedComponent(name)
  81. {
  82. }
  83. ProcFSExposedLink::ProcFSExposedLink(StringView name, InodeIndex preallocated_index)
  84. : ProcFSExposedComponent(name, preallocated_index)
  85. {
  86. }
  87. struct ProcFSInodeData : public FileDescriptionData {
  88. RefPtr<KBufferImpl> buffer;
  89. };
  90. KResultOr<size_t> ProcFSGlobalInformation::read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, FileDescription* description) const
  91. {
  92. dbgln_if(PROCFS_DEBUG, "ProcFSGlobalInformation @ {}: read_bytes offset: {} count: {}", name(), offset, count);
  93. VERIFY(offset >= 0);
  94. VERIFY(buffer.user_or_kernel_ptr());
  95. if (!description)
  96. return KResult(EIO);
  97. if (!description->data()) {
  98. dbgln("ProcFSGlobalInformation: Do not have cached data!");
  99. return KResult(EIO);
  100. }
  101. // Be sure to keep a reference to data_buffer while we use it!
  102. RefPtr<KBufferImpl> data_buffer = static_cast<ProcFSInodeData&>(*description->data()).buffer;
  103. if (!data_buffer || (size_t)offset >= data_buffer->size())
  104. return 0;
  105. ssize_t nread = min(static_cast<off_t>(data_buffer->size() - offset), static_cast<off_t>(count));
  106. if (!buffer.write(data_buffer->data() + offset, nread))
  107. return KResult(EFAULT);
  108. return nread;
  109. }
  110. KResult ProcFSGlobalInformation::refresh_data(FileDescription& description) const
  111. {
  112. ScopedSpinLock lock(m_refresh_lock);
  113. auto& cached_data = description.data();
  114. if (!cached_data)
  115. cached_data = adopt_own_if_nonnull(new (nothrow) ProcFSInodeData);
  116. VERIFY(description.data());
  117. auto& buffer = static_cast<ProcFSInodeData&>(*cached_data).buffer;
  118. if (buffer) {
  119. // If we're reusing the buffer, reset the size to 0 first. This
  120. // ensures we don't accidentally leak previously written data.
  121. buffer->set_size(0);
  122. }
  123. KBufferBuilder builder(buffer, true);
  124. if (!const_cast<ProcFSGlobalInformation&>(*this).output(builder))
  125. return ENOENT;
  126. // We don't use builder.build() here, which would steal our buffer
  127. // and turn it into an OwnPtr. Instead, just flush to the buffer so
  128. // that we can read all the data that was written.
  129. if (!builder.flush())
  130. return ENOMEM;
  131. if (!buffer)
  132. return ENOMEM;
  133. return KSuccess;
  134. }
  135. RefPtr<ProcFSProcessFolder> ProcFSRootFolder::process_folder_for(Process& process)
  136. {
  137. RefPtr<Process> checked_process = process;
  138. for (auto& folder : m_process_folders) {
  139. if (folder.associated_process().ptr() == checked_process.ptr())
  140. return folder;
  141. }
  142. return {};
  143. }
  144. KResultOr<size_t> ProcFSProcessInformation::read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, FileDescription* description) const
  145. {
  146. dbgln_if(PROCFS_DEBUG, "ProcFSProcessInformation @ {}: read_bytes offset: {} count: {}", name(), offset, count);
  147. VERIFY(offset >= 0);
  148. VERIFY(buffer.user_or_kernel_ptr());
  149. if (!description)
  150. return KResult(EIO);
  151. if (!description->data()) {
  152. dbgln("ProcFSGlobalInformation: Do not have cached data!");
  153. return KResult(EIO);
  154. }
  155. // Be sure to keep a reference to data_buffer while we use it!
  156. RefPtr<KBufferImpl> data_buffer = static_cast<ProcFSInodeData&>(*description->data()).buffer;
  157. if (!data_buffer || (size_t)offset >= data_buffer->size())
  158. return 0;
  159. ssize_t nread = min(static_cast<off_t>(data_buffer->size() - offset), static_cast<off_t>(count));
  160. if (!buffer.write(data_buffer->data() + offset, nread))
  161. return KResult(EFAULT);
  162. return nread;
  163. }
  164. KResult ProcFSProcessInformation::refresh_data(FileDescription& description) const
  165. {
  166. // For process-specific inodes, hold the process's ptrace lock across refresh
  167. // and refuse to load data if the process is not dumpable.
  168. // Without this, files opened before a process went non-dumpable could still be used for dumping.
  169. auto process = const_cast<ProcFSProcessInformation&>(*this).m_parent_folder->m_associated_process;
  170. process->ptrace_lock().lock();
  171. if (!process->is_dumpable()) {
  172. process->ptrace_lock().unlock();
  173. return EPERM;
  174. }
  175. ScopeGuard guard = [&] {
  176. process->ptrace_lock().unlock();
  177. };
  178. ScopedSpinLock lock(m_refresh_lock);
  179. auto& cached_data = description.data();
  180. if (!cached_data)
  181. cached_data = adopt_own_if_nonnull(new (nothrow) ProcFSInodeData);
  182. VERIFY(description.data());
  183. auto& buffer = static_cast<ProcFSInodeData&>(*cached_data).buffer;
  184. if (buffer) {
  185. // If we're reusing the buffer, reset the size to 0 first. This
  186. // ensures we don't accidentally leak previously written data.
  187. buffer->set_size(0);
  188. }
  189. KBufferBuilder builder(buffer, true);
  190. if (!const_cast<ProcFSProcessInformation&>(*this).output(builder))
  191. return ENOENT;
  192. // We don't use builder.build() here, which would steal our buffer
  193. // and turn it into an OwnPtr. Instead, just flush to the buffer so
  194. // that we can read all the data that was written.
  195. if (!builder.flush())
  196. return ENOMEM;
  197. if (!buffer)
  198. return ENOMEM;
  199. return KSuccess;
  200. }
  201. class ProcFSSystemDirectory;
  202. class ProcFSDumpKmallocStacks : public ProcFSSystemBoolean {
  203. public:
  204. static NonnullRefPtr<ProcFSDumpKmallocStacks> must_create(const ProcFSSystemDirectory&);
  205. virtual bool value() const override
  206. {
  207. Locker locker(m_lock);
  208. return g_dump_kmalloc_stacks;
  209. }
  210. virtual void set_value(bool new_value) override
  211. {
  212. Locker locker(m_lock);
  213. g_dump_kmalloc_stacks = new_value;
  214. }
  215. private:
  216. ProcFSDumpKmallocStacks();
  217. mutable Lock m_lock;
  218. };
  219. class ProcFSUBSanDeadly : public ProcFSSystemBoolean {
  220. public:
  221. static NonnullRefPtr<ProcFSUBSanDeadly> must_create(const ProcFSSystemDirectory&);
  222. virtual bool value() const override
  223. {
  224. Locker locker(m_lock);
  225. return AK::UBSanitizer::g_ubsan_is_deadly;
  226. }
  227. virtual void set_value(bool new_value) override
  228. {
  229. Locker locker(m_lock);
  230. AK::UBSanitizer::g_ubsan_is_deadly = new_value;
  231. }
  232. private:
  233. ProcFSUBSanDeadly();
  234. mutable Lock m_lock;
  235. };
  236. class ProcFSCapsLockRemap : public ProcFSSystemBoolean {
  237. public:
  238. static NonnullRefPtr<ProcFSCapsLockRemap> must_create(const ProcFSSystemDirectory&);
  239. virtual bool value() const override
  240. {
  241. Locker locker(m_lock);
  242. return g_caps_lock_remapped_to_ctrl.load();
  243. }
  244. virtual void set_value(bool new_value) override
  245. {
  246. Locker locker(m_lock);
  247. g_caps_lock_remapped_to_ctrl.exchange(new_value);
  248. }
  249. private:
  250. ProcFSCapsLockRemap();
  251. mutable Lock m_lock;
  252. };
  253. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSDumpKmallocStacks> ProcFSDumpKmallocStacks::must_create(const ProcFSSystemDirectory&)
  254. {
  255. return adopt_ref_if_nonnull(new (nothrow) ProcFSDumpKmallocStacks).release_nonnull();
  256. }
  257. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSUBSanDeadly> ProcFSUBSanDeadly::must_create(const ProcFSSystemDirectory&)
  258. {
  259. return adopt_ref_if_nonnull(new (nothrow) ProcFSUBSanDeadly).release_nonnull();
  260. }
  261. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSCapsLockRemap> ProcFSCapsLockRemap::must_create(const ProcFSSystemDirectory&)
  262. {
  263. return adopt_ref_if_nonnull(new (nothrow) ProcFSCapsLockRemap).release_nonnull();
  264. }
  265. UNMAP_AFTER_INIT ProcFSDumpKmallocStacks::ProcFSDumpKmallocStacks()
  266. : ProcFSSystemBoolean("kmalloc_stacks"sv)
  267. {
  268. }
  269. UNMAP_AFTER_INIT ProcFSUBSanDeadly::ProcFSUBSanDeadly()
  270. : ProcFSSystemBoolean("ubsan_is_deadly"sv)
  271. {
  272. }
  273. UNMAP_AFTER_INIT ProcFSCapsLockRemap::ProcFSCapsLockRemap()
  274. : ProcFSSystemBoolean("caps_lock_to_ctrl"sv)
  275. {
  276. }
  277. class ProcFSSelfProcessFolder final : public ProcFSExposedLink {
  278. public:
  279. static NonnullRefPtr<ProcFSSelfProcessFolder> must_create();
  280. private:
  281. ProcFSSelfProcessFolder();
  282. virtual bool acquire_link(KBufferBuilder& builder) override
  283. {
  284. builder.appendff("{}", Process::current()->pid().value());
  285. return true;
  286. }
  287. };
  288. class ProcFSDiskUsage final : public ProcFSGlobalInformation {
  289. public:
  290. static NonnullRefPtr<ProcFSDiskUsage> must_create();
  291. private:
  292. ProcFSDiskUsage();
  293. virtual bool output(KBufferBuilder& builder) override
  294. {
  295. JsonArraySerializer array { builder };
  296. VFS::the().for_each_mount([&array](auto& mount) {
  297. auto& fs = mount.guest_fs();
  298. auto fs_object = array.add_object();
  299. fs_object.add("class_name", fs.class_name());
  300. fs_object.add("total_block_count", fs.total_block_count());
  301. fs_object.add("free_block_count", fs.free_block_count());
  302. fs_object.add("total_inode_count", fs.total_inode_count());
  303. fs_object.add("free_inode_count", fs.free_inode_count());
  304. fs_object.add("mount_point", mount.absolute_path());
  305. fs_object.add("block_size", static_cast<u64>(fs.block_size()));
  306. fs_object.add("readonly", fs.is_readonly());
  307. fs_object.add("mount_flags", mount.flags());
  308. if (fs.is_file_backed())
  309. fs_object.add("source", static_cast<const FileBackedFS&>(fs).file_description().absolute_path());
  310. else
  311. fs_object.add("source", "none");
  312. });
  313. array.finish();
  314. return true;
  315. }
  316. };
  317. class ProcFSMemoryStatus final : public ProcFSGlobalInformation {
  318. public:
  319. static NonnullRefPtr<ProcFSMemoryStatus> must_create();
  320. private:
  321. ProcFSMemoryStatus();
  322. virtual bool output(KBufferBuilder& builder) override
  323. {
  324. InterruptDisabler disabler;
  325. kmalloc_stats stats;
  326. get_kmalloc_stats(stats);
  327. ScopedSpinLock mm_lock(s_mm_lock);
  328. auto user_physical_pages_total = MM.user_physical_pages();
  329. auto user_physical_pages_used = MM.user_physical_pages_used();
  330. auto user_physical_pages_committed = MM.user_physical_pages_committed();
  331. auto user_physical_pages_uncommitted = MM.user_physical_pages_uncommitted();
  332. auto super_physical_total = MM.super_physical_pages();
  333. auto super_physical_used = MM.super_physical_pages_used();
  334. mm_lock.unlock();
  335. JsonObjectSerializer<KBufferBuilder> json { builder };
  336. json.add("kmalloc_allocated", stats.bytes_allocated);
  337. json.add("kmalloc_available", stats.bytes_free);
  338. json.add("kmalloc_eternal_allocated", stats.bytes_eternal);
  339. json.add("user_physical_allocated", user_physical_pages_used);
  340. json.add("user_physical_available", user_physical_pages_total - user_physical_pages_used);
  341. json.add("user_physical_committed", user_physical_pages_committed);
  342. json.add("user_physical_uncommitted", user_physical_pages_uncommitted);
  343. json.add("super_physical_allocated", super_physical_used);
  344. json.add("super_physical_available", super_physical_total - super_physical_used);
  345. json.add("kmalloc_call_count", stats.kmalloc_call_count);
  346. json.add("kfree_call_count", stats.kfree_call_count);
  347. slab_alloc_stats([&json](size_t slab_size, size_t num_allocated, size_t num_free) {
  348. auto prefix = String::formatted("slab_{}", slab_size);
  349. json.add(String::formatted("{}_num_allocated", prefix), num_allocated);
  350. json.add(String::formatted("{}_num_free", prefix), num_free);
  351. });
  352. json.finish();
  353. return true;
  354. }
  355. };
  356. class ProcFSOverallProcesses final : public ProcFSGlobalInformation {
  357. public:
  358. static NonnullRefPtr<ProcFSOverallProcesses> must_create();
  359. private:
  360. ProcFSOverallProcesses();
  361. virtual bool output(KBufferBuilder& builder) override
  362. {
  363. JsonArraySerializer array { builder };
  364. // Keep this in sync with CProcessStatistics.
  365. auto build_process = [&](const Process& process) {
  366. auto process_object = array.add_object();
  367. if (process.is_user_process()) {
  368. StringBuilder pledge_builder;
  369. #define __ENUMERATE_PLEDGE_PROMISE(promise) \
  370. if (process.has_promised(Pledge::promise)) { \
  371. pledge_builder.append(#promise " "); \
  372. }
  373. ENUMERATE_PLEDGE_PROMISES
  374. #undef __ENUMERATE_PLEDGE_PROMISE
  375. process_object.add("pledge", pledge_builder.to_string());
  376. switch (process.veil_state()) {
  377. case VeilState::None:
  378. process_object.add("veil", "None");
  379. break;
  380. case VeilState::Dropped:
  381. process_object.add("veil", "Dropped");
  382. break;
  383. case VeilState::Locked:
  384. process_object.add("veil", "Locked");
  385. break;
  386. }
  387. } else {
  388. process_object.add("pledge", String());
  389. process_object.add("veil", String());
  390. }
  391. process_object.add("pid", process.pid().value());
  392. process_object.add("pgid", process.tty() ? process.tty()->pgid().value() : 0);
  393. process_object.add("pgp", process.pgid().value());
  394. process_object.add("sid", process.sid().value());
  395. process_object.add("uid", process.uid());
  396. process_object.add("gid", process.gid());
  397. process_object.add("ppid", process.ppid().value());
  398. process_object.add("nfds", process.number_of_open_file_descriptors());
  399. process_object.add("name", process.name());
  400. process_object.add("executable", process.executable() ? process.executable()->absolute_path() : "");
  401. process_object.add("tty", process.tty() ? process.tty()->tty_name() : "notty");
  402. process_object.add("amount_virtual", process.space().amount_virtual());
  403. process_object.add("amount_resident", process.space().amount_resident());
  404. process_object.add("amount_dirty_private", process.space().amount_dirty_private());
  405. process_object.add("amount_clean_inode", process.space().amount_clean_inode());
  406. process_object.add("amount_shared", process.space().amount_shared());
  407. process_object.add("amount_purgeable_volatile", process.space().amount_purgeable_volatile());
  408. process_object.add("amount_purgeable_nonvolatile", process.space().amount_purgeable_nonvolatile());
  409. process_object.add("dumpable", process.is_dumpable());
  410. process_object.add("kernel", process.is_kernel_process());
  411. auto thread_array = process_object.add_array("threads");
  412. process.for_each_thread([&](const Thread& thread) {
  413. auto thread_object = thread_array.add_object();
  414. #if LOCK_DEBUG
  415. thread_object.add("lock_count", thread.lock_count());
  416. #endif
  417. thread_object.add("tid", thread.tid().value());
  418. thread_object.add("name", thread.name());
  419. thread_object.add("times_scheduled", thread.times_scheduled());
  420. thread_object.add("ticks_user", thread.ticks_in_user());
  421. thread_object.add("ticks_kernel", thread.ticks_in_kernel());
  422. thread_object.add("state", thread.state_string());
  423. thread_object.add("cpu", thread.cpu());
  424. thread_object.add("priority", thread.priority());
  425. thread_object.add("syscall_count", thread.syscall_count());
  426. thread_object.add("inode_faults", thread.inode_faults());
  427. thread_object.add("zero_faults", thread.zero_faults());
  428. thread_object.add("cow_faults", thread.cow_faults());
  429. thread_object.add("file_read_bytes", thread.file_read_bytes());
  430. thread_object.add("file_write_bytes", thread.file_write_bytes());
  431. thread_object.add("unix_socket_read_bytes", thread.unix_socket_read_bytes());
  432. thread_object.add("unix_socket_write_bytes", thread.unix_socket_write_bytes());
  433. thread_object.add("ipv4_socket_read_bytes", thread.ipv4_socket_read_bytes());
  434. thread_object.add("ipv4_socket_write_bytes", thread.ipv4_socket_write_bytes());
  435. });
  436. };
  437. ScopedSpinLock lock(g_scheduler_lock);
  438. auto processes = Process::all_processes();
  439. build_process(*Scheduler::colonel());
  440. for (auto& process : processes)
  441. build_process(process);
  442. array.finish();
  443. return true;
  444. }
  445. };
  446. class ProcFSCPUInformation final : public ProcFSGlobalInformation {
  447. public:
  448. static NonnullRefPtr<ProcFSCPUInformation> must_create();
  449. private:
  450. ProcFSCPUInformation();
  451. virtual bool output(KBufferBuilder& builder) override
  452. {
  453. JsonArraySerializer array { builder };
  454. Processor::for_each(
  455. [&](Processor& proc) {
  456. auto& info = proc.info();
  457. auto obj = array.add_object();
  458. JsonArray features;
  459. for (auto& feature : info.features().split(' '))
  460. features.append(feature);
  461. obj.add("processor", proc.get_id());
  462. obj.add("cpuid", info.cpuid());
  463. obj.add("family", info.display_family());
  464. obj.add("features", features);
  465. obj.add("model", info.display_model());
  466. obj.add("stepping", info.stepping());
  467. obj.add("type", info.type());
  468. obj.add("brandstr", info.brandstr());
  469. });
  470. array.finish();
  471. return true;
  472. }
  473. };
  474. class ProcFSDmesg final : public ProcFSGlobalInformation {
  475. public:
  476. static NonnullRefPtr<ProcFSDmesg> must_create();
  477. private:
  478. ProcFSDmesg();
  479. virtual bool output(KBufferBuilder& builder) override
  480. {
  481. InterruptDisabler disabler;
  482. for (char ch : ConsoleDevice::the().logbuffer())
  483. builder.append(ch);
  484. return true;
  485. }
  486. };
  487. class ProcFSInterrupts final : public ProcFSGlobalInformation {
  488. public:
  489. static NonnullRefPtr<ProcFSInterrupts> must_create();
  490. private:
  491. ProcFSInterrupts();
  492. virtual bool output(KBufferBuilder& builder) override
  493. {
  494. JsonArraySerializer array { builder };
  495. InterruptManagement::the().enumerate_interrupt_handlers([&array](GenericInterruptHandler& handler) {
  496. auto obj = array.add_object();
  497. obj.add("purpose", handler.purpose());
  498. obj.add("interrupt_line", handler.interrupt_number());
  499. obj.add("controller", handler.controller());
  500. obj.add("cpu_handler", 0); // FIXME: Determine the responsible CPU for each interrupt handler.
  501. obj.add("device_sharing", (unsigned)handler.sharing_devices_count());
  502. obj.add("call_count", (unsigned)handler.get_invoking_count());
  503. });
  504. array.finish();
  505. return true;
  506. }
  507. };
  508. class ProcFSKeymap final : public ProcFSGlobalInformation {
  509. public:
  510. static NonnullRefPtr<ProcFSKeymap> must_create();
  511. private:
  512. ProcFSKeymap();
  513. virtual bool output(KBufferBuilder& builder) override
  514. {
  515. JsonObjectSerializer<KBufferBuilder> json { builder };
  516. json.add("keymap", HIDManagement::the().keymap_name());
  517. json.finish();
  518. return true;
  519. }
  520. };
  521. // FIXME: Remove this after we enumerate the SysFS from lspci and SystemMonitor
  522. class ProcFSPCI final : public ProcFSGlobalInformation {
  523. public:
  524. static NonnullRefPtr<ProcFSPCI> must_create();
  525. private:
  526. ProcFSPCI();
  527. virtual bool output(KBufferBuilder& builder) override
  528. {
  529. JsonArraySerializer array { builder };
  530. PCI::enumerate([&array](PCI::Address address, PCI::ID id) {
  531. auto obj = array.add_object();
  532. obj.add("seg", address.seg());
  533. obj.add("bus", address.bus());
  534. obj.add("device", address.device());
  535. obj.add("function", address.function());
  536. obj.add("vendor_id", id.vendor_id);
  537. obj.add("device_id", id.device_id);
  538. obj.add("revision_id", PCI::get_revision_id(address));
  539. obj.add("subclass", PCI::get_subclass(address));
  540. obj.add("class", PCI::get_class(address));
  541. obj.add("subsystem_id", PCI::get_subsystem_id(address));
  542. obj.add("subsystem_vendor_id", PCI::get_subsystem_vendor_id(address));
  543. });
  544. array.finish();
  545. return true;
  546. }
  547. };
  548. class ProcFSDevices final : public ProcFSGlobalInformation {
  549. public:
  550. static NonnullRefPtr<ProcFSDevices> must_create();
  551. private:
  552. ProcFSDevices();
  553. virtual bool output(KBufferBuilder& builder) override
  554. {
  555. JsonArraySerializer array { builder };
  556. Device::for_each([&array](auto& device) {
  557. auto obj = array.add_object();
  558. obj.add("major", device.major());
  559. obj.add("minor", device.minor());
  560. obj.add("class_name", device.class_name());
  561. if (device.is_block_device())
  562. obj.add("type", "block");
  563. else if (device.is_character_device())
  564. obj.add("type", "character");
  565. else
  566. VERIFY_NOT_REACHED();
  567. });
  568. array.finish();
  569. return true;
  570. }
  571. };
  572. class ProcFSUptime final : public ProcFSGlobalInformation {
  573. public:
  574. static NonnullRefPtr<ProcFSUptime> must_create();
  575. private:
  576. ProcFSUptime();
  577. virtual bool output(KBufferBuilder& builder) override
  578. {
  579. builder.appendff("{}\n", TimeManagement::the().uptime_ms() / 1000);
  580. return true;
  581. }
  582. };
  583. class ProcFSCommandLine final : public ProcFSGlobalInformation {
  584. public:
  585. static NonnullRefPtr<ProcFSCommandLine> must_create();
  586. private:
  587. ProcFSCommandLine();
  588. virtual bool output(KBufferBuilder& builder) override
  589. {
  590. builder.append(kernel_command_line().string());
  591. builder.append('\n');
  592. return true;
  593. }
  594. };
  595. class ProcFSModules final : public ProcFSGlobalInformation {
  596. public:
  597. static NonnullRefPtr<ProcFSModules> must_create();
  598. private:
  599. ProcFSModules();
  600. virtual bool output(KBufferBuilder& builder) override
  601. {
  602. extern HashMap<String, OwnPtr<Module>>* g_modules;
  603. JsonArraySerializer array { builder };
  604. for (auto& it : *g_modules) {
  605. auto obj = array.add_object();
  606. obj.add("name", it.value->name);
  607. obj.add("module_init", it.value->module_init);
  608. obj.add("module_fini", it.value->module_fini);
  609. u32 size = 0;
  610. for (auto& section : it.value->sections) {
  611. size += section.capacity();
  612. }
  613. obj.add("size", size);
  614. }
  615. array.finish();
  616. return true;
  617. }
  618. };
  619. class ProcFSProfile final : public ProcFSGlobalInformation {
  620. public:
  621. static NonnullRefPtr<ProcFSProfile> must_create();
  622. private:
  623. ProcFSProfile();
  624. virtual bool output(KBufferBuilder& builder) override
  625. {
  626. extern PerformanceEventBuffer* g_global_perf_events;
  627. if (!g_global_perf_events)
  628. return false;
  629. return g_global_perf_events->to_json(builder);
  630. }
  631. };
  632. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSSelfProcessFolder> ProcFSSelfProcessFolder::must_create()
  633. {
  634. return adopt_ref_if_nonnull(new (nothrow) ProcFSSelfProcessFolder()).release_nonnull();
  635. }
  636. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSDiskUsage> ProcFSDiskUsage::must_create()
  637. {
  638. return adopt_ref_if_nonnull(new (nothrow) ProcFSDiskUsage).release_nonnull();
  639. }
  640. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSMemoryStatus> ProcFSMemoryStatus::must_create()
  641. {
  642. return adopt_ref_if_nonnull(new (nothrow) ProcFSMemoryStatus).release_nonnull();
  643. }
  644. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSOverallProcesses> ProcFSOverallProcesses::must_create()
  645. {
  646. return adopt_ref_if_nonnull(new (nothrow) ProcFSOverallProcesses).release_nonnull();
  647. }
  648. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSCPUInformation> ProcFSCPUInformation::must_create()
  649. {
  650. return adopt_ref_if_nonnull(new (nothrow) ProcFSCPUInformation).release_nonnull();
  651. }
  652. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSDmesg> ProcFSDmesg::must_create()
  653. {
  654. return adopt_ref_if_nonnull(new (nothrow) ProcFSDmesg).release_nonnull();
  655. }
  656. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSInterrupts> ProcFSInterrupts::must_create()
  657. {
  658. return adopt_ref_if_nonnull(new (nothrow) ProcFSInterrupts).release_nonnull();
  659. }
  660. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSKeymap> ProcFSKeymap::must_create()
  661. {
  662. return adopt_ref_if_nonnull(new (nothrow) ProcFSKeymap).release_nonnull();
  663. }
  664. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSPCI> ProcFSPCI::must_create()
  665. {
  666. return adopt_ref_if_nonnull(new (nothrow) ProcFSPCI).release_nonnull();
  667. }
  668. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSDevices> ProcFSDevices::must_create()
  669. {
  670. return adopt_ref_if_nonnull(new (nothrow) ProcFSDevices).release_nonnull();
  671. }
  672. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSUptime> ProcFSUptime::must_create()
  673. {
  674. return adopt_ref_if_nonnull(new (nothrow) ProcFSUptime).release_nonnull();
  675. }
  676. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSCommandLine> ProcFSCommandLine::must_create()
  677. {
  678. return adopt_ref_if_nonnull(new (nothrow) ProcFSCommandLine).release_nonnull();
  679. }
  680. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSModules> ProcFSModules::must_create()
  681. {
  682. return adopt_ref_if_nonnull(new (nothrow) ProcFSModules).release_nonnull();
  683. }
  684. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSProfile> ProcFSProfile::must_create()
  685. {
  686. return adopt_ref_if_nonnull(new (nothrow) ProcFSProfile).release_nonnull();
  687. }
  688. UNMAP_AFTER_INIT ProcFSSelfProcessFolder::ProcFSSelfProcessFolder()
  689. : ProcFSExposedLink("self"sv)
  690. {
  691. }
  692. UNMAP_AFTER_INIT ProcFSDiskUsage::ProcFSDiskUsage()
  693. : ProcFSGlobalInformation("df"sv)
  694. {
  695. }
  696. UNMAP_AFTER_INIT ProcFSMemoryStatus::ProcFSMemoryStatus()
  697. : ProcFSGlobalInformation("memstat"sv)
  698. {
  699. }
  700. UNMAP_AFTER_INIT ProcFSOverallProcesses::ProcFSOverallProcesses()
  701. : ProcFSGlobalInformation("all"sv)
  702. {
  703. }
  704. UNMAP_AFTER_INIT ProcFSCPUInformation::ProcFSCPUInformation()
  705. : ProcFSGlobalInformation("cpuinfo"sv)
  706. {
  707. }
  708. UNMAP_AFTER_INIT ProcFSDmesg::ProcFSDmesg()
  709. : ProcFSGlobalInformation("dmesg"sv)
  710. {
  711. }
  712. UNMAP_AFTER_INIT ProcFSInterrupts::ProcFSInterrupts()
  713. : ProcFSGlobalInformation("interrupts"sv)
  714. {
  715. }
  716. UNMAP_AFTER_INIT ProcFSKeymap::ProcFSKeymap()
  717. : ProcFSGlobalInformation("keymap"sv)
  718. {
  719. }
  720. UNMAP_AFTER_INIT ProcFSPCI::ProcFSPCI()
  721. : ProcFSGlobalInformation("pci"sv)
  722. {
  723. }
  724. UNMAP_AFTER_INIT ProcFSDevices::ProcFSDevices()
  725. : ProcFSGlobalInformation("devices"sv)
  726. {
  727. }
  728. UNMAP_AFTER_INIT ProcFSUptime::ProcFSUptime()
  729. : ProcFSGlobalInformation("uptime"sv)
  730. {
  731. }
  732. UNMAP_AFTER_INIT ProcFSCommandLine::ProcFSCommandLine()
  733. : ProcFSGlobalInformation("cmdline"sv)
  734. {
  735. }
  736. UNMAP_AFTER_INIT ProcFSModules::ProcFSModules()
  737. : ProcFSGlobalInformation("modules"sv)
  738. {
  739. }
  740. UNMAP_AFTER_INIT ProcFSProfile::ProcFSProfile()
  741. : ProcFSGlobalInformation("profile"sv)
  742. {
  743. }
  744. class ProcFSAdapters final : public ProcFSGlobalInformation {
  745. public:
  746. static NonnullRefPtr<ProcFSAdapters> must_create();
  747. private:
  748. ProcFSAdapters();
  749. virtual bool output(KBufferBuilder& builder) override
  750. {
  751. JsonArraySerializer array { builder };
  752. NetworkingManagement::the().for_each([&array](auto& adapter) {
  753. auto obj = array.add_object();
  754. obj.add("name", adapter.name());
  755. obj.add("class_name", adapter.class_name());
  756. obj.add("mac_address", adapter.mac_address().to_string());
  757. if (!adapter.ipv4_address().is_zero()) {
  758. obj.add("ipv4_address", adapter.ipv4_address().to_string());
  759. obj.add("ipv4_netmask", adapter.ipv4_netmask().to_string());
  760. }
  761. if (!adapter.ipv4_gateway().is_zero())
  762. obj.add("ipv4_gateway", adapter.ipv4_gateway().to_string());
  763. obj.add("packets_in", adapter.packets_in());
  764. obj.add("bytes_in", adapter.bytes_in());
  765. obj.add("packets_out", adapter.packets_out());
  766. obj.add("bytes_out", adapter.bytes_out());
  767. obj.add("link_up", adapter.link_up());
  768. obj.add("mtu", adapter.mtu());
  769. });
  770. array.finish();
  771. return true;
  772. }
  773. };
  774. class ProcFSARP final : public ProcFSGlobalInformation {
  775. public:
  776. static NonnullRefPtr<ProcFSARP> must_create();
  777. private:
  778. ProcFSARP();
  779. virtual bool output(KBufferBuilder& builder) override
  780. {
  781. JsonArraySerializer array { builder };
  782. Locker locker(arp_table().lock(), Lock::Mode::Shared);
  783. for (auto& it : arp_table().resource()) {
  784. auto obj = array.add_object();
  785. obj.add("mac_address", it.value.to_string());
  786. obj.add("ip_address", it.key.to_string());
  787. }
  788. array.finish();
  789. return true;
  790. }
  791. };
  792. class ProcFSTCP final : public ProcFSGlobalInformation {
  793. public:
  794. static NonnullRefPtr<ProcFSTCP> must_create();
  795. private:
  796. ProcFSTCP();
  797. virtual bool output(KBufferBuilder& builder) override
  798. {
  799. JsonArraySerializer array { builder };
  800. TCPSocket::for_each([&array](auto& socket) {
  801. auto obj = array.add_object();
  802. obj.add("local_address", socket.local_address().to_string());
  803. obj.add("local_port", socket.local_port());
  804. obj.add("peer_address", socket.peer_address().to_string());
  805. obj.add("peer_port", socket.peer_port());
  806. obj.add("state", TCPSocket::to_string(socket.state()));
  807. obj.add("ack_number", socket.ack_number());
  808. obj.add("sequence_number", socket.sequence_number());
  809. obj.add("packets_in", socket.packets_in());
  810. obj.add("bytes_in", socket.bytes_in());
  811. obj.add("packets_out", socket.packets_out());
  812. obj.add("bytes_out", socket.bytes_out());
  813. });
  814. array.finish();
  815. return true;
  816. }
  817. };
  818. class ProcFSLocalNet final : public ProcFSGlobalInformation {
  819. public:
  820. static NonnullRefPtr<ProcFSLocalNet> must_create();
  821. private:
  822. ProcFSLocalNet();
  823. virtual bool output(KBufferBuilder& builder) override
  824. {
  825. JsonArraySerializer array { builder };
  826. LocalSocket::for_each([&array](auto& socket) {
  827. auto obj = array.add_object();
  828. obj.add("path", String(socket.socket_path()));
  829. obj.add("origin_pid", socket.origin_pid());
  830. obj.add("origin_uid", socket.origin_uid());
  831. obj.add("origin_gid", socket.origin_gid());
  832. obj.add("acceptor_pid", socket.acceptor_pid());
  833. obj.add("acceptor_uid", socket.acceptor_uid());
  834. obj.add("acceptor_gid", socket.acceptor_gid());
  835. });
  836. array.finish();
  837. return true;
  838. }
  839. };
  840. class ProcFSUDP final : public ProcFSGlobalInformation {
  841. public:
  842. static NonnullRefPtr<ProcFSUDP> must_create();
  843. private:
  844. ProcFSUDP();
  845. virtual bool output(KBufferBuilder& builder) override
  846. {
  847. JsonArraySerializer array { builder };
  848. UDPSocket::for_each([&array](auto& socket) {
  849. auto obj = array.add_object();
  850. obj.add("local_address", socket.local_address().to_string());
  851. obj.add("local_port", socket.local_port());
  852. obj.add("peer_address", socket.peer_address().to_string());
  853. obj.add("peer_port", socket.peer_port());
  854. });
  855. array.finish();
  856. return true;
  857. }
  858. };
  859. class ProcFSNetworkDirectory : public ProcFSExposedFolder {
  860. public:
  861. static NonnullRefPtr<ProcFSNetworkDirectory> must_create(const ProcFSRootFolder& parent_folder);
  862. private:
  863. ProcFSNetworkDirectory(const ProcFSRootFolder& parent_folder);
  864. };
  865. class ProcFSSystemDirectory : public ProcFSExposedFolder {
  866. public:
  867. static NonnullRefPtr<ProcFSSystemDirectory> must_create(const ProcFSRootFolder& parent_folder);
  868. private:
  869. ProcFSSystemDirectory(const ProcFSRootFolder& parent_folder);
  870. };
  871. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSAdapters> ProcFSAdapters::must_create()
  872. {
  873. return adopt_ref_if_nonnull(new (nothrow) ProcFSAdapters).release_nonnull();
  874. }
  875. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSARP> ProcFSARP::must_create()
  876. {
  877. return adopt_ref_if_nonnull(new (nothrow) ProcFSARP).release_nonnull();
  878. }
  879. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSTCP> ProcFSTCP::must_create()
  880. {
  881. return adopt_ref_if_nonnull(new (nothrow) ProcFSTCP).release_nonnull();
  882. }
  883. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSLocalNet> ProcFSLocalNet::must_create()
  884. {
  885. return adopt_ref_if_nonnull(new (nothrow) ProcFSLocalNet).release_nonnull();
  886. }
  887. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSUDP> ProcFSUDP::must_create()
  888. {
  889. return adopt_ref_if_nonnull(new (nothrow) ProcFSUDP).release_nonnull();
  890. }
  891. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSNetworkDirectory> ProcFSNetworkDirectory::must_create(const ProcFSRootFolder& parent_folder)
  892. {
  893. auto folder = adopt_ref(*new (nothrow) ProcFSNetworkDirectory(parent_folder));
  894. folder->m_components.append(ProcFSAdapters::must_create());
  895. folder->m_components.append(ProcFSARP::must_create());
  896. folder->m_components.append(ProcFSTCP::must_create());
  897. folder->m_components.append(ProcFSLocalNet::must_create());
  898. folder->m_components.append(ProcFSUDP::must_create());
  899. return folder;
  900. }
  901. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSBusDirectory> ProcFSBusDirectory::must_create(const ProcFSRootFolder& parent_folder)
  902. {
  903. auto folder = adopt_ref(*new (nothrow) ProcFSBusDirectory(parent_folder));
  904. return folder;
  905. }
  906. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSSystemDirectory> ProcFSSystemDirectory::must_create(const ProcFSRootFolder& parent_folder)
  907. {
  908. auto folder = adopt_ref(*new (nothrow) ProcFSSystemDirectory(parent_folder));
  909. folder->m_components.append(ProcFSDumpKmallocStacks::must_create(folder));
  910. folder->m_components.append(ProcFSUBSanDeadly::must_create(folder));
  911. folder->m_components.append(ProcFSCapsLockRemap::must_create(folder));
  912. return folder;
  913. }
  914. UNMAP_AFTER_INIT ProcFSAdapters::ProcFSAdapters()
  915. : ProcFSGlobalInformation("adapters"sv)
  916. {
  917. }
  918. UNMAP_AFTER_INIT ProcFSARP::ProcFSARP()
  919. : ProcFSGlobalInformation("arp"sv)
  920. {
  921. }
  922. UNMAP_AFTER_INIT ProcFSTCP::ProcFSTCP()
  923. : ProcFSGlobalInformation("tcp"sv)
  924. {
  925. }
  926. UNMAP_AFTER_INIT ProcFSLocalNet::ProcFSLocalNet()
  927. : ProcFSGlobalInformation("local"sv)
  928. {
  929. }
  930. UNMAP_AFTER_INIT ProcFSUDP::ProcFSUDP()
  931. : ProcFSGlobalInformation("udp"sv)
  932. {
  933. }
  934. UNMAP_AFTER_INIT ProcFSNetworkDirectory::ProcFSNetworkDirectory(const ProcFSRootFolder& parent_folder)
  935. : ProcFSExposedFolder("net"sv, parent_folder)
  936. {
  937. }
  938. UNMAP_AFTER_INIT ProcFSBusDirectory::ProcFSBusDirectory(const ProcFSRootFolder& parent_folder)
  939. : ProcFSExposedFolder("bus"sv, parent_folder)
  940. {
  941. }
  942. UNMAP_AFTER_INIT ProcFSSystemDirectory::ProcFSSystemDirectory(const ProcFSRootFolder& parent_folder)
  943. : ProcFSExposedFolder("sys"sv, parent_folder)
  944. {
  945. }
  946. UNMAP_AFTER_INIT NonnullRefPtr<ProcFSRootFolder> ProcFSRootFolder::must_create()
  947. {
  948. auto folder = adopt_ref(*new (nothrow) ProcFSRootFolder);
  949. folder->m_components.append(ProcFSSelfProcessFolder::must_create());
  950. folder->m_components.append(ProcFSDiskUsage::must_create());
  951. folder->m_components.append(ProcFSMemoryStatus::must_create());
  952. folder->m_components.append(ProcFSOverallProcesses::must_create());
  953. folder->m_components.append(ProcFSCPUInformation::must_create());
  954. folder->m_components.append(ProcFSDmesg::must_create());
  955. folder->m_components.append(ProcFSInterrupts::must_create());
  956. folder->m_components.append(ProcFSKeymap::must_create());
  957. folder->m_components.append(ProcFSPCI::must_create());
  958. folder->m_components.append(ProcFSDevices::must_create());
  959. folder->m_components.append(ProcFSUptime::must_create());
  960. folder->m_components.append(ProcFSCommandLine::must_create());
  961. folder->m_components.append(ProcFSModules::must_create());
  962. folder->m_components.append(ProcFSProfile::must_create());
  963. folder->m_components.append(ProcFSNetworkDirectory::must_create(*folder));
  964. auto buses_folder = ProcFSBusDirectory::must_create(*folder);
  965. folder->m_components.append(buses_folder);
  966. folder->m_buses_folder = buses_folder;
  967. folder->m_components.append(ProcFSSystemDirectory::must_create(*folder));
  968. return folder;
  969. }
  970. UNMAP_AFTER_INIT ProcFSRootFolder::ProcFSRootFolder()
  971. : ProcFSExposedFolder("."sv)
  972. {
  973. }
  974. UNMAP_AFTER_INIT ProcFSRootFolder::~ProcFSRootFolder()
  975. {
  976. }
  977. class ProcFSProcessStacks;
  978. class ProcFSThreadStack final : public ProcFSProcessInformation {
  979. public:
  980. // Note: We pass const ProcFSProcessStacks& to enforce creation with this type of folder
  981. static NonnullRefPtr<ProcFSThreadStack> create(const ProcFSProcessFolder& process_folder, const ProcFSProcessStacks&, const Thread& thread)
  982. {
  983. return adopt_ref(*new (nothrow) ProcFSThreadStack(process_folder, thread));
  984. }
  985. private:
  986. explicit ProcFSThreadStack(const ProcFSProcessFolder& process_folder, const Thread& thread)
  987. : ProcFSProcessInformation(String::formatted("{}", thread.tid()), process_folder)
  988. , m_associated_thread(thread)
  989. {
  990. }
  991. virtual bool output(KBufferBuilder& builder) override
  992. {
  993. JsonArraySerializer array { builder };
  994. bool show_kernel_addresses = Process::current()->is_superuser();
  995. bool kernel_address_added = false;
  996. for (auto address : Processor::capture_stack_trace(*m_associated_thread, 1024)) {
  997. if (!show_kernel_addresses && !is_user_address(VirtualAddress { address })) {
  998. if (kernel_address_added)
  999. continue;
  1000. address = 0xdeadc0de;
  1001. kernel_address_added = true;
  1002. }
  1003. array.add(JsonValue(address));
  1004. }
  1005. array.finish();
  1006. return true;
  1007. }
  1008. NonnullRefPtr<Thread> m_associated_thread;
  1009. };
  1010. class ProcFSProcessStacks final : public ProcFSExposedFolder {
  1011. // Note: This folder is special, because everything that is created here is dynamic!
  1012. // This means we don't register anything in the m_components Vector, and every inode
  1013. // is created in runtime when called to get it
  1014. // Every ProcFSThreadStack (that represents a thread stack) is created only as a temporary object
  1015. // therefore, we don't use m_components so when we are done with the ProcFSThreadStack object,
  1016. // It should be deleted (as soon as possible)
  1017. public:
  1018. virtual KResultOr<size_t> entries_count() const override;
  1019. virtual KResult traverse_as_directory(unsigned, Function<bool(const FS::DirectoryEntryView&)>) const override;
  1020. virtual RefPtr<ProcFSExposedComponent> lookup(StringView name) override;
  1021. static NonnullRefPtr<ProcFSProcessStacks> create(const ProcFSProcessFolder& parent_folder)
  1022. {
  1023. auto folder = adopt_ref(*new (nothrow) ProcFSProcessStacks(parent_folder));
  1024. return folder;
  1025. }
  1026. virtual void prepare_for_deletion() override
  1027. {
  1028. ProcFSExposedFolder::prepare_for_deletion();
  1029. m_process_folder.clear();
  1030. }
  1031. private:
  1032. ProcFSProcessStacks(const ProcFSProcessFolder& parent_folder)
  1033. : ProcFSExposedFolder("stacks"sv, parent_folder)
  1034. , m_process_folder(parent_folder)
  1035. {
  1036. }
  1037. RefPtr<ProcFSProcessFolder> m_process_folder;
  1038. mutable Lock m_lock;
  1039. };
  1040. KResultOr<size_t> ProcFSProcessStacks::entries_count() const
  1041. {
  1042. Locker locker(m_lock);
  1043. auto process = m_process_folder->m_associated_process;
  1044. return process->thread_count();
  1045. }
  1046. KResult ProcFSProcessStacks::traverse_as_directory(unsigned fsid, Function<bool(const FS::DirectoryEntryView&)> callback) const
  1047. {
  1048. Locker locker(m_lock);
  1049. callback({ ".", { fsid, component_index() }, 0 });
  1050. callback({ "..", { fsid, m_parent_folder->component_index() }, 0 });
  1051. auto process = m_process_folder->m_associated_process;
  1052. process->for_each_thread([&](const Thread& thread) {
  1053. int tid = thread.tid().value();
  1054. InodeIdentifier identifier = { fsid, thread.global_procfs_inode_index() };
  1055. callback({ String::number(tid), identifier, 0 });
  1056. });
  1057. return KSuccess;
  1058. }
  1059. RefPtr<ProcFSExposedComponent> ProcFSProcessStacks::lookup(StringView name)
  1060. {
  1061. Locker locker(m_lock);
  1062. auto process = m_process_folder->m_associated_process;
  1063. RefPtr<ProcFSThreadStack> procfd_stack;
  1064. // FIXME: Try to exit the loop earlier
  1065. process->for_each_thread([&](const Thread& thread) {
  1066. int tid = thread.tid().value();
  1067. if (name == String::number(tid)) {
  1068. procfd_stack = ProcFSThreadStack::create(*m_process_folder, *this, thread);
  1069. }
  1070. });
  1071. return procfd_stack;
  1072. }
  1073. class ProcFSProcessFileDescriptions;
  1074. class ProcFSProcessFileDescription final : public ProcFSExposedLink {
  1075. public:
  1076. // Note: we pass const ProcFSProcessFileDescriptions& just to enforce creation of this in the correct folder.
  1077. static NonnullRefPtr<ProcFSProcessFileDescription> create(unsigned fd_number, const FileDescription& fd, InodeIndex preallocated_index, const ProcFSProcessFileDescriptions&)
  1078. {
  1079. return adopt_ref(*new (nothrow) ProcFSProcessFileDescription(fd_number, fd, preallocated_index));
  1080. }
  1081. private:
  1082. explicit ProcFSProcessFileDescription(unsigned fd_number, const FileDescription& fd, InodeIndex preallocated_index)
  1083. : ProcFSExposedLink(String::formatted("{}", fd_number), preallocated_index)
  1084. , m_associated_file_description(fd)
  1085. {
  1086. }
  1087. virtual bool acquire_link(KBufferBuilder& builder) override
  1088. {
  1089. builder.append_bytes(m_associated_file_description->absolute_path().bytes());
  1090. return true;
  1091. }
  1092. NonnullRefPtr<FileDescription> m_associated_file_description;
  1093. };
  1094. class ProcFSProcessFileDescriptions final : public ProcFSExposedFolder {
  1095. // Note: This folder is special, because everything that is created here is dynamic!
  1096. // This means we don't register anything in the m_components Vector, and every inode
  1097. // is created in runtime when called to get it
  1098. // Every ProcFSProcessFileDescription (that represents a file descriptor) is created only as a temporary object
  1099. // therefore, we don't use m_components so when we are done with the ProcFSProcessFileDescription object,
  1100. // It should be deleted (as soon as possible)
  1101. public:
  1102. virtual KResultOr<size_t> entries_count() const override;
  1103. virtual KResult traverse_as_directory(unsigned, Function<bool(const FS::DirectoryEntryView&)>) const override;
  1104. virtual RefPtr<ProcFSExposedComponent> lookup(StringView name) override;
  1105. static NonnullRefPtr<ProcFSProcessFileDescriptions> create(const ProcFSProcessFolder& parent_folder)
  1106. {
  1107. return adopt_ref(*new (nothrow) ProcFSProcessFileDescriptions(parent_folder));
  1108. }
  1109. virtual void prepare_for_deletion() override
  1110. {
  1111. ProcFSExposedFolder::prepare_for_deletion();
  1112. m_process_folder.clear();
  1113. }
  1114. private:
  1115. explicit ProcFSProcessFileDescriptions(const ProcFSProcessFolder& parent_folder)
  1116. : ProcFSExposedFolder("fd"sv, parent_folder)
  1117. , m_process_folder(parent_folder)
  1118. {
  1119. }
  1120. RefPtr<ProcFSProcessFolder> m_process_folder;
  1121. mutable Lock m_lock;
  1122. };
  1123. KResultOr<size_t> ProcFSProcessFileDescriptions::entries_count() const
  1124. {
  1125. Locker locker(m_lock);
  1126. return m_process_folder->m_associated_process->number_of_open_file_descriptors();
  1127. }
  1128. KResult ProcFSProcessFileDescriptions::traverse_as_directory(unsigned fsid, Function<bool(const FS::DirectoryEntryView&)> callback) const
  1129. {
  1130. Locker locker(m_lock);
  1131. callback({ ".", { fsid, component_index() }, 0 });
  1132. callback({ "..", { fsid, m_parent_folder->component_index() }, 0 });
  1133. auto process = m_process_folder->m_associated_process;
  1134. for (int i = 0; i < process->max_open_file_descriptors(); ++i) {
  1135. auto description_metadata = process->fds()[i];
  1136. if (!description_metadata.is_valid())
  1137. continue;
  1138. InodeIdentifier identifier = { fsid, description_metadata.global_procfs_inode_index() };
  1139. callback({ String::number(i), identifier, 0 });
  1140. }
  1141. return KSuccess;
  1142. }
  1143. RefPtr<ProcFSExposedComponent> ProcFSProcessFileDescriptions::lookup(StringView name)
  1144. {
  1145. Locker locker(m_lock);
  1146. auto process = m_process_folder->m_associated_process;
  1147. ScopedSpinLock lock(process->m_fds_lock);
  1148. for (int i = 0; i < process->max_open_file_descriptors(); ++i) {
  1149. auto description_metadata = process->fds()[i];
  1150. if (!description_metadata.is_valid())
  1151. continue;
  1152. if (name == String::number(i)) {
  1153. return ProcFSProcessFileDescription::create(i, *description_metadata.description(), description_metadata.global_procfs_inode_index(), *this);
  1154. }
  1155. }
  1156. return nullptr;
  1157. }
  1158. class ProcFSProcessUnveil final : public ProcFSProcessInformation {
  1159. public:
  1160. static NonnullRefPtr<ProcFSProcessUnveil> create(const ProcFSProcessFolder& parent_folder)
  1161. {
  1162. return adopt_ref(*new (nothrow) ProcFSProcessUnveil(parent_folder));
  1163. }
  1164. private:
  1165. explicit ProcFSProcessUnveil(const ProcFSProcessFolder& parent_folder)
  1166. : ProcFSProcessInformation("unveil"sv, parent_folder)
  1167. {
  1168. }
  1169. virtual bool output(KBufferBuilder& builder) override
  1170. {
  1171. JsonArraySerializer array { builder };
  1172. for (auto& unveiled_path : m_parent_folder->m_associated_process->unveiled_paths()) {
  1173. if (!unveiled_path.was_explicitly_unveiled())
  1174. continue;
  1175. auto obj = array.add_object();
  1176. obj.add("path", unveiled_path.path());
  1177. StringBuilder permissions_builder;
  1178. if (unveiled_path.permissions() & UnveilAccess::Read)
  1179. permissions_builder.append('r');
  1180. if (unveiled_path.permissions() & UnveilAccess::Write)
  1181. permissions_builder.append('w');
  1182. if (unveiled_path.permissions() & UnveilAccess::Execute)
  1183. permissions_builder.append('x');
  1184. if (unveiled_path.permissions() & UnveilAccess::CreateOrRemove)
  1185. permissions_builder.append('c');
  1186. if (unveiled_path.permissions() & UnveilAccess::Browse)
  1187. permissions_builder.append('b');
  1188. obj.add("permissions", permissions_builder.to_string());
  1189. }
  1190. array.finish();
  1191. return true;
  1192. }
  1193. };
  1194. class ProcFSProcessPerformanceEvents final : public ProcFSProcessInformation {
  1195. public:
  1196. static NonnullRefPtr<ProcFSProcessPerformanceEvents> create(const ProcFSProcessFolder& parent_folder)
  1197. {
  1198. return adopt_ref(*new (nothrow) ProcFSProcessPerformanceEvents(parent_folder));
  1199. }
  1200. private:
  1201. explicit ProcFSProcessPerformanceEvents(const ProcFSProcessFolder& parent_folder)
  1202. : ProcFSProcessInformation("perf_events"sv, parent_folder)
  1203. {
  1204. }
  1205. virtual bool output(KBufferBuilder& builder) override
  1206. {
  1207. InterruptDisabler disabler;
  1208. if (!m_parent_folder->m_associated_process->perf_events()) {
  1209. dbgln("ProcFS: No perf events for {}", m_parent_folder->m_associated_process->pid());
  1210. return false;
  1211. }
  1212. return m_parent_folder->m_associated_process->perf_events()->to_json(builder);
  1213. }
  1214. };
  1215. class ProcFSProcessOverallFileDescriptions final : public ProcFSProcessInformation {
  1216. public:
  1217. static NonnullRefPtr<ProcFSProcessOverallFileDescriptions> create(const ProcFSProcessFolder& parent_folder)
  1218. {
  1219. return adopt_ref(*new (nothrow) ProcFSProcessOverallFileDescriptions(parent_folder));
  1220. }
  1221. private:
  1222. explicit ProcFSProcessOverallFileDescriptions(const ProcFSProcessFolder& parent_folder)
  1223. : ProcFSProcessInformation("fds"sv, parent_folder)
  1224. {
  1225. }
  1226. virtual bool output(KBufferBuilder& builder) override
  1227. {
  1228. JsonArraySerializer array { builder };
  1229. auto process = m_parent_folder->m_associated_process;
  1230. if (process->number_of_open_file_descriptors() == 0) {
  1231. array.finish();
  1232. return true;
  1233. }
  1234. for (int i = 0; i < process->max_open_file_descriptors(); ++i) {
  1235. auto description = process->file_description(i);
  1236. if (!description)
  1237. continue;
  1238. bool cloexec = process->fd_flags(i) & FD_CLOEXEC;
  1239. auto description_object = array.add_object();
  1240. description_object.add("fd", i);
  1241. description_object.add("absolute_path", description->absolute_path());
  1242. description_object.add("seekable", description->file().is_seekable());
  1243. description_object.add("class", description->file().class_name());
  1244. description_object.add("offset", description->offset());
  1245. description_object.add("cloexec", cloexec);
  1246. description_object.add("blocking", description->is_blocking());
  1247. description_object.add("can_read", description->can_read());
  1248. description_object.add("can_write", description->can_write());
  1249. }
  1250. array.finish();
  1251. return true;
  1252. }
  1253. };
  1254. class ProcFSProcessRoot final : public ProcFSExposedLink {
  1255. public:
  1256. static NonnullRefPtr<ProcFSProcessRoot> create(const ProcFSProcessFolder& parent_folder)
  1257. {
  1258. return adopt_ref(*new (nothrow) ProcFSProcessRoot(parent_folder));
  1259. }
  1260. private:
  1261. explicit ProcFSProcessRoot(const ProcFSProcessFolder& parent_folder)
  1262. : ProcFSExposedLink("root"sv)
  1263. , m_parent_process_directory(parent_folder)
  1264. {
  1265. }
  1266. virtual bool acquire_link(KBufferBuilder& builder) override
  1267. {
  1268. builder.append_bytes(m_parent_process_directory->m_associated_process->root_directory_relative_to_global_root().absolute_path().to_byte_buffer());
  1269. return true;
  1270. }
  1271. NonnullRefPtr<ProcFSProcessFolder> m_parent_process_directory;
  1272. };
  1273. class ProcFSProcessVirtualMemory final : public ProcFSProcessInformation {
  1274. public:
  1275. static NonnullRefPtr<ProcFSProcessRoot> create(const ProcFSProcessFolder& parent_folder)
  1276. {
  1277. return adopt_ref(*new (nothrow) ProcFSProcessVirtualMemory(parent_folder));
  1278. }
  1279. private:
  1280. explicit ProcFSProcessVirtualMemory(const ProcFSProcessFolder& parent_folder)
  1281. : ProcFSProcessInformation("vm"sv, parent_folder)
  1282. {
  1283. }
  1284. virtual bool output(KBufferBuilder& builder) override
  1285. {
  1286. auto process = m_parent_folder->m_associated_process;
  1287. JsonArraySerializer array { builder };
  1288. {
  1289. ScopedSpinLock lock(process->space().get_lock());
  1290. for (auto& region : process->space().regions()) {
  1291. if (!region->is_user() && !Process::current()->is_superuser())
  1292. continue;
  1293. auto region_object = array.add_object();
  1294. region_object.add("readable", region->is_readable());
  1295. region_object.add("writable", region->is_writable());
  1296. region_object.add("executable", region->is_executable());
  1297. region_object.add("stack", region->is_stack());
  1298. region_object.add("shared", region->is_shared());
  1299. region_object.add("syscall", region->is_syscall_region());
  1300. region_object.add("purgeable", region->vmobject().is_anonymous());
  1301. if (region->vmobject().is_anonymous()) {
  1302. region_object.add("volatile", static_cast<const AnonymousVMObject&>(region->vmobject()).is_any_volatile());
  1303. }
  1304. region_object.add("cacheable", region->is_cacheable());
  1305. region_object.add("address", region->vaddr().get());
  1306. region_object.add("size", region->size());
  1307. region_object.add("amount_resident", region->amount_resident());
  1308. region_object.add("amount_dirty", region->amount_dirty());
  1309. region_object.add("cow_pages", region->cow_pages());
  1310. region_object.add("name", region->name());
  1311. region_object.add("vmobject", region->vmobject().class_name());
  1312. StringBuilder pagemap_builder;
  1313. for (size_t i = 0; i < region->page_count(); ++i) {
  1314. auto* page = region->physical_page(i);
  1315. if (!page)
  1316. pagemap_builder.append('N');
  1317. else if (page->is_shared_zero_page() || page->is_lazy_committed_page())
  1318. pagemap_builder.append('Z');
  1319. else
  1320. pagemap_builder.append('P');
  1321. }
  1322. region_object.add("pagemap", pagemap_builder.to_string());
  1323. }
  1324. }
  1325. array.finish();
  1326. return true;
  1327. }
  1328. };
  1329. class ProcFSProcessCurrentWorkDirectory final : public ProcFSExposedLink {
  1330. public:
  1331. static NonnullRefPtr<ProcFSProcessCurrentWorkDirectory> create(const ProcFSProcessFolder& parent_folder)
  1332. {
  1333. return adopt_ref(*new (nothrow) ProcFSProcessCurrentWorkDirectory(parent_folder));
  1334. }
  1335. private:
  1336. explicit ProcFSProcessCurrentWorkDirectory(const ProcFSProcessFolder& parent_folder)
  1337. : ProcFSExposedLink("cwd"sv)
  1338. , m_parent_process_directory(parent_folder)
  1339. {
  1340. }
  1341. virtual bool acquire_link(KBufferBuilder& builder) override
  1342. {
  1343. builder.append_bytes(m_parent_process_directory->m_associated_process->current_directory().absolute_path().bytes());
  1344. return true;
  1345. }
  1346. NonnullRefPtr<ProcFSProcessFolder> m_parent_process_directory;
  1347. };
  1348. class ProcFSProcessBinary final : public ProcFSExposedLink {
  1349. public:
  1350. static NonnullRefPtr<ProcFSProcessBinary> create(const ProcFSProcessFolder& parent_folder)
  1351. {
  1352. return adopt_ref(*new (nothrow) ProcFSProcessBinary(parent_folder));
  1353. }
  1354. virtual mode_t required_mode() const override
  1355. {
  1356. if (!m_parent_process_directory->m_associated_process->executable())
  1357. return 0;
  1358. return ProcFSExposedComponent::required_mode();
  1359. }
  1360. private:
  1361. explicit ProcFSProcessBinary(const ProcFSProcessFolder& parent_folder)
  1362. : ProcFSExposedLink("exe"sv)
  1363. , m_parent_process_directory(parent_folder)
  1364. {
  1365. }
  1366. virtual bool acquire_link(KBufferBuilder& builder) override
  1367. {
  1368. auto* custody = m_parent_process_directory->m_associated_process->executable();
  1369. if (!custody)
  1370. return false;
  1371. builder.append(custody->absolute_path().bytes());
  1372. return true;
  1373. }
  1374. NonnullRefPtr<ProcFSProcessFolder> m_parent_process_directory;
  1375. };
  1376. NonnullRefPtr<ProcFSProcessFolder> ProcFSProcessFolder::create(const Process& process)
  1377. {
  1378. auto folder = adopt_ref_if_nonnull(new (nothrow) ProcFSProcessFolder(process)).release_nonnull();
  1379. folder->m_components.append(ProcFSProcessUnveil::create(folder));
  1380. folder->m_components.append(ProcFSProcessPerformanceEvents::create(folder));
  1381. folder->m_components.append(ProcFSProcessFileDescriptions::create(folder));
  1382. folder->m_components.append(ProcFSProcessOverallFileDescriptions::create(folder));
  1383. folder->m_components.append(ProcFSProcessRoot::create(folder));
  1384. folder->m_components.append(ProcFSProcessVirtualMemory::create(folder));
  1385. folder->m_components.append(ProcFSProcessCurrentWorkDirectory::create(folder));
  1386. folder->m_components.append(ProcFSProcessBinary::create(folder));
  1387. folder->m_components.append(ProcFSProcessStacks::create(folder));
  1388. return folder;
  1389. }
  1390. ProcFSProcessFolder::ProcFSProcessFolder(const Process& process)
  1391. : ProcFSExposedFolder(String::formatted("{:d}", process.pid().value()), ProcFSComponentsRegistrar::the().root_folder())
  1392. , m_associated_process(process)
  1393. {
  1394. }
  1395. KResultOr<size_t> ProcFSExposedLink::read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, FileDescription*) const
  1396. {
  1397. VERIFY(offset == 0);
  1398. Locker locker(m_lock);
  1399. KBufferBuilder builder;
  1400. if (!const_cast<ProcFSExposedLink&>(*this).acquire_link(builder))
  1401. return KResult(EFAULT);
  1402. auto blob = builder.build();
  1403. if (!blob)
  1404. return KResult(EFAULT);
  1405. ssize_t nread = min(static_cast<off_t>(blob->size() - offset), static_cast<off_t>(count));
  1406. if (!buffer.write(blob->data() + offset, nread))
  1407. return KResult(EFAULT);
  1408. return nread;
  1409. }
  1410. NonnullRefPtr<Inode> ProcFSExposedLink::to_inode(const ProcFS& procfs_instance) const
  1411. {
  1412. return ProcFSLinkInode::create(procfs_instance, *this);
  1413. }
  1414. NonnullRefPtr<Inode> ProcFSExposedComponent::to_inode(const ProcFS& procfs_instance) const
  1415. {
  1416. return ProcFSInode::create(procfs_instance, *this);
  1417. }
  1418. NonnullRefPtr<Inode> ProcFSExposedFolder::to_inode(const ProcFS& procfs_instance) const
  1419. {
  1420. return ProcFSDirectoryInode::create(procfs_instance, *this);
  1421. }
  1422. void ProcFSExposedFolder::add_component(const ProcFSExposedComponent&)
  1423. {
  1424. TODO();
  1425. }
  1426. RefPtr<ProcFSExposedComponent> ProcFSExposedFolder::lookup(StringView name)
  1427. {
  1428. for (auto& component : m_components) {
  1429. if (component.name() == name) {
  1430. return component;
  1431. }
  1432. }
  1433. return {};
  1434. }
  1435. KResult ProcFSExposedFolder::traverse_as_directory(unsigned fsid, Function<bool(const FS::DirectoryEntryView&)> callback) const
  1436. {
  1437. Locker locker(ProcFSComponentsRegistrar::the().m_lock);
  1438. VERIFY(m_parent_folder);
  1439. callback({ ".", { fsid, component_index() }, 0 });
  1440. callback({ "..", { fsid, m_parent_folder->component_index() }, 0 });
  1441. for (auto& component : m_components) {
  1442. InodeIdentifier identifier = { fsid, component.component_index() };
  1443. callback({ component.name(), identifier, 0 });
  1444. }
  1445. return KSuccess;
  1446. }
  1447. RefPtr<ProcFSExposedComponent> ProcFSRootFolder::lookup(StringView name)
  1448. {
  1449. if (auto candidate = ProcFSExposedFolder::lookup(name); !candidate.is_null())
  1450. return candidate;
  1451. for (auto& component : m_process_folders) {
  1452. if (component.name() == name) {
  1453. return component;
  1454. }
  1455. }
  1456. return {};
  1457. }
  1458. KResult ProcFSRootFolder::traverse_as_directory(unsigned fsid, Function<bool(const FS::DirectoryEntryView&)> callback) const
  1459. {
  1460. Locker locker(ProcFSComponentsRegistrar::the().m_lock);
  1461. callback({ ".", { fsid, component_index() }, 0 });
  1462. callback({ "..", { fsid, 0 }, 0 });
  1463. for (auto& component : m_components) {
  1464. InodeIdentifier identifier = { fsid, component.component_index() };
  1465. callback({ component.name(), identifier, 0 });
  1466. }
  1467. for (auto& component : m_process_folders) {
  1468. InodeIdentifier identifier = { fsid, component.component_index() };
  1469. callback({ component.name(), identifier, 0 });
  1470. }
  1471. return KSuccess;
  1472. }
  1473. }