X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fnspawn%2Fnspawn.c;h=0a81f972989305cd6610b9103c3ee2eeb7c37c28;hb=eb91eb187b7491e05fb95215b77cb62061f41d08;hp=f904ebea6439c80edaa91411e5cc3f0c3a1b7978;hpb=5d63309cf5a6fc5256391fa4ddb72cf68e2e27e5;p=elogind.git diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index f904ebea6..0a81f9729 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -80,8 +80,8 @@ static char *arg_directory = NULL; static char *arg_user = NULL; static sd_id128_t arg_uuid = {}; static char *arg_machine = NULL; -static char *arg_process_label = NULL; -static char *arg_file_label = NULL; +static char *arg_selinux_context = NULL; +static char *arg_selinux_apifs_context = NULL; static const char *arg_slice = NULL; static bool arg_private_network = false; static bool arg_read_only = false; @@ -118,6 +118,8 @@ static char **arg_bind = NULL; static char **arg_bind_ro = NULL; static char **arg_setenv = NULL; static bool arg_quiet = false; +static bool arg_share_system = false; +static bool arg_register = true; static int help(void) { @@ -131,11 +133,14 @@ static int help(void) { " --uuid=UUID Set a specific machine UUID for the container\n" " -M --machine=NAME Set the machine name for the container\n" " -S --slice=SLICE Place the container in the specified slice\n" - " -L --file-label=LABEL Set the MAC file label to be used by tmpfs file\n" - " systems in the container\n" - " -Z --process-label=LABEL Set the MAC label to be used by processes in\n" - " the container\n" + " -Z --selinux-context=SECLABEL\n" + " Set the SELinux security context to be used by\n" + " processes in the container\n" + " -L --selinux-apifs-context=SECLABEL\n" + " Set the SELinux security context to be used by\n" + " API/tmpfs file systems in the container\n" " --private-network Disable network in container\n" + " --share-system Share system namespaces with host\n" " --read-only Mount the root directory read-only\n" " --capability=CAP In addition to the default, retain specified\n" " capability\n" @@ -146,6 +151,7 @@ static int help(void) { " the container\n" " --bind-ro=PATH[:PATH] Similar, but creates a read-only bind mount\n" " --setenv=NAME=VALUE Pass an environment variable to PID 1\n" + " --register=BOOLEAN Register container as machine\n" " -q --quiet Do not show status information\n", program_invocation_short_name); @@ -165,28 +171,32 @@ static int parse_argv(int argc, char *argv[]) { ARG_BIND, ARG_BIND_RO, ARG_SETENV, + ARG_SHARE_SYSTEM, + ARG_REGISTER }; static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "directory", required_argument, NULL, 'D' }, - { "user", required_argument, NULL, 'u' }, - { "private-network", no_argument, NULL, ARG_PRIVATE_NETWORK }, - { "boot", no_argument, NULL, 'b' }, - { "uuid", required_argument, NULL, ARG_UUID }, - { "read-only", no_argument, NULL, ARG_READ_ONLY }, - { "capability", required_argument, NULL, ARG_CAPABILITY }, - { "drop-capability", required_argument, NULL, ARG_DROP_CAPABILITY }, - { "link-journal", required_argument, NULL, ARG_LINK_JOURNAL }, - { "bind", required_argument, NULL, ARG_BIND }, - { "bind-ro", required_argument, NULL, ARG_BIND_RO }, - { "machine", required_argument, NULL, 'M' }, - { "slice", required_argument, NULL, 'S' }, - { "setenv", required_argument, NULL, ARG_SETENV }, - { "process-label", required_argument, NULL, 'Z' }, - { "file-label", required_argument, NULL, 'L' }, - { "quiet", no_argument, NULL, 'q' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "directory", required_argument, NULL, 'D' }, + { "user", required_argument, NULL, 'u' }, + { "private-network", no_argument, NULL, ARG_PRIVATE_NETWORK }, + { "boot", no_argument, NULL, 'b' }, + { "uuid", required_argument, NULL, ARG_UUID }, + { "read-only", no_argument, NULL, ARG_READ_ONLY }, + { "capability", required_argument, NULL, ARG_CAPABILITY }, + { "drop-capability", required_argument, NULL, ARG_DROP_CAPABILITY }, + { "link-journal", required_argument, NULL, ARG_LINK_JOURNAL }, + { "bind", required_argument, NULL, ARG_BIND }, + { "bind-ro", required_argument, NULL, ARG_BIND_RO }, + { "machine", required_argument, NULL, 'M' }, + { "slice", required_argument, NULL, 'S' }, + { "setenv", required_argument, NULL, ARG_SETENV }, + { "selinux-context", required_argument, NULL, 'Z' }, + { "selinux-apifs-context", required_argument, NULL, 'L' }, + { "quiet", no_argument, NULL, 'q' }, + { "share-system", no_argument, NULL, ARG_SHARE_SYSTEM }, + { "register", required_argument, NULL, ARG_REGISTER }, {} }; @@ -249,24 +259,30 @@ static int parse_argv(int argc, char *argv[]) { break; case 'M': - if (!hostname_is_valid(optarg)) { - log_error("Invalid machine name: %s", optarg); - return -EINVAL; - } + if (isempty(optarg)) { + free(arg_machine); + arg_machine = NULL; + } else { - free(arg_machine); - arg_machine = strdup(optarg); - if (!arg_machine) - return log_oom(); + if (!hostname_is_valid(optarg)) { + log_error("Invalid machine name: %s", optarg); + return -EINVAL; + } - break; + free(arg_machine); + arg_machine = strdup(optarg); + if (!arg_machine) + return log_oom(); - case 'L': - arg_file_label = optarg; - break; + break; + } case 'Z': - arg_process_label = optarg; + arg_selinux_context = optarg; + break; + + case 'L': + arg_selinux_apifs_context = optarg; break; case ARG_READ_ONLY: @@ -380,6 +396,20 @@ static int parse_argv(int argc, char *argv[]) { arg_quiet = true; break; + case ARG_SHARE_SYSTEM: + arg_share_system = true; + break; + + case ARG_REGISTER: + r = parse_boolean(optarg); + if (r < 0) { + log_error("Failed to parse --register= argument: %s", optarg); + return r; + } + + arg_register = r; + break; + case '?': return -EINVAL; @@ -388,6 +418,14 @@ static int parse_argv(int argc, char *argv[]) { } } + if (arg_share_system) + arg_register = false; + + if (arg_boot && arg_share_system) { + log_error("--boot and --share-system may not be combined."); + return -EINVAL; + } + return 1; } @@ -449,8 +487,9 @@ static int mount_all(const char *dest) { mkdir_p(where, 0755); #ifdef HAVE_SELINUX - if (arg_file_label && (streq_ptr(mount_table[k].what, "tmpfs") || streq_ptr(mount_table[k].what, "devpts"))) { - options = strjoin(mount_table[k].options, ",context=\"", arg_file_label, "\"", NULL); + if (arg_selinux_apifs_context && + (streq_ptr(mount_table[k].what, "tmpfs") || streq_ptr(mount_table[k].what, "devpts"))) { + options = strjoin(mount_table[k].options, ",context=\"", arg_selinux_apifs_context, "\"", NULL); if (!options) return log_oom(); @@ -625,6 +664,9 @@ static int setup_boot_id(const char *dest) { assert(dest); + if (arg_share_system) + return 0; + /* Generate a new randomized boot ID, so that each boot-up of * the container gets a new one */ @@ -850,6 +892,9 @@ static int setup_kmsg(const char *dest, int kmsg_socket) { static int setup_hostname(void) { + if (arg_share_system) + return 0; + if (sethostname(arg_machine, strlen(arg_machine)) < 0) return -errno; @@ -1032,6 +1077,9 @@ static int register_machine(pid_t pid) { _cleanup_bus_unref_ sd_bus *bus = NULL; int r; + if (!arg_register) + return 0; + r = sd_bus_default_system(&bus); if (r < 0) { log_error("Failed to open system bus: %s", strerror(-r)); @@ -1069,6 +1117,9 @@ static int terminate_machine(pid_t pid) { const char *path; int r; + if (!arg_register) + return 0; + r = sd_bus_default_system(&bus); if (r < 0) { log_error("Failed to open system bus: %s", strerror(-r)); @@ -1135,7 +1186,6 @@ int main(int argc, char *argv[]) { _cleanup_close_pipe_ int kmsg_socket_pair[2] = { -1, -1 }; _cleanup_fdset_free_ FDSet *fds = NULL; _cleanup_free_ char *kdbus_domain = NULL; - const char *ns; log_parse_environment(); log_open(); @@ -1200,7 +1250,7 @@ int main(int argc, char *argv[]) { goto finish; } - if (path_is_os_tree(arg_directory) <= 0) { + if (arg_boot && path_is_os_tree(arg_directory) <= 0) { log_error("Directory %s doesn't look like an OS root directory (/etc/os-release is missing). Refusing.", arg_directory); goto finish; } @@ -1237,12 +1287,26 @@ int main(int argc, char *argv[]) { goto finish; } - ns = strappenda("machine-", arg_machine); - kdbus_fd = bus_kernel_create_domain(ns, &kdbus_domain); - if (r < 0) - log_debug("Failed to create kdbus domain: %s", strerror(-r)); - else - log_debug("Successfully created kdbus domain as %s", kdbus_domain); + + if (access("/dev/kdbus/control", F_OK) >= 0) { + + if (arg_share_system) { + kdbus_domain = strdup("/dev/kdbus"); + if (!kdbus_domain) { + log_oom(); + goto finish; + } + } else { + const char *ns; + + ns = strappenda("machine-", arg_machine); + kdbus_fd = bus_kernel_create_domain(ns, &kdbus_domain); + if (r < 0) + log_debug("Failed to create kdbus domain: %s", strerror(-r)); + else + log_debug("Successfully created kdbus domain as %s", kdbus_domain); + } + } if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, kmsg_socket_pair) < 0) { log_error("Failed to create kmsg socket pair: %m"); @@ -1264,7 +1328,10 @@ int main(int argc, char *argv[]) { goto finish; } - pid = syscall(__NR_clone, SIGCHLD|CLONE_NEWIPC|CLONE_NEWNS|CLONE_NEWPID|CLONE_NEWUTS|(arg_private_network ? CLONE_NEWNET : 0), NULL); + pid = syscall(__NR_clone, + SIGCHLD|CLONE_NEWNS| + (arg_share_system ? 0 : CLONE_NEWIPC|CLONE_NEWPID|CLONE_NEWUTS)| + (arg_private_network ? CLONE_NEWNET : 0), NULL); if (pid < 0) { if (errno == EINVAL) log_error("clone() failed, do you have namespace support enabled in your kernel? (You need UTS, IPC, PID and NET namespacing built in): %m"); @@ -1424,7 +1491,8 @@ int main(int argc, char *argv[]) { umask(0022); - loopback_setup(); + if (arg_private_network) + loopback_setup(); if (drop_capabilities() < 0) { log_error("drop_capabilities() failed: %m"); @@ -1535,9 +1603,9 @@ int main(int argc, char *argv[]) { env_use = (char**) envp; #ifdef HAVE_SELINUX - if (arg_process_label) - if (setexeccon(arg_process_label) < 0) - log_error("setexeccon(\"%s\") failed: %m", arg_process_label); + if (arg_selinux_context) + if (setexeccon(arg_selinux_context) < 0) + log_error("setexeccon(\"%s\") failed: %m", arg_selinux_context); #endif if (arg_boot) { char **a; @@ -1630,7 +1698,7 @@ int main(int argc, char *argv[]) { } else if (status.si_code == CLD_KILLED || status.si_code == CLD_DUMPED) { - log_error("Container %s terminated by signal %s.", arg_machine, signal_to_string(status.si_status)); + log_error("Container %s terminated by signal %s.", arg_machine, signal_to_string(status.si_status)); r = EXIT_FAILURE; break; } else {