From: Mike Yuan Date: Tue, 9 Jan 2024 14:29:18 +0000 (+0800) Subject: core: allow fstab-style nodes in mount/swap What= X-Git-Tag: v256-rc1~1221^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F30853%2Fhead;p=thirdparty%2Fsystemd.git core: allow fstab-style nodes in mount/swap What= Closes #28989 --- diff --git a/man/systemd.mount.xml b/man/systemd.mount.xml index 85eb7942698..307acc4ce9e 100644 --- a/man/systemd.mount.xml +++ b/man/systemd.mount.xml @@ -516,8 +516,8 @@ What= - Takes an absolute path of a device node, file or other resource to mount. See - Takes an absolute path or a fstab-style identifier of a device node, file or + other resource to mount. See mount8 for details. If this refers to a device node, a dependency on the respective device unit is automatically created. (See diff --git a/man/systemd.swap.xml b/man/systemd.swap.xml index 8b35a9469a6..2b3305ccdeb 100644 --- a/man/systemd.swap.xml +++ b/man/systemd.swap.xml @@ -191,7 +191,8 @@ What= - Takes an absolute path of a device node or file to use for paging. See Takes an absolute path or a fstab-style identifier of a device node or file to use + for paging. See swapon8 for details. If this refers to a device node, a dependency on the respective device unit is automatically created. (See diff --git a/src/core/dbus-mount.c b/src/core/dbus-mount.c index 7dbbdd07f50..2278c3ee2fa 100644 --- a/src/core/dbus-mount.c +++ b/src/core/dbus-mount.c @@ -6,6 +6,7 @@ #include "dbus-kill.h" #include "dbus-mount.h" #include "dbus-util.h" +#include "fstab-util.h" #include "mount.h" #include "string-util.h" #include "unit.h" @@ -88,6 +89,7 @@ static int bus_mount_set_transient_property( sd_bus_error *error) { Unit *u = UNIT(m); + int r; assert(m); assert(name); @@ -98,8 +100,31 @@ static int bus_mount_set_transient_property( if (streq(name, "Where")) return bus_set_transient_path(u, name, &m->where, message, flags, error); - if (streq(name, "What")) - return bus_set_transient_string(u, name, &m->parameters_fragment.what, message, flags, error); + if (streq(name, "What")) { + _cleanup_free_ char *path = NULL; + const char *v; + + r = sd_bus_message_read(message, "s", &v); + if (r < 0) + return r; + + if (!isempty(v)) { + path = fstab_node_to_udev_node(v); + if (!path) + return -ENOMEM; + + /* path_is_valid is not used - see the comment for config_parse_mount_node */ + if (strlen(path) >= PATH_MAX) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Resolved What=%s too long", path); + } + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + free_and_replace(m->parameters_fragment.what, path); + unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "What=%s", strempty(m->parameters_fragment.what)); + } + + return 1; + } if (streq(name, "Options")) return bus_set_transient_string(u, name, &m->parameters_fragment.options, message, flags, error); diff --git a/src/core/load-fragment-gperf.gperf.in b/src/core/load-fragment-gperf.gperf.in index ed19c846975..92d5fc4cc3f 100644 --- a/src/core/load-fragment-gperf.gperf.in +++ b/src/core/load-fragment-gperf.gperf.in @@ -531,7 +531,7 @@ Socket.SELinuxContextFromNet, config_parse_warn_compat, {{ EXEC_CONTEXT_CONFIG_ITEMS('Socket') }} {{ CGROUP_CONTEXT_CONFIG_ITEMS('Socket') }} {{ KILL_CONTEXT_CONFIG_ITEMS('Socket') }} -Mount.What, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.what) +Mount.What, config_parse_mount_node, 0, offsetof(Mount, parameters_fragment.what) Mount.Where, config_parse_unit_path_printf, 0, offsetof(Mount, where) Mount.Options, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.options) Mount.Type, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.fstype) @@ -548,7 +548,7 @@ Automount.Where, config_parse_unit_path_printf, Automount.ExtraOptions, config_parse_unit_string_printf, 0, offsetof(Automount, extra_options) Automount.DirectoryMode, config_parse_mode, 0, offsetof(Automount, directory_mode) Automount.TimeoutIdleSec, config_parse_sec_fix_0, 0, offsetof(Automount, timeout_idle_usec) -Swap.What, config_parse_unit_path_printf, 0, offsetof(Swap, parameters_fragment.what) +Swap.What, config_parse_mount_node, 0, offsetof(Swap, parameters_fragment.what) Swap.Priority, config_parse_swap_priority, 0, 0 Swap.Options, config_parse_unit_string_printf, 0, offsetof(Swap, parameters_fragment.options) Swap.TimeoutSec, config_parse_sec_fix_0, 0, offsetof(Swap, timeout_usec) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 5bfb8a6d1e4..6fc6bb36098 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -38,6 +38,7 @@ #include "fileio.h" #include "firewall-util.h" #include "fs-util.h" +#include "fstab-util.h" #include "hexdecoct.h" #include "iovec-util.h" #include "ioprio-util.h" @@ -6113,6 +6114,47 @@ int config_parse_restrict_network_interfaces( return 0; } +int config_parse_mount_node( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + const Unit *u = ASSERT_PTR(userdata); + _cleanup_free_ char *resolved = NULL, *path = NULL; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + r = unit_full_printf(u, rvalue, &resolved); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); + return 0; + } + + path = fstab_node_to_udev_node(resolved); + if (!path) + return log_oom(); + + /* The source passed is not necessarily something we understand, and we pass it as-is to mount/swapon, + * so path_is_valid is not used. But let's check for basic sanety, i.e. if the source is longer than + * PATH_MAX, you're likely doing something wrong. */ + if (strlen(path) >= PATH_MAX) { + log_syntax(unit, LOG_WARNING, filename, line, 0, "Resolved mount path '%s' too long, ignoring.", path); + return 0; + } + + return config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, path, data, userdata); +} + static int merge_by_names(Unit *u, Set *names, const char *id) { char *k; int r; @@ -6365,6 +6407,7 @@ void unit_dump_config_items(FILE *f) { { config_parse_job_mode_isolate, "BOOLEAN" }, { config_parse_personality, "PERSONALITY" }, { config_parse_log_filter_patterns, "REGEX" }, + { config_parse_mount_node, "NODE" }, }; const char *prev = NULL; diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h index c001397ff2c..9394347d683 100644 --- a/src/core/load-fragment.h +++ b/src/core/load-fragment.h @@ -159,6 +159,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_log_filter_patterns); CONFIG_PARSER_PROTOTYPE(config_parse_open_file); CONFIG_PARSER_PROTOTYPE(config_parse_memory_pressure_watch); CONFIG_PARSER_PROTOTYPE(config_parse_cgroup_nft_set); +CONFIG_PARSER_PROTOTYPE(config_parse_mount_node); /* gperf prototypes */ const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, GPERF_LEN_TYPE length);