From c600357ba608b42849c8d56aa75c24c849d6387e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Fri, 1 May 2020 10:20:17 +0200 Subject: [PATCH 1/4] mount: add ReadWriteOnly property to fail on read-only mounts Systems where a mount point is expected to be read-write needs a way to fail mount units that fallback as read-only. Add a property to allow setting the -w option when calling mount(8). --- src/core/dbus-mount.c | 4 ++++ src/core/load-fragment-gperf.gperf.m4 | 1 + src/core/mount.c | 6 ++++++ src/core/mount.h | 2 ++ src/shared/bus-unit-util.c | 3 ++- test/fuzz/fuzz-unit-file/directives.service | 1 + 6 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/core/dbus-mount.c b/src/core/dbus-mount.c index b6d61627eb..3ab5ecc425 100644 --- a/src/core/dbus-mount.c +++ b/src/core/dbus-mount.c @@ -51,6 +51,7 @@ const sd_bus_vtable bus_mount_vtable[] = { SD_BUS_PROPERTY("SloppyOptions", "b", bus_property_get_bool, offsetof(Mount, sloppy_options), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LazyUnmount", "b", bus_property_get_bool, offsetof(Mount, lazy_unmount), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ForceUnmount", "b", bus_property_get_bool, offsetof(Mount, force_unmount), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ReadWriteOnly", "b", bus_property_get_bool, offsetof(Mount, read_write_only), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Mount, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("UID", "u", bus_property_get_uid, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("GID", "u", bus_property_get_gid, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), @@ -102,6 +103,9 @@ static int bus_mount_set_transient_property( if (streq(name, "ForceUnmount")) return bus_set_transient_bool(u, name, &m->force_unmount, message, flags, error); + if (streq(name, "ReadWriteOnly")) + return bus_set_transient_bool(u, name, &m->read_write_only, message, flags, error); + return 0; } diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 165b9ca9c1..5fd58b379b 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -429,6 +429,7 @@ Mount.DirectoryMode, config_parse_mode, 0, Mount.SloppyOptions, config_parse_bool, 0, offsetof(Mount, sloppy_options) Mount.LazyUnmount, config_parse_bool, 0, offsetof(Mount, lazy_unmount) Mount.ForceUnmount, config_parse_bool, 0, offsetof(Mount, force_unmount) +Mount.ReadWriteOnly, config_parse_bool, 0, offsetof(Mount, read_write_only) EXEC_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl CGROUP_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl KILL_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl diff --git a/src/core/mount.c b/src/core/mount.c index 1c4aefd734..70c5ba0c24 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -752,6 +752,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) { "%sSloppyOptions: %s\n" "%sLazyUnmount: %s\n" "%sForceUnmount: %s\n" + "%sReadWriteOnly: %s\n" "%sTimeoutSec: %s\n", prefix, mount_state_to_string(m->state), prefix, mount_result_to_string(m->result), @@ -767,6 +768,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) { prefix, yes_no(m->sloppy_options), prefix, yes_no(m->lazy_unmount), prefix, yes_no(m->force_unmount), + prefix, yes_no(m->read_write_only), prefix, format_timespan(buf, sizeof(buf), m->timeout_usec, USEC_PER_SEC)); if (m->control_pid > 0) @@ -998,6 +1000,8 @@ static void mount_enter_mounting(Mount *m) { r = exec_command_set(m->control_command, MOUNT_PATH, p->what, m->where, NULL); if (r >= 0 && m->sloppy_options) r = exec_command_append(m->control_command, "-s", NULL); + if (r >= 0 && m->read_write_only) + r = exec_command_append(m->control_command, "-w", NULL); if (r >= 0 && p->fstype) r = exec_command_append(m->control_command, "-t", p->fstype, NULL); if (r >= 0 && !isempty(opts)) @@ -1058,6 +1062,8 @@ static void mount_enter_remounting(Mount *m) { "-o", o, NULL); if (r >= 0 && m->sloppy_options) r = exec_command_append(m->control_command, "-s", NULL); + if (r >= 0 && m->read_write_only) + r = exec_command_append(m->control_command, "-w", NULL); if (r >= 0 && p->fstype) r = exec_command_append(m->control_command, "-t", p->fstype, NULL); } else diff --git a/src/core/mount.h b/src/core/mount.h index 07fa05f3ca..a1bc2d71a6 100644 --- a/src/core/mount.h +++ b/src/core/mount.h @@ -59,6 +59,8 @@ struct Mount { bool lazy_unmount; bool force_unmount; + bool read_write_only; + MountResult result; MountResult reload_result; MountResult clean_result; diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index 463a0ddb71..3be75e6b4d 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -1436,7 +1436,8 @@ static int bus_append_mount_property(sd_bus_message *m, const char *field, const if (STR_IN_SET(field, "SloppyOptions", "LazyUnmount", - "ForceUnmount")) + "ForceUnmount", + "ReadwriteOnly")) return bus_append_parse_boolean(m, field, eq); return 0; diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service index 98cddad349..6fa96e1d58 100644 --- a/test/fuzz/fuzz-unit-file/directives.service +++ b/test/fuzz/fuzz-unit-file/directives.service @@ -856,6 +856,7 @@ RateLimitIntervalSec= ReadKMsg= ReadOnly= ReadOnlyPaths= +ReadWriteOnly= ReadWritePaths= RemoveIPC= ReserveVT= From 75f4bd7fd0a28e4080a3f0c05a574820dc9411ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Fri, 1 May 2020 10:27:06 +0200 Subject: [PATCH 2/4] man: document ReadWriteOnly property for mount units --- docs/TRANSIENT-SETTINGS.md | 1 + man/systemd.mount.xml | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/docs/TRANSIENT-SETTINGS.md b/docs/TRANSIENT-SETTINGS.md index d5a8046676..d9b1c20c77 100644 --- a/docs/TRANSIENT-SETTINGS.md +++ b/docs/TRANSIENT-SETTINGS.md @@ -332,6 +332,7 @@ All mount unit settings are available to transient units: ✓ SloppyOptions= ✓ LazyUnmount= ✓ ForceUnmount= +✓ ReadWriteOnly= ``` ## Automount Unit Settings diff --git a/man/systemd.mount.xml b/man/systemd.mount.xml index d775d74053..d18773663f 100644 --- a/man/systemd.mount.xml +++ b/man/systemd.mount.xml @@ -497,6 +497,19 @@ off. + + ReadWriteOnly= + + Takes a boolean argument. If false, a mount + point that shall be mounted read-write but cannot be mounted + so is retried to be mounted read-only. If true the operation + will fail immediately after the read-write mount attempt did + not succeed. This corresponds with + mount8's + -w switch. Defaults to + off. + + ForceUnmount= From f42aa416835b98119b31c24e6ce1b06b9a9d6be5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Mon, 4 May 2020 10:02:19 +0200 Subject: [PATCH 3/4] fstab-generator: add x-systemd.rw-only option support Support enabling the ReadwriteOnly= unit setting from fstab using 'x-systemd.rw-only' --- src/fstab-generator/fstab-generator.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index 08c7b76dba..a8e7c1c1ca 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -35,6 +35,7 @@ typedef enum MountpointFlags { AUTOMOUNT = 1 << 2, MAKEFS = 1 << 3, GROWFS = 1 << 4, + RWONLY = 1 << 5, } MountpointFlags; static const char *arg_dest = NULL; @@ -481,6 +482,9 @@ static int add_mount( if (r < 0) return r; + if (flags & RWONLY) + fprintf(f, "ReadWriteOnly=yes\n"); + r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write unit file %s: %m", name); @@ -594,7 +598,7 @@ static int parse_fstab(bool initrd) { while ((me = getmntent(f))) { _cleanup_free_ char *where = NULL, *what = NULL, *canonical_where = NULL; - bool makefs, growfs, noauto, nofail; + bool makefs, growfs, noauto, nofail, rwonly; int k; if (initrd && !mount_in_initrd(me)) @@ -634,6 +638,7 @@ static int parse_fstab(bool initrd) { makefs = fstab_test_option(me->mnt_opts, "x-systemd.makefs\0"); growfs = fstab_test_option(me->mnt_opts, "x-systemd.growfs\0"); + rwonly = fstab_test_option(me->mnt_opts, "x-systemd.rw-only\0"); noauto = fstab_test_yes_no_option(me->mnt_opts, "noauto\0" "auto\0"); nofail = fstab_test_yes_no_option(me->mnt_opts, "nofail\0" "fail\0"); @@ -666,7 +671,7 @@ static int parse_fstab(bool initrd) { me->mnt_type, me->mnt_opts, me->mnt_passno, - makefs*MAKEFS | growfs*GROWFS | noauto*NOAUTO | nofail*NOFAIL | automount*AUTOMOUNT, + makefs*MAKEFS | growfs*GROWFS | noauto*NOAUTO | nofail*NOFAIL | automount*AUTOMOUNT | rwonly*RWONLY, post, fstab); } From ad765605254d822df8b0557835444197ba12790d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Mon, 4 May 2020 10:03:54 +0200 Subject: [PATCH 4/4] man: document x-systemd.rw-only fstab option --- man/systemd.mount.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/man/systemd.mount.xml b/man/systemd.mount.xml index d18773663f..ed9ce635f2 100644 --- a/man/systemd.mount.xml +++ b/man/systemd.mount.xml @@ -359,6 +359,17 @@ Options= setting in a unit file. + + + + If a mount operation fails to mount the file system + read-write, it normally tries mounting the file system read-only instead. + This option disables that behaviour, and causes the mount to fail + immediately instead. This option is translated into the + ReadWriteOnly= setting in a unit file. + + +