]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
mount-setup: Add optional function which provides extra mount options
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 29 Oct 2025 15:28:40 +0000 (16:28 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 30 Oct 2025 21:28:39 +0000 (22:28 +0100)
src/shared/mount-setup.c

index 7fb3416c6cb513f3c4759f17cd285dc9677c615b..cd2b732b9bac4c62cc8bc1c2dbfd04699343d379 100644 (file)
@@ -29,7 +29,6 @@ typedef enum MountMode {
         MNT_IN_CONTAINER      = 1 << 1,
         MNT_CHECK_WRITABLE    = 1 << 2,
         MNT_FOLLOW_SYMLINK    = 1 << 3,
-        MNT_USRQUOTA_GRACEFUL = 1 << 4,
 } MountMode;
 
 typedef struct MountPoint {
@@ -37,38 +36,77 @@ typedef struct MountPoint {
         const char *where;
         const char *type;
         const char *options;
+        int (*options_fn)(int priority, const char *type, char **ret);
         unsigned long flags;
         MountMode mode;
         bool (*condition_fn)(void);
 } MountPoint;
 
-static bool cgroupfs_recursiveprot_supported(void) {
+static int cgroupfs_mount_options(int priority, const char *type, char **ret) {
         int r;
 
-        /* Added in kernel 5.7 */
+        assert(type);
+        assert(streq(type, "cgroup2"));
+        assert(ret);
 
-        r = mount_option_supported("cgroup2", "memory_recursiveprot", /* value = */ NULL);
-        if (r < 0)
-                log_debug_errno(r, "Failed to determine whether cgroupfs supports 'memory_recursiveprot' mount option, assuming not: %m");
-        else if (r == 0)
-                log_debug("'memory_recursiveprot' not supported by cgroupfs, not using mount option.");
+        _cleanup_free_ char *opts = NULL;
+        FOREACH_STRING(o, "memory_recursiveprot") {
+                r = mount_option_supported("cgroup2", o, /* value = */ NULL);
+                if (r < 0)
+                        log_full_errno(priority, r, "Failed to determine whether cgroupfs supports '%s' mount option, assuming not: %m", o);
+                else if (r == 0)
+                        log_debug("'%s' not supported by cgroupfs, not using mount option.", o);
+                else if (!strextend_with_separator(&opts, ",", o))
+                        return log_oom_full(priority);
+        }
 
-        return r > 0;
+        *ret = TAKE_PTR(opts);
+        return 0;
 }
 
 int mount_cgroupfs(const char *path) {
+        int r;
+
         assert(path);
 
         /* Mount a separate cgroupfs instance, taking all options we initial set into account. This is
          * especially useful when cgroup namespace is *not* employed, since the kernel overrides all
          * previous options if a new mount is established in initial cgns (c.f.
          * https://github.com/torvalds/linux/blob/b69bb476dee99d564d65d418e9a20acca6f32c3f/kernel/cgroup/cgroup.c#L1984)
-         *
-         * The options shall be kept in sync with those in mount_table below. */
+         */
 
-        return mount_nofollow_verbose(LOG_ERR, "cgroup2", path, "cgroup2",
-                                      MS_NOSUID|MS_NOEXEC|MS_NODEV,
-                                      cgroupfs_recursiveprot_supported() ? "nsdelegate,memory_recursiveprot" : "nsdelegate");
+        _cleanup_free_ char *opts = NULL;
+        r = cgroupfs_mount_options(LOG_WARNING, "cgroup2", &opts);
+        if (r < 0)
+                return r;
+
+        /* These options shall be kept in sync with those in mount_table below. */
+        if (!strprepend_with_separator(&opts, ",", "nsdelegate"))
+                return log_oom();
+
+        return mount_nofollow_verbose(LOG_ERR, "cgroup2", path, "cgroup2", MS_NOSUID|MS_NOEXEC|MS_NODEV, opts);
+}
+
+static int usrquota_mount_option(int priority, const char *type, char **ret) {
+        _cleanup_free_ char *o = NULL;
+        int r;
+
+        assert(type);
+        assert(ret);
+
+        r = mount_option_supported(type, "usrquota", /* value= */ NULL);
+        if (r < 0)
+                log_full_errno(priority, r, "Unable to determine whether %s supports 'usrquota' mount option, assuming not: %m", type);
+        else if (r == 0)
+                log_debug("Not enabling 'usrquota' for '%s' as kernel lacks support for it.", type);
+        else {
+                o = strdup("usrquota");
+                if (!o)
+                        return log_oom_full(priority);
+        }
+
+        *ret = TAKE_PTR(o);
+        return 0;
 }
 
 static const MountPoint mount_table[] = {
@@ -115,8 +153,9 @@ static const MountPoint mount_table[] = {
                 .where = "/dev/shm",
                 .type = "tmpfs",
                 .options = "mode=01777,smackfsroot=*",
+                .options_fn = usrquota_mount_option,
                 .flags = MS_NOSUID|MS_NODEV|MS_STRICTATIME,
-                .mode = MNT_FATAL|MNT_USRQUOTA_GRACEFUL,
+                .mode = MNT_FATAL,
                 .condition_fn = mac_smack_use,
         },
 #endif
@@ -125,8 +164,9 @@ static const MountPoint mount_table[] = {
                 .where = "/dev/shm",
                 .type = "tmpfs",
                 .options = "mode=01777",
+                .options_fn = usrquota_mount_option,
                 .flags = MS_NOSUID|MS_NODEV|MS_STRICTATIME,
-                .mode = MNT_FATAL|MNT_IN_CONTAINER|MNT_USRQUOTA_GRACEFUL,
+                .mode = MNT_FATAL|MNT_IN_CONTAINER,
         },
         {
                 .what = "devpts",
@@ -155,20 +195,12 @@ static const MountPoint mount_table[] = {
                 .flags = MS_NOSUID|MS_NODEV|MS_STRICTATIME,
                 .mode = MNT_FATAL|MNT_IN_CONTAINER,
         },
-        {
-                .what = "cgroup2",
-                .where = "/sys/fs/cgroup",
-                .type = "cgroup2",
-                .options = "nsdelegate,memory_recursiveprot",
-                .flags = MS_NOSUID|MS_NOEXEC|MS_NODEV,
-                .mode = MNT_FATAL|MNT_IN_CONTAINER|MNT_CHECK_WRITABLE,
-                .condition_fn = cgroupfs_recursiveprot_supported,
-        },
         {
                 .what = "cgroup2",
                 .where = "/sys/fs/cgroup",
                 .type = "cgroup2",
                 .options = "nsdelegate",
+                .options_fn = cgroupfs_mount_options,
                 .flags = MS_NOSUID|MS_NOEXEC|MS_NODEV,
                 .mode = MNT_FATAL|MNT_IN_CONTAINER|MNT_CHECK_WRITABLE,
         },
@@ -278,20 +310,18 @@ static int mount_one(const MountPoint *p, bool relabel) {
                 (void) mkdir_p(p->where, 0755);
 
         _cleanup_free_ char *extend_options = NULL;
-        const char *o = p->options;
-        if (FLAGS_SET(p->mode, MNT_USRQUOTA_GRACEFUL)) {
-                r = mount_option_supported(p->type, "usrquota", /* value= */ NULL);
+        const char *o;
+        if (p->options_fn) {
+                r = p->options_fn(priority, p->type, &extend_options);
                 if (r < 0)
-                        log_full_errno(priority, r, "Unable to determine whether %s supports 'usrquota' mount option, assuming not: %m", p->type);
-                else if (r == 0)
-                        log_debug("Not enabling 'usrquota' on '%s' as kernel lacks support for it.", p->where);
-                else {
-                        if (!strextend_with_separator(&extend_options, ",", p->options ?: POINTER_MAX, "usrquota"))
-                                return log_oom();
+                        return r;
 
-                        o = extend_options;
-                }
-        }
+                if (!strprepend_with_separator(&extend_options, ",", p->options))
+                        return log_oom();
+
+                o = extend_options;
+        } else
+                o = p->options;
 
         r = mount_verbose_full(priority, p->what, p->where, p->type, p->flags, o, FLAGS_SET(p->mode, MNT_FOLLOW_SYMLINK));
         if (r < 0)