diff options
-rw-r--r-- | src/core/load-fragment.c | 98 | ||||
-rw-r--r-- | src/core/unit-printf.c | 6 | ||||
-rw-r--r-- | src/core/unit-printf.h | 21 | ||||
-rw-r--r-- | src/partition/repart.c | 10 | ||||
-rw-r--r-- | src/resolve/resolved-conf.c | 2 | ||||
-rw-r--r-- | src/resolve/resolved-dnssd.c | 2 | ||||
-rw-r--r-- | src/shared/install-printf.c | 4 | ||||
-rw-r--r-- | src/shared/install-printf.h | 9 | ||||
-rw-r--r-- | src/shared/install.c | 8 | ||||
-rw-r--r-- | src/shared/specifier.c | 13 | ||||
-rw-r--r-- | src/shared/specifier.h | 2 | ||||
-rw-r--r-- | src/sysusers/sysusers.c | 10 | ||||
-rw-r--r-- | src/test/test-load-fragment.c | 2 | ||||
-rw-r--r-- | src/test/test-specifier.c | 8 | ||||
-rw-r--r-- | src/tmpfiles/tmpfiles.c | 6 |
15 files changed, 113 insertions, 88 deletions
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 2399089492..4eba2d1c02 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -293,15 +293,7 @@ int config_parse_unit_path_printf( assert(rvalue); assert(u); - /* Let's not bother with anything that is too long */ - if (strlen(rvalue) >= PATH_MAX) { - log_syntax(unit, fatal ? LOG_ERR : LOG_WARNING, filename, line, 0, - "%s value too long%s.", - lvalue, fatal ? "" : ", ignoring"); - return fatal ? -ENAMETOOLONG : 0; - } - - r = unit_full_printf(u, rvalue, &k); + r = unit_path_printf(u, rvalue, &k); if (r < 0) { log_syntax(unit, fatal ? LOG_ERR : LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s'%s: %m", @@ -352,7 +344,7 @@ int config_parse_unit_path_strv_printf( return 0; } - r = unit_full_printf(u, word, &k); + r = unit_path_printf(u, word, &k); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", word); @@ -433,7 +425,7 @@ int config_parse_socket_listen( if (ltype != SOCKET_SOCKET) { _cleanup_free_ char *k = NULL; - r = unit_full_printf(UNIT(s), rvalue, &k); + r = unit_path_printf(UNIT(s), 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; @@ -455,7 +447,7 @@ int config_parse_socket_listen( } else if (streq(lvalue, "ListenNetlink")) { _cleanup_free_ char *k = NULL; - r = unit_full_printf(UNIT(s), rvalue, &k); + r = unit_path_printf(UNIT(s), 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; @@ -472,7 +464,7 @@ int config_parse_socket_listen( } else { _cleanup_free_ char *k = NULL; - r = unit_full_printf(UNIT(s), rvalue, &k); + r = unit_path_printf(UNIT(s), 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; @@ -769,7 +761,7 @@ int config_parse_exec( f++; } - r = unit_full_printf(u, f, &path); + r = unit_path_printf(u, f, &path); if (r < 0) { log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s'%s: %m", @@ -856,7 +848,7 @@ int config_parse_exec( if (r < 0) return ignore ? 0 : -ENOEXEC; - r = unit_full_printf(u, word, &resolved); + r = unit_path_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", @@ -956,7 +948,7 @@ int config_parse_exec_input( if (n) { _cleanup_free_ char *resolved = NULL; - r = unit_full_printf(u, n, &resolved); + r = unit_fd_printf(u, n, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", n); return 0; @@ -976,7 +968,7 @@ int config_parse_exec_input( } else if ((n = startswith(rvalue, "file:"))) { _cleanup_free_ char *resolved = NULL; - r = unit_full_printf(u, n, &resolved); + r = unit_path_printf(u, n, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", n); return 0; @@ -1040,7 +1032,7 @@ int config_parse_exec_input_text( return 0; } - r = unit_full_printf(u, unescaped, &resolved); + r = unit_full_printf_full(u, unescaped, EXEC_STDIN_DATA_MAX, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", unescaped); @@ -1155,7 +1147,7 @@ int config_parse_exec_output( n = startswith(rvalue, "fd:"); if (n) { - r = unit_full_printf(u, n, &resolved); + r = unit_fd_printf(u, n, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s: %m", n); return 0; @@ -1180,7 +1172,7 @@ int config_parse_exec_output( } else if ((n = startswith(rvalue, "file:"))) { - r = unit_full_printf(u, n, &resolved); + r = unit_path_printf(u, n, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", n); return 0; @@ -1194,7 +1186,7 @@ int config_parse_exec_output( } else if ((n = startswith(rvalue, "append:"))) { - r = unit_full_printf(u, n, &resolved); + r = unit_path_printf(u, n, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", n); return 0; @@ -1208,7 +1200,7 @@ int config_parse_exec_output( } else if ((n = startswith(rvalue, "truncate:"))) { - r = unit_full_printf(u, n, &resolved); + r = unit_path_printf(u, n, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", n); return 0; @@ -2080,7 +2072,7 @@ int config_parse_path_spec(const char *unit, return 0; } - r = unit_full_printf(UNIT(p), rvalue, &k); + r = unit_path_printf(UNIT(p), 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; @@ -2175,7 +2167,7 @@ int config_parse_fdname( return 0; } - r = unit_full_printf(UNIT(s), rvalue, &p); + r = unit_fd_printf(UNIT(s), rvalue, &p); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); return 0; @@ -2264,7 +2256,7 @@ int config_parse_bus_name( assert(rvalue); assert(u); - r = unit_full_printf(u, rvalue, &k); + r = unit_full_printf_full(u, rvalue, SD_BUS_MAXIMUM_NAME_LENGTH, &k); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); return 0; @@ -2557,7 +2549,7 @@ int config_parse_working_directory( } else { _cleanup_free_ char *k = NULL; - r = unit_full_printf(u, rvalue, &k); + r = unit_path_printf(u, rvalue, &k); if (r < 0) { log_syntax(unit, missing_ok ? LOG_WARNING : LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in working directory path '%s'%s: %m", @@ -2604,7 +2596,7 @@ int config_parse_unit_env_file(const char *unit, return 0; } - r = unit_full_printf(u, rvalue, &n); + r = unit_full_printf_full(u, rvalue, PATH_MAX, &n); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); return 0; @@ -2665,7 +2657,7 @@ int config_parse_environ( return 0; if (u) { - r = unit_full_printf(u, word, &resolved); + r = unit_env_printf(u, word, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", word); @@ -2730,7 +2722,7 @@ int config_parse_pass_environ( break; if (u) { - r = unit_full_printf(u, word, &k); + r = unit_env_printf(u, word, &k); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve specifiers in %s, ignoring: %m", word); @@ -2805,7 +2797,7 @@ int config_parse_unset_environ( break; if (u) { - r = unit_full_printf(u, word, &k); + r = unit_env_printf(u, word, &k); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", word); @@ -2932,7 +2924,7 @@ int config_parse_log_namespace( return 0; } - r = unit_full_printf(u, rvalue, &k); + r = unit_full_printf_full(u, rvalue, NAME_MAX, &k); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); return 0; @@ -2985,7 +2977,7 @@ int config_parse_unit_condition_path( if (negate) rvalue++; - r = unit_full_printf(u, rvalue, &p); + r = unit_path_printf(u, rvalue, &p); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); return 0; @@ -3090,7 +3082,7 @@ int config_parse_unit_requires_mounts_for( if (r == 0) return 0; - r = unit_full_printf(u, word, &resolved); + r = unit_path_printf(u, word, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", word); continue; @@ -3960,7 +3952,7 @@ int config_parse_device_allow( return 0; } - r = unit_full_printf(userdata, path, &resolved); + r = unit_path_printf(userdata, path, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", path); @@ -4026,7 +4018,7 @@ int config_parse_io_device_weight( return 0; } - r = unit_full_printf(userdata, path, &resolved); + r = unit_path_printf(userdata, path, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", path); @@ -4095,7 +4087,7 @@ int config_parse_io_device_latency( return 0; } - r = unit_full_printf(userdata, path, &resolved); + r = unit_path_printf(userdata, path, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", path); @@ -4165,7 +4157,7 @@ int config_parse_io_limit( return 0; } - r = unit_full_printf(userdata, path, &resolved); + r = unit_path_printf(userdata, path, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", path); @@ -4251,7 +4243,7 @@ int config_parse_blockio_device_weight( return 0; } - r = unit_full_printf(userdata, path, &resolved); + r = unit_path_printf(userdata, path, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", path); @@ -4324,7 +4316,7 @@ int config_parse_blockio_bandwidth( return 0; } - r = unit_full_printf(userdata, path, &resolved); + r = unit_path_printf(userdata, path, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", path); @@ -4440,7 +4432,7 @@ int config_parse_exec_directories( if (r == 0) return 0; - r = unit_full_printf(u, word, &k); + r = unit_path_printf(u, word, &k); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in \"%s\", ignoring: %m", word); @@ -4503,7 +4495,7 @@ int config_parse_set_credential( return 0; } - r = unit_full_printf(u, word, &k); + r = unit_cred_printf(u, word, &k); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in \"%s\", ignoring: %m", word); return 0; @@ -4588,7 +4580,7 @@ int config_parse_load_credential( return 0; } - r = unit_full_printf(u, word, &k); + r = unit_cred_printf(u, word, &k); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in \"%s\", ignoring: %m", word); return 0; @@ -4605,7 +4597,7 @@ int config_parse_load_credential( if (!q) return log_oom(); } else { - r = unit_full_printf(u, p, &q); + r = unit_path_printf(u, p, &q); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in \"%s\", ignoring: %m", p); return 0; @@ -4740,7 +4732,7 @@ int config_parse_namespace_path_strv( w++; } - r = unit_full_printf(u, w, &resolved); + r = unit_path_printf(u, w, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s: %m", w); continue; @@ -4820,7 +4812,7 @@ int config_parse_temporary_filesystems( continue; } - r = unit_full_printf(u, path, &resolved); + r = unit_path_printf(u, path, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", path); continue; @@ -4881,7 +4873,7 @@ int config_parse_bind_paths( if (r == 0) break; - r = unit_full_printf(u, source, &sresolved); + r = unit_full_printf_full(u, source, PATH_MAX, &sresolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in \"%s\", ignoring: %m", source); @@ -4912,7 +4904,7 @@ int config_parse_bind_paths( continue; } - r = unit_full_printf(u, destination, &dresolved); + r = unit_path_printf(u, destination, &dresolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve specifiers in \"%s\", ignoring: %m", destination); @@ -5028,7 +5020,7 @@ int config_parse_mount_images( s++; } - r = unit_full_printf(u, s, &sresolved); + r = unit_path_printf(u, s, &sresolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in \"%s\", ignoring: %m", s); @@ -5044,7 +5036,7 @@ int config_parse_mount_images( continue; } - r = unit_full_printf(u, second, &dresolved); + r = unit_path_printf(u, second, &dresolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve specifiers in \"%s\", ignoring: %m", second); @@ -5187,7 +5179,7 @@ int config_parse_extension_images( s++; } - r = unit_full_printf(u, s, &sresolved); + r = unit_path_printf(u, s, &sresolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in \"%s\", ignoring: %m", s); @@ -5416,7 +5408,7 @@ int config_parse_pid_file( return 0; } - r = unit_full_printf(u, rvalue, &k); + r = unit_path_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; @@ -5537,7 +5529,7 @@ int config_parse_ip_filter_bpf_progs( return 0; } - r = unit_full_printf(u, rvalue, &resolved); + r = unit_path_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; @@ -5611,7 +5603,7 @@ int config_parse_bpf_foreign_program( return 0; } - r = unit_full_printf(u, rvalue, &resolved); + r = unit_path_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; diff --git a/src/core/unit-printf.c b/src/core/unit-printf.c index 8e50a81b97..ee8b0b3de8 100644 --- a/src/core/unit-printf.c +++ b/src/core/unit-printf.c @@ -201,10 +201,10 @@ int unit_name_printf(const Unit *u, const char* format, char **ret) { assert(format); assert(ret); - return specifier_printf(format, table, u, ret); + return specifier_printf(format, UNIT_NAME_MAX, table, u, ret); } -int unit_full_printf(const Unit *u, const char *format, char **ret) { +int unit_full_printf_full(const Unit *u, const char *format, size_t max_length, char **ret) { /* This is similar to unit_name_printf() but also supports unescaping. Also, adds a couple of additional codes * (which are likely not suitable for unescaped inclusion in unit names): * @@ -265,5 +265,5 @@ int unit_full_printf(const Unit *u, const char *format, char **ret) { {} }; - return specifier_printf(format, table, u, ret); + return specifier_printf(format, max_length, table, u, ret); } diff --git a/src/core/unit-printf.h b/src/core/unit-printf.h index de5183c113..2df07db26d 100644 --- a/src/core/unit-printf.h +++ b/src/core/unit-printf.h @@ -1,7 +1,26 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once +#include "creds-util.h" +#include "env-util.h" +#include "fd-util.h" +#include "fileio.h" #include "unit.h" int unit_name_printf(const Unit *u, const char* text, char **ret); -int unit_full_printf(const Unit *u, const char *text, char **ret); +int unit_full_printf_full(const Unit *u, const char *text, size_t max_length, char **ret); +static inline int unit_full_printf(const Unit *u, const char *text, char **ret) { + return unit_full_printf_full(u, text, LONG_LINE_MAX, ret); +} +static inline int unit_path_printf(const Unit *u, const char *text, char **ret) { + return unit_full_printf_full(u, text, PATH_MAX-1, ret); +} +static inline int unit_fd_printf(const Unit *u, const char *text, char **ret) { + return unit_full_printf_full(u, text, FDNAME_MAX, ret); +} +static inline int unit_cred_printf(const Unit *u, const char *text, char **ret) { + return unit_full_printf_full(u, text, CREDENTIAL_NAME_MAX, ret); +} +static inline int unit_env_printf(const Unit *u, const char *text, char **ret) { + return unit_full_printf_full(u, text, sc_arg_max(), ret); +} diff --git a/src/partition/repart.c b/src/partition/repart.c index 51b8f20dbc..1ecd9ffea4 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -977,7 +977,7 @@ static int config_parse_label( /* Nota bene: the empty label is a totally valid one. Let's hence not follow our usual rule of * assigning the empty string to reset to default here, but really accept it as label to set. */ - r = specifier_printf(rvalue, specifier_table, NULL, &resolved); + r = specifier_printf(rvalue, GPT_LABEL_MAX, specifier_table, NULL, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to expand specifiers in Label=, ignoring: %s", rvalue); @@ -1142,7 +1142,7 @@ static int config_parse_copy_files( if (!isempty(p)) return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), "Too many arguments: %s", rvalue); - r = specifier_printf(source, specifier_table, NULL, &resolved_source); + r = specifier_printf(source, PATH_MAX-1, specifier_table, NULL, &resolved_source); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to expand specifiers in CopyFiles= source, ignoring: %s", rvalue); @@ -1153,7 +1153,7 @@ static int config_parse_copy_files( if (r < 0) return 0; - r = specifier_printf(target, specifier_table, NULL, &resolved_target); + r = specifier_printf(target, PATH_MAX-1, specifier_table, NULL, &resolved_target); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to expand specifiers in CopyFiles= target, ignoring: %s", resolved_target); @@ -1202,7 +1202,7 @@ static int config_parse_copy_blocks( return 0; } - r = specifier_printf(rvalue, specifier_table, NULL, &d); + r = specifier_printf(rvalue, PATH_MAX-1, specifier_table, NULL, &d); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to expand specifiers in CopyBlocks= source path, ignoring: %s", rvalue); @@ -1250,7 +1250,7 @@ static int config_parse_make_dirs( if (r == 0) return 0; - r = specifier_printf(word, specifier_table, NULL, &d); + r = specifier_printf(word, PATH_MAX-1, specifier_table, NULL, &d); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to expand specifiers in MakeDirectories= parameter, ignoring: %s", word); diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c index 87d1794a74..9b7f7f9ba2 100644 --- a/src/resolve/resolved-conf.c +++ b/src/resolve/resolved-conf.c @@ -255,7 +255,7 @@ int config_parse_dnssd_service_name( return 0; } - r = specifier_printf(rvalue, specifier_table, NULL, &name); + r = specifier_printf(rvalue, DNS_LABEL_MAX, specifier_table, NULL, &name); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid service instance name template '%s', ignoring assignment: %m", rvalue); diff --git a/src/resolve/resolved-dnssd.c b/src/resolve/resolved-dnssd.c index aed9c5c1cd..1c7f16c4d2 100644 --- a/src/resolve/resolved-dnssd.c +++ b/src/resolve/resolved-dnssd.c @@ -170,7 +170,7 @@ int dnssd_render_instance_name(DnssdService *s, char **ret_name) { assert(s); assert(s->name_template); - r = specifier_printf(s->name_template, specifier_table, s, &name); + r = specifier_printf(s->name_template, DNS_LABEL_MAX, specifier_table, s, &name); if (r < 0) return log_debug_errno(r, "Failed to replace specifiers: %m"); diff --git a/src/shared/install-printf.c b/src/shared/install-printf.c index 6bc3f15def..a697b5c4e7 100644 --- a/src/shared/install-printf.c +++ b/src/shared/install-printf.c @@ -103,7 +103,7 @@ static int specifier_last_component(char specifier, const void *data, const void return 0; } -int install_full_printf(const UnitFileInstallInfo *i, const char *format, char **ret) { +int install_full_printf_internal(const UnitFileInstallInfo *i, const char *format, size_t max_length, char **ret) { /* This is similar to unit_name_printf() */ const Specifier table[] = { @@ -123,5 +123,5 @@ int install_full_printf(const UnitFileInstallInfo *i, const char *format, char * assert(format); assert(ret); - return specifier_printf(format, table, i, ret); + return specifier_printf(format, max_length, table, i, ret); } diff --git a/src/shared/install-printf.h b/src/shared/install-printf.h index 34e129413e..13a39829e9 100644 --- a/src/shared/install-printf.h +++ b/src/shared/install-printf.h @@ -2,5 +2,12 @@ #pragma once #include "install.h" +#include "unit-name.h" -int install_full_printf(const UnitFileInstallInfo *i, const char *format, char **ret); +int install_full_printf_internal(const UnitFileInstallInfo *i, const char *format, size_t max_length, char **ret); +static inline int install_name_printf(const UnitFileInstallInfo *i, const char *format, char **ret) { + return install_full_printf_internal(i, format, UNIT_NAME_MAX, ret); +} +static inline int install_path_printf(const UnitFileInstallInfo *i, const char *format, char **ret) { + return install_full_printf_internal(i, format, PATH_MAX-1, ret); +} diff --git a/src/shared/install.c b/src/shared/install.c index 3e9f6a3df3..407de0af5e 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -1143,7 +1143,7 @@ static int config_parse_also( if (r == 0) break; - r = install_full_printf(info, word, &printed); + r = install_name_printf(info, word, &printed); if (r < 0) return r; @@ -1190,7 +1190,7 @@ static int config_parse_default_instance( return log_syntax(unit, LOG_WARNING, filename, line, 0, "DefaultInstance= only makes sense for template units, ignoring."); - r = install_full_printf(i, rvalue, &printed); + r = install_name_printf(i, rvalue, &printed); if (r < 0) return r; @@ -1816,7 +1816,7 @@ static int install_info_symlink_alias( STRV_FOREACH(s, i->aliases) { _cleanup_free_ char *alias_path = NULL, *dst = NULL, *dst_updated = NULL; - q = install_full_printf(i, *s, &dst); + q = install_path_printf(i, *s, &dst); if (q < 0) return q; @@ -1891,7 +1891,7 @@ static int install_info_symlink_wants( STRV_FOREACH(s, list) { _cleanup_free_ char *path = NULL, *dst = NULL; - q = install_full_printf(i, *s, &dst); + q = install_name_printf(i, *s, &dst); if (q < 0) return q; diff --git a/src/shared/specifier.c b/src/shared/specifier.c index dc86b04b83..ef164b3942 100644 --- a/src/shared/specifier.c +++ b/src/shared/specifier.c @@ -29,7 +29,7 @@ * and "%" used for escaping. */ #define POSSIBLE_SPECIFIERS ALPHANUMERICAL "%" -int specifier_printf(const char *text, const Specifier table[], const void *userdata, char **ret) { +int specifier_printf(const char *text, size_t max_length, const Specifier table[], const void *userdata, char **ret) { size_t l, allocated = 0; _cleanup_free_ char *result = NULL; char *t; @@ -45,7 +45,7 @@ int specifier_printf(const char *text, const Specifier table[], const void *user return -ENOMEM; t = result; - for (f = text; *f; f++, l--) + for (f = text; *f != '\0'; f++, l--) { if (percent) { if (*f == '%') *(t++) = '%'; @@ -86,9 +86,16 @@ int specifier_printf(const char *text, const Specifier table[], const void *user else *(t++) = *f; + if ((size_t) (t - result) > max_length) + return -ENAMETOOLONG; + } + /* If string ended with a stray %, also end with % */ - if (percent) + if (percent) { *(t++) = '%'; + if ((size_t) (t - result) > max_length) + return -ENAMETOOLONG; + } *(t++) = 0; /* Try to deallocate unused bytes, but don't sweat it too much */ diff --git a/src/shared/specifier.h b/src/shared/specifier.h index 6735a7a363..0c5bb3d0c4 100644 --- a/src/shared/specifier.h +++ b/src/shared/specifier.h @@ -11,7 +11,7 @@ typedef struct Specifier { const void *data; } Specifier; -int specifier_printf(const char *text, const Specifier table[], const void *userdata, char **ret); +int specifier_printf(const char *text, size_t max_length, const Specifier table[], const void *userdata, char **ret); int specifier_string(char specifier, const void *data, const void *userdata, char **ret); diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index 848e5e867c..dd55360ee5 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -1492,7 +1492,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { name = mfree(name); if (name) { - r = specifier_printf(name, specifier_table, NULL, &resolved_name); + r = specifier_printf(name, NAME_MAX, specifier_table, NULL, &resolved_name); if (r < 0) return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m", fname, line, name); @@ -1507,7 +1507,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { id = mfree(id); if (id) { - r = specifier_printf(id, specifier_table, NULL, &resolved_id); + r = specifier_printf(id, PATH_MAX-1, specifier_table, NULL, &resolved_id); if (r < 0) return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m", fname, line, name); @@ -1518,7 +1518,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { description = mfree(description); if (description) { - r = specifier_printf(description, specifier_table, NULL, &resolved_description); + r = specifier_printf(description, LONG_LINE_MAX, specifier_table, NULL, &resolved_description); if (r < 0) return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m", fname, line, description); @@ -1534,7 +1534,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { home = mfree(home); if (home) { - r = specifier_printf(home, specifier_table, NULL, &resolved_home); + r = specifier_printf(home, PATH_MAX-1, specifier_table, NULL, &resolved_home); if (r < 0) return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m", fname, line, home); @@ -1550,7 +1550,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { shell = mfree(shell); if (shell) { - r = specifier_printf(shell, specifier_table, NULL, &resolved_shell); + r = specifier_printf(shell, PATH_MAX-1, specifier_table, NULL, &resolved_shell); if (r < 0) return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m", fname, line, shell); diff --git a/src/test/test-load-fragment.c b/src/test/test-load-fragment.c index 40c1fd0532..50345b7b1e 100644 --- a/src/test/test-load-fragment.c +++ b/src/test/test-load-fragment.c @@ -512,7 +512,7 @@ static void test_install_printf(void) { _cleanup_free_ char \ *d1 = strdup(i.name), \ *d2 = strdup(i.path); \ - assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \ + assert_se(install_name_printf(&src, pattern, &t) >= 0 || !result); \ memzero(i.name, strlen(i.name)); \ memzero(i.path, strlen(i.path)); \ assert_se(d1 && d2); \ diff --git a/src/test/test-specifier.c b/src/test/test-specifier.c index cad4aa56ec..e9d501955c 100644 --- a/src/test/test-specifier.c +++ b/src/test/test-specifier.c @@ -69,7 +69,7 @@ static void test_specifier_printf(void) { log_info("/* %s */", __func__); - r = specifier_printf("xxx a=%X b=%Y yyy", table, NULL, &w); + r = specifier_printf("xxx a=%X b=%Y yyy", SIZE_MAX, table, NULL, &w); assert_se(r >= 0); assert_se(w); @@ -77,13 +77,13 @@ static void test_specifier_printf(void) { assert_se(streq(w, "xxx a=AAAA b=BBBB yyy")); free(w); - r = specifier_printf("machine=%m, boot=%b, host=%H, version=%v, arch=%a", table, NULL, &w); + r = specifier_printf("machine=%m, boot=%b, host=%H, version=%v, arch=%a", SIZE_MAX, table, NULL, &w); assert_se(r >= 0); assert_se(w); puts(w); w = mfree(w); - specifier_printf("os=%o, os-version=%w, build=%B, variant=%W", table, NULL, &w); + specifier_printf("os=%o, os-version=%w, build=%B, variant=%W", SIZE_MAX, table, NULL, &w); if (w) puts(w); } @@ -97,7 +97,7 @@ static void test_specifiers(void) { xsprintf(spec, "%%%c", s->specifier); - assert_se(specifier_printf(spec, specifier_table, NULL, &resolved) >= 0); + assert_se(specifier_printf(spec, SIZE_MAX, specifier_table, NULL, &resolved) >= 0); log_info("%%%c → %s", s->specifier, resolved); } diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 9529b09b3f..1e09c256b0 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -2522,7 +2522,7 @@ static int specifier_expansion_from_arg(Item *i) { if (r < 0) return log_error_errno(r, "Failed to unescape parameter to write: %s", i->argument); - r = specifier_printf(unescaped, specifier_table, NULL, &resolved); + r = specifier_printf(unescaped, PATH_MAX-1, specifier_table, NULL, &resolved); if (r < 0) return r; @@ -2532,7 +2532,7 @@ static int specifier_expansion_from_arg(Item *i) { case SET_XATTR: case RECURSIVE_SET_XATTR: STRV_FOREACH(xattr, i->xattrs) { - r = specifier_printf(*xattr, specifier_table, NULL, &resolved); + r = specifier_printf(*xattr, SIZE_MAX, specifier_table, NULL, &resolved); if (r < 0) return r; @@ -2706,7 +2706,7 @@ static int parse_line( i.append_or_force = append_or_force; i.allow_failure = allow_failure; - r = specifier_printf(path, specifier_table, NULL, &i.path); + r = specifier_printf(path, PATH_MAX-1, specifier_table, NULL, &i.path); if (r == -ENXIO) return log_unresolvable_specifier(fname, line); if (r < 0) { |