chiark / gitweb /
switch-root: reopen /dev/console before we switch root
[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_label(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         if (chdir("/run/initramfs") < 0) {
271                 log_error("Failed to change directory to /run/initramfs: %m");
272                 return -errno;
273         }
274
275         /*
276           In case some evil process made "/" MS_SHARED
277           It works for pivot_root, but the ref count for the root device
278           is not decreasing :-/
279         */
280         if (mount(NULL, "/", NULL, MS_PRIVATE, NULL) < 0) {
281                 log_error("Failed to make \"/\" private mount %m");
282                 return -errno;
283         }
284
285         if (pivot_root(".", "oldroot") < 0) {
286                 log_error("pivot failed: %m");
287                 /* only chroot if pivot root succeded */
288                 return -errno;
289         }
290
291         chroot(".");
292
293         setsid();
294         make_console_stdio();
295
296         log_info("Successfully changed into root pivot.");
297
298         return 0;
299 }
300
301 int main(int argc, char *argv[]) {
302         int cmd, r;
303         unsigned retries;
304         bool need_umount = true, need_swapoff = true, need_loop_detach = true, need_dm_detach = true;
305         bool killed_everbody = false, in_container, use_watchdog = false;
306         char *arguments[3];
307
308         log_parse_environment();
309         log_set_target(LOG_TARGET_CONSOLE); /* syslog will die if not gone yet */
310         log_open();
311
312         umask(0022);
313
314         if (getpid() != 1) {
315                 log_error("Not executed by init (pid 1).");
316                 r = -EPERM;
317                 goto error;
318         }
319
320         if (argc != 2) {
321                 log_error("Invalid number of arguments.");
322                 r = -EINVAL;
323                 goto error;
324         }
325
326         in_container = detect_container(NULL) > 0;
327
328         if (streq(argv[1], "reboot"))
329                 cmd = RB_AUTOBOOT;
330         else if (streq(argv[1], "poweroff"))
331                 cmd = RB_POWER_OFF;
332         else if (streq(argv[1], "halt"))
333                 cmd = RB_HALT_SYSTEM;
334         else if (streq(argv[1], "kexec"))
335                 cmd = LINUX_REBOOT_CMD_KEXEC;
336         else {
337                 log_error("Unknown action '%s'.", argv[1]);
338                 r = -EINVAL;
339                 goto error;
340         }
341
342         use_watchdog = !!getenv("WATCHDOG_USEC");
343
344         /* lock us into memory */
345         mlockall(MCL_CURRENT|MCL_FUTURE);
346
347         log_info("Sending SIGTERM to remaining processes...");
348         send_signal(SIGTERM);
349
350         log_info("Sending SIGKILL to remaining processes...");
351         send_signal(SIGKILL);
352
353         if (in_container) {
354                 need_swapoff = false;
355                 need_dm_detach = false;
356         }
357
358         /* Unmount all mountpoints, swaps, and loopback devices */
359         for (retries = 0; retries < FINALIZE_ATTEMPTS; retries++) {
360                 bool changed = false;
361
362                 if (use_watchdog)
363                         watchdog_ping();
364
365                 if (need_umount) {
366                         log_info("Unmounting file systems.");
367                         r = umount_all(&changed);
368                         if (r == 0)
369                                 need_umount = false;
370                         else if (r > 0)
371                                 log_info("Not all file systems unmounted, %d left.", r);
372                         else
373                                 log_error("Failed to unmount file systems: %s", strerror(-r));
374                 }
375
376                 if (need_swapoff) {
377                         log_info("Disabling swaps.");
378                         r = swapoff_all(&changed);
379                         if (r == 0)
380                                 need_swapoff = false;
381                         else if (r > 0)
382                                 log_info("Not all swaps are turned off, %d left.", r);
383                         else
384                                 log_error("Failed to turn off swaps: %s", strerror(-r));
385                 }
386
387                 if (need_loop_detach) {
388                         log_info("Detaching loop devices.");
389                         r = loopback_detach_all(&changed);
390                         if (r == 0)
391                                 need_loop_detach = false;
392                         else if (r > 0)
393                                 log_info("Not all loop devices detached, %d left.", r);
394                         else
395                                 log_error("Failed to detach loop devices: %s", strerror(-r));
396                 }
397
398                 if (need_dm_detach) {
399                         log_info("Detaching DM devices.");
400                         r = dm_detach_all(&changed);
401                         if (r == 0)
402                                 need_dm_detach = false;
403                         else if (r > 0)
404                                 log_warning("Not all DM devices detached, %d left.", r);
405                         else
406                                 log_error("Failed to detach DM devices: %s", strerror(-r));
407                 }
408
409                 if (!need_umount && !need_swapoff && !need_loop_detach && !need_dm_detach) {
410                         if (retries > 0)
411                                 log_info("All filesystems, swaps, loop devices, DM devices detached.");
412                         /* Yay, done */
413                         break;
414                 }
415
416                 /* If in this iteration we didn't manage to
417                  * unmount/deactivate anything, we either kill more
418                  * processes, or simply give up */
419                 if (!changed) {
420
421                         if (killed_everbody) {
422                                 /* Hmm, we already killed everybody,
423                                  * let's just give up */
424                                 log_error("Cannot finalize remaining file systems and devices, giving up.");
425                                 break;
426                         }
427
428                         log_warning("Cannot finalize remaining file systems and devices, trying to kill remaining processes.");
429                         ultimate_send_signal(SIGTERM);
430                         ultimate_send_signal(SIGKILL);
431                         killed_everbody = true;
432                 }
433
434                 log_debug("Couldn't finalize remaining file systems and devices after %u retries, trying again.", retries+1);
435         }
436
437         if (retries >= FINALIZE_ATTEMPTS)
438                 log_error("Too many iterations, giving up.");
439
440         arguments[0] = NULL;
441         arguments[1] = argv[1];
442         arguments[2] = NULL;
443         execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, arguments);
444
445         /* If we are in a container, just exit, this will kill our
446          * container for good. */
447         if (in_container) {
448                 log_error("Exiting container.");
449                 exit(0);
450         }
451
452         if (access("/run/initramfs/shutdown", X_OK) == 0) {
453
454                 if (prepare_new_root() >= 0 &&
455                     pivot_to_new_root() >= 0) {
456                         execv("/shutdown", argv);
457                         log_error("Failed to execute shutdown binary: %m");
458                 }
459         }
460
461         sync();
462
463         if (cmd == LINUX_REBOOT_CMD_KEXEC) {
464                 /* We cheat and exec kexec to avoid doing all its work */
465                 pid_t pid = fork();
466
467                 if (pid < 0)
468                         log_error("Could not fork: %m. Falling back to normal reboot.");
469                 else if (pid > 0) {
470                         wait_for_terminate_and_warn("kexec", pid);
471                         log_warning("kexec failed. Falling back to normal reboot.");
472                 } else {
473                         /* Child */
474                         const char *args[3] = { "/sbin/kexec", "-e", NULL };
475                         execv(args[0], (char * const *) args);
476                         return EXIT_FAILURE;
477                 }
478
479                 cmd = RB_AUTOBOOT;
480         }
481
482         reboot(cmd);
483         log_error("Failed to invoke reboot(): %m");
484         r = -errno;
485
486   error:
487         log_error("Critical error while doing system shutdown: %s", strerror(-r));
488
489         freeze();
490         return EXIT_FAILURE;
491 }