X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fnspawn%2Fnspawn.c;h=583912f57c51bb3c0b40c7646896c69c5e374ffb;hb=cde93897cdefdd7c7f66c400a61e42ceee5f6a46;hp=cd757c497b73ee63867b855aba686c1f94e90ea9;hpb=898d5c913733d869820f85422a903da0f0685c6c;p=elogind.git diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index cd757c497..583912f57 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -61,6 +61,7 @@ #include "bus-util.h" #include "bus-error.h" #include "ptyfwd.h" +#include "bus-kernel.h" #ifndef TTY_GID #define TTY_GID 5 @@ -417,39 +418,46 @@ static int mount_binds(const char *dest, char **l, unsigned long flags) { char **x, **y; STRV_FOREACH_PAIR(x, y, l) { - _cleanup_free_ char *where = NULL; + char *where; struct stat source_st, dest_st; + int r; if (stat(*x, &source_st) < 0) { log_error("failed to stat %s: %m", *x); return -errno; } - where = strjoin(dest, "/", *y, NULL); - if (!where) - return log_oom(); - - if (stat(where, &dest_st) == 0) { + where = strappenda(dest, *y); + r = stat(where, &dest_st); + if (r == 0) { if ((source_st.st_mode & S_IFMT) != (dest_st.st_mode & S_IFMT)) { log_error("The file types of %s and %s do not match. Refusing bind mount", *x, where); return -EINVAL; } - } else { - /* Create the mount point, but be conservative -- refuse to create block - * and char devices. */ - if (S_ISDIR(source_st.st_mode)) - mkdir_p_label(where, 0755); - else if (S_ISFIFO(source_st.st_mode)) - mkfifo(where, 0644); - else if (S_ISSOCK(source_st.st_mode)) - mknod(where, 0644 | S_IFSOCK, 0); - else if (S_ISREG(source_st.st_mode)) - touch(where); - else { - log_error("Refusing to create mountpoint for file: %s", *x); - return -ENOTSUP; + } else if (errno == ENOENT) { + r = mkdir_parents_label(where, 0755); + if (r < 0) { + log_error("Failed to bind mount %s: %s", *x, strerror(-r)); + return r; } + } else { + log_error("Failed to bind mount %s: %s", *x, strerror(errno)); + return -errno; + } + /* Create the mount point, but be conservative -- refuse to create block + * and char devices. */ + if (S_ISDIR(source_st.st_mode)) + mkdir_label(where, 0755); + else if (S_ISFIFO(source_st.st_mode)) + mkfifo(where, 0644); + else if (S_ISSOCK(source_st.st_mode)) + mknod(where, 0644 | S_IFSOCK, 0); + else if (S_ISREG(source_st.st_mode)) + touch(where); + else { + log_error("Refusing to create mountpoint for file: %s", *x); + return -ENOTSUP; } if (mount(*x, where, "bind", MS_BIND, NULL) < 0) { @@ -927,6 +935,26 @@ static int setup_journal(const char *directory) { return 0; } +static int setup_kdbus(const char *dest, const char *path) { + const char *p; + + if (!path) + return 0; + + p = strappenda(dest, "/dev/kdbus"); + if (mkdir(p, 0755) < 0) { + log_error("Failed to create kdbus path: %m"); + return -errno; + } + + if (mount(path, p, "bind", MS_BIND, NULL) < 0) { + log_error("Failed to mount kdbus namespace path: %m"); + return -errno; + } + + return 0; +} + static int drop_capabilities(void) { return capability_bounding_set_drop(~arg_retain, false); } @@ -1032,12 +1060,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; + _cleanup_close_ int master = -1, kdbus_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; log_parse_environment(); log_open(); @@ -1067,7 +1096,7 @@ int main(int argc, char *argv[]) { path_kill_slashes(arg_directory); if (!arg_machine) { - arg_machine = strdup(path_get_file_name(arg_directory)); + arg_machine = strdup(basename(arg_directory)); if (!arg_machine) { log_oom(); goto finish; @@ -1138,6 +1167,12 @@ int main(int argc, char *argv[]) { goto finish; } + kdbus_fd = bus_kernel_create_namespace(arg_machine, &kdbus_namespace); + if (r < 0) + log_debug("Failed to create kdbus namespace: %s", strerror(-r)); + else + log_debug("Successfully created kdbus namespace as %s", kdbus_namespace); + if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, kmsg_socket_pair) < 0) { log_error("Failed to create kmsg socket pair."); goto finish; @@ -1289,6 +1324,9 @@ 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) + goto child_fail; + if (chdir(arg_directory) < 0) { log_error("chdir(%s) failed: %m", arg_directory); goto child_fail;