X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fnspawn%2Fnspawn.c;h=f0e7b0619fd6eb44958e8f4c0605e4f0fba86f48;hb=486e99a387adec15738c2822c2df5c813955f433;hp=a85579b9402a0c8310fd10cd8c4cb20055449c23;hpb=f4889f656b477887b02caa5e9d27387309c75a87;p=elogind.git diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index a85579b94..f0e7b0619 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -40,6 +40,7 @@ #include #include #include +#include #include "sd-daemon.h" #include "sd-bus.h" @@ -63,10 +64,7 @@ #include "ptyfwd.h" #include "bus-kernel.h" #include "env-util.h" - -#ifndef TTY_GID -#define TTY_GID 5 -#endif +#include "def.h" typedef enum LinkJournal { LINK_NO, @@ -109,7 +107,8 @@ static uint64_t arg_retain = (1ULL << CAP_SYS_RESOURCE) | (1ULL << CAP_SYS_BOOT) | (1ULL << CAP_AUDIT_WRITE) | - (1ULL << CAP_AUDIT_CONTROL); + (1ULL << CAP_AUDIT_CONTROL) | + (1ULL << CAP_MKNOD); static char **arg_bind = NULL; static char **arg_bind_ro = NULL; static char **arg_setenv = NULL; @@ -638,40 +637,30 @@ static int copy_devnodes(const char *dest) { u = umask(0000); NULSTR_FOREACH(d, devnodes) { - struct stat st; _cleanup_free_ char *from = NULL, *to = NULL; + struct stat st; - asprintf(&from, "/dev/%s", d); - asprintf(&to, "%s/dev/%s", dest, d); - - if (!from || !to) { - log_oom(); - - if (r == 0) - r = -ENOMEM; - - break; - } + from = strappend("/dev/", d); + to = strjoin(dest, "/dev/", d, NULL); + if (!from || !to) + return log_oom(); if (stat(from, &st) < 0) { if (errno != ENOENT) { log_error("Failed to stat %s: %m", from); - if (r == 0) - r = -errno; + return -errno; } } else if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) { log_error("%s is not a char or block device, cannot copy", from); - if (r == 0) - r = -EIO; + return -EIO; } else if (mknod(to, st.st_mode, st.st_rdev) < 0) { log_error("mknod(%s) failed: %m", dest); - if (r == 0) - r = -errno; + return -errno; } } @@ -985,7 +974,7 @@ static int setup_kdbus(const char *dest, const char *path) { } if (mount(path, p, "bind", MS_BIND, NULL) < 0) { - log_error("Failed to mount kdbus namespace path: %m"); + log_error("Failed to mount kdbus domain path: %m"); return -errno; } @@ -996,7 +985,7 @@ static int drop_capabilities(void) { return capability_bounding_set_drop(~arg_retain, false); } -static int register_machine(void) { +static int register_machine(pid_t pid) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_unref_ sd_bus *bus = NULL; int r; @@ -1020,7 +1009,7 @@ static int register_machine(void) { SD_BUS_MESSAGE_APPEND_ID128(arg_uuid), "nspawn", "container", - (uint32_t) 0, + (uint32_t) pid, strempty(arg_directory), !isempty(arg_slice), "Slice", "s", arg_slice); if (r < 0) { @@ -1097,13 +1086,13 @@ static bool audit_enabled(void) { int main(int argc, char *argv[]) { pid_t pid = 0; int r = EXIT_FAILURE, k; - _cleanup_close_ int master = -1, kdbus_fd = -1; + _cleanup_close_ int master = -1, kdbus_fd = -1, sync_fd = -1; int n_fd_passed; const char *console = NULL; sigset_t mask; _cleanup_close_pipe_ int kmsg_socket_pair[2] = { -1, -1 }; _cleanup_fdset_free_ FDSet *fds = NULL; - _cleanup_free_ char *kdbus_namespace = NULL; + _cleanup_free_ char *kdbus_domain = NULL; const char *ns; log_parse_environment(); @@ -1206,14 +1195,14 @@ int main(int argc, char *argv[]) { } ns = strappenda("machine-", arg_machine); - kdbus_fd = bus_kernel_create_namespace(ns, &kdbus_namespace); + kdbus_fd = bus_kernel_create_domain(ns, &kdbus_domain); if (r < 0) - log_debug("Failed to create kdbus namespace: %s", strerror(-r)); + log_debug("Failed to create kdbus domain: %s", strerror(-r)); else - log_debug("Successfully created kdbus namespace as %s", kdbus_namespace); + 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."); + log_error("Failed to create kmsg socket pair: %m"); goto finish; } @@ -1226,6 +1215,12 @@ int main(int argc, char *argv[]) { for (;;) { siginfo_t status; + sync_fd = eventfd(0, EFD_CLOEXEC); + if (sync_fd < 0) { + log_error("Failed to create event fd: %m"); + goto finish; + } + pid = syscall(__NR_clone, SIGCHLD|CLONE_NEWIPC|CLONE_NEWNS|CLONE_NEWPID|CLONE_NEWUTS|(arg_private_network ? CLONE_NEWNET : 0), NULL); if (pid < 0) { if (errno == EINVAL) @@ -1243,7 +1238,7 @@ int main(int argc, char *argv[]) { gid_t gid = (gid_t) -1; unsigned n_env = 2; const char *envp[] = { - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", + "PATH=" DEFAULT_PATH_SPLIT_USR, "container=systemd-nspawn", /* LXC sets container=lxc, so follow the scheme here */ NULL, /* TERM */ NULL, /* HOME */ @@ -1255,6 +1250,7 @@ int main(int argc, char *argv[]) { NULL }; char **env_use; + eventfd_t x; envp[n_env] = strv_find_prefix(environ, "TERM="); if (envp[n_env]) @@ -1302,10 +1298,6 @@ int main(int argc, char *argv[]) { goto child_fail; } - r = register_machine(); - if (r < 0) - goto finish; - /* Mark everything as slave, so that we still * receive mounts from the real root, but don't * propagate mounts to the real root. */ @@ -1364,7 +1356,7 @@ int main(int argc, char *argv[]) { if (mount_binds(arg_directory, arg_bind_ro, MS_RDONLY) < 0) goto child_fail; - if (setup_kdbus(arg_directory, kdbus_namespace) < 0) + if (setup_kdbus(arg_directory, kdbus_domain) < 0) goto child_fail; if (chdir(arg_directory) < 0) { @@ -1482,6 +1474,10 @@ int main(int argc, char *argv[]) { setup_hostname(); + eventfd_read(sync_fd, &x); + close_nointr_nofail(sync_fd); + sync_fd = -1; + if (!strv_isempty(arg_setenv)) { char **n; @@ -1529,6 +1525,14 @@ int main(int argc, char *argv[]) { fdset_free(fds); fds = NULL; + r = register_machine(pid); + if (r < 0) + goto finish; + + eventfd_write(sync_fd, 1); + close_nointr_nofail(sync_fd); + sync_fd = -1; + k = process_pty(master, &mask, arg_boot ? pid : 0, SIGRTMIN+3); if (k < 0) { r = EXIT_FAILURE;