]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/killall.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 Copyright © 2010 ProFUSION embedded systems
11 #include "alloc-util.h"
12 #include "constants.h"
13 #include "dirent-util.h"
14 #include "errno-util.h"
16 #include "format-util.h"
17 #include "initrd-util.h"
19 #include "parse-util.h"
20 #include "process-util.h"
22 #include "stdio-util.h"
23 #include "string-util.h"
24 #include "terminal-util.h"
26 static bool argv_has_at(pid_t pid
) {
27 _cleanup_fclose_
FILE *f
= NULL
;
31 p
= procfs_file_alloca(pid
, "cmdline");
34 log_debug_errno(errno
, "Failed to open %s, ignoring: %m", p
);
35 return true; /* not really, but has the desired effect */
38 /* Try to read the first character of the command line. If the cmdline is empty (which might be the case for
39 * kernel threads but potentially also other stuff), this line won't do anything, but we don't care much, as
40 * actual kernel threads are already filtered out above. */
41 (void) fread(&c
, 1, 1, f
);
43 /* Processes with argv[0][0] = '@' we ignore from the killing spree.
45 * https://systemd.io/ROOT_STORAGE_DAEMONS */
49 static bool is_survivor_cgroup(const PidRef
*pid
) {
50 _cleanup_free_
char *cgroup_path
= NULL
;
53 assert(pidref_is_set(pid
));
55 r
= cg_pidref_get_path(/* root= */ NULL
, pid
, &cgroup_path
);
57 log_warning_errno(r
, "Failed to get cgroup path of process " PID_FMT
", ignoring: %m", pid
->pid
);
61 r
= cg_get_xattr_bool(cgroup_path
, "user.survive_final_kill_signal");
62 /* user xattr support was added to kernel v5.7, try with the trusted namespace as a fallback */
63 if (ERRNO_IS_NEG_XATTR_ABSENT(r
))
64 r
= cg_get_xattr_bool(cgroup_path
, "trusted.survive_final_kill_signal");
65 if (r
< 0 && !ERRNO_IS_NEG_XATTR_ABSENT(r
))
67 "Failed to get survive_final_kill_signal xattr of %s, ignoring: %m",
73 static bool ignore_proc(const PidRef
*pid
, bool warn_rootfs
) {
77 assert(pidref_is_set(pid
));
79 /* We are PID 1, let's not commit suicide */
83 /* Ignore kernel threads */
84 r
= pidref_is_kernel_thread(pid
);
86 return true; /* also ignore processes where we can't determine this */
88 /* Ignore processes that are part of a cgroup marked with the user.survive_final_kill_signal xattr */
89 if (is_survivor_cgroup(pid
))
92 r
= pidref_get_uid(pid
, &uid
);
94 return true; /* not really, but better safe than sorry */
96 /* Non-root processes otherwise are always subject to be killed */
100 if (!argv_has_at(pid
->pid
))
104 pid_from_same_root_fs(pid
->pid
) > 0) {
106 _cleanup_free_
char *comm
= NULL
;
108 (void) pidref_get_comm(pid
, &comm
);
110 log_notice("Process " PID_FMT
" (%s) has been marked to be excluded from killing. It is "
111 "running from the root file system, and thus likely to block re-mounting of the "
112 "root file system to read-only. Please consider moving it into an initrd file "
113 "system instead.", pid
->pid
, strna(comm
));
119 static void log_children_not_yet_killed(Set
*pids
) {
120 _cleanup_free_
char *lst_child
= NULL
;
124 SET_FOREACH(p
, pids
) {
125 _cleanup_free_
char *s
= NULL
;
127 if (pid_get_comm(PTR_TO_PID(p
), &s
) >= 0)
128 r
= strextendf_with_separator(&lst_child
, ", ", PID_FMT
" (%s)", PTR_TO_PID(p
), s
);
130 r
= strextendf_with_separator(&lst_child
, ", ", PID_FMT
, PTR_TO_PID(p
));
132 return (void) log_oom_warning();
135 if (isempty(lst_child
))
138 log_warning("Waiting for process: %s", lst_child
);
141 static int wait_for_children(Set
*pids
, sigset_t
*mask
, usec_t timeout
) {
142 usec_t until
, date_log_child
, n
;
146 /* Return the number of children remaining in the pids set: That correspond to the number
147 * of processes still "alive" after the timeout */
149 if (set_isempty(pids
))
152 n
= now(CLOCK_MONOTONIC
);
153 until
= usec_add(n
, timeout
);
154 date_log_child
= usec_add(n
, 10u * USEC_PER_SEC
);
155 if (date_log_child
> until
)
156 date_log_child
= usec_add(n
, timeout
/ 2u);
163 /* First, let the kernel inform us about killed
164 * children. Most processes will probably be our
165 * children, but some are not (might be our
166 * grandchildren instead...). */
170 pid
= waitpid(-1, NULL
, WNOHANG
);
177 return log_error_errno(errno
, "waitpid() failed: %m");
180 (void) set_remove(pids
, PID_TO_PTR(pid
));
183 /* Now explicitly check who might be remaining, who
184 * might not be our child. */
185 SET_FOREACH(p
, pids
) {
187 /* kill(pid, 0) sends no signal, but it tells
188 * us whether the process still exists. */
189 if (kill(PTR_TO_PID(p
), 0) == 0)
198 if (set_isempty(pids
))
201 n
= now(CLOCK_MONOTONIC
);
202 if (date_log_child
> 0 && n
>= date_log_child
) {
203 log_children_not_yet_killed(pids
);
204 /* Log the children not yet killed only once */
209 return set_size(pids
);
211 if (date_log_child
> 0)
212 timespec_store(&ts
, MIN(until
- n
, date_log_child
- n
));
214 timespec_store(&ts
, until
- n
);
216 k
= sigtimedwait(mask
, NULL
, &ts
);
219 if (k
< 0 && errno
!= EAGAIN
)
220 return log_error_errno(errno
, "sigtimedwait() failed: %m");
223 log_warning("sigtimedwait() returned unexpected signal.");
228 static int killall(int sig
, Set
*pids
, bool send_sighup
) {
229 _cleanup_closedir_
DIR *dir
= NULL
;
232 /* Send the specified signal to all remaining processes, if not excluded by ignore_proc().
233 * Returns the number of processes to which the specified signal was sent */
235 r
= proc_dir_open(&dir
);
237 return log_warning_errno(r
, "Failed to open /proc/: %m");
240 _cleanup_(pidref_done
) PidRef pidref
= PIDREF_NULL
;
242 r
= proc_dir_read_pidref(dir
, &pidref
);
244 return log_warning_errno(r
, "Failed to enumerate /proc/: %m");
248 if (ignore_proc(&pidref
, sig
== SIGKILL
&& !in_initrd()))
251 if (sig
== SIGKILL
) {
252 _cleanup_free_
char *s
= NULL
;
254 (void) pidref_get_comm(&pidref
, &s
);
255 log_notice("Sending SIGKILL to PID "PID_FMT
" (%s).", pidref
.pid
, strna(s
));
258 r
= pidref_kill(&pidref
, sig
);
261 log_warning_errno(errno
, "Could not kill " PID_FMT
", ignoring: %m", pidref
.pid
);
265 r
= set_put(pids
, PID_TO_PTR(pidref
.pid
));
267 (void) log_oom_warning();
272 /* Optionally, also send a SIGHUP signal, but only if the process has a controlling
273 * tty. This is useful to allow handling of shells which ignore SIGTERM but react to
274 * SIGHUP. We do not send this to processes that have no controlling TTY since we
275 * don't want to trigger reloads of daemon processes. Also we make sure to only send
276 * this after SIGTERM so that SIGTERM is always first in the queue. */
278 if (get_ctty_devnr(pidref
.pid
, NULL
) >= 0)
279 /* it's OK if the process is gone, just ignore the result */
280 (void) pidref_kill(&pidref
, SIGHUP
);
287 int broadcast_signal(int sig
, bool wait_for_exit
, bool send_sighup
, usec_t timeout
) {
289 sigset_t mask
, oldmask
;
290 _cleanup_set_free_ Set
*pids
= NULL
;
292 /* Send the specified signal to all remaining processes, if not excluded by ignore_proc().
294 * - The number of processes still "alive" after the timeout (that should have been killed)
295 * if the function needs to wait for the end of the processes (wait_for_exit).
296 * - Otherwise, the number of processes to which the specified signal was sent */
299 pids
= set_new(NULL
);
301 assert_se(sigemptyset(&mask
) == 0);
302 assert_se(sigaddset(&mask
, SIGCHLD
) == 0);
303 assert_se(sigprocmask(SIG_BLOCK
, &mask
, &oldmask
) == 0);
305 if (kill(-1, SIGSTOP
) < 0 && errno
!= ESRCH
)
306 log_warning_errno(errno
, "kill(-1, SIGSTOP) failed: %m");
308 n_children_left
= killall(sig
, pids
, send_sighup
);
310 if (kill(-1, SIGCONT
) < 0 && errno
!= ESRCH
)
311 log_warning_errno(errno
, "kill(-1, SIGCONT) failed: %m");
313 if (wait_for_exit
&& n_children_left
> 0)
314 n_children_left
= wait_for_children(pids
, &mask
, timeout
);
316 assert_se(sigprocmask(SIG_SETMASK
, &oldmask
, NULL
) == 0);
318 return n_children_left
;