chiark / gitweb /
9631f92885d44e816979754c1861a514656b0352
[elogind.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                 need_dm_detach = false;
362         }
363
364         /* Unmount all mountpoints, swaps, and loopback devices */
365         for (retries = 0; retries < FINALIZE_ATTEMPTS; retries++) {
366                 bool changed = false;
367
368                 if (use_watchdog)
369                         watchdog_ping();
370
371                 if (need_umount) {
372                         log_info("Unmounting file systems.");
373                         r = umount_all(&changed);
374                         if (r == 0)
375                                 need_umount = false;
376                         else if (r > 0)
377                                 log_info("Not all file systems unmounted, %d left.", r);
378                         else
379                                 log_error("Failed to unmount file systems: %s", strerror(-r));
380                 }
381
382                 if (need_swapoff) {
383                         log_info("Disabling swaps.");
384                         r = swapoff_all(&changed);
385                         if (r == 0)
386                                 need_swapoff = false;
387                         else if (r > 0)
388                                 log_info("Not all swaps are turned off, %d left.", r);
389                         else
390                                 log_error("Failed to turn off swaps: %s", strerror(-r));
391                 }
392
393                 if (need_loop_detach) {
394                         log_info("Detaching loop devices.");
395                         r = loopback_detach_all(&changed);
396                         if (r == 0)
397                                 need_loop_detach = false;
398                         else if (r > 0)
399                                 log_info("Not all loop devices detached, %d left.", r);
400                         else
401                                 log_error("Failed to detach loop devices: %s", strerror(-r));
402                 }
403
404                 if (need_dm_detach) {
405                         log_info("Detaching DM devices.");
406                         r = dm_detach_all(&changed);
407                         if (r == 0)
408                                 need_dm_detach = false;
409                         else if (r > 0)
410                                 log_warning("Not all DM devices detached, %d left.", r);
411                         else
412                                 log_error("Failed to detach DM devices: %s", strerror(-r));
413                 }
414
415                 if (!need_umount && !need_swapoff && !need_loop_detach && !need_dm_detach) {
416                         if (retries > 0)
417                                 log_info("All filesystems, swaps, loop devices, DM devices detached.");
418                         /* Yay, done */
419                         break;
420                 }
421
422                 /* If in this iteration we didn't manage to
423                  * unmount/deactivate anything, we either kill more
424                  * processes, or simply give up */
425                 if (!changed) {
426
427                         if (killed_everbody) {
428                                 /* Hmm, we already killed everybody,
429                                  * let's just give up */
430                                 log_error("Cannot finalize remaining file systems and devices, giving up.");
431                                 break;
432                         }
433
434                         log_warning("Cannot finalize remaining file systems and devices, trying to kill remaining processes.");
435                         ultimate_send_signal(SIGTERM);
436                         ultimate_send_signal(SIGKILL);
437                         killed_everbody = true;
438                 }
439
440                 log_debug("Couldn't finalize remaining file systems and devices after %u retries, trying again.", retries+1);
441         }
442
443         if (retries >= FINALIZE_ATTEMPTS)
444                 log_error("Too many iterations, giving up.");
445
446         execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, NULL);
447
448         /* If we are in a container, just exit, this will kill our
449          * container for good. */
450         if (in_container) {
451                 log_error("Exiting container.");
452                 exit(0);
453         }
454
455         if (access("/run/initramfs/shutdown", X_OK) == 0) {
456
457                 if (prepare_new_root() >= 0 &&
458                     pivot_to_new_root() >= 0) {
459                         execv("/shutdown", argv);
460                         log_error("Failed to execute shutdown binary: %m");
461                 }
462         }
463
464         sync();
465
466         if (cmd == LINUX_REBOOT_CMD_KEXEC) {
467                 /* We cheat and exec kexec to avoid doing all its work */
468                 pid_t pid = fork();
469
470                 if (pid < 0)
471                         log_error("Could not fork: %m. Falling back to normal reboot.");
472                 else if (pid > 0) {
473                         wait_for_terminate_and_warn("kexec", pid);
474                         log_warning("kexec failed. Falling back to normal reboot.");
475                 } else {
476                         /* Child */
477                         const char *args[3] = { "/sbin/kexec", "-e", NULL };
478                         execv(args[0], (char * const *) args);
479                         return EXIT_FAILURE;
480                 }
481
482                 cmd = RB_AUTOBOOT;
483         }
484
485         reboot(cmd);
486         log_error("Failed to invoke reboot(): %m");
487         r = -errno;
488
489   error:
490         log_error("Critical error while doing system shutdown: %s", strerror(-r));
491
492         freeze();
493         return EXIT_FAILURE;
494 }