chiark / gitweb /
mkdir: append _label to all mkdir() calls that explicitly set the selinux context
[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         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         char *arguments[3];
313
314         log_parse_environment();
315         log_set_target(LOG_TARGET_CONSOLE); /* syslog will die if not gone yet */
316         log_open();
317
318         umask(0022);
319
320         if (getpid() != 1) {
321                 log_error("Not executed by init (pid 1).");
322                 r = -EPERM;
323                 goto error;
324         }
325
326         if (argc != 2) {
327                 log_error("Invalid number of arguments.");
328                 r = -EINVAL;
329                 goto error;
330         }
331
332         in_container = detect_container(NULL) > 0;
333
334         if (streq(argv[1], "reboot"))
335                 cmd = RB_AUTOBOOT;
336         else if (streq(argv[1], "poweroff"))
337                 cmd = RB_POWER_OFF;
338         else if (streq(argv[1], "halt"))
339                 cmd = RB_HALT_SYSTEM;
340         else if (streq(argv[1], "kexec"))
341                 cmd = LINUX_REBOOT_CMD_KEXEC;
342         else {
343                 log_error("Unknown action '%s'.", argv[1]);
344                 r = -EINVAL;
345                 goto error;
346         }
347
348         use_watchdog = !!getenv("WATCHDOG_USEC");
349
350         /* lock us into memory */
351         mlockall(MCL_CURRENT|MCL_FUTURE);
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         arguments[0] = NULL;
447         arguments[1] = argv[1];
448         arguments[2] = NULL;
449         execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, arguments);
450
451         /* If we are in a container, just exit, this will kill our
452          * container for good. */
453         if (in_container) {
454                 log_error("Exiting container.");
455                 exit(0);
456         }
457
458         if (access("/run/initramfs/shutdown", X_OK) == 0) {
459
460                 if (prepare_new_root() >= 0 &&
461                     pivot_to_new_root() >= 0) {
462                         execv("/shutdown", argv);
463                         log_error("Failed to execute shutdown binary: %m");
464                 }
465         }
466
467         sync();
468
469         if (cmd == LINUX_REBOOT_CMD_KEXEC) {
470                 /* We cheat and exec kexec to avoid doing all its work */
471                 pid_t pid = fork();
472
473                 if (pid < 0)
474                         log_error("Could not fork: %m. Falling back to normal reboot.");
475                 else if (pid > 0) {
476                         wait_for_terminate_and_warn("kexec", pid);
477                         log_warning("kexec failed. Falling back to normal reboot.");
478                 } else {
479                         /* Child */
480                         const char *args[3] = { "/sbin/kexec", "-e", NULL };
481                         execv(args[0], (char * const *) args);
482                         return EXIT_FAILURE;
483                 }
484
485                 cmd = RB_AUTOBOOT;
486         }
487
488         reboot(cmd);
489         log_error("Failed to invoke reboot(): %m");
490         r = -errno;
491
492   error:
493         log_error("Critical error while doing system shutdown: %s", strerror(-r));
494
495         freeze();
496         return EXIT_FAILURE;
497 }