diff options
Diffstat (limited to 'src/nspawn/nspawn.c')
-rw-r--r-- | src/nspawn/nspawn.c | 70 |
1 files changed, 46 insertions, 24 deletions
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index fcf14bba4c..6d0420965a 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -169,7 +169,6 @@ static CustomMount *arg_custom_mounts = NULL; static unsigned arg_n_custom_mounts = 0; static char **arg_setenv = NULL; static bool arg_quiet = false; -static bool arg_share_system = false; static bool arg_register = true; static bool arg_keep_unit = false; static char **arg_network_interfaces = NULL; @@ -188,13 +187,14 @@ static UserNamespaceMode arg_userns_mode = USER_NAMESPACE_NO; static uid_t arg_uid_shift = UID_INVALID, arg_uid_range = 0x10000U; static bool arg_userns_chown = false; static int arg_kill_signal = 0; -static bool arg_unified_cgroup_hierarchy = false; +static CGroupUnified arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_UNKNOWN; static SettingsMask arg_settings_mask = 0; static int arg_settings_trusted = -1; static char **arg_parameters = NULL; static const char *arg_container_service_name = "systemd-nspawn"; static bool arg_notify_ready = false; static bool arg_use_cgns = true; +static unsigned long arg_clone_ns_flags = CLONE_NEWIPC|CLONE_NEWPID|CLONE_NEWUTS; static void help(void) { printf("%s [OPTIONS...] [PATH] [ARGUMENTS...]\n\n" @@ -318,7 +318,14 @@ static int custom_mounts_prepare(void) { static int detect_unified_cgroup_hierarchy(void) { const char *e; - int r; + int r, all_unified, systemd_unified; + + all_unified = cg_all_unified(); + systemd_unified = cg_unified(SYSTEMD_CGROUP_CONTROLLER); + + if (all_unified < 0 || systemd_unified < 0) + return log_error_errno(all_unified < 0 ? all_unified : systemd_unified, + "Failed to determine whether the unified cgroups hierarchy is used: %m"); /* Allow the user to control whether the unified hierarchy is used */ e = getenv("UNIFIED_CGROUP_HIERARCHY"); @@ -326,20 +333,36 @@ static int detect_unified_cgroup_hierarchy(void) { r = parse_boolean(e); if (r < 0) return log_error_errno(r, "Failed to parse $UNIFIED_CGROUP_HIERARCHY."); + if (r > 0) + arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_ALL; + else + arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_NONE; - arg_unified_cgroup_hierarchy = r; return 0; } /* Otherwise inherit the default from the host system */ - r = cg_unified(); - if (r < 0) - return log_error_errno(r, "Failed to determine whether the unified cgroups hierarchy is used: %m"); + if (all_unified > 0) + arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_ALL; + else if (systemd_unified > 0) + arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_SYSTEMD; + else + arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_NONE; - arg_unified_cgroup_hierarchy = r; return 0; } +static void parse_share_ns_env(const char *name, unsigned long ns_flag) { + int r; + + r = getenv_bool(name); + if (r == -ENXIO) + return; + if (r < 0) + log_warning_errno(r, "Failed to parse %s from environment, defaulting to false.", name); + arg_clone_ns_flags = (arg_clone_ns_flags & ~ns_flag) | (r > 0 ? 0 : ns_flag); +} + static int parse_argv(int argc, char *argv[]) { enum { @@ -812,8 +835,8 @@ static int parse_argv(int argc, char *argv[]) { case ARG_SHARE_SYSTEM: /* We don't officially support this anymore, except for compat reasons. People should use the - * $SYSTEMD_NSPAWN_SHARE_SYSTEM environment variable instead. */ - arg_share_system = true; + * $SYSTEMD_NSPAWN_SHARE_* environment variables instead. */ + arg_clone_ns_flags = 0; break; case ARG_REGISTER: @@ -1017,20 +1040,22 @@ static int parse_argv(int argc, char *argv[]) { assert_not_reached("Unhandled option"); } - if (getenv_bool("SYSTEMD_NSPAWN_SHARE_SYSTEM") > 0) - arg_share_system = true; + parse_share_ns_env("SYSTEMD_NSPAWN_SHARE_NS_IPC", CLONE_NEWIPC); + parse_share_ns_env("SYSTEMD_NSPAWN_SHARE_NS_PID", CLONE_NEWPID); + parse_share_ns_env("SYSTEMD_NSPAWN_SHARE_NS_UTS", CLONE_NEWUTS); + parse_share_ns_env("SYSTEMD_NSPAWN_SHARE_SYSTEM", CLONE_NEWIPC|CLONE_NEWPID|CLONE_NEWUTS); - if (arg_share_system) + if (arg_clone_ns_flags != (CLONE_NEWIPC|CLONE_NEWPID|CLONE_NEWUTS)) { arg_register = false; + if (arg_start_mode != START_PID1) { + log_error("--boot cannot be used without namespacing."); + return -EINVAL; + } + } if (arg_userns_mode == USER_NAMESPACE_PICK) arg_userns_chown = true; - if (arg_start_mode != START_PID1 && arg_share_system) { - log_error("--boot and SYSTEMD_NSPAWN_SHARE_SYSTEM=1 may not be combined."); - return -EINVAL; - } - if (arg_keep_unit && cg_pid_get_owner_uid(0, NULL) >= 0) { log_error("--keep-unit may not be used when invoked from a user session."); return -EINVAL; @@ -1298,9 +1323,6 @@ static int setup_boot_id(const char *dest) { const char *from, *to; int r; - if (arg_share_system) - return 0; - /* Generate a new randomized boot ID, so that each boot-up of * the container gets a new one */ @@ -1518,7 +1540,7 @@ static int on_address_change(sd_netlink *rtnl, sd_netlink_message *m, void *user static int setup_hostname(void) { - if (arg_share_system) + if ((arg_clone_ns_flags & CLONE_NEWUTS) == 0) return 0; if (sethostname_idempotent(arg_machine) < 0) @@ -1669,7 +1691,7 @@ static int reset_audit_loginuid(void) { _cleanup_free_ char *p = NULL; int r; - if (arg_share_system) + if ((arg_clone_ns_flags & CLONE_NEWPID) == 0) return 0; r = read_one_line_file("/proc/self/loginuid", &p); @@ -3076,7 +3098,7 @@ static int outer_child( return fd; pid = raw_clone(SIGCHLD|CLONE_NEWNS| - (arg_share_system ? 0 : CLONE_NEWIPC|CLONE_NEWPID|CLONE_NEWUTS) | + arg_clone_ns_flags | (arg_private_network ? CLONE_NEWNET : 0) | (arg_userns_mode != USER_NAMESPACE_NO ? CLONE_NEWUSER : 0)); if (pid < 0) |