(backport) nspawn: Move cgroup mount stuff from nspawn-mount.c to nspawn-cgroup.c
authorLuke Shumaker <lukeshu@parabola.nu>
Fri, 7 Jul 2017 22:57:08 +0000 (18:57 -0400)
committerŁukasz Stelmach <l.stelmach@samsung.com>
Mon, 12 Feb 2024 15:37:46 +0000 (16:37 +0100)
Change-Id: Iaf44ed696c287b1cc0aa7a8c79773095a3c1ecc6

src/nspawn/nspawn-cgroup.c
src/nspawn/nspawn-cgroup.h
src/nspawn/nspawn-mount.c
src/nspawn/nspawn-mount.h

index d8a39a6..0be9119 100644 (file)
@@ -5,12 +5,16 @@
 #include "alloc-util.h"
 #include "fd-util.h"
 #include "fileio.h"
+#include "fs-util.h"
 #include "mkdir.h"
 #include "mount-util.h"
 #include "nspawn-cgroup.h"
+#include "nspawn-mount.h"
+#include "path-util.h"
 #include "rm-rf.h"
 #include "string-util.h"
 #include "strv.h"
+#include "user-util.h"
 #include "util.h"
 
 static int chown_cgroup_path(const char *path, uid_t uid_shift) {
@@ -188,3 +192,416 @@ int create_subcgroup(pid_t pid, bool keep_unit, CGroupUnified unified_requested)
         (void) cg_enable_everywhere(supported, supported, cgroup);
         return 0;
 }
+
+/* Retrieve existing subsystems. This function is called in a new cgroup
+ * namespace.
+ */
+static int get_process_controllers(Set **ret) {
+        _cleanup_set_free_free_ Set *controllers = NULL;
+        _cleanup_fclose_ FILE *f = NULL;
+        int r;
+
+        assert(ret);
+
+        controllers = set_new(&string_hash_ops);
+        if (!controllers)
+                return -ENOMEM;
+
+        f = fopen("/proc/self/cgroup", "re");
+        if (!f)
+                return errno == ENOENT ? -ESRCH : -errno;
+
+        for (;;) {
+                _cleanup_free_ char *line = NULL;
+                char *e, *l;
+
+                r = read_line(f, LONG_LINE_MAX, &line);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        break;
+
+                l = strchr(line, ':');
+                if (!l)
+                        continue;
+
+                l++;
+                e = strchr(l, ':');
+                if (!e)
+                        continue;
+
+                *e = 0;
+
+                if (STR_IN_SET(l, "", "name=systemd", "name=unified"))
+                        continue;
+
+                r = set_put_strdup(controllers, l);
+                if (r < 0)
+                        return r;
+        }
+
+        *ret = TAKE_PTR(controllers);
+
+        return 0;
+}
+
+static int mount_legacy_cgroup_hierarchy(
+                const char *dest,
+                const char *controller,
+                const char *hierarchy,
+                bool read_only) {
+
+        const char *to, *fstype, *opts;
+        int r;
+
+        to = strjoina(strempty(dest), "/sys/fs/cgroup/", hierarchy);
+
+        r = path_is_mount_point(to, dest, 0);
+        if (r < 0 && r != -ENOENT)
+                return log_error_errno(r, "Failed to determine if %s is mounted already: %m", to);
+        if (r > 0)
+                return 0;
+
+        mkdir_p(to, 0755);
+
+        /* The superblock mount options of the mount point need to be
+         * identical to the hosts', and hence writable... */
+        if (streq(controller, SYSTEMD_CGROUP_CONTROLLER_HYBRID)) {
+                fstype = "cgroup2";
+                opts = NULL;
+        } else if (streq(controller, SYSTEMD_CGROUP_CONTROLLER_LEGACY)) {
+                fstype = "cgroup";
+                opts = "none,name=systemd,xattr";
+        } else {
+                fstype = "cgroup";
+                opts = controller;
+        }
+
+        r = mount_verbose(LOG_ERR, "cgroup", to, fstype, MS_NOSUID|MS_NOEXEC|MS_NODEV, opts);
+        if (r < 0)
+                return r;
+
+        /* ... hence let's only make the bind mount read-only, not the superblock. */
+        if (read_only) {
+                r = mount_verbose(LOG_ERR, NULL, to, NULL,
+                                  MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, NULL);
+                if (r < 0)
+                        return r;
+        }
+
+        return 1;
+}
+
+/* Mount a legacy cgroup hierarchy when cgroup namespaces are supported. */
+static int mount_legacy_cgns_supported(
+                const char *dest,
+                CGroupUnified unified_requested,
+                bool userns,
+                uid_t uid_shift,
+                uid_t uid_range,
+                const char *selinux_apifs_context) {
+
+        _cleanup_set_free_free_ Set *controllers = NULL;
+        const char *cgroup_root = "/sys/fs/cgroup", *c;
+        int r;
+
+        (void) mkdir_p(cgroup_root, 0755);
+
+        /* Mount a tmpfs to /sys/fs/cgroup if it's not mounted there yet. */
+        r = path_is_mount_point(cgroup_root, dest, AT_SYMLINK_FOLLOW);
+        if (r < 0)
+                return log_error_errno(r, "Failed to determine if /sys/fs/cgroup is already mounted: %m");
+        if (r == 0) {
+                _cleanup_free_ char *options = NULL;
+
+                /* When cgroup namespaces are enabled and user namespaces are
+                 * used then the mount of the cgroupfs is done *inside* the new
+                 * user namespace. We're root in the new user namespace and the
+                 * kernel will happily translate our uid/gid to the correct
+                 * uid/gid as seen from e.g. /proc/1/mountinfo. So we simply
+                 * pass uid 0 and not uid_shift to tmpfs_patch_options().
+                 */
+                r = tmpfs_patch_options("mode=755", 0, selinux_apifs_context, &options);
+                if (r < 0)
+                        return log_oom();
+
+                r = mount_verbose(LOG_ERR, "tmpfs", cgroup_root, "tmpfs",
+                                  MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, options);
+                if (r < 0)
+                        return r;
+        }
+
+        r = cg_all_unified();
+        if (r < 0)
+                return r;
+        if (r > 0)
+                goto skip_controllers;
+
+        r = get_process_controllers(&controllers);
+        if (r < 0)
+                return log_error_errno(r, "Failed to determine cgroup controllers: %m");
+
+        for (;;) {
+                _cleanup_free_ const char *controller = NULL;
+
+                controller = set_steal_first(controllers);
+                if (!controller)
+                        break;
+
+                r = mount_legacy_cgroup_hierarchy("", controller, controller, !userns);
+                if (r < 0)
+                        return r;
+
+                /* When multiple hierarchies are co-mounted, make their
+                 * constituting individual hierarchies a symlink to the
+                 * co-mount.
+                 */
+                c = controller;
+                for (;;) {
+                        _cleanup_free_ char *target = NULL, *tok = NULL;
+
+                        r = extract_first_word(&c, &tok, ",", 0);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to extract co-mounted cgroup controller: %m");
+                        if (r == 0)
+                                break;
+
+                        if (streq(controller, tok))
+                                break;
+
+                        target = prefix_root("/sys/fs/cgroup/", tok);
+                        if (!target)
+                                return log_oom();
+
+                        r = symlink_idempotent(controller, target);
+                        if (r == -EINVAL)
+                                return log_error_errno(r, "Invalid existing symlink for combined hierarchy: %m");
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to create symlink for combined hierarchy: %m");
+                }
+        }
+
+skip_controllers:
+        if (unified_requested >= CGROUP_UNIFIED_SYSTEMD) {
+                r = mount_legacy_cgroup_hierarchy("", SYSTEMD_CGROUP_CONTROLLER_HYBRID, "unified", false);
+                if (r < 0)
+                        return r;
+        }
+
+        r = mount_legacy_cgroup_hierarchy("", SYSTEMD_CGROUP_CONTROLLER_LEGACY, "systemd", false);
+        if (r < 0)
+                return r;
+
+        if (!userns)
+                return mount_verbose(LOG_ERR, NULL, cgroup_root, NULL,
+                                     MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755");
+
+        return 0;
+}
+
+/* Mount legacy cgroup hierarchy when cgroup namespaces are unsupported. */
+static int mount_legacy_cgns_unsupported(
+                const char *dest,
+                CGroupUnified unified_requested,
+                bool userns,
+                uid_t uid_shift,
+                uid_t uid_range,
+                const char *selinux_apifs_context) {
+
+        _cleanup_set_free_free_ Set *controllers = NULL;
+        const char *cgroup_root;
+        int r;
+
+        cgroup_root = prefix_roota(dest, "/sys/fs/cgroup");
+
+        (void) mkdir_p(cgroup_root, 0755);
+
+        /* Mount a tmpfs to /sys/fs/cgroup if it's not mounted there yet. */
+        r = path_is_mount_point(cgroup_root, dest, AT_SYMLINK_FOLLOW);
+        if (r < 0)
+                return log_error_errno(r, "Failed to determine if /sys/fs/cgroup is already mounted: %m");
+        if (r == 0) {
+                _cleanup_free_ char *options = NULL;
+
+                r = tmpfs_patch_options("mode=755", uid_shift == 0 ? UID_INVALID : uid_shift, selinux_apifs_context, &options);
+                if (r < 0)
+                        return log_oom();
+
+                r = mount_verbose(LOG_ERR, "tmpfs", cgroup_root, "tmpfs",
+                                  MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, options);
+                if (r < 0)
+                        return r;
+        }
+
+        r = cg_all_unified();
+        if (r < 0)
+                return r;
+        if (r > 0)
+                goto skip_controllers;
+
+        r = cg_kernel_controllers(&controllers);
+        if (r < 0)
+                return log_error_errno(r, "Failed to determine cgroup controllers: %m");
+
+        for (;;) {
+                _cleanup_free_ char *controller = NULL, *origin = NULL, *combined = NULL;
+
+                controller = set_steal_first(controllers);
+                if (!controller)
+                        break;
+
+                origin = prefix_root("/sys/fs/cgroup/", controller);
+                if (!origin)
+                        return log_oom();
+
+                r = readlink_malloc(origin, &combined);
+                if (r == -EINVAL) {
+                        /* Not a symbolic link, but directly a single cgroup hierarchy */
+
+                        r = mount_legacy_cgroup_hierarchy(dest, controller, controller, true);
+                        if (r < 0)
+                                return r;
+
+                } else if (r < 0)
+                        return log_error_errno(r, "Failed to read link %s: %m", origin);
+                else {
+                        _cleanup_free_ char *target = NULL;
+
+                        target = prefix_root(dest, origin);
+                        if (!target)
+                                return log_oom();
+
+                        /* A symbolic link, a combination of controllers in one hierarchy */
+
+                        if (!filename_is_valid(combined)) {
+                                log_warning("Ignoring invalid combined hierarchy %s.", combined);
+                                continue;
+                        }
+
+                        r = mount_legacy_cgroup_hierarchy(dest, combined, combined, true);
+                        if (r < 0)
+                                return r;
+
+                        r = symlink_idempotent(combined, target);
+                        if (r == -EINVAL)
+                                return log_error_errno(r, "Invalid existing symlink for combined hierarchy: %m");
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to create symlink for combined hierarchy: %m");
+                }
+        }
+
+skip_controllers:
+        if (unified_requested >= CGROUP_UNIFIED_SYSTEMD) {
+                r = mount_legacy_cgroup_hierarchy(dest, SYSTEMD_CGROUP_CONTROLLER_HYBRID, "unified", false);
+                if (r < 0)
+                        return r;
+        }
+
+        r = mount_legacy_cgroup_hierarchy(dest, SYSTEMD_CGROUP_CONTROLLER_LEGACY, "systemd", false);
+        if (r < 0)
+                return r;
+
+        return mount_verbose(LOG_ERR, NULL, cgroup_root, NULL,
+                             MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755");
+}
+
+static int mount_unified_cgroups(const char *dest) {
+        const char *p;
+        int r;
+
+        assert(dest);
+
+        p = prefix_roota(dest, "/sys/fs/cgroup");
+
+        (void) mkdir_p(p, 0755);
+
+        r = path_is_mount_point(p, dest, AT_SYMLINK_FOLLOW);
+        if (r < 0)
+                return log_error_errno(r, "Failed to determine if %s is mounted already: %m", p);
+        if (r > 0) {
+                p = prefix_roota(dest, "/sys/fs/cgroup/cgroup.procs");
+                if (access(p, F_OK) >= 0)
+                        return 0;
+                if (errno != ENOENT)
+                        return log_error_errno(errno, "Failed to determine if mount point %s contains the unified cgroup hierarchy: %m", p);
+
+                log_error("%s is already mounted but not a unified cgroup hierarchy. Refusing.", p);
+                return -EINVAL;
+        }
+
+        return mount_verbose(LOG_ERR, "cgroup", p, "cgroup2", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL);
+}
+
+int mount_cgroups(
+                const char *dest,
+                CGroupUnified unified_requested,
+                bool userns,
+                uid_t uid_shift,
+                uid_t uid_range,
+                const char *selinux_apifs_context,
+                bool use_cgns) {
+
+        if (unified_requested >= CGROUP_UNIFIED_ALL)
+                return mount_unified_cgroups(dest);
+        if (use_cgns)
+                return mount_legacy_cgns_supported(dest, unified_requested, userns, uid_shift, uid_range, selinux_apifs_context);
+
+        return mount_legacy_cgns_unsupported(dest, unified_requested, userns, uid_shift, uid_range, selinux_apifs_context);
+}
+
+static int mount_systemd_cgroup_writable_one(const char *root, const char *own) {
+        int r;
+
+        assert(root);
+        assert(own);
+
+        /* Make our own cgroup a (writable) bind mount */
+        r = mount_verbose(LOG_ERR, own, own, NULL, MS_BIND, NULL);
+        if (r < 0)
+                return r;
+
+        /* And then remount the systemd cgroup root read-only */
+        return mount_verbose(LOG_ERR, NULL, root, NULL,
+                             MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, NULL);
+}
+
+int mount_systemd_cgroup_writable(
+                const char *dest,
+                CGroupUnified unified_requested) {
+
+        _cleanup_free_ char *own_cgroup_path = NULL;
+        const char *root, *own;
+        int r;
+
+        assert(dest);
+
+        r = cg_pid_get_path(NULL, 0, &own_cgroup_path);
+        if (r < 0)
+                return log_error_errno(r, "Failed to determine our own cgroup path: %m");
+
+        /* If we are living in the top-level, then there's nothing to do... */
+        if (path_equal(own_cgroup_path, "/"))
+                return 0;
+
+        if (unified_requested >= CGROUP_UNIFIED_ALL) {
+
+                root = prefix_roota(dest, "/sys/fs/cgroup");
+                own = strjoina(root, own_cgroup_path);
+
+        } else {
+
+                if (unified_requested >= CGROUP_UNIFIED_SYSTEMD) {
+                        root = prefix_roota(dest, "/sys/fs/cgroup/unified");
+                        own = strjoina(root, own_cgroup_path);
+
+                        r = mount_systemd_cgroup_writable_one(root, own);
+                        if (r < 0)
+                                return r;
+                }
+
+                root = prefix_roota(dest, "/sys/fs/cgroup/systemd");
+                own = strjoina(root, own_cgroup_path);
+        }
+
+        return mount_systemd_cgroup_writable_one(root, own);
+}
index 6783c3a..035e8fb 100644 (file)
@@ -9,3 +9,6 @@
 int chown_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t uid_shift);
 int sync_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t uid_shift);
 int create_subcgroup(pid_t pid, bool keep_unit, CGroupUnified unified_requested);
+
+int mount_cgroups(const char *dest, CGroupUnified unified_requested, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context, bool use_cgns);
+int mount_systemd_cgroup_writable(const char *dest, CGroupUnified unified_requested);
index 2c16946..1423f75 100644 (file)
@@ -327,7 +327,7 @@ int overlay_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_onl
         return 0;
 }
 
-static int tmpfs_patch_options(
+int tmpfs_patch_options(
                 const char *options,
                 uid_t uid_shift,
                 const char *selinux_apifs_context,
@@ -853,419 +853,6 @@ int mount_custom(
         return 0;
 }
 
-/* Retrieve existing subsystems. This function is called in a new cgroup
- * namespace.
- */
-static int get_process_controllers(Set **ret) {
-        _cleanup_set_free_free_ Set *controllers = NULL;
-        _cleanup_fclose_ FILE *f = NULL;
-        int r;
-
-        assert(ret);
-
-        controllers = set_new(&string_hash_ops);
-        if (!controllers)
-                return -ENOMEM;
-
-        f = fopen("/proc/self/cgroup", "re");
-        if (!f)
-                return errno == ENOENT ? -ESRCH : -errno;
-
-        for (;;) {
-                _cleanup_free_ char *line = NULL;
-                char *e, *l;
-
-                r = read_line(f, LONG_LINE_MAX, &line);
-                if (r < 0)
-                        return r;
-                if (r == 0)
-                        break;
-
-                l = strchr(line, ':');
-                if (!l)
-                        continue;
-
-                l++;
-                e = strchr(l, ':');
-                if (!e)
-                        continue;
-
-                *e = 0;
-
-                if (STR_IN_SET(l, "", "name=systemd", "name=unified"))
-                        continue;
-
-                r = set_put_strdup(controllers, l);
-                if (r < 0)
-                        return r;
-        }
-
-        *ret = TAKE_PTR(controllers);
-
-        return 0;
-}
-
-static int mount_legacy_cgroup_hierarchy(
-                const char *dest,
-                const char *controller,
-                const char *hierarchy,
-                bool read_only) {
-
-        const char *to, *fstype, *opts;
-        int r;
-
-        to = strjoina(strempty(dest), "/sys/fs/cgroup/", hierarchy);
-
-        r = path_is_mount_point(to, dest, 0);
-        if (r < 0 && r != -ENOENT)
-                return log_error_errno(r, "Failed to determine if %s is mounted already: %m", to);
-        if (r > 0)
-                return 0;
-
-        mkdir_p(to, 0755);
-
-        /* The superblock mount options of the mount point need to be
-         * identical to the hosts', and hence writable... */
-        if (streq(controller, SYSTEMD_CGROUP_CONTROLLER_HYBRID)) {
-                fstype = "cgroup2";
-                opts = NULL;
-        } else if (streq(controller, SYSTEMD_CGROUP_CONTROLLER_LEGACY)) {
-                fstype = "cgroup";
-                opts = "none,name=systemd,xattr";
-        } else {
-                fstype = "cgroup";
-                opts = controller;
-        }
-
-        r = mount_verbose(LOG_ERR, "cgroup", to, fstype, MS_NOSUID|MS_NOEXEC|MS_NODEV, opts);
-        if (r < 0)
-                return r;
-
-        /* ... hence let's only make the bind mount read-only, not the superblock. */
-        if (read_only) {
-                r = mount_verbose(LOG_ERR, NULL, to, NULL,
-                                  MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, NULL);
-                if (r < 0)
-                        return r;
-        }
-
-        return 1;
-}
-
-/* Mount a legacy cgroup hierarchy when cgroup namespaces are supported. */
-static int mount_legacy_cgns_supported(
-                const char *dest,
-                CGroupUnified unified_requested,
-                bool userns,
-                uid_t uid_shift,
-                uid_t uid_range,
-                const char *selinux_apifs_context) {
-
-        _cleanup_set_free_free_ Set *controllers = NULL;
-        const char *cgroup_root = "/sys/fs/cgroup", *c;
-        int r;
-
-        (void) mkdir_p(cgroup_root, 0755);
-
-        /* Mount a tmpfs to /sys/fs/cgroup if it's not mounted there yet. */
-        r = path_is_mount_point(cgroup_root, dest, AT_SYMLINK_FOLLOW);
-        if (r < 0)
-                return log_error_errno(r, "Failed to determine if /sys/fs/cgroup is already mounted: %m");
-        if (r == 0) {
-                _cleanup_free_ char *options = NULL;
-
-                /* When cgroup namespaces are enabled and user namespaces are
-                 * used then the mount of the cgroupfs is done *inside* the new
-                 * user namespace. We're root in the new user namespace and the
-                 * kernel will happily translate our uid/gid to the correct
-                 * uid/gid as seen from e.g. /proc/1/mountinfo. So we simply
-                 * pass uid 0 and not uid_shift to tmpfs_patch_options().
-                 */
-                r = tmpfs_patch_options("mode=755", 0, selinux_apifs_context, &options);
-                if (r < 0)
-                        return log_oom();
-
-                r = mount_verbose(LOG_ERR, "tmpfs", cgroup_root, "tmpfs",
-                                  MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, options);
-                if (r < 0)
-                        return r;
-        }
-
-        r = cg_all_unified();
-        if (r < 0)
-                return r;
-        if (r > 0)
-                goto skip_controllers;
-
-        r = get_process_controllers(&controllers);
-        if (r < 0)
-                return log_error_errno(r, "Failed to determine cgroup controllers: %m");
-
-        for (;;) {
-                _cleanup_free_ const char *controller = NULL;
-
-                controller = set_steal_first(controllers);
-                if (!controller)
-                        break;
-
-                r = mount_legacy_cgroup_hierarchy("", controller, controller, !userns);
-                if (r < 0)
-                        return r;
-
-                /* When multiple hierarchies are co-mounted, make their
-                 * constituting individual hierarchies a symlink to the
-                 * co-mount.
-                 */
-                c = controller;
-                for (;;) {
-                        _cleanup_free_ char *target = NULL, *tok = NULL;
-
-                        r = extract_first_word(&c, &tok, ",", 0);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to extract co-mounted cgroup controller: %m");
-                        if (r == 0)
-                                break;
-
-                        if (streq(controller, tok))
-                                break;
-
-                        target = prefix_root("/sys/fs/cgroup/", tok);
-                        if (!target)
-                                return log_oom();
-
-                        r = symlink_idempotent(controller, target);
-                        if (r == -EINVAL)
-                                return log_error_errno(r, "Invalid existing symlink for combined hierarchy: %m");
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to create symlink for combined hierarchy: %m");
-                }
-        }
-
-skip_controllers:
-        if (unified_requested >= CGROUP_UNIFIED_SYSTEMD) {
-                r = mount_legacy_cgroup_hierarchy("", SYSTEMD_CGROUP_CONTROLLER_HYBRID, "unified", false);
-                if (r < 0)
-                        return r;
-        }
-
-        r = mount_legacy_cgroup_hierarchy("", SYSTEMD_CGROUP_CONTROLLER_LEGACY, "systemd", false);
-        if (r < 0)
-                return r;
-
-        if (!userns)
-                return mount_verbose(LOG_ERR, NULL, cgroup_root, NULL,
-                                     MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755");
-
-        return 0;
-}
-
-/* Mount legacy cgroup hierarchy when cgroup namespaces are unsupported. */
-static int mount_legacy_cgns_unsupported(
-                const char *dest,
-                CGroupUnified unified_requested,
-                bool userns,
-                uid_t uid_shift,
-                uid_t uid_range,
-                const char *selinux_apifs_context) {
-
-        _cleanup_set_free_free_ Set *controllers = NULL;
-        const char *cgroup_root;
-        int r;
-
-        cgroup_root = prefix_roota(dest, "/sys/fs/cgroup");
-
-        (void) mkdir_p(cgroup_root, 0755);
-
-        /* Mount a tmpfs to /sys/fs/cgroup if it's not mounted there yet. */
-        r = path_is_mount_point(cgroup_root, dest, AT_SYMLINK_FOLLOW);
-        if (r < 0)
-                return log_error_errno(r, "Failed to determine if /sys/fs/cgroup is already mounted: %m");
-        if (r == 0) {
-                _cleanup_free_ char *options = NULL;
-
-                r = tmpfs_patch_options("mode=755", uid_shift == 0 ? UID_INVALID : uid_shift, selinux_apifs_context, &options);
-                if (r < 0)
-                        return log_oom();
-
-                r = mount_verbose(LOG_ERR, "tmpfs", cgroup_root, "tmpfs",
-                                  MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, options);
-                if (r < 0)
-                        return r;
-        }
-
-        r = cg_all_unified();
-        if (r < 0)
-                return r;
-        if (r > 0)
-                goto skip_controllers;
-
-        r = cg_kernel_controllers(&controllers);
-        if (r < 0)
-                return log_error_errno(r, "Failed to determine cgroup controllers: %m");
-
-        for (;;) {
-                _cleanup_free_ char *controller = NULL, *origin = NULL, *combined = NULL;
-
-                controller = set_steal_first(controllers);
-                if (!controller)
-                        break;
-
-                origin = prefix_root("/sys/fs/cgroup/", controller);
-                if (!origin)
-                        return log_oom();
-
-                r = readlink_malloc(origin, &combined);
-                if (r == -EINVAL) {
-                        /* Not a symbolic link, but directly a single cgroup hierarchy */
-
-                        r = mount_legacy_cgroup_hierarchy(dest, controller, controller, true);
-                        if (r < 0)
-                                return r;
-
-                } else if (r < 0)
-                        return log_error_errno(r, "Failed to read link %s: %m", origin);
-                else {
-                        _cleanup_free_ char *target = NULL;
-
-                        target = prefix_root(dest, origin);
-                        if (!target)
-                                return log_oom();
-
-                        /* A symbolic link, a combination of controllers in one hierarchy */
-
-                        if (!filename_is_valid(combined)) {
-                                log_warning("Ignoring invalid combined hierarchy %s.", combined);
-                                continue;
-                        }
-
-                        r = mount_legacy_cgroup_hierarchy(dest, combined, combined, true);
-                        if (r < 0)
-                                return r;
-
-                        r = symlink_idempotent(combined, target);
-                        if (r == -EINVAL)
-                                return log_error_errno(r, "Invalid existing symlink for combined hierarchy: %m");
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to create symlink for combined hierarchy: %m");
-                }
-        }
-
-skip_controllers:
-        if (unified_requested >= CGROUP_UNIFIED_SYSTEMD) {
-                r = mount_legacy_cgroup_hierarchy(dest, SYSTEMD_CGROUP_CONTROLLER_HYBRID, "unified", false);
-                if (r < 0)
-                        return r;
-        }
-
-        r = mount_legacy_cgroup_hierarchy(dest, SYSTEMD_CGROUP_CONTROLLER_LEGACY, "systemd", false);
-        if (r < 0)
-                return r;
-
-        return mount_verbose(LOG_ERR, NULL, cgroup_root, NULL,
-                             MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755");
-}
-
-static int mount_unified_cgroups(const char *dest) {
-        const char *p;
-        int r;
-
-        assert(dest);
-
-        p = prefix_roota(dest, "/sys/fs/cgroup");
-
-        (void) mkdir_p(p, 0755);
-
-        r = path_is_mount_point(p, dest, AT_SYMLINK_FOLLOW);
-        if (r < 0)
-                return log_error_errno(r, "Failed to determine if %s is mounted already: %m", p);
-        if (r > 0) {
-                p = prefix_roota(dest, "/sys/fs/cgroup/cgroup.procs");
-                if (access(p, F_OK) >= 0)
-                        return 0;
-                if (errno != ENOENT)
-                        return log_error_errno(errno, "Failed to determine if mount point %s contains the unified cgroup hierarchy: %m", p);
-
-                log_error("%s is already mounted but not a unified cgroup hierarchy. Refusing.", p);
-                return -EINVAL;
-        }
-
-        return mount_verbose(LOG_ERR, "cgroup", p, "cgroup2", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL);
-}
-
-int mount_cgroups(
-                const char *dest,
-                CGroupUnified unified_requested,
-                bool userns,
-                uid_t uid_shift,
-                uid_t uid_range,
-                const char *selinux_apifs_context,
-                bool use_cgns) {
-
-        if (unified_requested >= CGROUP_UNIFIED_ALL)
-                return mount_unified_cgroups(dest);
-        if (use_cgns)
-                return mount_legacy_cgns_supported(dest, unified_requested, userns, uid_shift, uid_range, selinux_apifs_context);
-
-        return mount_legacy_cgns_unsupported(dest, unified_requested, userns, uid_shift, uid_range, selinux_apifs_context);
-}
-
-static int mount_systemd_cgroup_writable_one(const char *root, const char *own) {
-        int r;
-
-        assert(root);
-        assert(own);
-
-        /* Make our own cgroup a (writable) bind mount */
-        r = mount_verbose(LOG_ERR, own, own, NULL, MS_BIND, NULL);
-        if (r < 0)
-                return r;
-
-        /* And then remount the systemd cgroup root read-only */
-        return mount_verbose(LOG_ERR, NULL, root, NULL,
-                             MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, NULL);
-}
-
-int mount_systemd_cgroup_writable(
-                const char *dest,
-                CGroupUnified unified_requested) {
-
-        _cleanup_free_ char *own_cgroup_path = NULL;
-        const char *root, *own;
-        int r;
-
-        assert(dest);
-
-        r = cg_pid_get_path(NULL, 0, &own_cgroup_path);
-        if (r < 0)
-                return log_error_errno(r, "Failed to determine our own cgroup path: %m");
-
-        /* If we are living in the top-level, then there's nothing to do... */
-        if (path_equal(own_cgroup_path, "/"))
-                return 0;
-
-        if (unified_requested >= CGROUP_UNIFIED_ALL) {
-
-                root = prefix_roota(dest, "/sys/fs/cgroup");
-                own = strjoina(root, own_cgroup_path);
-
-        } else {
-
-                if (unified_requested >= CGROUP_UNIFIED_SYSTEMD) {
-                        root = prefix_roota(dest, "/sys/fs/cgroup/unified");
-                        own = strjoina(root, own_cgroup_path);
-
-                        r = mount_systemd_cgroup_writable_one(root, own);
-                        if (r < 0)
-                                return r;
-                }
-
-                root = prefix_roota(dest, "/sys/fs/cgroup/systemd");
-                own = strjoina(root, own_cgroup_path);
-        }
-
-        return mount_systemd_cgroup_writable_one(root, own);
-}
-
 int setup_volatile_state(
                 const char *directory,
                 VolatileMode mode,
index e948d02..db55759 100644 (file)
@@ -46,9 +46,6 @@ int overlay_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_onl
 int mount_all(const char *dest, MountSettingsMask mount_settings, uid_t uid_shift, const char *selinux_apifs_context);
 int mount_sysfs(const char *dest, MountSettingsMask mount_settings);
 
-int mount_cgroups(const char *dest, CGroupUnified unified_requested, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context, bool use_cgns);
-int mount_systemd_cgroup_writable(const char *dest, CGroupUnified unified_requested);
-
 int mount_custom(const char *dest, CustomMount *mounts, size_t n, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context);
 
 int setup_volatile(const char *directory, VolatileMode mode, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context);
@@ -56,3 +53,5 @@ int setup_volatile_state(const char *directory, VolatileMode mode, bool userns,
 
 int pivot_root_parse(char **pivot_root_new, char **pivot_root_old, const char *s);
 int setup_pivot_root(const char *directory, const char *pivot_root_new, const char *pivot_root_old);
+
+int tmpfs_patch_options(const char *options,uid_t uid_shift, const char *selinux_apifs_context, char **ret);