X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fnspawn%2Fnspawn.c;h=97ef6c799d4281705e97e4533c6f60feb7bda604;hb=89f7c8465cd1ab37347dd0c15920bce31e8225df;hp=759f9c1aef046729ced5bfdadac8ab3066dda296;hpb=8a96d94e4c33173d1426b7e0a6325405804ba224;p=elogind.git diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 759f9c1ae..97ef6c799 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -119,6 +119,8 @@ 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 bool arg_keep_unit = false; static int help(void) { @@ -150,6 +152,9 @@ 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" + " --keep-unit Do not register a scope for the machine, reuse\n" + " the service unit nspawn is running in\n" " -q --quiet Do not show status information\n", program_invocation_short_name); @@ -169,7 +174,9 @@ static int parse_argv(int argc, char *argv[]) { ARG_BIND, ARG_BIND_RO, ARG_SETENV, - ARG_SHARE_SYSTEM + ARG_SHARE_SYSTEM, + ARG_REGISTER, + ARG_KEEP_UNIT }; static const struct option options[] = { @@ -193,6 +200,8 @@ static int parse_argv(int argc, char *argv[]) { { "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 }, + { "keep-unit", no_argument, NULL, ARG_KEEP_UNIT }, {} }; @@ -255,17 +264,23 @@ 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(); + + break; + } case 'Z': arg_selinux_context = optarg; @@ -390,6 +405,20 @@ static int parse_argv(int argc, char *argv[]) { 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 ARG_KEEP_UNIT: + arg_keep_unit = true; + break; + case '?': return -EINVAL; @@ -398,6 +427,19 @@ 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; + } + + 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; + } + return 1; } @@ -636,6 +678,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 */ @@ -861,6 +906,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; @@ -1043,28 +1091,50 @@ 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)); return r; } - r = sd_bus_call_method( - bus, - "org.freedesktop.machine1", - "/org/freedesktop/machine1", - "org.freedesktop.machine1.Manager", - "CreateMachine", - &error, - NULL, - "sayssusa(sv)", - arg_machine, - SD_BUS_MESSAGE_APPEND_ID128(arg_uuid), - "nspawn", - "container", - (uint32_t) pid, - strempty(arg_directory), - !isempty(arg_slice), "Slice", "s", arg_slice); + if (arg_keep_unit) { + r = sd_bus_call_method( + bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "RegisterMachine", + &error, + NULL, + "sayssus", + arg_machine, + SD_BUS_MESSAGE_APPEND_ID128(arg_uuid), + "nspawn", + "container", + (uint32_t) pid, + strempty(arg_directory)); + } else { + r = sd_bus_call_method( + bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "CreateMachine", + &error, + NULL, + "sayssusa(sv)", + arg_machine, + SD_BUS_MESSAGE_APPEND_ID128(arg_uuid), + "nspawn", + "container", + (uint32_t) pid, + strempty(arg_directory), + !isempty(arg_slice), "Slice", "s", arg_slice); + } + if (r < 0) { log_error("Failed to register machine: %s", bus_error_message(&error, r)); return r; @@ -1080,6 +1150,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)); @@ -1146,7 +1219,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(); @@ -1248,12 +1320,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"); @@ -1438,7 +1524,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"); @@ -1644,7 +1731,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 {