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