summaryrefslogtreecommitdiff
path: root/src/nspawn/nspawn.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nspawn/nspawn.c')
-rw-r--r--src/nspawn/nspawn.c103
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);