ProcessSpecificExposed.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  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/JsonObjectSerializer.h>
  8. #include <AK/JsonValue.h>
  9. #include <Kernel/Arch/x86/InterruptDisabler.h>
  10. #include <Kernel/FileSystem/Custody.h>
  11. #include <Kernel/FileSystem/ProcFS.h>
  12. #include <Kernel/KBufferBuilder.h>
  13. #include <Kernel/Memory/AnonymousVMObject.h>
  14. #include <Kernel/Memory/MemoryManager.h>
  15. #include <Kernel/Process.h>
  16. #include <Kernel/ProcessExposed.h>
  17. namespace Kernel {
  18. KResultOr<size_t> Process::procfs_get_thread_stack(ThreadID thread_id, KBufferBuilder& builder) const
  19. {
  20. JsonArraySerializer array { builder };
  21. auto thread = Thread::from_tid(thread_id);
  22. if (!thread)
  23. return KResult(ESRCH);
  24. bool show_kernel_addresses = Process::current().is_superuser();
  25. bool kernel_address_added = false;
  26. for (auto address : Processor::capture_stack_trace(*thread, 1024)) {
  27. if (!show_kernel_addresses && !Memory::is_user_address(VirtualAddress { address })) {
  28. if (kernel_address_added)
  29. continue;
  30. address = 0xdeadc0de;
  31. kernel_address_added = true;
  32. }
  33. array.add(address);
  34. }
  35. array.finish();
  36. return KSuccess;
  37. }
  38. KResult Process::traverse_stacks_directory(unsigned fsid, Function<bool(FileSystem::DirectoryEntryView const&)> callback) const
  39. {
  40. callback({ ".", { fsid, SegmentedProcFSIndex::build_segmented_index_for_main_property(pid(), SegmentedProcFSIndex::ProcessSubDirectory::Stacks, SegmentedProcFSIndex::MainProcessProperty::Reserved) }, 0 });
  41. callback({ "..", { fsid, m_procfs_traits->component_index() }, 0 });
  42. for_each_thread([&](const Thread& thread) {
  43. int tid = thread.tid().value();
  44. InodeIdentifier identifier = { fsid, SegmentedProcFSIndex::build_segmented_index_for_thread_stack(pid(), thread.tid()) };
  45. callback({ String::number(tid), identifier, 0 });
  46. });
  47. return KSuccess;
  48. }
  49. KResultOr<NonnullRefPtr<Inode>> Process::lookup_stacks_directory(const ProcFS& procfs, StringView name) const
  50. {
  51. KResultOr<NonnullRefPtr<ProcFSProcessPropertyInode>> thread_stack_inode { ENOENT };
  52. // FIXME: Try to exit the loop earlier
  53. for_each_thread([&](const Thread& thread) {
  54. int tid = thread.tid().value();
  55. VERIFY(!(tid < 0));
  56. if (name.to_int() == tid) {
  57. auto maybe_inode = ProcFSProcessPropertyInode::try_create_for_thread_stack(procfs, thread.tid(), pid());
  58. if (maybe_inode.is_error()) {
  59. thread_stack_inode = maybe_inode.error();
  60. return;
  61. }
  62. thread_stack_inode = maybe_inode.release_value();
  63. }
  64. });
  65. if (thread_stack_inode.is_error())
  66. return thread_stack_inode.error();
  67. return thread_stack_inode.release_value();
  68. }
  69. KResultOr<size_t> Process::procfs_get_file_description_link(unsigned fd, KBufferBuilder& builder) const
  70. {
  71. auto file_description = m_fds.file_description(fd);
  72. if (!file_description)
  73. return EBADF;
  74. auto data = file_description->absolute_path();
  75. builder.append(data);
  76. return data.length();
  77. }
  78. KResult Process::traverse_file_descriptions_directory(unsigned fsid, Function<bool(FileSystem::DirectoryEntryView const&)> callback) const
  79. {
  80. callback({ ".", { fsid, m_procfs_traits->component_index() }, 0 });
  81. callback({ "..", { fsid, m_procfs_traits->component_index() }, 0 });
  82. size_t count = 0;
  83. fds().enumerate([&](auto& file_description_metadata) {
  84. if (!file_description_metadata.is_valid()) {
  85. count++;
  86. return;
  87. }
  88. StringBuilder builder;
  89. builder.appendff("{}", count);
  90. callback({ builder.string_view(), { fsid, SegmentedProcFSIndex::build_segmented_index_for_file_description(pid(), count) }, DT_LNK });
  91. count++;
  92. });
  93. return KSuccess;
  94. }
  95. KResultOr<NonnullRefPtr<Inode>> Process::lookup_file_descriptions_directory(const ProcFS& procfs, StringView name) const
  96. {
  97. auto maybe_index = name.to_uint();
  98. if (!maybe_index.has_value())
  99. return ENOENT;
  100. if (!fds().get_if_valid(*maybe_index))
  101. return ENOENT;
  102. auto maybe_inode = ProcFSProcessPropertyInode::try_create_for_file_description_link(procfs, *maybe_index, pid());
  103. if (maybe_inode.is_error())
  104. return maybe_inode.error();
  105. return maybe_inode.release_value();
  106. }
  107. KResult Process::procfs_get_pledge_stats(KBufferBuilder& builder) const
  108. {
  109. JsonObjectSerializer obj { builder };
  110. #define __ENUMERATE_PLEDGE_PROMISE(x) \
  111. if (has_promised(Pledge::x)) { \
  112. if (!builder.is_empty()) \
  113. builder.append(' '); \
  114. builder.append(#x); \
  115. }
  116. if (has_promises()) {
  117. StringBuilder builder;
  118. ENUMERATE_PLEDGE_PROMISES
  119. obj.add("promises", builder.build());
  120. }
  121. #undef __ENUMERATE_PLEDGE_PROMISE
  122. obj.finish();
  123. return KSuccess;
  124. }
  125. KResult Process::procfs_get_unveil_stats(KBufferBuilder& builder) const
  126. {
  127. JsonArraySerializer array { builder };
  128. for (auto& unveiled_path : unveiled_paths()) {
  129. if (!unveiled_path.was_explicitly_unveiled())
  130. continue;
  131. auto obj = array.add_object();
  132. obj.add("path", unveiled_path.path());
  133. StringBuilder permissions_builder;
  134. if (unveiled_path.permissions() & UnveilAccess::Read)
  135. permissions_builder.append('r');
  136. if (unveiled_path.permissions() & UnveilAccess::Write)
  137. permissions_builder.append('w');
  138. if (unveiled_path.permissions() & UnveilAccess::Execute)
  139. permissions_builder.append('x');
  140. if (unveiled_path.permissions() & UnveilAccess::CreateOrRemove)
  141. permissions_builder.append('c');
  142. if (unveiled_path.permissions() & UnveilAccess::Browse)
  143. permissions_builder.append('b');
  144. obj.add("permissions", permissions_builder.to_string());
  145. }
  146. array.finish();
  147. return KSuccess;
  148. }
  149. KResult Process::procfs_get_perf_events(KBufferBuilder& builder) const
  150. {
  151. InterruptDisabler disabler;
  152. if (!const_cast<Process&>(*this).perf_events()) {
  153. dbgln("ProcFS: No perf events for {}", pid());
  154. return KResult(ENOBUFS);
  155. }
  156. return const_cast<Process&>(*this).perf_events()->to_json(builder) ? KSuccess : KResult(EINVAL);
  157. }
  158. KResult Process::procfs_get_fds_stats(KBufferBuilder& builder) const
  159. {
  160. JsonArraySerializer array { builder };
  161. if (fds().open_count() == 0) {
  162. array.finish();
  163. return KSuccess;
  164. }
  165. size_t count = 0;
  166. fds().enumerate([&](auto& file_description_metadata) {
  167. if (!file_description_metadata.is_valid()) {
  168. count++;
  169. return;
  170. }
  171. bool cloexec = file_description_metadata.flags() & FD_CLOEXEC;
  172. RefPtr<FileDescription> description = file_description_metadata.description();
  173. auto description_object = array.add_object();
  174. description_object.add("fd", count);
  175. description_object.add("absolute_path", description->absolute_path());
  176. description_object.add("seekable", description->file().is_seekable());
  177. description_object.add("class", description->file().class_name());
  178. description_object.add("offset", description->offset());
  179. description_object.add("cloexec", cloexec);
  180. description_object.add("blocking", description->is_blocking());
  181. description_object.add("can_read", description->can_read());
  182. description_object.add("can_write", description->can_write());
  183. count++;
  184. });
  185. array.finish();
  186. return KSuccess;
  187. }
  188. KResult Process::procfs_get_virtual_memory_stats(KBufferBuilder& builder) const
  189. {
  190. JsonArraySerializer array { builder };
  191. {
  192. SpinlockLocker lock(address_space().get_lock());
  193. for (auto& region : address_space().regions()) {
  194. if (!region->is_user() && !Process::current().is_superuser())
  195. continue;
  196. auto region_object = array.add_object();
  197. region_object.add("readable", region->is_readable());
  198. region_object.add("writable", region->is_writable());
  199. region_object.add("executable", region->is_executable());
  200. region_object.add("stack", region->is_stack());
  201. region_object.add("shared", region->is_shared());
  202. region_object.add("syscall", region->is_syscall_region());
  203. region_object.add("purgeable", region->vmobject().is_anonymous());
  204. if (region->vmobject().is_anonymous()) {
  205. region_object.add("volatile", static_cast<Memory::AnonymousVMObject const&>(region->vmobject()).is_volatile());
  206. }
  207. region_object.add("cacheable", region->is_cacheable());
  208. region_object.add("address", region->vaddr().get());
  209. region_object.add("size", region->size());
  210. region_object.add("amount_resident", region->amount_resident());
  211. region_object.add("amount_dirty", region->amount_dirty());
  212. region_object.add("cow_pages", region->cow_pages());
  213. region_object.add("name", region->name());
  214. region_object.add("vmobject", region->vmobject().class_name());
  215. StringBuilder pagemap_builder;
  216. for (size_t i = 0; i < region->page_count(); ++i) {
  217. auto* page = region->physical_page(i);
  218. if (!page)
  219. pagemap_builder.append('N');
  220. else if (page->is_shared_zero_page() || page->is_lazy_committed_page())
  221. pagemap_builder.append('Z');
  222. else
  223. pagemap_builder.append('P');
  224. }
  225. region_object.add("pagemap", pagemap_builder.to_string());
  226. }
  227. }
  228. array.finish();
  229. return KSuccess;
  230. }
  231. KResult Process::procfs_get_current_work_directory_link(KBufferBuilder& builder) const
  232. {
  233. builder.append_bytes(const_cast<Process&>(*this).current_directory().absolute_path().bytes());
  234. return KSuccess;
  235. }
  236. mode_t Process::binary_link_required_mode() const
  237. {
  238. if (!executable())
  239. return 0;
  240. return m_procfs_traits->required_mode();
  241. }
  242. KResult Process::procfs_get_binary_link(KBufferBuilder& builder) const
  243. {
  244. auto* custody = executable();
  245. if (!custody)
  246. return KResult(ENOEXEC);
  247. builder.append(custody->absolute_path().bytes());
  248. return KSuccess;
  249. }
  250. }