X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fnspawn%2Fnspawn.c;h=1e6e7bf302c2e6745f551750ce55a9cb2c019278;hb=63c372cb9df3bee01e3bf8cd7f96f336bddda846;hp=d0e4ee785ce6740ee45e5f9ba129219aad808232;hpb=c09ef2e4e8331ddc7ee063d295c322a0939ea851;p=elogind.git diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index d0e4ee785..1e6e7bf30 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) @@ -966,7 +962,7 @@ static int mount_cgroup_hierarchy(const char *dest, const char *controller, cons char *to; int r; - to = strappenda(dest, "/sys/fs/cgroup/", hierarchy); + to = strjoina(dest, "/sys/fs/cgroup/", hierarchy); r = path_is_mount_point(to, false); if (r < 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; } @@ -1000,7 +1004,7 @@ static int mount_cgroup(const char *dest) { if (r < 0) return log_error_errno(r, "Failed to determine our own cgroup path: %m"); - cgroup_root = strappenda(dest, "/sys/fs/cgroup"); + cgroup_root = strjoina(dest, "/sys/fs/cgroup"); if (mount("tmpfs", cgroup_root, "tmpfs", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, "mode=755") < 0) return log_error_errno(errno, "Failed to mount tmpfs to /sys/fs/cgroup: %m"); @@ -1048,17 +1052,17 @@ 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; /* Make our own cgroup a (writable) bind mount */ - systemd_own = strappenda(dest, "/sys/fs/cgroup/systemd", own_cgroup_path); + systemd_own = strjoina(dest, "/sys/fs/cgroup/systemd", own_cgroup_path); if (mount(systemd_own, systemd_own, NULL, MS_BIND, NULL) < 0) return log_error_errno(errno, "Failed to turn %s into a bind mount: %m", own_cgroup_path); /* And then remount the systemd cgroup root read-only */ - systemd_root = strappenda(dest, "/sys/fs/cgroup/systemd"); + systemd_root = strjoina(dest, "/sys/fs/cgroup/systemd"); if (mount(NULL, systemd_root, NULL, MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, NULL) < 0) return log_error_errno(errno, "Failed to mount cgroup root read-only: %m"); @@ -1211,7 +1215,7 @@ static int setup_volatile_state(const char *directory) { if (r < 0) return log_error_errno(r, "Failed to remount %s read-only: %m", directory); - p = strappenda(directory, "/var"); + p = strjoina(directory, "/var"); r = mkdir(p, 0755); if (r < 0 && errno != EEXIST) return log_error_errno(errno, "Failed to create %s: %m", directory); @@ -1247,8 +1251,8 @@ static int setup_volatile(const char *directory) { tmpfs_mounted = true; - f = strappenda(directory, "/usr"); - t = strappenda(template, "/usr"); + f = strjoina(directory, "/usr"); + t = strjoina(template, "/usr"); r = mkdir(t, 0755); if (r < 0 && errno != EEXIST) { @@ -1430,7 +1434,7 @@ static int setup_dev_console(const char *dest, const char *console) { * /dev/console. (Note that the major minor doesn't actually * matter here, since we mount it over anyway). */ - to = strappenda(dest, "/dev/console"); + to = strjoina(dest, "/dev/console"); if (mknod(to, (st.st_mode & ~07777) | 0600, st.st_rdev) < 0) return log_error_errno(errno, "mknod() for /dev/console failed: %m"); @@ -2560,10 +2564,10 @@ static int setup_propagate(const char *root) { (void) mkdir_p("/run/systemd/nspawn/", 0755); (void) mkdir_p("/run/systemd/nspawn/propagate", 0600); - p = strappenda("/run/systemd/nspawn/propagate/", arg_machine); + p = strjoina("/run/systemd/nspawn/propagate/", arg_machine); (void) mkdir_p(p, 0600); - q = strappenda(root, "/run/systemd/nspawn/incoming"); + q = strjoina(root, "/run/systemd/nspawn/incoming"); mkdir_parents(q, 0755); mkdir_p(q, 0600); @@ -3046,7 +3050,7 @@ static int mount_device(const char *what, const char *where, const char *directo rw = false; if (directory) - p = strappenda(where, directory); + p = strjoina(where, directory); else p = where; @@ -3606,7 +3610,6 @@ int main(int argc, char *argv[]) { } if (arg_ephemeral) { - _cleanup_release_lock_file_ LockFile original_lock = LOCK_FILE_INIT; char *np; /* If the specified path is a mount point we @@ -3682,7 +3685,7 @@ int main(int argc, char *argv[]) { } else { const char *p; - p = strappenda(arg_directory, + p = strjoina(arg_directory, argc > optind && path_is_absolute(argv[optind]) ? argv[optind] : "/usr/bin/"); if (access(p, F_OK) < 0) { log_error("Directory %s lacks the binary to execute or doesn't look like a binary tree. Refusing.", arg_directory); @@ -4291,7 +4294,7 @@ finish: if (arg_machine) { const char *p; - p = strappenda("/run/systemd/nspawn/propagate/", arg_machine); + p = strjoina("/run/systemd/nspawn/propagate/", arg_machine); (void) rm_rf(p, false, true, false); }