]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/nspawn/nspawn-cgroup.c
tree-wide: add size limits for tmpfs mounts
[thirdparty/systemd.git] / src / nspawn / nspawn-cgroup.c
index 4a3cd29094a8a9695622c54eb1e6c1154680d39e..a16ee5c60a23491ace496cd79b53310c7fbd118f 100644 (file)
@@ -3,11 +3,14 @@
 #include <sys/mount.h>
 
 #include "alloc-util.h"
+#include "cgroup-setup.h"
 #include "fd-util.h"
 #include "fileio.h"
+#include "format-util.h"
 #include "fs-util.h"
 #include "mkdir.h"
 #include "mount-util.h"
+#include "mountpoint-util.h"
 #include "nspawn-cgroup.h"
 #include "nspawn-mount.h"
 #include "path-util.h"
@@ -59,7 +62,7 @@ int chown_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t uid_shift) {
         if (r < 0)
                 return log_error_errno(r, "Failed to chown() cgroup %s: %m", fs);
 
-        if (unified_requested == CGROUP_UNIFIED_SYSTEMD) {
+        if (unified_requested == CGROUP_UNIFIED_SYSTEMD || (unified_requested == CGROUP_UNIFIED_NONE && cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER) > 0)) {
                 _cleanup_free_ char *lfs = NULL;
                 /* Always propagate access rights from unified to legacy controller */
 
@@ -119,10 +122,9 @@ int sync_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t uid_shift) {
         (void) rm_rf(fn, REMOVE_ROOT|REMOVE_ONLY_DIRECTORIES);
 
         fn = strjoina(tree, cgroup, "/cgroup.procs");
-        (void) mkdir_parents(fn, 0755);
 
         sprintf(pid_string, PID_FMT, pid);
-        r = write_string_file(fn, pid_string, 0);
+        r = write_string_file(fn, pid_string, WRITE_STRING_FILE_DISABLE_BUFFER|WRITE_STRING_FILE_MKDIR_0755);
         if (r < 0) {
                 log_error_errno(r, "Failed to move process: %m");
                 goto finish;
@@ -159,7 +161,7 @@ int create_subcgroup(pid_t pid, bool keep_unit, CGroupUnified unified_requested)
          * attributes. Hence, let's insert an intermediary cgroup to cover that case too.
          *
          * Note that we only bother with the main hierarchy here, not with any secondary ones. On the unified setup
-         * that's fine because there's only one hiearchy anyway and controllers are enabled directly on it. On the
+         * that's fine because there's only one hierarchy anyway and controllers are enabled directly on it. On the
          * legacy setup, this is fine too, since delegation of controllers is generally not safe there, hence we won't
          * do it. */
 
@@ -189,7 +191,7 @@ int create_subcgroup(pid_t pid, bool keep_unit, CGroupUnified unified_requested)
         }
 
         /* Try to enable as many controllers as possible for the new payload. */
-        (void) cg_enable_everywhere(supported, supported, cgroup);
+        (void) cg_enable_everywhere(supported, supported, cgroup, NULL);
         return 0;
 }
 
@@ -197,16 +199,12 @@ int create_subcgroup(pid_t pid, bool keep_unit, CGroupUnified unified_requested)
  * namespace.
  */
 static int get_process_controllers(Set **ret) {
-        _cleanup_set_free_free_ Set *controllers = NULL;
+        _cleanup_set_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;
@@ -235,7 +233,7 @@ static int get_process_controllers(Set **ret) {
                 if (STR_IN_SET(l, "", "name=systemd", "name=unified"))
                         continue;
 
-                r = set_put_strdup(controllers, l);
+                r = set_put_strdup(&controllers, l);
                 if (r < 0)
                         return r;
         }
@@ -262,7 +260,7 @@ static int mount_legacy_cgroup_hierarchy(
         if (r > 0)
                 return 0;
 
-        mkdir_p(to, 0755);
+        (void) mkdir_p(to, 0755);
 
         /* The superblock mount options of the mount point need to be
          * identical to the hosts', and hence writable... */
@@ -301,7 +299,7 @@ static int mount_legacy_cgns_supported(
                 uid_t uid_range,
                 const char *selinux_apifs_context) {
 
-        _cleanup_set_free_free_ Set *controllers = NULL;
+        _cleanup_set_free_ Set *controllers = NULL;
         const char *cgroup_root = "/sys/fs/cgroup", *c;
         int r;
 
@@ -321,7 +319,7 @@ static int mount_legacy_cgns_supported(
                  * 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);
+                r = tmpfs_patch_options("mode=755" TMPFS_LIMITS_SYS_FS_CGROUP, 0, selinux_apifs_context, &options);
                 if (r < 0)
                         return log_oom();
 
@@ -369,11 +367,11 @@ static int mount_legacy_cgns_supported(
                         if (streq(controller, tok))
                                 break;
 
-                        target = prefix_root("/sys/fs/cgroup/", tok);
+                        target = path_join("/sys/fs/cgroup/", tok);
                         if (!target)
                                 return log_oom();
 
-                        r = symlink_idempotent(controller, target);
+                        r = symlink_idempotent(controller, target, false);
                         if (r == -EINVAL)
                                 return log_error_errno(r, "Invalid existing symlink for combined hierarchy: %m");
                         if (r < 0)
@@ -423,7 +421,7 @@ static int mount_legacy_cgns_unsupported(
         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);
+                r = tmpfs_patch_options("mode=755" TMPFS_LIMITS_SYS_FS_CGROUP, uid_shift == 0 ? UID_INVALID : uid_shift, selinux_apifs_context, &options);
                 if (r < 0)
                         return log_oom();
 
@@ -450,7 +448,7 @@ static int mount_legacy_cgns_unsupported(
                 if (!controller)
                         break;
 
-                origin = prefix_root("/sys/fs/cgroup/", controller);
+                origin = path_join("/sys/fs/cgroup/", controller);
                 if (!origin)
                         return log_oom();
 
@@ -467,7 +465,7 @@ static int mount_legacy_cgns_unsupported(
                 else {
                         _cleanup_free_ char *target = NULL;
 
-                        target = prefix_root(dest, origin);
+                        target = path_join(dest, origin);
                         if (!target)
                                 return log_oom();
 
@@ -482,7 +480,7 @@ static int mount_legacy_cgns_unsupported(
                         if (r < 0)
                                 return r;
 
-                        r = symlink_idempotent(combined, target);
+                        r = symlink_idempotent(combined, target, false);
                         if (r == -EINVAL)
                                 return log_error_errno(r, "Invalid existing symlink for combined hierarchy: %m");
                         if (r < 0)
@@ -525,8 +523,8 @@ static int mount_unified_cgroups(const char *dest) {
                 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 log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                       "%s is already mounted but not a unified cgroup hierarchy. Refusing.", p);
         }
 
         return mount_verbose(LOG_ERR, "cgroup", p, "cgroup2", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL);