diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 03:50:45 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 03:50:45 +0000 |
commit | efeb864cb547a2cbf96dc0053a8bdb4d9190b364 (patch) | |
tree | c0b83368f18be983fcc763200c4c24d633244588 /src/core/load-fragment.c | |
parent | Releasing progress-linux version 255.5-1~progress7.99u1. (diff) | |
download | systemd-efeb864cb547a2cbf96dc0053a8bdb4d9190b364.tar.xz systemd-efeb864cb547a2cbf96dc0053a8bdb4d9190b364.zip |
Merging upstream version 256.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/core/load-fragment.c')
-rw-r--r-- | src/core/load-fragment.c | 353 |
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; |