]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/killall.c
execute: split check if we might touch a tty out of exec_context_may_touch_console()
[thirdparty/systemd.git] / src / core / killall.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
bd3fa1d2 2/***
96b2fb93 3 Copyright © 2010 ProFUSION embedded systems
bd3fa1d2
LP
4***/
5
bd3fa1d2 6#include <errno.h>
07630cea
LP
7#include <signal.h>
8#include <sys/wait.h>
aaf7eb81 9#include <unistd.h>
bd3fa1d2 10
b5efdb8a 11#include "alloc-util.h"
d4506129 12#include "def.h"
8fb3f009 13#include "dirent-util.h"
3ffd4af2 14#include "fd-util.h"
f97b34a6 15#include "format-util.h"
3ffd4af2 16#include "killall.h"
6bedfcbb 17#include "parse-util.h"
0b452006 18#include "process-util.h"
07630cea
LP
19#include "set.h"
20#include "string-util.h"
288a74cc 21#include "terminal-util.h"
07630cea 22#include "util.h"
bd3fa1d2 23
1359fffa 24static bool ignore_proc(pid_t pid, bool warn_rootfs) {
31885cd5 25 _cleanup_fclose_ FILE *f = NULL;
b68fa010 26 const char *p;
e45154c7 27 char c = 0;
bd3fa1d2
LP
28 uid_t uid;
29 int r;
30
31 /* We are PID 1, let's not commit suicide */
20ca2d10 32 if (pid <= 1)
bd3fa1d2
LP
33 return true;
34
e45154c7
LP
35 /* Ignore kernel threads */
36 r = is_kernel_thread(pid);
37 if (r != 0)
38 return true; /* also ignore processes where we can't determine this */
39
bd3fa1d2
LP
40 r = get_process_uid(pid, &uid);
41 if (r < 0)
42 return true; /* not really, but better safe than sorry */
43
44 /* Non-root processes otherwise are always subject to be killed */
45 if (uid != 0)
46 return false;
47
5841bd80
ZJS
48 p = procfs_file_alloca(pid, "cmdline");
49 f = fopen(p, "re");
bd3fa1d2
LP
50 if (!f)
51 return true; /* not really, but has the desired effect */
52
e45154c7
LP
53 /* Try to read the first character of the command line. If the cmdline is empty (which might be the case for
54 * kernel threads but potentially also other stuff), this line won't do anything, but we don't care much, as
55 * actual kernel threads are already filtered out above. */
56 (void) fread(&c, 1, 1, f);
bd3fa1d2 57
9e615117 58 /* Processes with argv[0][0] = '@' we ignore from the killing spree.
bd3fa1d2
LP
59 *
60 * http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons */
9e615117
ZJS
61 if (c != '@')
62 return false;
63
64 if (warn_rootfs &&
65 pid_from_same_root_fs(pid) == 0) {
1359fffa 66
9e615117 67 _cleanup_free_ char *comm = NULL;
1359fffa 68
d3a94b3e 69 (void) get_process_comm(pid, &comm);
1359fffa 70
9e615117
ZJS
71 log_notice("Process " PID_FMT " (%s) has been marked to be excluded from killing. It is "
72 "running from the root file system, and thus likely to block re-mounting of the "
73 "root file system to read-only. Please consider moving it into an initrd file "
74 "system instead.", pid, strna(comm));
75 }
bd3fa1d2 76
9e615117 77 return true;
bd3fa1d2
LP
78}
79
e73c54b8 80static void wait_for_children(Set *pids, sigset_t *mask, usec_t timeout) {
bd3fa1d2
LP
81 usec_t until;
82
83 assert(mask);
84
aaf7eb81
LP
85 if (set_isempty(pids))
86 return;
87
e73c54b8 88 until = now(CLOCK_MONOTONIC) + timeout;
bd3fa1d2
LP
89 for (;;) {
90 struct timespec ts;
91 int k;
92 usec_t n;
aaf7eb81
LP
93 void *p;
94 Iterator i;
bd3fa1d2 95
aaf7eb81
LP
96 /* First, let the kernel inform us about killed
97 * children. Most processes will probably be our
98 * children, but some are not (might be our
99 * grandchildren instead...). */
bd3fa1d2 100 for (;;) {
aaf7eb81 101 pid_t pid;
bd3fa1d2 102
aaf7eb81 103 pid = waitpid(-1, NULL, WNOHANG);
bd3fa1d2
LP
104 if (pid == 0)
105 break;
aaf7eb81
LP
106 if (pid < 0) {
107 if (errno == ECHILD)
108 break;
bd3fa1d2 109
56f64d95 110 log_error_errno(errno, "waitpid() failed: %m");
bd3fa1d2 111 return;
aaf7eb81
LP
112 }
113
fea72cc0 114 (void) set_remove(pids, PID_TO_PTR(pid));
aaf7eb81 115 }
bd3fa1d2 116
aaf7eb81
LP
117 /* Now explicitly check who might be remaining, who
118 * might not be our child. */
119 SET_FOREACH(p, pids, i) {
120
3448a969
AJ
121 /* kill(pid, 0) sends no signal, but it tells
122 * us whether the process still exists. */
123 if (kill(PTR_TO_PID(p), 0) == 0)
aaf7eb81
LP
124 continue;
125
126 if (errno != ESRCH)
127 continue;
128
129 set_remove(pids, p);
bd3fa1d2
LP
130 }
131
aaf7eb81
LP
132 if (set_isempty(pids))
133 return;
134
bd3fa1d2
LP
135 n = now(CLOCK_MONOTONIC);
136 if (n >= until)
137 return;
138
139 timespec_store(&ts, until - n);
aaf7eb81
LP
140 k = sigtimedwait(mask, NULL, &ts);
141 if (k != SIGCHLD) {
bd3fa1d2
LP
142
143 if (k < 0 && errno != EAGAIN) {
56f64d95 144 log_error_errno(errno, "sigtimedwait() failed: %m");
bd3fa1d2
LP
145 return;
146 }
147
148 if (k >= 0)
149 log_warning("sigtimedwait() returned unexpected signal.");
150 }
151 }
152}
153
0bee65f0 154static int killall(int sig, Set *pids, bool send_sighup) {
aaf7eb81 155 _cleanup_closedir_ DIR *dir = NULL;
bd3fa1d2 156 struct dirent *d;
bd3fa1d2
LP
157
158 dir = opendir("/proc");
159 if (!dir)
160 return -errno;
161
8fb3f009 162 FOREACH_DIRENT_ALL(d, dir, break) {
bd3fa1d2 163 pid_t pid;
60053efb 164 int r;
bd3fa1d2 165
ec2ce0c5 166 if (!IN_SET(d->d_type, DT_DIR, DT_UNKNOWN))
bd3fa1d2
LP
167 continue;
168
169 if (parse_pid(d->d_name, &pid) < 0)
170 continue;
171
1359fffa 172 if (ignore_proc(pid, sig == SIGKILL && !in_initrd()))
bd3fa1d2
LP
173 continue;
174
df758e98 175 if (sig == SIGKILL) {
3e09eb5c 176 _cleanup_free_ char *s = NULL;
df758e98
KS
177
178 get_process_comm(pid, &s);
ccd06097 179 log_notice("Sending SIGKILL to PID "PID_FMT" (%s).", pid, strna(s));
df758e98
KS
180 }
181
aaf7eb81 182 if (kill(pid, sig) >= 0) {
60053efb 183 if (pids) {
fea72cc0 184 r = set_put(pids, PID_TO_PTR(pid));
60053efb
TA
185 if (r < 0)
186 log_oom();
187 }
aaf7eb81 188 } else if (errno != ENOENT)
56f64d95 189 log_warning_errno(errno, "Could not kill %d: %m", pid);
0bee65f0
LP
190
191 if (send_sighup) {
192 /* Optionally, also send a SIGHUP signal, but
193 only if the process has a controlling
194 tty. This is useful to allow handling of
195 shells which ignore SIGTERM but react to
196 SIGHUP. We do not send this to processes that
197 have no controlling TTY since we don't want to
198 trigger reloads of daemon processes. Also we
199 make sure to only send this after SIGTERM so
200 that SIGTERM is always first in the queue. */
201
0bee65f0 202 if (get_ctty_devnr(pid, NULL) >= 0)
5c5d9f26
ZJS
203 /* it's OK if the process is gone, just ignore the result */
204 (void) kill(pid, SIGHUP);
0bee65f0 205 }
bd3fa1d2
LP
206 }
207
aaf7eb81 208 return set_size(pids);
bd3fa1d2
LP
209}
210
e73c54b8 211void broadcast_signal(int sig, bool wait_for_exit, bool send_sighup, usec_t timeout) {
bd3fa1d2 212 sigset_t mask, oldmask;
e1d75803 213 _cleanup_set_free_ Set *pids = NULL;
aaf7eb81
LP
214
215 if (wait_for_exit)
d5099efc 216 pids = set_new(NULL);
bd3fa1d2
LP
217
218 assert_se(sigemptyset(&mask) == 0);
219 assert_se(sigaddset(&mask, SIGCHLD) == 0);
220 assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) == 0);
221
222 if (kill(-1, SIGSTOP) < 0 && errno != ESRCH)
56f64d95 223 log_warning_errno(errno, "kill(-1, SIGSTOP) failed: %m");
bd3fa1d2 224
0bee65f0 225 killall(sig, pids, send_sighup);
bd3fa1d2
LP
226
227 if (kill(-1, SIGCONT) < 0 && errno != ESRCH)
56f64d95 228 log_warning_errno(errno, "kill(-1, SIGCONT) failed: %m");
bd3fa1d2 229
3d141780 230 if (wait_for_exit)
e73c54b8 231 wait_for_children(pids, &mask, timeout);
aaf7eb81
LP
232
233 assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) == 0);
bd3fa1d2 234}