Syscall.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /*
  2. * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2022, the SerenityOS developers.
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <Kernel/API/Syscall.h>
  8. #include <Kernel/Arch/RegisterState.h>
  9. #include <Kernel/Arch/TrapFrame.h>
  10. #include <Kernel/Memory/MemoryManager.h>
  11. #include <Kernel/Panic.h>
  12. #include <Kernel/PerformanceManager.h>
  13. #include <Kernel/Sections.h>
  14. #include <Kernel/Tasks/Process.h>
  15. #include <Kernel/Tasks/Scheduler.h>
  16. #include <Kernel/Tasks/ThreadTracer.h>
  17. namespace Kernel {
  18. namespace Syscall {
  19. using Handler = auto(Process::*)(FlatPtr, FlatPtr, FlatPtr, FlatPtr) -> ErrorOr<FlatPtr>;
  20. using HandlerWithRegisterState = auto(Process::*)(RegisterState&) -> ErrorOr<FlatPtr>;
  21. struct HandlerMetadata {
  22. Handler handler;
  23. NeedsBigProcessLock needs_lock;
  24. };
  25. #define __ENUMERATE_SYSCALL(sys_call, needs_lock) { bit_cast<Handler>(&Process::sys$##sys_call), needs_lock },
  26. static const HandlerMetadata s_syscall_table[] = {
  27. ENUMERATE_SYSCALLS(__ENUMERATE_SYSCALL)
  28. };
  29. #undef __ENUMERATE_SYSCALL
  30. ErrorOr<FlatPtr> handle(RegisterState& regs, FlatPtr function, FlatPtr arg1, FlatPtr arg2, FlatPtr arg3, FlatPtr arg4)
  31. {
  32. VERIFY_INTERRUPTS_ENABLED();
  33. auto* current_thread = Thread::current();
  34. auto& process = current_thread->process();
  35. current_thread->did_syscall();
  36. PerformanceManager::add_syscall_event(*current_thread, regs);
  37. if (function >= Function::__Count) {
  38. dbgln("Unknown syscall {} requested ({:p}, {:p}, {:p}, {:p})", function, arg1, arg2, arg3, arg4);
  39. return ENOSYS;
  40. }
  41. auto const syscall_metadata = s_syscall_table[function];
  42. if (syscall_metadata.handler == nullptr) {
  43. dbgln("Null syscall {} requested, you probably need to rebuild this program!", function);
  44. return ENOSYS;
  45. }
  46. MutexLocker mutex_locker;
  47. auto const needs_big_lock = syscall_metadata.needs_lock == NeedsBigProcessLock::Yes;
  48. if (needs_big_lock) {
  49. mutex_locker.attach_and_lock(process.big_lock());
  50. };
  51. if (function == SC_exit || function == SC_exit_thread) {
  52. // These syscalls need special handling since they never return to the caller.
  53. // In these cases the process big lock will get released on the exit of the thread.
  54. if (auto* tracer = process.tracer(); tracer && tracer->is_tracing_syscalls()) {
  55. regs.set_return_reg(0);
  56. tracer->set_trace_syscalls(false);
  57. process.tracer_trap(*current_thread, regs); // this triggers SIGTRAP and stops the thread!
  58. }
  59. switch (function) {
  60. case SC_exit:
  61. process.sys$exit(arg1);
  62. case SC_exit_thread:
  63. process.sys$exit_thread(arg1, arg2, arg3);
  64. default:
  65. VERIFY_NOT_REACHED();
  66. }
  67. }
  68. ErrorOr<FlatPtr> result { FlatPtr(nullptr) };
  69. if (function == SC_fork || function == SC_sigreturn) {
  70. // These syscalls want the RegisterState& rather than individual parameters.
  71. auto handler = bit_cast<HandlerWithRegisterState>(syscall_metadata.handler);
  72. result = (process.*(handler))(regs);
  73. } else {
  74. result = (process.*(syscall_metadata.handler))(arg1, arg2, arg3, arg4);
  75. }
  76. return result;
  77. }
  78. }
  79. extern "C" NEVER_INLINE void syscall_handler(TrapFrame* trap);
  80. NEVER_INLINE void syscall_handler(TrapFrame* trap)
  81. {
  82. #if ARCH(X86_64)
  83. // Make sure SMAP protection is enabled on syscall entry.
  84. clac();
  85. #elif ARCH(AARCH64)
  86. // FIXME: Implement the security mechanism for aarch64
  87. #else
  88. # error Unknown architecture
  89. #endif
  90. auto& regs = *trap->regs;
  91. auto* current_thread = Thread::current();
  92. VERIFY(current_thread->previous_mode() == ExecutionMode::User);
  93. auto& process = current_thread->process();
  94. if (process.is_dying()) {
  95. // It's possible this thread is just about to make a syscall while another is
  96. // is killing our process.
  97. current_thread->die_if_needed();
  98. return;
  99. }
  100. if (auto* tracer = process.tracer(); tracer && tracer->is_tracing_syscalls()) {
  101. tracer->set_trace_syscalls(false);
  102. process.tracer_trap(*current_thread, regs); // this triggers SIGTRAP and stops the thread!
  103. }
  104. current_thread->yield_if_stopped();
  105. #if ARCH(X86_64)
  106. // Apply a random offset in the range 0-255 to the stack pointer,
  107. // to make kernel stacks a bit less deterministic.
  108. u32 lsw;
  109. u32 msw;
  110. read_tsc(lsw, msw);
  111. auto* ptr = (char*)__builtin_alloca(lsw & 0xff);
  112. asm volatile(""
  113. : "=m"(*ptr));
  114. constexpr FlatPtr iopl_mask = 3u << 12;
  115. FlatPtr flags = regs.flags();
  116. if ((flags & (iopl_mask)) != 0) {
  117. PANIC("Syscall from process with IOPL != 0");
  118. }
  119. #elif ARCH(AARCH64)
  120. // FIXME: Implement the security mechanism for aarch64
  121. #else
  122. # error Unknown architecture
  123. #endif
  124. Memory::MemoryManager::validate_syscall_preconditions(process, regs);
  125. FlatPtr function;
  126. FlatPtr arg1;
  127. FlatPtr arg2;
  128. FlatPtr arg3;
  129. FlatPtr arg4;
  130. regs.capture_syscall_params(function, arg1, arg2, arg3, arg4);
  131. auto result = Syscall::handle(regs, function, arg1, arg2, arg3, arg4);
  132. if (result.is_error()) {
  133. regs.set_return_reg(-result.error().code());
  134. } else {
  135. regs.set_return_reg(result.value());
  136. }
  137. if (auto* tracer = process.tracer(); tracer && tracer->is_tracing_syscalls()) {
  138. tracer->set_trace_syscalls(false);
  139. process.tracer_trap(*current_thread, regs); // this triggers SIGTRAP and stops the thread!
  140. }
  141. current_thread->yield_if_stopped();
  142. current_thread->check_dispatch_pending_signal();
  143. // If the previous mode somehow changed something is seriously messed up...
  144. VERIFY(current_thread->previous_mode() == ExecutionMode::User);
  145. // Check if we're supposed to return to userspace or just die.
  146. current_thread->die_if_needed();
  147. // Crash any processes which have committed a promise violation during syscall handling.
  148. if (result.is_error() && result.error().code() == EPROMISEVIOLATION) {
  149. VERIFY(current_thread->is_promise_violation_pending());
  150. current_thread->set_promise_violation_pending(false);
  151. process.crash(SIGABRT, {});
  152. } else {
  153. VERIFY(!current_thread->is_promise_violation_pending());
  154. }
  155. VERIFY(!g_scheduler_lock.is_locked_by_current_processor());
  156. }
  157. }