kill.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <Kernel/Arch/x86/InterruptDisabler.h>
  7. #include <Kernel/Process.h>
  8. namespace Kernel {
  9. KResult Process::do_kill(Process& process, int signal)
  10. {
  11. // FIXME: Allow sending SIGCONT to everyone in the process group.
  12. // FIXME: Should setuid processes have some special treatment here?
  13. if (!is_superuser() && euid() != process.uid() && uid() != process.uid())
  14. return EPERM;
  15. if (process.is_kernel_process()) {
  16. dbgln("Attempted to send signal {} to kernel process {} ({})", signal, process.name(), process.pid());
  17. return EPERM;
  18. }
  19. if (signal != 0)
  20. return process.send_signal(signal, this);
  21. return KSuccess;
  22. }
  23. KResult Process::do_killpg(ProcessGroupID pgrp, int signal)
  24. {
  25. InterruptDisabler disabler;
  26. VERIFY(pgrp >= 0);
  27. // Send the signal to all processes in the given group.
  28. if (pgrp == 0) {
  29. // Send the signal to our own pgrp.
  30. pgrp = pgid();
  31. }
  32. bool group_was_empty = true;
  33. bool any_succeeded = false;
  34. KResult error = KSuccess;
  35. Process::for_each_in_pgrp(pgrp, [&](auto& process) {
  36. group_was_empty = false;
  37. KResult res = do_kill(process, signal);
  38. if (res.is_success())
  39. any_succeeded = true;
  40. else
  41. error = res;
  42. });
  43. if (group_was_empty)
  44. return ESRCH;
  45. if (any_succeeded)
  46. return KSuccess;
  47. return error;
  48. }
  49. KResult Process::do_killall(int signal)
  50. {
  51. InterruptDisabler disabler;
  52. bool any_succeeded = false;
  53. KResult error = KSuccess;
  54. // Send the signal to all processes we have access to for.
  55. ScopedSpinLock lock(g_processes_lock);
  56. for (auto& process : *g_processes) {
  57. KResult res = KSuccess;
  58. if (process.pid() == pid())
  59. res = do_killself(signal);
  60. else
  61. res = do_kill(process, signal);
  62. if (res.is_success())
  63. any_succeeded = true;
  64. else
  65. error = res;
  66. }
  67. if (any_succeeded)
  68. return KSuccess;
  69. return error;
  70. }
  71. KResult Process::do_killself(int signal)
  72. {
  73. if (signal == 0)
  74. return KSuccess;
  75. auto current_thread = Thread::current();
  76. if (!current_thread->should_ignore_signal(signal))
  77. current_thread->send_signal(signal, this);
  78. return KSuccess;
  79. }
  80. KResultOr<FlatPtr> Process::sys$kill(pid_t pid_or_pgid, int signal)
  81. {
  82. if (pid_or_pgid == pid().value())
  83. REQUIRE_PROMISE(stdio);
  84. else
  85. REQUIRE_PROMISE(proc);
  86. if (signal < 0 || signal >= 32)
  87. return EINVAL;
  88. if (pid_or_pgid < -1) {
  89. if (pid_or_pgid == NumericLimits<i32>::min())
  90. return EINVAL;
  91. return do_killpg(-pid_or_pgid, signal);
  92. }
  93. if (pid_or_pgid == -1)
  94. return do_killall(signal);
  95. if (pid_or_pgid == pid().value()) {
  96. return do_killself(signal);
  97. }
  98. VERIFY(pid_or_pgid >= 0);
  99. ScopedSpinLock lock(g_processes_lock);
  100. auto peer = Process::from_pid(pid_or_pgid);
  101. if (!peer)
  102. return ESRCH;
  103. return do_kill(*peer, signal);
  104. }
  105. KResultOr<FlatPtr> Process::sys$killpg(pid_t pgrp, int signum)
  106. {
  107. REQUIRE_PROMISE(proc);
  108. if (signum < 1 || signum >= 32)
  109. return EINVAL;
  110. if (pgrp < 0)
  111. return EINVAL;
  112. return do_killpg(pgrp, signum);
  113. }
  114. }