X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Fmain.c;h=486dac8a8aa2487b0a225c7038b64c2ee3b097d3;hb=401cc72da8e59a1e49acafee69280f7ebaa52e74;hp=d7143edae2b5d062c51df61872fd3b0f8cab8897;hpb=e148ac5a6cccd1c9c23bf7b3085b50fdb1cd1cf9;p=elogind.git diff --git a/src/core/main.c b/src/core/main.c index d7143edae..486dac8a8 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -49,6 +49,7 @@ #include "virt.h" #include "watchdog.h" #include "path-util.h" +#include "switch-root.h" #include "mount-setup.h" #include "loopback-setup.h" @@ -746,7 +747,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_SHOW_STATUS, ARG_SYSV_CONSOLE, ARG_DESERIALIZE, - ARG_SWITCHEDROOT, + ARG_SWITCHED_ROOT, ARG_INTROSPECT, ARG_DEFAULT_STD_OUTPUT, ARG_DEFAULT_STD_ERROR @@ -771,7 +772,7 @@ static int parse_argv(int argc, char *argv[]) { { "sysv-console", optional_argument, NULL, ARG_SYSV_CONSOLE }, #endif { "deserialize", required_argument, NULL, ARG_DESERIALIZE }, - { "switchedroot", no_argument, NULL, ARG_SWITCHEDROOT }, + { "switched-root", no_argument, NULL, ARG_SWITCHED_ROOT }, { "introspect", optional_argument, NULL, ARG_INTROSPECT }, { "default-standard-output", required_argument, NULL, ARG_DEFAULT_STD_OUTPUT, }, { "default-standard-error", required_argument, NULL, ARG_DEFAULT_STD_ERROR, }, @@ -943,7 +944,7 @@ static int parse_argv(int argc, char *argv[]) { break; } - case ARG_SWITCHEDROOT: + case ARG_SWITCHED_ROOT: /* Nothing special yet */ break; @@ -1173,83 +1174,6 @@ static void test_cgroups(void) { sleep(10); } -static int do_switch_root(const char *switch_root) { - int r=0; - /* Don't try to unmount the old "/", there's no way to do it. */ - const char *umounts[] = { "/dev", "/proc", "/sys", "/run", NULL }; - int i; - int cfd = -1; - struct stat switch_root_stat, sb; - bool remove_old_root; - - if (path_equal(switch_root, "/")) - return 0; - - if (stat(switch_root, &switch_root_stat) != 0) { - r = -errno; - log_error("failed to stat directory %s", switch_root); - goto fail; - } - - remove_old_root = in_initrd(); - - for (i = 0; umounts[i] != NULL; i++) { - char newmount[PATH_MAX]; - - snprintf(newmount, sizeof(newmount), "%s%s", switch_root, umounts[i]); - - if ((stat(newmount, &sb) != 0) || (sb.st_dev != switch_root_stat.st_dev)) { - /* mount point seems to be mounted already or stat failed */ - umount2(umounts[i], MNT_DETACH); - continue; - } - - if (mount(umounts[i], newmount, NULL, MS_MOVE, NULL) < 0) { - log_error("failed to mount moving %s to %s", - umounts[i], newmount); - log_error("forcing unmount of %s", umounts[i]); - umount2(umounts[i], MNT_FORCE); - } - } - - if (chdir(switch_root)) { - r = -errno; - log_error("failed to change directory to %s", switch_root); - goto fail; - } - - if (remove_old_root) - cfd = open("/", O_RDONLY); - - if (mount(switch_root, "/", NULL, MS_MOVE, NULL) < 0) { - r = -errno; - log_error("failed to mount moving %s to /", switch_root); - goto fail; - } - - if (chroot(".")) { - r = -errno; - log_error("failed to change root"); - goto fail; - } - - if (cfd >= 0) { - rm_rf_children(cfd, false, false); - close(cfd); - cfd=-1; - } - - return 0; - -fail: - if (cfd >= 0) - close(cfd); - - log_error("Failed to switch root, ignoring: %s", strerror(-r)); - - return r; -} - int main(int argc, char *argv[]) { Manager *m = NULL; int r, retval = EXIT_FAILURE; @@ -1260,11 +1184,11 @@ int main(int argc, char *argv[]) { const char *shutdown_verb = NULL; dual_timestamp initrd_timestamp = { 0ULL, 0ULL }; static char systemd[] = "systemd"; - bool is_reexec = false; + bool skip_setup = false; int j; bool loaded_policy = false; bool arm_reboot_watchdog = false; - char *switch_root = NULL, *switch_root_init = NULL; + char *switch_root_dir = NULL, *switch_root_init = NULL; #ifdef HAVE_SYSV_COMPAT if (getpid() != 1 && strstr(program_invocation_short_name, "init")) { @@ -1281,17 +1205,17 @@ int main(int argc, char *argv[]) { /* Determine if this is a reexecution or normal bootup. We do * the full command line parsing much later, so let's just * have a quick peek here. */ - for (j = 1; j < argc; j++) if (streq(argv[j], "--deserialize")) { - is_reexec = true; + skip_setup = true; break; } - /* If we have switched root, do all the special things */ + /* If we have switched root, do all the special setup + * things */ for (j = 1; j < argc; j++) - if (streq(argv[j], "--switchedroot")) { - is_reexec = false; + if (streq(argv[j], "--switched-root")) { + skip_setup = false; break; } @@ -1310,10 +1234,23 @@ int main(int argc, char *argv[]) { log_set_max_level(LOG_INFO); if (getpid() == 1) { + if (in_initrd()) { + char *rd_timestamp = NULL; + + dual_timestamp_get(&initrd_timestamp); + asprintf(&rd_timestamp, "%llu %llu", + (unsigned long long) initrd_timestamp.realtime, + (unsigned long long) initrd_timestamp.monotonic); + if (rd_timestamp) { + setenv("RD_TIMESTAMP", rd_timestamp, 1); + free(rd_timestamp); + } + } + arg_running_as = MANAGER_SYSTEM; log_set_target(detect_container(NULL) > 0 ? LOG_TARGET_JOURNAL : LOG_TARGET_JOURNAL_OR_KMSG); - if (!is_reexec) { + if (!skip_setup) { if (selinux_setup(&loaded_policy) < 0) goto finish; if (ima_setup() < 0) @@ -1325,7 +1262,7 @@ int main(int argc, char *argv[]) { if (label_init(NULL) < 0) goto finish; - if (!is_reexec) + if (!skip_setup) if (hwclock_is_localtime() > 0) { int min; @@ -1437,7 +1374,8 @@ int main(int argc, char *argv[]) { /* Parse the data passed to us. We leave this * variables set, but the manager later on will not * pass them on to our children. */ - parse_initrd_timestamp(&initrd_timestamp); + if (!in_initrd()) + parse_initrd_timestamp(&initrd_timestamp); /* Unset some environment variables passed in from the * kernel that don't really make sense for us. */ @@ -1450,7 +1388,7 @@ int main(int argc, char *argv[]) { unsetenv("SHLVL"); unsetenv("_"); - /* When we are invoked by a tool chroot-like such as + /* When we are invoked by a chroot-like tool such as * nspawn, these might be set, but make little sense * to pass on */ unsetenv("USER"); @@ -1477,7 +1415,7 @@ int main(int argc, char *argv[]) { /* Reset the console, but only if this is really init and we * are freshly booted */ if (arg_running_as == MANAGER_SYSTEM && arg_action == ACTION_RUN) { - console_setup(getpid() == 1 && !is_reexec); + console_setup(getpid() == 1 && !skip_setup); make_null_stdio(); } @@ -1498,7 +1436,7 @@ int main(int argc, char *argv[]) { log_full(arg_running_as == MANAGER_SYSTEM ? LOG_INFO : LOG_DEBUG, PACKAGE_STRING " running in %s mode. (" SYSTEMD_FEATURES "; " DISTRIBUTION ")", manager_running_as_to_string(arg_running_as)); - if (arg_running_as == MANAGER_SYSTEM && !is_reexec) { + if (arg_running_as == MANAGER_SYSTEM && !skip_setup) { locale_setup(); if (arg_show_status || plymouth_running()) @@ -1652,7 +1590,7 @@ int main(int argc, char *argv[]) { case MANAGER_SWITCH_ROOT: /* Steal the switch root parameters */ - switch_root = m->switch_root; + switch_root_dir = m->switch_root; switch_root_init = m->switch_root_init; m->switch_root = m->switch_root_init = NULL; @@ -1707,8 +1645,11 @@ finish: * rebooted while we do that */ watchdog_close(true); - if (switch_root) - do_switch_root(switch_root); + if (switch_root_dir) { + r = switch_root(switch_root_dir); + if (r < 0) + log_error("Failed to switch root, ignoring: %s", strerror(-r)); + } args_size = MAX(6, argc+1); args = newa(const char*, args_size); @@ -1729,8 +1670,8 @@ finish: i = 0; args[i++] = SYSTEMD_BINARY_PATH; - if (switch_root) - args[i++] = "--switchedroot"; + if (switch_root_dir) + args[i++] = "--switched-root"; args[i++] = arg_running_as == MANAGER_SYSTEM ? "--system" : "--user"; args[i++] = "--deserialize"; args[i++] = sfd;