X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fnspawn%2Fnspawn.c;h=2beb810e5def98b949e9305418d82878fdf8f96c;hb=d14b5bc621fc1fa57ef0db3ccba6957efed8e7d4;hp=d0e4ee785ce6740ee45e5f9ba129219aad808232;hpb=c09ef2e4e8331ddc7ee063d295c322a0939ea851;p=elogind.git diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index d0e4ee785..2beb810e5 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -816,6 +816,7 @@ static int mount_all(const char *dest) { { "devpts", "/dev/pts", "devpts","newinstance,ptmxmode=0666,mode=620,gid=" STRINGIFY(TTY_GID), MS_NOSUID|MS_NOEXEC, true }, { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true }, { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true }, + { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_STRICTATIME, true }, #ifdef HAVE_SELINUX { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND, false }, /* Bind mount first */ { NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, false }, /* Then, make it r/o */ @@ -913,8 +914,12 @@ static int mount_binds(const char *dest, char **l, bool ro) { 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); + if (S_ISDIR(source_st.st_mode) && !S_ISDIR(dest_st.st_mode)) { + log_error("Cannot bind mount directory %s on file %s.", *x, where); + return -EINVAL; + } + if (!S_ISDIR(source_st.st_mode) && S_ISDIR(dest_st.st_mode)) { + log_error("Cannot bind mount file %s on directory %s.", *x, where); return -EINVAL; } } else if (errno == ENOENT) { @@ -926,27 +931,18 @@ static int mount_binds(const char *dest, char **l, bool ro) { return -errno; } - /* Create the mount point, but be conservative -- refuse to create block - * and char devices. */ + /* Create the mount point. Any non-directory file can be + * mounted on any non-directory file (regular, fifo, socket, + * char, block). + */ if (S_ISDIR(source_st.st_mode)) { r = mkdir_label(where, 0755); if (r < 0 && errno != EEXIST) return log_error_errno(r, "Failed to create mount point %s: %m", where); - } else if (S_ISFIFO(source_st.st_mode)) { - r = mkfifo(where, 0644); - if (r < 0 && errno != EEXIST) - return log_error_errno(errno, "Failed to create mount point %s: %m", where); - } else if (S_ISSOCK(source_st.st_mode)) { - r = mknod(where, 0644 | S_IFSOCK, 0); - if (r < 0 && errno != EEXIST) - return log_error_errno(errno, "Failed to create mount point %s: %m", where); - } else if (S_ISREG(source_st.st_mode)) { + } else { r = touch(where); if (r < 0) return log_error_errno(r, "Failed to create mount point %s: %m", where); - } else { - log_error("Refusing to create mountpoint for file: %s", *x); - return -ENOTSUP; } if (mount(*x, where, "bind", MS_BIND, NULL) < 0) @@ -976,9 +972,17 @@ static int mount_cgroup_hierarchy(const char *dest, const char *controller, cons mkdir_p(to, 0755); - if (mount("cgroup", to, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV|(read_only ? MS_RDONLY : 0), controller) < 0) + /* The superblock mount options of the mount point need to be + * identical to the hosts', and hence writable... */ + if (mount("cgroup", to, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV, controller) < 0) return log_error_errno(errno, "Failed to mount to %s: %m", to); + /* ... hence let's only make the bind mount read-only, not the + * superblock. */ + if (read_only) { + if (mount(NULL, to, NULL, MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, NULL) < 0) + return log_error_errno(errno, "Failed to remount %s read-only: %m", to); + } return 1; } @@ -1048,7 +1052,7 @@ static int mount_cgroup(const char *dest) { } } - r = mount_cgroup_hierarchy(dest, "name=systemd", "systemd", false); + r = mount_cgroup_hierarchy(dest, "name=systemd,xattr", "systemd", false); if (r < 0) return r;