diff options
Diffstat (limited to 'src/nspawn/nspawn.c')
-rw-r--r-- | src/nspawn/nspawn.c | 103 |
1 files changed, 47 insertions, 56 deletions
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 532be148a6..b172b44933 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -132,6 +132,8 @@ typedef enum LinkJournal { static char *arg_directory = NULL; static char *arg_template = NULL; static char *arg_chdir = NULL; +static char *arg_pivot_root_new = NULL; +static char *arg_pivot_root_old = NULL; static char *arg_user = NULL; static sd_id128_t arg_uuid = {}; static char *arg_machine = NULL; @@ -221,6 +223,8 @@ static void help(void) { " -a --as-pid2 Maintain a stub init as PID1, invoke binary as PID2\n" " -b --boot Boot up full system (i.e. invoke init)\n" " --chdir=PATH Set working directory in the container\n" + " --pivot-root=PATH[:PATH]\n" + " Pivot root to given directory in the container\n" " -u --user=USER Run the command under specified user or uid\n" " -M --machine=NAME Set the machine name for the container\n" " --uuid=UUID Set a specific machine UUID for the container\n" @@ -427,6 +431,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_KILL_SIGNAL, ARG_SETTINGS, ARG_CHDIR, + ARG_PIVOT_ROOT, ARG_PRIVATE_USERS_CHOWN, ARG_NOTIFY_READY, ARG_ROOT_HASH, @@ -478,6 +483,7 @@ static int parse_argv(int argc, char *argv[]) { { "kill-signal", required_argument, NULL, ARG_KILL_SIGNAL }, { "settings", required_argument, NULL, ARG_SETTINGS }, { "chdir", required_argument, NULL, ARG_CHDIR }, + { "pivot-root", required_argument, NULL, ARG_PIVOT_ROOT }, { "notify-ready", required_argument, NULL, ARG_NOTIFY_READY }, { "root-hash", required_argument, NULL, ARG_ROOT_HASH }, {} @@ -676,9 +682,8 @@ static int parse_argv(int argc, char *argv[]) { r = free_and_strdup(&arg_machine, optarg); if (r < 0) return log_oom(); - - break; } + break; case 'Z': arg_selinux_context = optarg; @@ -1013,6 +1018,14 @@ static int parse_argv(int argc, char *argv[]) { arg_settings_mask |= SETTING_WORKING_DIRECTORY; break; + case ARG_PIVOT_ROOT: + r = pivot_root_parse(&arg_pivot_root_new, &arg_pivot_root_old, optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --pivot-root= argument %s: %m", optarg); + + arg_settings_mask |= SETTING_PIVOT_ROOT; + break; + case ARG_NOTIFY_READY: r = parse_boolean(optarg); if (r < 0) { @@ -1918,7 +1931,7 @@ static int wait_for_container(pid_t pid, ContainerStatus *container) { return 0; } - /* CLD_KILLED fallthrough */ + /* fall through */ case CLD_DUMPED: log_error("Container %s terminated by signal %s.", arg_machine, signal_to_string(status.si_status)); @@ -2131,6 +2144,7 @@ static int inner_child( NULL, /* NOTIFY_SOCKET */ NULL }; + const char *exec_target; _cleanup_strv_free_ char **env_use = NULL; int r; @@ -2325,20 +2339,25 @@ static int inner_child( a[0] = (char*) "/sbin/init"; execve(a[0], a, env_use); - } else if (!strv_isempty(arg_parameters)) + + exec_target = "/usr/lib/systemd/systemd, /lib/systemd/systemd, /sbin/init"; + } else if (!strv_isempty(arg_parameters)) { + exec_target = arg_parameters[0]; execvpe(arg_parameters[0], arg_parameters, env_use); - else { + } else { if (!arg_chdir) /* If we cannot change the directory, we'll end up in /, that is expected. */ (void) chdir(home ?: "/root"); execle("/bin/bash", "-bash", NULL, env_use); execle("/bin/sh", "-sh", NULL, env_use); + + exec_target = "/bin/bash, /bin/sh"; } r = -errno; (void) log_open(); - return log_error_errno(r, "execv() failed: %m"); + return log_error_errno(r, "execv(%s) failed: %m", exec_target); } static int setup_sd_notify_child(void) { @@ -2488,6 +2507,13 @@ static int outer_child( if (r < 0) return r; + r = setup_pivot_root( + directory, + arg_pivot_root_new, + arg_pivot_root_old); + if (r < 0) + return r; + r = setup_volatile( directory, arg_volatile_mode, @@ -2910,6 +2936,12 @@ static int load_settings(void) { settings->parameters = NULL; } + if ((arg_settings_mask & SETTING_PIVOT_ROOT) == 0 && + settings->pivot_root_new) { + free_and_replace(arg_pivot_root_new, settings->pivot_root_new); + free_and_replace(arg_pivot_root_old, settings->pivot_root_old); + } + if ((arg_settings_mask & SETTING_WORKING_DIRECTORY) == 0 && settings->working_directory) { free(arg_chdir); @@ -3475,53 +3507,6 @@ static int run(int master, return 1; /* loop again */ } -static int load_root_hash(const char *image) { - _cleanup_free_ char *text = NULL, *fn = NULL; - char *n, *e; - void *k; - size_t l; - int r; - - assert_se(image); - - /* Try to load the root hash from a file next to the image file if it exists. */ - - if (arg_root_hash) - return 0; - - fn = new(char, strlen(image) + strlen(".roothash") + 1); - if (!fn) - return log_oom(); - - n = stpcpy(fn, image); - e = endswith(fn, ".raw"); - if (e) - n = e; - - strcpy(n, ".roothash"); - - r = read_one_line_file(fn, &text); - if (r == -ENOENT) - return 0; - if (r < 0) { - log_warning_errno(r, "Failed to read %s, ignoring: %m", fn); - return 0; - } - - r = unhexmem(text, strlen(text), &k, &l); - if (r < 0) - return log_error_errno(r, "Invalid root hash: %s", text); - if (l < sizeof(sd_id128_t)) { - free(k); - return log_error_errno(r, "Root hash too short: %s", text); - } - - arg_root_hash = k; - arg_root_hash_size = l; - - return 0; -} - int main(int argc, char *argv[]) { _cleanup_free_ char *console = NULL; @@ -3737,9 +3722,13 @@ int main(int argc, char *argv[]) { goto finish; } - r = load_root_hash(arg_image); - if (r < 0) - goto finish; + if (!arg_root_hash) { + r = root_hash_load(arg_image, &arg_root_hash, &arg_root_hash_size); + if (r < 0) { + log_error_errno(r, "Failed to load root hash file for %s: %m", arg_image); + goto finish; + } + } } if (!mkdtemp(tmprootdir)) { @@ -3910,6 +3899,8 @@ finish: free(arg_image); free(arg_machine); free(arg_user); + free(arg_pivot_root_new); + free(arg_pivot_root_old); free(arg_chdir); strv_free(arg_setenv); free(arg_network_bridge); |