]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/shutdown.c
shutdown: move shutdown to core since it replaces PID 1
[thirdparty/systemd.git] / src / core / shutdown.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 ProFUSION embedded systems
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <sys/mman.h>
23 #include <sys/types.h>
24 #include <sys/reboot.h>
25 #include <linux/reboot.h>
26 #include <sys/wait.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <sys/mount.h>
30 #include <sys/syscall.h>
31 #include <fcntl.h>
32 #include <dirent.h>
33 #include <errno.h>
34 #include <unistd.h>
35 #include <signal.h>
36 #include <stdbool.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 #include "missing.h"
41 #include "log.h"
42 #include "umount.h"
43 #include "util.h"
44 #include "mkdir.h"
45 #include "virt.h"
46 #include "watchdog.h"
47
48 #define TIMEOUT_USEC (5 * USEC_PER_SEC)
49 #define FINALIZE_ATTEMPTS 50
50
51 static bool ignore_proc(pid_t pid) {
52 char buf[PATH_MAX];
53 FILE *f;
54 char c;
55 size_t count;
56 uid_t uid;
57 int r;
58
59 /* We are PID 1, let's not commit suicide */
60 if (pid == 1)
61 return true;
62
63 r = get_process_uid(pid, &uid);
64 if (r < 0)
65 return true; /* not really, but better safe than sorry */
66
67 /* Non-root processes otherwise are always subject to be killed */
68 if (uid != 0)
69 return false;
70
71 snprintf(buf, sizeof(buf), "/proc/%lu/cmdline", (unsigned long) pid);
72 char_array_0(buf);
73
74 f = fopen(buf, "re");
75 if (!f)
76 return true; /* not really, but has the desired effect */
77
78 count = fread(&c, 1, 1, f);
79 fclose(f);
80
81 /* Kernel threads have an empty cmdline */
82 if (count <= 0)
83 return true;
84
85 /* Processes with argv[0][0] = '@' we ignore from the killing
86 * spree.
87 *
88 * http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons */
89 if (count == 1 && c == '@')
90 return true;
91
92 return false;
93 }
94
95 static int killall(int sign) {
96 DIR *dir;
97 struct dirent *d;
98 unsigned int n_processes = 0;
99
100 dir = opendir("/proc");
101 if (!dir)
102 return -errno;
103
104 while ((d = readdir(dir))) {
105 pid_t pid;
106
107 if (parse_pid(d->d_name, &pid) < 0)
108 continue;
109
110 if (ignore_proc(pid))
111 continue;
112
113 if (kill(pid, sign) == 0)
114 n_processes++;
115 else
116 log_warning("Could not kill %d: %m", pid);
117 }
118
119 closedir(dir);
120
121 return n_processes;
122 }
123
124 static void wait_for_children(int n_processes, sigset_t *mask) {
125 usec_t until;
126
127 assert(mask);
128
129 until = now(CLOCK_MONOTONIC) + TIMEOUT_USEC;
130 for (;;) {
131 struct timespec ts;
132 int k;
133 usec_t n;
134
135 for (;;) {
136 pid_t pid = waitpid(-1, NULL, WNOHANG);
137
138 if (pid == 0)
139 break;
140
141 if (pid < 0 && errno == ECHILD)
142 return;
143
144 if (n_processes > 0)
145 if (--n_processes == 0)
146 return;
147 }
148
149 n = now(CLOCK_MONOTONIC);
150 if (n >= until)
151 return;
152
153 timespec_store(&ts, until - n);
154
155 if ((k = sigtimedwait(mask, NULL, &ts)) != SIGCHLD) {
156
157 if (k < 0 && errno != EAGAIN) {
158 log_error("sigtimedwait() failed: %m");
159 return;
160 }
161
162 if (k >= 0)
163 log_warning("sigtimedwait() returned unexpected signal.");
164 }
165 }
166 }
167
168 static void send_signal(int sign) {
169 sigset_t mask, oldmask;
170 int n_processes;
171
172 assert_se(sigemptyset(&mask) == 0);
173 assert_se(sigaddset(&mask, SIGCHLD) == 0);
174 assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) == 0);
175
176 if (kill(-1, SIGSTOP) < 0 && errno != ESRCH)
177 log_warning("kill(-1, SIGSTOP) failed: %m");
178
179 n_processes = killall(sign);
180
181 if (kill(-1, SIGCONT) < 0 && errno != ESRCH)
182 log_warning("kill(-1, SIGCONT) failed: %m");
183
184 if (n_processes <= 0)
185 goto finish;
186
187 wait_for_children(n_processes, &mask);
188
189 finish:
190 sigprocmask(SIG_SETMASK, &oldmask, NULL);
191 }
192
193 static void ultimate_send_signal(int sign) {
194 sigset_t mask, oldmask;
195 int r;
196
197 assert_se(sigemptyset(&mask) == 0);
198 assert_se(sigaddset(&mask, SIGCHLD) == 0);
199 assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) == 0);
200
201 if (kill(-1, SIGSTOP) < 0 && errno != ESRCH)
202 log_warning("kill(-1, SIGSTOP) failed: %m");
203
204 r = kill(-1, sign);
205 if (r < 0 && errno != ESRCH)
206 log_warning("kill(-1, %s) failed: %m", signal_to_string(sign));
207
208 if (kill(-1, SIGCONT) < 0 && errno != ESRCH)
209 log_warning("kill(-1, SIGCONT) failed: %m");
210
211 if (r < 0)
212 goto finish;
213
214 wait_for_children(0, &mask);
215
216 finish:
217 sigprocmask(SIG_SETMASK, &oldmask, NULL);
218 }
219
220 static int prepare_new_root(void) {
221 static const char dirs[] =
222 "/run/initramfs/oldroot\0"
223 "/run/initramfs/proc\0"
224 "/run/initramfs/sys\0"
225 "/run/initramfs/dev\0"
226 "/run/initramfs/run\0";
227
228 const char *dir;
229
230 if (mount("/run/initramfs", "/run/initramfs", NULL, MS_BIND, NULL) < 0) {
231 log_error("Failed to mount bind /run/initramfs on /run/initramfs: %m");
232 return -errno;
233 }
234
235 if (mount(NULL, "/run/initramfs", NULL, MS_PRIVATE, NULL) < 0) {
236 log_error("Failed to make /run/initramfs private mount: %m");
237 return -errno;
238 }
239
240 NULSTR_FOREACH(dir, dirs)
241 if (mkdir_p(dir, 0755) < 0 && errno != EEXIST) {
242 log_error("Failed to mkdir %s: %m", dir);
243 return -errno;
244 }
245
246 if (mount("/sys", "/run/initramfs/sys", NULL, MS_BIND, NULL) < 0) {
247 log_error("Failed to mount bind /sys on /run/initramfs/sys: %m");
248 return -errno;
249 }
250
251 if (mount("/proc", "/run/initramfs/proc", NULL, MS_BIND, NULL) < 0) {
252 log_error("Failed to mount bind /proc on /run/initramfs/proc: %m");
253 return -errno;
254 }
255
256 if (mount("/dev", "/run/initramfs/dev", NULL, MS_BIND, NULL) < 0) {
257 log_error("Failed to mount bind /dev on /run/initramfs/dev: %m");
258 return -errno;
259 }
260
261 if (mount("/run", "/run/initramfs/run", NULL, MS_BIND, NULL) < 0) {
262 log_error("Failed to mount bind /run on /run/initramfs/run: %m");
263 return -errno;
264 }
265
266 return 0;
267 }
268
269 static int pivot_to_new_root(void) {
270 int fd;
271
272 chdir("/run/initramfs");
273
274 /*
275 In case some evil process made "/" MS_SHARED
276 It works for pivot_root, but the ref count for the root device
277 is not decreasing :-/
278 */
279 if (mount(NULL, "/", NULL, MS_PRIVATE, NULL) < 0) {
280 log_error("Failed to make \"/\" private mount %m");
281 return -errno;
282 }
283
284 if (pivot_root(".", "oldroot") < 0) {
285 log_error("pivot failed: %m");
286 /* only chroot if pivot root succeded */
287 return -errno;
288 }
289
290 chroot(".");
291 log_info("Successfully changed into root pivot.");
292
293 fd = open("/dev/console", O_RDWR);
294 if (fd < 0)
295 log_error("Failed to open /dev/console: %m");
296 else {
297 make_stdio(fd);
298
299 /* Initialize the controlling terminal */
300 setsid();
301 ioctl(STDIN_FILENO, TIOCSCTTY, NULL);
302 }
303
304 return 0;
305 }
306
307 int main(int argc, char *argv[]) {
308 int cmd, r;
309 unsigned retries;
310 bool need_umount = true, need_swapoff = true, need_loop_detach = true, need_dm_detach = true;
311 bool killed_everbody = false, in_container, use_watchdog = false;
312
313 log_parse_environment();
314 log_set_target(LOG_TARGET_CONSOLE); /* syslog will die if not gone yet */
315 log_open();
316
317 umask(0022);
318
319 if (getpid() != 1) {
320 log_error("Not executed by init (pid 1).");
321 r = -EPERM;
322 goto error;
323 }
324
325 if (argc != 2) {
326 log_error("Invalid number of arguments.");
327 r = -EINVAL;
328 goto error;
329 }
330
331 in_container = detect_container(NULL) > 0;
332
333 if (streq(argv[1], "reboot"))
334 cmd = RB_AUTOBOOT;
335 else if (streq(argv[1], "poweroff"))
336 cmd = RB_POWER_OFF;
337 else if (streq(argv[1], "halt"))
338 cmd = RB_HALT_SYSTEM;
339 else if (streq(argv[1], "kexec"))
340 cmd = LINUX_REBOOT_CMD_KEXEC;
341 else {
342 log_error("Unknown action '%s'.", argv[1]);
343 r = -EINVAL;
344 goto error;
345 }
346
347 use_watchdog = !!getenv("WATCHDOG_USEC");
348
349 /* lock us into memory */
350 if (mlockall(MCL_CURRENT|MCL_FUTURE) != 0)
351 log_warning("Cannot lock process memory: %m");
352
353 log_info("Sending SIGTERM to remaining processes...");
354 send_signal(SIGTERM);
355
356 log_info("Sending SIGKILL to remaining processes...");
357 send_signal(SIGKILL);
358
359 if (in_container)
360 need_swapoff = false;
361
362 /* Unmount all mountpoints, swaps, and loopback devices */
363 for (retries = 0; retries < FINALIZE_ATTEMPTS; retries++) {
364 bool changed = false;
365
366 if (use_watchdog)
367 watchdog_ping();
368
369 if (need_umount) {
370 log_info("Unmounting file systems.");
371 r = umount_all(&changed);
372 if (r == 0)
373 need_umount = false;
374 else if (r > 0)
375 log_info("Not all file systems unmounted, %d left.", r);
376 else
377 log_error("Failed to unmount file systems: %s", strerror(-r));
378 }
379
380 if (need_swapoff) {
381 log_info("Disabling swaps.");
382 r = swapoff_all(&changed);
383 if (r == 0)
384 need_swapoff = false;
385 else if (r > 0)
386 log_info("Not all swaps are turned off, %d left.", r);
387 else
388 log_error("Failed to turn off swaps: %s", strerror(-r));
389 }
390
391 if (need_loop_detach) {
392 log_info("Detaching loop devices.");
393 r = loopback_detach_all(&changed);
394 if (r == 0)
395 need_loop_detach = false;
396 else if (r > 0)
397 log_info("Not all loop devices detached, %d left.", r);
398 else
399 log_error("Failed to detach loop devices: %s", strerror(-r));
400 }
401
402 if (need_dm_detach) {
403 log_info("Detaching DM devices.");
404 r = dm_detach_all(&changed);
405 if (r == 0)
406 need_dm_detach = false;
407 else if (r > 0)
408 log_warning("Not all DM devices detached, %d left.", r);
409 else
410 log_error("Failed to detach DM devices: %s", strerror(-r));
411 }
412
413 if (!need_umount && !need_swapoff && !need_loop_detach && !need_dm_detach) {
414 if (retries > 0)
415 log_info("All filesystems, swaps, loop devices, DM devices detached.");
416 /* Yay, done */
417 break;
418 }
419
420 /* If in this iteration we didn't manage to
421 * unmount/deactivate anything, we either kill more
422 * processes, or simply give up */
423 if (!changed) {
424
425 if (killed_everbody) {
426 /* Hmm, we already killed everybody,
427 * let's just give up */
428 log_error("Cannot finalize remaining file systems and devices, giving up.");
429 break;
430 }
431
432 log_warning("Cannot finalize remaining file systems and devices, trying to kill remaining processes.");
433 ultimate_send_signal(SIGTERM);
434 ultimate_send_signal(SIGKILL);
435 killed_everbody = true;
436 }
437
438 log_debug("Couldn't finalize remaining file systems and devices after %u retries, trying again.", retries+1);
439 }
440
441 if (retries >= FINALIZE_ATTEMPTS)
442 log_error("Too many iterations, giving up.");
443
444 execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, NULL);
445
446 /* If we are in a container, just exit, this will kill our
447 * container for good. */
448 if (in_container) {
449 log_error("Exiting container.");
450 exit(0);
451 }
452
453 if (access("/run/initramfs/shutdown", X_OK) == 0) {
454
455 if (prepare_new_root() >= 0 &&
456 pivot_to_new_root() >= 0) {
457 execv("/shutdown", argv);
458 log_error("Failed to execute shutdown binary: %m");
459 }
460 }
461
462 sync();
463
464 if (cmd == LINUX_REBOOT_CMD_KEXEC) {
465 /* We cheat and exec kexec to avoid doing all its work */
466 pid_t pid = fork();
467
468 if (pid < 0)
469 log_error("Could not fork: %m. Falling back to normal reboot.");
470 else if (pid > 0) {
471 wait_for_terminate_and_warn("kexec", pid);
472 log_warning("kexec failed. Falling back to normal reboot.");
473 } else {
474 /* Child */
475 const char *args[3] = { "/sbin/kexec", "-e", NULL };
476 execv(args[0], (char * const *) args);
477 return EXIT_FAILURE;
478 }
479
480 cmd = RB_AUTOBOOT;
481 }
482
483 reboot(cmd);
484 log_error("Failed to invoke reboot(): %m");
485 r = -errno;
486
487 error:
488 log_error("Critical error while doing system shutdown: %s", strerror(-r));
489
490 freeze();
491 return EXIT_FAILURE;
492 }