summaryrefslogtreecommitdiffstats
path: root/src/core/load-fragment.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/load-fragment.c')
-rw-r--r--src/core/load-fragment.c353
1 files changed, 185 insertions, 168 deletions
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 0baf08e..5ae6888 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -16,8 +16,8 @@
#include "all-units.h"
#include "alloc-util.h"
#include "bpf-firewall.h"
-#include "bpf-lsm.h"
#include "bpf-program.h"
+#include "bpf-restrict-fs.h"
#include "bpf-socket-bind.h"
#include "bus-error.h"
#include "bus-internal.h"
@@ -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"
@@ -56,6 +57,7 @@
#include "pcre2-util.h"
#include "percent-util.h"
#include "process-util.h"
+#include "reboot-util.h"
#include "seccomp-util.h"
#include "securebits-util.h"
#include "selinux-util.h"
@@ -248,7 +250,7 @@ int unit_is_likely_recursive_template_dependency(Unit *u, const char *name, cons
/* Fragment paths should also be equal as a custom fragment for a specific template instance
* wouldn't necessarily lead to infinite recursion. */
- if (!path_equal_ptr(u->fragment_path, fragment_path))
+ if (!path_equal(u->fragment_path, fragment_path))
return false;
if (!contains_instance_specifier_superset(format))
@@ -361,6 +363,40 @@ int config_parse_unit_string_printf(
return config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata);
}
+int config_parse_reboot_parameter(
+ 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) {
+
+ _cleanup_free_ char *k = NULL;
+ const Unit *u = ASSERT_PTR(userdata);
+ int r;
+
+ assert(filename);
+ assert(line);
+ assert(rvalue);
+
+ r = unit_full_printf(u, rvalue, &k);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
+ return 0;
+ }
+
+ if (!reboot_parameter_is_valid(k)) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid reboot parameter '%s', ignoring.", k);
+ return 0;
+ }
+
+ return config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata);
+}
+
int config_parse_unit_strv_printf(
const char *unit,
const char *filename,
@@ -433,8 +469,9 @@ int config_parse_colon_separated_paths(
const char *rvalue,
void *data,
void *userdata) {
+
char ***sv = ASSERT_PTR(data);
- const Unit *u = userdata;
+ const Unit *u = ASSERT_PTR(userdata);
int r;
assert(filename);
@@ -574,17 +611,13 @@ int config_parse_socket_listen(
void *data,
void *userdata) {
+ Socket *s = ASSERT_PTR(SOCKET(data));
_cleanup_free_ SocketPort *p = NULL;
- SocketPort *tail;
- Socket *s;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
- assert(data);
-
- s = SOCKET(data);
if (isempty(rvalue)) {
/* An empty assignment removes all ports */
@@ -592,10 +625,15 @@ int config_parse_socket_listen(
return 0;
}
- p = new0(SocketPort, 1);
+ p = new(SocketPort, 1);
if (!p)
return log_oom();
+ *p = (SocketPort) {
+ .socket = s,
+ .fd = -EBADF,
+ };
+
if (ltype != SOCKET_SOCKET) {
_cleanup_free_ char *k = NULL;
@@ -605,7 +643,11 @@ int config_parse_socket_listen(
return 0;
}
- r = path_simplify_and_warn(k, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
+ PathSimplifyWarnFlags flags = PATH_CHECK_ABSOLUTE;
+ if (ltype != SOCKET_SPECIAL)
+ flags |= PATH_CHECK_NON_API_VFS;
+
+ r = path_simplify_and_warn(k, flags, unit, filename, line, lvalue);
if (r < 0)
return 0;
@@ -619,7 +661,7 @@ int config_parse_socket_listen(
p->type = ltype;
} else if (streq(lvalue, "ListenNetlink")) {
- _cleanup_free_ char *k = NULL;
+ _cleanup_free_ char *k = NULL;
r = unit_path_printf(UNIT(s), rvalue, &k);
if (r < 0) {
@@ -644,7 +686,7 @@ int config_parse_socket_listen(
return 0;
}
- if (k[0] == '/') { /* Only for AF_UNIX file system sockets… */
+ if (path_is_absolute(k)) { /* Only for AF_UNIX file system sockets… */
r = patch_var_run(unit, filename, line, lvalue, &k);
if (r < 0)
return r;
@@ -674,16 +716,7 @@ int config_parse_socket_listen(
p->type = SOCKET_SOCKET;
}
- p->fd = -EBADF;
- p->auxiliary_fds = NULL;
- p->n_auxiliary_fds = 0;
- p->socket = s;
-
- tail = LIST_FIND_TAIL(port, s->ports);
- LIST_INSERT_AFTER(port, s->ports, tail, p);
-
- p = NULL;
-
+ LIST_APPEND(port, s->ports, TAKE_PTR(p));
return 0;
}
@@ -858,9 +891,7 @@ int config_parse_exec(
void *userdata) {
ExecCommand **e = ASSERT_PTR(data);
- const Unit *u = userdata;
- const char *p;
- bool semicolon;
+ const Unit *u = ASSERT_PTR(userdata);
int r;
assert(filename);
@@ -875,15 +906,11 @@ int config_parse_exec(
return 0;
}
- p = rvalue;
+ const char *p = rvalue;
+ bool semicolon;
+
do {
_cleanup_free_ char *path = NULL, *firstword = NULL;
- ExecCommandFlags flags = 0;
- bool ignore = false, separate_argv0 = false;
- _cleanup_free_ ExecCommand *nce = NULL;
- _cleanup_strv_free_ char **n = NULL;
- size_t nlen = 0;
- const char *f;
semicolon = false;
@@ -897,25 +924,30 @@ int config_parse_exec(
continue;
}
- f = firstword;
- for (;;) {
- /* We accept an absolute path as first argument. If it's prefixed with - and the path doesn't
- * exist, we ignore it instead of erroring out; if it's prefixed with @, we allow overriding of
- * argv[0]; if it's prefixed with :, we will not do environment variable substitution;
- * if it's prefixed with +, it will be run with full privileges and no sandboxing; if
- * it's prefixed with '!' we apply sandboxing, but do not change user/group credentials; if
- * it's prefixed with '!!', then we apply user/group credentials if the kernel supports ambient
- * capabilities -- if it doesn't we don't apply the credentials themselves, but do apply most
- * other sandboxing, with some special exceptions for changing UID.
+ const char *f = firstword;
+ bool ignore, separate_argv0 = false;
+ ExecCommandFlags flags = 0;
+
+ for (;; f++) {
+ /* We accept an absolute path as first argument. Valid prefixes and their effect:
+ *
+ * "-": Ignore if the path doesn't exist
+ * "@": Allow overriding argv[0] (supplied as a separate argument)
+ * ":": Disable environment variable substitution
+ * "+": Run with full privileges and no sandboxing
+ * "!": Apply sandboxing except for user/group credentials
+ * "!!": Apply user/group credentials if the kernel supports ambient capabilities -
+ * if it doesn't we don't apply the credentials themselves, but do apply
+ * most other sandboxing, with some special exceptions for changing UID.
*
- * The idea is that '!!' may be used to write services that can take benefit of systemd's
- * UID/GID dropping if the kernel supports ambient creds, but provide an automatic fallback to
- * privilege dropping within the daemon if the kernel does not offer that. */
+ * The idea is that '!!' may be used to write services that can take benefit of
+ * systemd's UID/GID dropping if the kernel supports ambient creds, but provide
+ * an automatic fallback to privilege dropping within the daemon if the kernel
+ * does not offer that. */
- if (*f == '-' && !(flags & EXEC_COMMAND_IGNORE_FAILURE)) {
+ if (*f == '-' && !(flags & EXEC_COMMAND_IGNORE_FAILURE))
flags |= EXEC_COMMAND_IGNORE_FAILURE;
- ignore = true;
- } else if (*f == '@' && !separate_argv0)
+ else if (*f == '@' && !separate_argv0)
separate_argv0 = true;
else if (*f == ':' && !(flags & EXEC_COMMAND_NO_ENV_EXPAND))
flags |= EXEC_COMMAND_NO_ENV_EXPAND;
@@ -928,9 +960,10 @@ int config_parse_exec(
flags |= EXEC_COMMAND_AMBIENT_MAGIC;
} else
break;
- f++;
}
+ ignore = FLAGS_SET(flags, EXEC_COMMAND_IGNORE_FAILURE);
+
r = unit_path_printf(u, f, &path);
if (r < 0) {
log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, r,
@@ -940,19 +973,18 @@ int config_parse_exec(
}
if (isempty(path)) {
- /* First word is either "-" or "@" with no command. */
log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, 0,
- "Empty path in command line%s: '%s'",
+ "Empty path in command line%s: %s",
ignore ? ", ignoring" : "", rvalue);
return ignore ? 0 : -ENOEXEC;
}
if (!string_is_safe(path)) {
log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, 0,
- "Executable name contains special characters%s: %s",
+ "Executable path contains special characters%s: %s",
ignore ? ", ignoring" : "", path);
return ignore ? 0 : -ENOEXEC;
}
- if (endswith(path, "/")) {
+ if (path_implies_directory(path)) {
log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, 0,
"Executable path specifies a directory%s: %s",
ignore ? ", ignoring" : "", path);
@@ -966,92 +998,71 @@ int config_parse_exec(
return ignore ? 0 : -ENOEXEC;
}
- if (!separate_argv0) {
- char *w = NULL;
-
- if (!GREEDY_REALLOC0(n, nlen + 2))
- return log_oom();
+ _cleanup_strv_free_ char **args = NULL;
- w = strdup(path);
- if (!w)
+ if (!separate_argv0)
+ if (strv_extend(&args, path) < 0)
return log_oom();
- n[nlen++] = w;
- n[nlen] = NULL;
- }
-
- path_simplify(path);
while (!isempty(p)) {
_cleanup_free_ char *word = NULL, *resolved = NULL;
- /* Check explicitly for an unquoted semicolon as
- * command separator token. */
+ /* Check explicitly for an unquoted semicolon as command separator token. */
if (p[0] == ';' && (!p[1] || strchr(WHITESPACE, p[1]))) {
p++;
- p += strspn(p, WHITESPACE);
+ p = skip_leading_chars(p, /* bad = */ NULL);
semicolon = true;
break;
}
/* Check for \; explicitly, to not confuse it with \\; or "\;" or "\\;" etc.
- * extract_first_word() would return the same for all of those. */
+ * extract_first_word() would return the same for all of those. */
if (p[0] == '\\' && p[1] == ';' && (!p[2] || strchr(WHITESPACE, p[2]))) {
- char *w;
-
p += 2;
- p += strspn(p, WHITESPACE);
+ p = skip_leading_chars(p, /* bad = */ NULL);
- if (!GREEDY_REALLOC0(n, nlen + 2))
+ if (strv_extend(&args, ";") < 0)
return log_oom();
- w = strdup(";");
- if (!w)
- return log_oom();
- n[nlen++] = w;
- n[nlen] = NULL;
continue;
}
r = extract_first_word_and_warn(&p, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE, unit, filename, line, rvalue);
- if (r == 0)
- break;
if (r < 0)
return ignore ? 0 : -ENOEXEC;
+ if (r == 0)
+ break;
r = unit_full_printf(u, word, &resolved);
if (r < 0) {
log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, r,
- "Failed to resolve unit specifiers in %s%s: %m",
+ "Failed to resolve unit specifiers in '%s'%s: %m",
word, ignore ? ", ignoring" : "");
return ignore ? 0 : -ENOEXEC;
}
- if (!GREEDY_REALLOC(n, nlen + 2))
+ if (strv_consume(&args, TAKE_PTR(resolved)) < 0)
return log_oom();
-
- n[nlen++] = TAKE_PTR(resolved);
- n[nlen] = NULL;
}
- if (!n || !n[0]) {
+ if (strv_isempty(args)) {
log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, 0,
"Empty executable name or zeroeth argument%s: %s",
ignore ? ", ignoring" : "", rvalue);
return ignore ? 0 : -ENOEXEC;
}
- nce = new0(ExecCommand, 1);
- if (!nce)
+ ExecCommand *nec = new(ExecCommand, 1);
+ if (!nec)
return log_oom();
- nce->argv = TAKE_PTR(n);
- nce->path = TAKE_PTR(path);
- nce->flags = flags;
-
- exec_command_append_list(e, nce);
+ *nec = (ExecCommand) {
+ .path = path_simplify(TAKE_PTR(path)),
+ .argv = TAKE_PTR(args),
+ .flags = flags,
+ };
- /* Do not _cleanup_free_ these. */
- nce = NULL;
+ exec_command_append_list(e, nec);
rvalue = p;
} while (semicolon);
@@ -1254,7 +1265,7 @@ int config_parse_exec_input_data(
return 0;
}
- r = unbase64mem(rvalue, SIZE_MAX, &p, &sz);
+ r = unbase64mem(rvalue, &p, &sz);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to decode base64 data, ignoring: %s", rvalue);
@@ -1520,43 +1531,6 @@ int config_parse_exec_cpu_sched_policy(const char *unit,
return 0;
}
-int config_parse_exec_mount_apivfs(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) {
-
- ExecContext *c = ASSERT_PTR(data);
- int k;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- if (isempty(rvalue)) {
- c->mount_apivfs_set = false;
- c->mount_apivfs = false;
- return 0;
- }
-
- k = parse_boolean(rvalue);
- if (k < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, k,
- "Failed to parse boolean value, ignoring: %s",
- rvalue);
- return 0;
- }
-
- c->mount_apivfs_set = true;
- c->mount_apivfs = k;
- return 0;
-}
-
int config_parse_numa_mask(const char *unit,
const char *filename,
unsigned line,
@@ -1748,7 +1722,7 @@ int config_parse_exec_root_hash(
}
/* We have a roothash to decode, eg: RootHash=012345789abcdef */
- r = unhexmem(rvalue, strlen(rvalue), &roothash_decoded, &roothash_decoded_size);
+ r = unhexmem(rvalue, &roothash_decoded, &roothash_decoded_size);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to decode RootHash=, ignoring: %s", rvalue);
return 0;
@@ -1816,7 +1790,7 @@ int config_parse_exec_root_hash_sig(
}
/* We have a roothash signature to decode, eg: RootHashSignature=base64:012345789abcdef */
- r = unbase64mem(value, strlen(value), &roothash_sig_decoded, &roothash_sig_decoded_size);
+ r = unbase64mem(value, &roothash_sig_decoded, &roothash_sig_decoded_size);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to decode RootHashSignature=, ignoring: %s", rvalue);
return 0;
@@ -2634,6 +2608,7 @@ int config_parse_working_directory(
assert(rvalue);
if (isempty(rvalue)) {
+ c->working_directory_missing_ok = false;
c->working_directory_home = false;
c->working_directory = mfree(c->working_directory);
return 0;
@@ -2659,7 +2634,7 @@ int config_parse_working_directory(
return missing_ok ? 0 : -ENOEXEC;
}
- r = path_simplify_and_warn(k, PATH_CHECK_ABSOLUTE | (missing_ok ? 0 : PATH_CHECK_FATAL), unit, filename, line, lvalue);
+ r = path_simplify_and_warn(k, PATH_CHECK_ABSOLUTE|PATH_CHECK_NON_API_VFS|(missing_ok ? 0 : PATH_CHECK_FATAL), unit, filename, line, lvalue);
if (r < 0)
return missing_ok ? 0 : -ENOEXEC;
@@ -2697,7 +2672,7 @@ int config_parse_unit_env_file(const char *unit,
return 0;
}
- r = unit_full_printf_full(u, rvalue, PATH_MAX, &n);
+ r = unit_path_printf(u, rvalue, &n);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0;
@@ -3152,7 +3127,7 @@ int config_parse_unit_condition_string(
return 0;
}
-int config_parse_unit_requires_mounts_for(
+int config_parse_unit_mounts_for(
const char *unit,
const char *filename,
unsigned line,
@@ -3171,6 +3146,7 @@ int config_parse_unit_requires_mounts_for(
assert(lvalue);
assert(rvalue);
assert(data);
+ assert(STR_IN_SET(lvalue, "RequiresMountsFor", "WantsMountsFor"));
for (const char *p = rvalue;;) {
_cleanup_free_ char *word = NULL, *resolved = NULL;
@@ -3196,9 +3172,9 @@ int config_parse_unit_requires_mounts_for(
if (r < 0)
continue;
- r = unit_require_mounts_for(u, resolved, UNIT_DEPENDENCY_FILE);
+ r = unit_add_mounts_for(u, resolved, UNIT_DEPENDENCY_FILE, unit_mount_dependency_type_from_string(lvalue));
if (r < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to add required mount '%s', ignoring: %m", resolved);
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to add requested mount '%s', ignoring: %m", resolved);
continue;
}
}
@@ -3695,7 +3671,7 @@ int config_parse_restrict_filesystems(
break;
}
- r = lsm_bpf_parse_filesystem(
+ r = bpf_restrict_fs_parse_filesystem(
word,
&c->restrict_filesystems,
FILESYSTEM_PARSE_LOG|
@@ -4693,7 +4669,7 @@ int config_parse_exec_directories(
_cleanup_free_ char *src = NULL, *dest = NULL;
const char *q = tuple;
- r = extract_many_words(&q, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, &src, &dest, NULL);
+ r = extract_many_words(&q, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, &src, &dest);
if (r == -ENOMEM)
return log_oom();
if (r <= 0) {
@@ -4908,11 +4884,8 @@ int config_parse_load_credential(
void *data,
void *userdata) {
- _cleanup_free_ char *word = NULL, *k = NULL, *q = NULL;
ExecContext *context = ASSERT_PTR(data);
- bool encrypted = ltype;
- Unit *u = userdata;
- const char *p;
+ const Unit *u = ASSERT_PTR(userdata);
int r;
assert(filename);
@@ -4925,7 +4898,10 @@ int config_parse_load_credential(
return 0;
}
- p = rvalue;
+ _cleanup_free_ char *word = NULL, *id = NULL, *path = NULL;
+ const char *p = rvalue;
+ bool encrypted = ltype;
+
r = extract_first_word(&p, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
if (r == -ENOMEM)
return log_oom();
@@ -4934,35 +4910,35 @@ int config_parse_load_credential(
return 0;
}
- r = unit_cred_printf(u, word, &k);
+ r = unit_cred_printf(u, word, &id);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in \"%s\", ignoring: %m", word);
return 0;
}
- if (!credential_name_valid(k)) {
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Credential name \"%s\" not valid, ignoring.", k);
+ if (!credential_name_valid(id)) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Credential name \"%s\" not valid, ignoring.", id);
return 0;
}
if (isempty(p)) {
/* If only one field is specified take it as shortcut for inheriting a credential named
* the same way from our parent */
- q = strdup(k);
- if (!q)
+ path = strdup(id);
+ if (!path)
return log_oom();
} else {
- r = unit_path_printf(u, p, &q);
+ r = unit_path_printf(u, p, &path);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in \"%s\", ignoring: %m", p);
return 0;
}
- if (path_is_absolute(q) ? !path_is_normalized(q) : !credential_name_valid(q)) {
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Credential source \"%s\" not valid, ignoring.", q);
+ if (path_is_absolute(path) ? !path_is_normalized(path) : !credential_name_valid(path)) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Credential source \"%s\" not valid, ignoring.", path);
return 0;
}
}
- r = hashmap_put_credential(&context->load_credentials, k, q, encrypted);
+ r = hashmap_put_credential(&context->load_credentials, id, path, encrypted);
if (r < 0)
return log_error_errno(r, "Failed to store load credential '%s': %m", rvalue);
@@ -5236,7 +5212,7 @@ int config_parse_bind_paths(
void *userdata) {
ExecContext *c = ASSERT_PTR(data);
- const Unit *u = userdata;
+ const Unit *u = ASSERT_PTR(userdata);
int r;
assert(filename);
@@ -5267,7 +5243,7 @@ int config_parse_bind_paths(
if (r == 0)
break;
- r = unit_full_printf_full(u, source, PATH_MAX, &sresolved);
+ r = unit_path_printf(u, source, &sresolved);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to resolve unit specifiers in \"%s\", ignoring: %m", source);
@@ -5396,7 +5372,7 @@ int config_parse_mount_images(
return 0;
q = tuple;
- r = extract_many_words(&q, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, &first, &second, NULL);
+ r = extract_many_words(&q, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, &first, &second);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@@ -5420,7 +5396,7 @@ int config_parse_mount_images(
continue;
}
- r = path_simplify_and_warn(sresolved, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
+ r = path_simplify_and_warn(sresolved, PATH_CHECK_ABSOLUTE|PATH_CHECK_NON_API_VFS, unit, filename, line, lvalue);
if (r < 0)
continue;
@@ -5436,7 +5412,7 @@ int config_parse_mount_images(
continue;
}
- r = path_simplify_and_warn(dresolved, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
+ r = path_simplify_and_warn(dresolved, PATH_CHECK_ABSOLUTE|PATH_CHECK_NON_API_VFS, unit, filename, line, lvalue);
if (r < 0)
continue;
@@ -5445,7 +5421,7 @@ int config_parse_mount_images(
MountOptions *o = NULL;
PartitionDesignator partition_designator;
- r = extract_many_words(&q, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, &partition, &mount_options, NULL);
+ r = extract_many_words(&q, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, &partition, &mount_options);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@@ -5578,7 +5554,7 @@ int config_parse_extension_images(
continue;
}
- r = path_simplify_and_warn(sresolved, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
+ r = path_simplify_and_warn(sresolved, PATH_CHECK_ABSOLUTE|PATH_CHECK_NON_API_VFS, unit, filename, line, lvalue);
if (r < 0)
continue;
@@ -5587,7 +5563,7 @@ int config_parse_extension_images(
MountOptions *o = NULL;
PartitionDesignator partition_designator;
- r = extract_many_words(&q, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, &partition, &mount_options, NULL);
+ r = extract_many_words(&q, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, &partition, &mount_options);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@@ -5799,7 +5775,7 @@ int config_parse_pid_file(
return log_oom();
/* Check that the result is a sensible path */
- r = path_simplify_and_warn(n, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
+ r = path_simplify_and_warn(n, PATH_CHECK_ABSOLUTE|PATH_CHECK_NON_API_VFS, unit, filename, line, lvalue);
if (r < 0)
return r;
@@ -6095,7 +6071,7 @@ int config_parse_restrict_network_interfaces(
break;
}
- if (!ifname_valid(word)) {
+ if (!ifname_valid_full(word, IFNAME_VALID_ALTERNATIVE)) {
log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid interface name, ignoring: %s", word);
continue;
}
@@ -6112,6 +6088,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 sanity, 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;
@@ -6316,8 +6333,7 @@ void unit_dump_config_items(FILE *f) {
{ config_parse_nsec, "NANOSECONDS" },
{ config_parse_namespace_path_strv, "PATH [...]" },
{ config_parse_bind_paths, "PATH[:PATH[:OPTIONS]] [...]" },
- { config_parse_unit_requires_mounts_for,
- "PATH [...]" },
+ { config_parse_unit_mounts_for, "PATH [...]" },
{ config_parse_exec_mount_propagation_flag,
"MOUNTFLAG" },
{ config_parse_unit_string_printf, "STRING" },
@@ -6365,6 +6381,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;