crash.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2019-2020, Shannon Booth <shannon.ml.booth@gmail.com>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/Assertions.h>
  8. #include <AK/Function.h>
  9. #include <AK/String.h>
  10. #if ARCH(I386) || ARCH(X86_64)
  11. # include <Kernel/Arch/x86/IO.h>
  12. #endif
  13. #include <LibCore/ArgsParser.h>
  14. #include <LibCore/Object.h>
  15. #include <LibTest/CrashTest.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <sys/mman.h>
  19. #include <sys/wait.h>
  20. #include <syscall.h>
  21. #include <unistd.h>
  22. using Test::Crash;
  23. #if defined(AK_COMPILER_CLANG)
  24. # pragma clang optimize off
  25. #else
  26. # pragma GCC optimize("O0")
  27. #endif
  28. int main(int argc, char** argv)
  29. {
  30. bool do_all_crash_types = false;
  31. bool do_segmentation_violation = false;
  32. bool do_division_by_zero = false;
  33. bool do_illegal_instruction = false;
  34. bool do_abort = false;
  35. bool do_write_to_uninitialized_malloc_memory = false;
  36. bool do_write_to_freed_memory = false;
  37. bool do_write_to_read_only_memory = false;
  38. bool do_read_from_uninitialized_malloc_memory = false;
  39. bool do_read_from_freed_memory = false;
  40. bool do_invalid_stack_pointer_on_syscall = false;
  41. bool do_invalid_stack_pointer_on_page_fault = false;
  42. bool do_syscall_from_writeable_memory = false;
  43. bool do_legitimate_syscall = false;
  44. bool do_execute_non_executable_memory = false;
  45. bool do_trigger_user_mode_instruction_prevention = false;
  46. #if ARCH(I386) || ARCH(X86_64)
  47. bool do_use_io_instruction = false;
  48. #endif
  49. bool do_pledge_violation = false;
  50. bool do_failing_assertion = false;
  51. bool do_deref_null_refptr = false;
  52. auto args_parser = Core::ArgsParser();
  53. args_parser.set_general_help(
  54. "Exercise error-handling paths of the execution environment "
  55. "(i.e., Kernel or UE) by crashing in many different ways.");
  56. args_parser.add_option(do_all_crash_types, "Test that all (except -U) of the following crash types crash as expected (default behavior)", nullptr, 'A');
  57. args_parser.add_option(do_segmentation_violation, "Perform a segmentation violation by dereferencing an invalid pointer", nullptr, 's');
  58. args_parser.add_option(do_division_by_zero, "Perform a division by zero", nullptr, 'd');
  59. args_parser.add_option(do_illegal_instruction, "Execute an illegal CPU instruction", nullptr, 'i');
  60. args_parser.add_option(do_abort, "Call `abort()`", nullptr, 'a');
  61. args_parser.add_option(do_read_from_uninitialized_malloc_memory, "Read a pointer from uninitialized malloc memory, then read from it", nullptr, 'm');
  62. args_parser.add_option(do_read_from_freed_memory, "Read a pointer from memory freed using `free()`, then read from it", nullptr, 'f');
  63. args_parser.add_option(do_write_to_uninitialized_malloc_memory, "Read a pointer from uninitialized malloc memory, then write to it", nullptr, 'M');
  64. args_parser.add_option(do_write_to_freed_memory, "Read a pointer from memory freed using `free()`, then write to it", nullptr, 'F');
  65. args_parser.add_option(do_write_to_read_only_memory, "Write to read-only memory", nullptr, 'r');
  66. args_parser.add_option(do_invalid_stack_pointer_on_syscall, "Make a syscall while using an invalid stack pointer", nullptr, 'T');
  67. args_parser.add_option(do_invalid_stack_pointer_on_page_fault, "Trigger a page fault while using an invalid stack pointer", nullptr, 't');
  68. args_parser.add_option(do_syscall_from_writeable_memory, "Make a syscall from writeable memory", nullptr, 'S');
  69. args_parser.add_option(do_legitimate_syscall, "Make a syscall from legitimate memory (but outside msyscall)", nullptr, 'y');
  70. args_parser.add_option(do_execute_non_executable_memory, "Attempt to execute non-executable memory (not mapped with PROT_EXEC)", nullptr, 'X');
  71. args_parser.add_option(do_trigger_user_mode_instruction_prevention, "Attempt to trigger an x86 User Mode Instruction Prevention fault. WARNING: This test runs only when invoked manually, see #10042.", nullptr, 'U');
  72. #if ARCH(I386) || ARCH(X86_64)
  73. args_parser.add_option(do_use_io_instruction, "Use an x86 I/O instruction in userspace", nullptr, 'I');
  74. #endif
  75. args_parser.add_option(do_pledge_violation, "Violate pledge()'d promises", nullptr, 'p');
  76. args_parser.add_option(do_failing_assertion, "Perform a failing assertion", nullptr, 'n');
  77. args_parser.add_option(do_deref_null_refptr, "Dereference a null RefPtr", nullptr, 'R');
  78. if (argc == 1) {
  79. do_all_crash_types = true;
  80. } else if (argc != 2) {
  81. args_parser.print_usage(stderr, argv[0]);
  82. exit(1);
  83. }
  84. args_parser.parse(argc, argv);
  85. Crash::RunType run_type = do_all_crash_types ? Crash::RunType::UsingChildProcess
  86. : Crash::RunType::UsingCurrentProcess;
  87. bool any_failures = false;
  88. if (do_segmentation_violation || do_all_crash_types) {
  89. any_failures |= !Crash("Segmentation violation", []() {
  90. volatile int* crashme = nullptr;
  91. *crashme = 0xbeef;
  92. return Crash::Failure::DidNotCrash;
  93. }).run(run_type);
  94. }
  95. if (do_division_by_zero || do_all_crash_types) {
  96. any_failures |= !Crash("Division by zero", []() {
  97. volatile int lala = 10;
  98. volatile int zero = 0;
  99. [[maybe_unused]] volatile int test = lala / zero;
  100. return Crash::Failure::DidNotCrash;
  101. }).run(run_type);
  102. }
  103. if (do_illegal_instruction || do_all_crash_types) {
  104. any_failures |= !Crash("Illegal instruction", []() {
  105. __builtin_trap();
  106. return Crash::Failure::DidNotCrash;
  107. }).run(run_type);
  108. }
  109. if (do_abort || do_all_crash_types) {
  110. any_failures |= !Crash("Abort", []() {
  111. abort();
  112. return Crash::Failure::DidNotCrash;
  113. }).run(run_type);
  114. }
  115. if (do_read_from_uninitialized_malloc_memory || do_all_crash_types) {
  116. any_failures |= !Crash("Read from uninitialized malloc memory", []() {
  117. auto* uninitialized_memory = (volatile u32**)malloc(1024);
  118. if (!uninitialized_memory)
  119. return Crash::Failure::UnexpectedError;
  120. [[maybe_unused]] volatile auto x = uninitialized_memory[0][0];
  121. return Crash::Failure::DidNotCrash;
  122. }).run(run_type);
  123. }
  124. if (do_read_from_freed_memory || do_all_crash_types) {
  125. any_failures |= !Crash("Read from freed memory", []() {
  126. auto* uninitialized_memory = (volatile u32**)malloc(1024);
  127. if (!uninitialized_memory)
  128. return Crash::Failure::UnexpectedError;
  129. free(uninitialized_memory);
  130. #pragma GCC diagnostic push
  131. #pragma GCC diagnostic ignored "-Wuse-after-free"
  132. [[maybe_unused]] volatile auto x = uninitialized_memory[4][0];
  133. #pragma GCC diagnostic pop
  134. return Crash::Failure::DidNotCrash;
  135. }).run(run_type);
  136. }
  137. if (do_write_to_uninitialized_malloc_memory || do_all_crash_types) {
  138. any_failures |= !Crash("Write to uninitialized malloc memory", []() {
  139. auto* uninitialized_memory = (volatile u32**)malloc(1024);
  140. if (!uninitialized_memory)
  141. return Crash::Failure::UnexpectedError;
  142. uninitialized_memory[4][0] = 1;
  143. return Crash::Failure::DidNotCrash;
  144. }).run(run_type);
  145. }
  146. if (do_write_to_freed_memory || do_all_crash_types) {
  147. any_failures |= !Crash("Write to freed memory", []() {
  148. auto* uninitialized_memory = (volatile u32**)malloc(1024);
  149. if (!uninitialized_memory)
  150. return Crash::Failure::UnexpectedError;
  151. #pragma GCC diagnostic push
  152. #pragma GCC diagnostic ignored "-Wuse-after-free"
  153. free(uninitialized_memory);
  154. uninitialized_memory[4][0] = 1;
  155. #pragma GCC diagnostic pop
  156. return Crash::Failure::DidNotCrash;
  157. }).run(run_type);
  158. }
  159. if (do_write_to_read_only_memory || do_all_crash_types) {
  160. any_failures |= !Crash("Write to read only memory", []() {
  161. auto* ptr = (u8*)mmap(nullptr, 4096, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, 0);
  162. if (ptr == MAP_FAILED)
  163. return Crash::Failure::UnexpectedError;
  164. *ptr = 'x'; // This should work fine.
  165. int rc = mprotect(ptr, 4096, PROT_READ);
  166. if (rc != 0 || *ptr != 'x')
  167. return Crash::Failure::UnexpectedError;
  168. *ptr = 'y'; // This should crash!
  169. return Crash::Failure::DidNotCrash;
  170. }).run(run_type);
  171. }
  172. if (do_invalid_stack_pointer_on_syscall || do_all_crash_types) {
  173. any_failures |= !Crash("Invalid stack pointer on syscall", []() {
  174. u8* makeshift_stack = (u8*)mmap(nullptr, 0, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_STACK, 0, 0);
  175. if (!makeshift_stack)
  176. return Crash::Failure::UnexpectedError;
  177. u8* makeshift_esp = makeshift_stack + 2048;
  178. #if ARCH(I386) || ARCH(X86_64)
  179. asm volatile("mov %%eax, %%esp" ::"a"(makeshift_esp));
  180. #elif ARCH(AARCH64)
  181. (void)makeshift_esp;
  182. TODO_AARCH64();
  183. #else
  184. # error Unknown architecture
  185. #endif
  186. getuid();
  187. dbgln("Survived syscall with MAP_STACK stack");
  188. u8* bad_stack = (u8*)mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
  189. if (!bad_stack)
  190. return Crash::Failure::UnexpectedError;
  191. u8* bad_esp = bad_stack + 2048;
  192. #if ARCH(I386) || ARCH(X86_64)
  193. asm volatile("mov %%eax, %%esp" ::"a"(bad_esp));
  194. #elif ARCH(AARCH64)
  195. (void)bad_esp;
  196. TODO_AARCH64();
  197. #else
  198. # error Unknown architecture
  199. #endif
  200. getuid();
  201. return Crash::Failure::DidNotCrash;
  202. }).run(run_type);
  203. }
  204. if (do_invalid_stack_pointer_on_page_fault || do_all_crash_types) {
  205. any_failures |= !Crash("Invalid stack pointer on page fault", []() {
  206. u8* bad_stack = (u8*)mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
  207. if (!bad_stack)
  208. return Crash::Failure::UnexpectedError;
  209. u8* bad_esp = bad_stack + 2048;
  210. #if ARCH(I386)
  211. asm volatile("mov %%eax, %%esp" ::"a"(bad_esp));
  212. asm volatile("pushl $0");
  213. #elif ARCH(X86_64)
  214. asm volatile("movq %%rax, %%rsp" ::"a"(bad_esp));
  215. asm volatile("pushq $0");
  216. #elif ARCH(AARCH64)
  217. (void)bad_esp;
  218. TODO_AARCH64();
  219. #else
  220. # error Unknown architecture
  221. #endif
  222. return Crash::Failure::DidNotCrash;
  223. }).run(run_type);
  224. }
  225. if (do_syscall_from_writeable_memory || do_all_crash_types) {
  226. any_failures |= !Crash("Syscall from writable memory", []() {
  227. u8 buffer[] = { 0xb8, Syscall::SC_getuid, 0, 0, 0, 0xcd, 0x82 };
  228. ((void (*)())buffer)();
  229. return Crash::Failure::DidNotCrash;
  230. }).run(run_type);
  231. }
  232. if (do_legitimate_syscall || do_all_crash_types) {
  233. any_failures |= !Crash("Regular syscall from outside msyscall", []() {
  234. // Since 'crash' is dynamically linked, and DynamicLoader only allows LibSystem to make syscalls, this should kill us:
  235. Syscall::invoke(Syscall::SC_getuid);
  236. return Crash::Failure::DidNotCrash;
  237. }).run(run_type);
  238. }
  239. if (do_execute_non_executable_memory || do_all_crash_types) {
  240. any_failures |= !Crash("Execute non executable memory", []() {
  241. auto* ptr = (u8*)mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
  242. if (ptr == MAP_FAILED)
  243. return Crash::Failure::UnexpectedError;
  244. ptr[0] = 0xc3; // ret
  245. typedef void* (*CrashyFunctionPtr)();
  246. ((CrashyFunctionPtr)ptr)();
  247. return Crash::Failure::DidNotCrash;
  248. }).run(run_type);
  249. }
  250. if (do_trigger_user_mode_instruction_prevention) {
  251. any_failures |= !Crash("Trigger x86 User Mode Instruction Prevention", []() {
  252. #if ARCH(I386) || ARCH(X86_64)
  253. asm volatile("str %eax");
  254. #elif ARCH(AARCH64)
  255. TODO_AARCH64();
  256. #else
  257. # error Unknown architecture
  258. #endif
  259. return Crash::Failure::DidNotCrash;
  260. }).run(run_type);
  261. }
  262. #if ARCH(I386) || ARCH(X86_64)
  263. if (do_use_io_instruction || do_all_crash_types) {
  264. any_failures |= !Crash("Attempt to use an I/O instruction", [] {
  265. u8 keyboard_status = IO::in8(0x64);
  266. outln("Keyboard status: {:#02x}", keyboard_status);
  267. return Crash::Failure::DidNotCrash;
  268. }).run(run_type);
  269. }
  270. #endif
  271. if (do_pledge_violation || do_all_crash_types) {
  272. any_failures |= !Crash("Violate pledge()'d promises", [] {
  273. if (pledge("", nullptr) < 0) {
  274. perror("pledge");
  275. return Crash::Failure::DidNotCrash;
  276. }
  277. outln("Didn't pledge 'stdio', this should fail!");
  278. return Crash::Failure::DidNotCrash;
  279. }).run(run_type);
  280. }
  281. if (do_failing_assertion || do_all_crash_types) {
  282. any_failures |= !Crash("Perform a failing assertion", [] {
  283. VERIFY(1 == 2);
  284. return Crash::Failure::DidNotCrash;
  285. }).run(run_type);
  286. }
  287. if (do_deref_null_refptr || do_all_crash_types) {
  288. any_failures |= !Crash("Dereference a null RefPtr", [] {
  289. RefPtr<Core::Object> p;
  290. *p;
  291. return Crash::Failure::DidNotCrash;
  292. }).run(run_type);
  293. }
  294. return any_failures;
  295. }