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. processes().for_each([&](auto& process) {
  56. KResult res = KSuccess;
  57. if (process.pid() == pid())
  58. res = do_killself(signal);
  59. else
  60. res = do_kill(process, signal);
  61. if (res.is_success())
  62. any_succeeded = true;
  63. else
  64. error = res;
  65. });
  66. if (any_succeeded)
  67. return KSuccess;
  68. return error;
  69. }
  70. KResult Process::do_killself(int signal)
  71. {
  72. if (signal == 0)
  73. return KSuccess;
  74. auto current_thread = Thread::current();
  75. if (!current_thread->should_ignore_signal(signal))
  76. current_thread->send_signal(signal, this);
  77. return KSuccess;
  78. }
  79. KResultOr<FlatPtr> Process::sys$kill(pid_t pid_or_pgid, int signal)
  80. {
  81. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
  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. auto peer = Process::from_pid(pid_or_pgid);
  100. if (!peer)
  101. return ESRCH;
  102. return do_kill(*peer, signal);
  103. }
  104. KResultOr<FlatPtr> Process::sys$killpg(pid_t pgrp, int signum)
  105. {
  106. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
  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. }