mount-setup: Add optional function which provides extra mount options
This commit is contained in:
+67
-37
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user