ProcessExposed.cpp 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637
  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.fds().open_count());
  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->fds().open_count();
  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. size_t count = 0;
  1135. m_process_folder->m_associated_process->fds().enumerate([&](auto& file_description_metadata) {
  1136. if (!file_description_metadata.is_valid()) {
  1137. count++;
  1138. return;
  1139. }
  1140. InodeIdentifier identifier = { fsid, file_description_metadata.global_procfs_inode_index() };
  1141. callback({ String::number(count), identifier, 0 });
  1142. count++;
  1143. });
  1144. return KSuccess;
  1145. }
  1146. RefPtr<ProcFSExposedComponent> ProcFSProcessFileDescriptions::lookup(StringView name)
  1147. {
  1148. Locker locker(m_lock);
  1149. auto process = m_process_folder->m_associated_process;
  1150. RefPtr<ProcFSProcessFileDescription> procfd_fd;
  1151. // FIXME: Try to exit the loop earlier
  1152. size_t count = 0;
  1153. m_process_folder->m_associated_process->fds().enumerate([&](auto& file_description_metadata) {
  1154. if (!file_description_metadata.is_valid()) {
  1155. count++;
  1156. return;
  1157. }
  1158. if (name == String::number(count)) {
  1159. procfd_fd = ProcFSProcessFileDescription::create(count, *file_description_metadata.description(), file_description_metadata.global_procfs_inode_index(), *this);
  1160. }
  1161. count++;
  1162. });
  1163. return procfd_fd;
  1164. }
  1165. class ProcFSProcessUnveil final : public ProcFSProcessInformation {
  1166. public:
  1167. static NonnullRefPtr<ProcFSProcessUnveil> create(const ProcFSProcessFolder& parent_folder)
  1168. {
  1169. return adopt_ref(*new (nothrow) ProcFSProcessUnveil(parent_folder));
  1170. }
  1171. private:
  1172. explicit ProcFSProcessUnveil(const ProcFSProcessFolder& parent_folder)
  1173. : ProcFSProcessInformation("unveil"sv, parent_folder)
  1174. {
  1175. }
  1176. virtual bool output(KBufferBuilder& builder) override
  1177. {
  1178. JsonArraySerializer array { builder };
  1179. for (auto& unveiled_path : m_parent_folder->m_associated_process->unveiled_paths()) {
  1180. if (!unveiled_path.was_explicitly_unveiled())
  1181. continue;
  1182. auto obj = array.add_object();
  1183. obj.add("path", unveiled_path.path());
  1184. StringBuilder permissions_builder;
  1185. if (unveiled_path.permissions() & UnveilAccess::Read)
  1186. permissions_builder.append('r');
  1187. if (unveiled_path.permissions() & UnveilAccess::Write)
  1188. permissions_builder.append('w');
  1189. if (unveiled_path.permissions() & UnveilAccess::Execute)
  1190. permissions_builder.append('x');
  1191. if (unveiled_path.permissions() & UnveilAccess::CreateOrRemove)
  1192. permissions_builder.append('c');
  1193. if (unveiled_path.permissions() & UnveilAccess::Browse)
  1194. permissions_builder.append('b');
  1195. obj.add("permissions", permissions_builder.to_string());
  1196. }
  1197. array.finish();
  1198. return true;
  1199. }
  1200. };
  1201. class ProcFSProcessPerformanceEvents final : public ProcFSProcessInformation {
  1202. public:
  1203. static NonnullRefPtr<ProcFSProcessPerformanceEvents> create(const ProcFSProcessFolder& parent_folder)
  1204. {
  1205. return adopt_ref(*new (nothrow) ProcFSProcessPerformanceEvents(parent_folder));
  1206. }
  1207. private:
  1208. explicit ProcFSProcessPerformanceEvents(const ProcFSProcessFolder& parent_folder)
  1209. : ProcFSProcessInformation("perf_events"sv, parent_folder)
  1210. {
  1211. }
  1212. virtual bool output(KBufferBuilder& builder) override
  1213. {
  1214. InterruptDisabler disabler;
  1215. if (!m_parent_folder->m_associated_process->perf_events()) {
  1216. dbgln("ProcFS: No perf events for {}", m_parent_folder->m_associated_process->pid());
  1217. return false;
  1218. }
  1219. return m_parent_folder->m_associated_process->perf_events()->to_json(builder);
  1220. }
  1221. };
  1222. class ProcFSProcessOverallFileDescriptions final : public ProcFSProcessInformation {
  1223. public:
  1224. static NonnullRefPtr<ProcFSProcessOverallFileDescriptions> create(const ProcFSProcessFolder& parent_folder)
  1225. {
  1226. return adopt_ref(*new (nothrow) ProcFSProcessOverallFileDescriptions(parent_folder));
  1227. }
  1228. private:
  1229. explicit ProcFSProcessOverallFileDescriptions(const ProcFSProcessFolder& parent_folder)
  1230. : ProcFSProcessInformation("fds"sv, parent_folder)
  1231. {
  1232. }
  1233. virtual bool output(KBufferBuilder& builder) override
  1234. {
  1235. JsonArraySerializer array { builder };
  1236. auto process = m_parent_folder->m_associated_process;
  1237. if (process->fds().open_count() == 0) {
  1238. array.finish();
  1239. return true;
  1240. }
  1241. size_t count = 0;
  1242. process->fds().enumerate([&](auto& file_description_metadata) {
  1243. if (!file_description_metadata.is_valid()) {
  1244. count++;
  1245. return;
  1246. }
  1247. bool cloexec = file_description_metadata.flags() & FD_CLOEXEC;
  1248. RefPtr<FileDescription> description = file_description_metadata.description();
  1249. auto description_object = array.add_object();
  1250. description_object.add("fd", count);
  1251. description_object.add("absolute_path", description->absolute_path());
  1252. description_object.add("seekable", description->file().is_seekable());
  1253. description_object.add("class", description->file().class_name());
  1254. description_object.add("offset", description->offset());
  1255. description_object.add("cloexec", cloexec);
  1256. description_object.add("blocking", description->is_blocking());
  1257. description_object.add("can_read", description->can_read());
  1258. description_object.add("can_write", description->can_write());
  1259. count++;
  1260. });
  1261. array.finish();
  1262. return true;
  1263. }
  1264. };
  1265. class ProcFSProcessRoot final : public ProcFSExposedLink {
  1266. public:
  1267. static NonnullRefPtr<ProcFSProcessRoot> create(const ProcFSProcessFolder& parent_folder)
  1268. {
  1269. return adopt_ref(*new (nothrow) ProcFSProcessRoot(parent_folder));
  1270. }
  1271. private:
  1272. explicit ProcFSProcessRoot(const ProcFSProcessFolder& parent_folder)
  1273. : ProcFSExposedLink("root"sv)
  1274. , m_parent_process_directory(parent_folder)
  1275. {
  1276. }
  1277. virtual bool acquire_link(KBufferBuilder& builder) override
  1278. {
  1279. builder.append_bytes(m_parent_process_directory->m_associated_process->root_directory_relative_to_global_root().absolute_path().to_byte_buffer());
  1280. return true;
  1281. }
  1282. NonnullRefPtr<ProcFSProcessFolder> m_parent_process_directory;
  1283. };
  1284. class ProcFSProcessVirtualMemory final : public ProcFSProcessInformation {
  1285. public:
  1286. static NonnullRefPtr<ProcFSProcessRoot> create(const ProcFSProcessFolder& parent_folder)
  1287. {
  1288. return adopt_ref(*new (nothrow) ProcFSProcessVirtualMemory(parent_folder));
  1289. }
  1290. private:
  1291. explicit ProcFSProcessVirtualMemory(const ProcFSProcessFolder& parent_folder)
  1292. : ProcFSProcessInformation("vm"sv, parent_folder)
  1293. {
  1294. }
  1295. virtual bool output(KBufferBuilder& builder) override
  1296. {
  1297. auto process = m_parent_folder->m_associated_process;
  1298. JsonArraySerializer array { builder };
  1299. {
  1300. ScopedSpinLock lock(process->space().get_lock());
  1301. for (auto& region : process->space().regions()) {
  1302. if (!region->is_user() && !Process::current()->is_superuser())
  1303. continue;
  1304. auto region_object = array.add_object();
  1305. region_object.add("readable", region->is_readable());
  1306. region_object.add("writable", region->is_writable());
  1307. region_object.add("executable", region->is_executable());
  1308. region_object.add("stack", region->is_stack());
  1309. region_object.add("shared", region->is_shared());
  1310. region_object.add("syscall", region->is_syscall_region());
  1311. region_object.add("purgeable", region->vmobject().is_anonymous());
  1312. if (region->vmobject().is_anonymous()) {
  1313. region_object.add("volatile", static_cast<const AnonymousVMObject&>(region->vmobject()).is_any_volatile());
  1314. }
  1315. region_object.add("cacheable", region->is_cacheable());
  1316. region_object.add("address", region->vaddr().get());
  1317. region_object.add("size", region->size());
  1318. region_object.add("amount_resident", region->amount_resident());
  1319. region_object.add("amount_dirty", region->amount_dirty());
  1320. region_object.add("cow_pages", region->cow_pages());
  1321. region_object.add("name", region->name());
  1322. region_object.add("vmobject", region->vmobject().class_name());
  1323. StringBuilder pagemap_builder;
  1324. for (size_t i = 0; i < region->page_count(); ++i) {
  1325. auto* page = region->physical_page(i);
  1326. if (!page)
  1327. pagemap_builder.append('N');
  1328. else if (page->is_shared_zero_page() || page->is_lazy_committed_page())
  1329. pagemap_builder.append('Z');
  1330. else
  1331. pagemap_builder.append('P');
  1332. }
  1333. region_object.add("pagemap", pagemap_builder.to_string());
  1334. }
  1335. }
  1336. array.finish();
  1337. return true;
  1338. }
  1339. };
  1340. class ProcFSProcessCurrentWorkDirectory final : public ProcFSExposedLink {
  1341. public:
  1342. static NonnullRefPtr<ProcFSProcessCurrentWorkDirectory> create(const ProcFSProcessFolder& parent_folder)
  1343. {
  1344. return adopt_ref(*new (nothrow) ProcFSProcessCurrentWorkDirectory(parent_folder));
  1345. }
  1346. private:
  1347. explicit ProcFSProcessCurrentWorkDirectory(const ProcFSProcessFolder& parent_folder)
  1348. : ProcFSExposedLink("cwd"sv)
  1349. , m_parent_process_directory(parent_folder)
  1350. {
  1351. }
  1352. virtual bool acquire_link(KBufferBuilder& builder) override
  1353. {
  1354. builder.append_bytes(m_parent_process_directory->m_associated_process->current_directory().absolute_path().bytes());
  1355. return true;
  1356. }
  1357. NonnullRefPtr<ProcFSProcessFolder> m_parent_process_directory;
  1358. };
  1359. class ProcFSProcessBinary final : public ProcFSExposedLink {
  1360. public:
  1361. static NonnullRefPtr<ProcFSProcessBinary> create(const ProcFSProcessFolder& parent_folder)
  1362. {
  1363. return adopt_ref(*new (nothrow) ProcFSProcessBinary(parent_folder));
  1364. }
  1365. virtual mode_t required_mode() const override
  1366. {
  1367. if (!m_parent_process_directory->m_associated_process->executable())
  1368. return 0;
  1369. return ProcFSExposedComponent::required_mode();
  1370. }
  1371. private:
  1372. explicit ProcFSProcessBinary(const ProcFSProcessFolder& parent_folder)
  1373. : ProcFSExposedLink("exe"sv)
  1374. , m_parent_process_directory(parent_folder)
  1375. {
  1376. }
  1377. virtual bool acquire_link(KBufferBuilder& builder) override
  1378. {
  1379. auto* custody = m_parent_process_directory->m_associated_process->executable();
  1380. if (!custody)
  1381. return false;
  1382. builder.append(custody->absolute_path().bytes());
  1383. return true;
  1384. }
  1385. NonnullRefPtr<ProcFSProcessFolder> m_parent_process_directory;
  1386. };
  1387. NonnullRefPtr<ProcFSProcessFolder> ProcFSProcessFolder::create(const Process& process)
  1388. {
  1389. auto folder = adopt_ref_if_nonnull(new (nothrow) ProcFSProcessFolder(process)).release_nonnull();
  1390. folder->m_components.append(ProcFSProcessUnveil::create(folder));
  1391. folder->m_components.append(ProcFSProcessPerformanceEvents::create(folder));
  1392. folder->m_components.append(ProcFSProcessFileDescriptions::create(folder));
  1393. folder->m_components.append(ProcFSProcessOverallFileDescriptions::create(folder));
  1394. folder->m_components.append(ProcFSProcessRoot::create(folder));
  1395. folder->m_components.append(ProcFSProcessVirtualMemory::create(folder));
  1396. folder->m_components.append(ProcFSProcessCurrentWorkDirectory::create(folder));
  1397. folder->m_components.append(ProcFSProcessBinary::create(folder));
  1398. folder->m_components.append(ProcFSProcessStacks::create(folder));
  1399. return folder;
  1400. }
  1401. ProcFSProcessFolder::ProcFSProcessFolder(const Process& process)
  1402. : ProcFSExposedFolder(String::formatted("{:d}", process.pid().value()), ProcFSComponentsRegistrar::the().root_folder())
  1403. , m_associated_process(process)
  1404. {
  1405. }
  1406. KResultOr<size_t> ProcFSExposedLink::read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, FileDescription*) const
  1407. {
  1408. VERIFY(offset == 0);
  1409. Locker locker(m_lock);
  1410. KBufferBuilder builder;
  1411. if (!const_cast<ProcFSExposedLink&>(*this).acquire_link(builder))
  1412. return KResult(EFAULT);
  1413. auto blob = builder.build();
  1414. if (!blob)
  1415. return KResult(EFAULT);
  1416. ssize_t nread = min(static_cast<off_t>(blob->size() - offset), static_cast<off_t>(count));
  1417. if (!buffer.write(blob->data() + offset, nread))
  1418. return KResult(EFAULT);
  1419. return nread;
  1420. }
  1421. NonnullRefPtr<Inode> ProcFSExposedLink::to_inode(const ProcFS& procfs_instance) const
  1422. {
  1423. return ProcFSLinkInode::create(procfs_instance, *this);
  1424. }
  1425. NonnullRefPtr<Inode> ProcFSExposedComponent::to_inode(const ProcFS& procfs_instance) const
  1426. {
  1427. return ProcFSInode::create(procfs_instance, *this);
  1428. }
  1429. NonnullRefPtr<Inode> ProcFSExposedFolder::to_inode(const ProcFS& procfs_instance) const
  1430. {
  1431. return ProcFSDirectoryInode::create(procfs_instance, *this);
  1432. }
  1433. void ProcFSExposedFolder::add_component(const ProcFSExposedComponent&)
  1434. {
  1435. TODO();
  1436. }
  1437. RefPtr<ProcFSExposedComponent> ProcFSExposedFolder::lookup(StringView name)
  1438. {
  1439. for (auto& component : m_components) {
  1440. if (component.name() == name) {
  1441. return component;
  1442. }
  1443. }
  1444. return {};
  1445. }
  1446. KResult ProcFSExposedFolder::traverse_as_directory(unsigned fsid, Function<bool(const FS::DirectoryEntryView&)> callback) const
  1447. {
  1448. Locker locker(ProcFSComponentsRegistrar::the().m_lock);
  1449. VERIFY(m_parent_folder);
  1450. callback({ ".", { fsid, component_index() }, 0 });
  1451. callback({ "..", { fsid, m_parent_folder->component_index() }, 0 });
  1452. for (auto& component : m_components) {
  1453. InodeIdentifier identifier = { fsid, component.component_index() };
  1454. callback({ component.name(), identifier, 0 });
  1455. }
  1456. return KSuccess;
  1457. }
  1458. RefPtr<ProcFSExposedComponent> ProcFSRootFolder::lookup(StringView name)
  1459. {
  1460. if (auto candidate = ProcFSExposedFolder::lookup(name); !candidate.is_null())
  1461. return candidate;
  1462. for (auto& component : m_process_folders) {
  1463. if (component.name() == name) {
  1464. return component;
  1465. }
  1466. }
  1467. return {};
  1468. }
  1469. KResult ProcFSRootFolder::traverse_as_directory(unsigned fsid, Function<bool(const FS::DirectoryEntryView&)> callback) const
  1470. {
  1471. Locker locker(ProcFSComponentsRegistrar::the().m_lock);
  1472. callback({ ".", { fsid, component_index() }, 0 });
  1473. callback({ "..", { fsid, 0 }, 0 });
  1474. for (auto& component : m_components) {
  1475. InodeIdentifier identifier = { fsid, component.component_index() };
  1476. callback({ component.name(), identifier, 0 });
  1477. }
  1478. for (auto& component : m_process_folders) {
  1479. InodeIdentifier identifier = { fsid, component.component_index() };
  1480. callback({ component.name(), identifier, 0 });
  1481. }
  1482. return KSuccess;
  1483. }
  1484. }