int entry(unsigned int cpu_id, struct per_cpu *cpu_data) { static volatile bool activate; bool master = false; cpu_data->cpu_id = cpu_id; spin_lock(&init_lock); if (master_cpu_id == -1) { master = true; init_early(cpu_id); } if (!error) cpu_init(cpu_data); spin_unlock(&init_lock); while (!error && initialized_cpus < hypervisor_header.online_cpus) cpu_relax(); if (!error && master) { init_late(cpu_data); if (!error) { /* * Make sure everything was committed before we signal * the other CPUs that they can continue. */ memory_barrier(); activate = true; } } else { while (!error && !activate) cpu_relax(); } if (error) { if (master) arch_shutdown(); arch_cpu_restore(cpu_data); return error; } if (master) printk("Activating hypervisor\n"); /* point of no return */ arch_cpu_activate_vmm(cpu_data); }
static int init_chain(const char* target) { init_early(); prepare_block_devices(); load_fstab(); if ( atexit(init_chain_atexit) != 0 ) fatal("atexit: %m"); if ( !mkdtemp(chain_location) ) fatal("mkdtemp: /tmp/fs.XXXXXX: %m"); chain_location_made = true; bool found_root = false; for ( size_t i = 0; i < mountpoints_used; i++ ) { struct mountpoint* mountpoint = &mountpoints[i]; if ( !strcmp(mountpoint->entry.fs_file, "/") ) found_root = true; char* absolute = join_paths(chain_location, mountpoint->absolute); free(mountpoint->absolute); mountpoint->absolute = absolute; } if ( !found_root ) fatal("/etc/fstab: Root filesystem not found in filesystem table"); if ( atexit(mountpoints_unmount) != 0 ) fatal("atexit: %m"); mountpoints_mount(true); snprintf(chain_location_dev, sizeof(chain_location_dev), "%s/dev", chain_location); if ( mkdir(chain_location_dev, 755) < 0 && errno != EEXIST ) fatal("mkdir: %s: %m", chain_location_dev); int old_dev_fd = open("/dev", O_DIRECTORY | O_RDONLY); if ( old_dev_fd < 0 ) fatal("%s: %m", "/dev"); int new_dev_fd = open(chain_location_dev, O_DIRECTORY | O_RDONLY); if ( new_dev_fd < 0 ) fatal("%s: %m", chain_location_dev); if ( fsm_fsbind(old_dev_fd, new_dev_fd, 0) < 0 ) fatal("mount: `%s' onto `%s': %m", "/dev", chain_location_dev); close(new_dev_fd); close(old_dev_fd); int result; while ( true ) { pid_t child_pid = fork(); if ( child_pid < 0 ) fatal("fork: %m"); if ( !child_pid ) { if ( chroot(chain_location) < 0 ) fatal("chroot: %s: %m", chain_location); if ( chdir("/") < 0 ) fatal("chdir: %s: %m", chain_location); if ( !strcmp(target, "chain-merge") ) { const char* argv[] = { "sysmerge", "--booting", NULL }; execv("/sysmerge/sbin/sysmerge", (char* const*) argv); fatal("Failed to run automatic update: %s: %m", argv[0]); } else { unsetenv("INIT_PID"); const char* argv[] = { "init", NULL }; execv("/sbin/init", (char* const*) argv); fatal("Failed to load chain init: %s: %m", argv[0]); } } int status; if ( waitpid(child_pid, &status, 0) < 0 ) fatal("waitpid"); const char* back = ": Trying to bring it back up again"; if ( !strcmp(target, "chain-merge") ) { if ( WIFEXITED(status) && WEXITSTATUS(status) == 0 ) { target = "chain"; continue; } if ( WIFEXITED(status) ) fatal("Automatic upgrade failed: Exit status %i", WEXITSTATUS(status)); else if ( WIFSIGNALED(status) ) fatal("Automatic upgrade failed: %s", strsignal(WTERMSIG(status))); else fatal("Automatic upgrade failed: Unexpected unusual termination"); } if ( WIFEXITED(status) ) { result = WEXITSTATUS(status); break; } else if ( WIFSIGNALED(status) ) note("chain init: %s%s", strsignal(WTERMSIG(status)), back); else note("chain init: Unexpected unusual termination%s", back); } mountpoints_unmount(); init_chain_atexit(); return result; }
static int init(const char* target) { init_early(); set_hostname(); set_kblayout(); set_videomode(); prepare_block_devices(); load_fstab(); if ( atexit(mountpoints_unmount) != 0 ) fatal("atexit: %m"); mountpoints_mount(false); sigset_t oldset, sigttou; sigemptyset(&sigttou); sigaddset(&sigttou, SIGTTOU); int result; while ( true ) { struct termios tio; if ( tcgetattr(0, &tio) ) fatal("tcgetattr: %m"); pid_t child_pid = fork(); if ( child_pid < 0 ) fatal("fork: %m"); if ( !child_pid ) { uid_t uid = getuid(); pid_t pid = getpid(); pid_t ppid = getppid(); if ( setpgid(0, 0) < 0 ) fatal("setpgid: %m"); sigprocmask(SIG_BLOCK, &sigttou, &oldset); if ( tcsetpgrp(0, pid) < 0 ) fatal("tcsetpgrp: %m"); sigprocmask(SIG_SETMASK, &oldset, NULL); struct passwd* pwd = getpwuid(uid); if ( !pwd ) fatal("looking up user by uid %" PRIuUID ": %m", uid); const char* home = pwd->pw_dir[0] ? pwd->pw_dir : "/"; const char* shell = pwd->pw_shell[0] ? pwd->pw_shell : "sh"; char ppid_str[sizeof(pid_t) * 3]; snprintf(ppid_str, sizeof(ppid_str), "%" PRIiPID, ppid); if ( setenv("INIT_PID", ppid_str, 1) < 0 || setenv("LOGNAME", pwd->pw_name, 1) < 0 || setenv("USER", pwd->pw_name, 1) < 0 || setenv("HOME", home, 1) < 0 || setenv("SHELL", shell, 1) < 0 ) fatal("setenv: %m"); if ( chdir(home) < 0 ) warning("chdir: %s: %m", home); const char* program = "login"; bool activate_terminal = false; if ( !strcmp(target, "single-user") ) { activate_terminal = true; program = shell; } if ( !strcmp(target, "sysinstall") ) { activate_terminal = true; program = "sysinstall"; } if ( !strcmp(target, "sysupgrade") ) { program = "sysupgrade"; activate_terminal = true; } if ( activate_terminal ) { tio.c_cflag |= CREAD; if ( tcsetattr(0, TCSANOW, &tio) ) fatal("tcgetattr: %m"); } const char* argv[] = { program, NULL }; execvp(program, (char* const*) argv); fatal("%s: %m", program); } int status; if ( waitpid(child_pid, &status, 0) < 0 ) fatal("waitpid"); sigprocmask(SIG_BLOCK, &sigttou, &oldset); if ( tcsetattr(0, TCSAFLUSH, &tio) ) fatal("tcgetattr: %m"); if ( tcsetpgrp(0, getpgid(0)) < 0 ) fatal("tcsetpgrp: %m"); sigprocmask(SIG_SETMASK, &oldset, NULL); const char* back = ": Trying to bring it back up again"; if ( WIFEXITED(status) ) { result = WEXITSTATUS(status); break; } else if ( WIFSIGNALED(status) ) note("session: %s%s", strsignal(WTERMSIG(status)), back); else note("session: Unexpected unusual termination%s", back); } mountpoints_unmount(); return result; }