]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tree-wide: refuse too long strings earlier in specifier_printf() 19581/head
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 9 May 2021 16:46:48 +0000 (01:46 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 12 May 2021 01:26:07 +0000 (10:26 +0900)
We usually call specifier_printf() and then check the validity of
the result. In many cases, validity checkers, e.g. path_is_valid(),
refuse too long strings. This makes specifier_printf() refuse such
long results earlier.

Moreover, unit_full_string() and description field in sysuser now
refuse results longer than LONG_LINE_MAX. config_parse() already
refuses the line longer than LONG_LINE_MAX. Hence, it should be ok
to set the same value as the maximum length of the resolved string.

15 files changed:
src/core/load-fragment.c
src/core/unit-printf.c
src/core/unit-printf.h
src/partition/repart.c
src/resolve/resolved-conf.c
src/resolve/resolved-dnssd.c
src/shared/install-printf.c
src/shared/install-printf.h
src/shared/install.c
src/shared/specifier.c
src/shared/specifier.h
src/sysusers/sysusers.c
src/test/test-load-fragment.c
src/test/test-specifier.c
src/tmpfiles/tmpfiles.c

index 2399089492e6a6f12bc079137a7ead1f7e393b4d..4eba2d1c02950b439fc7f7ace6e9c77d55e18715 100644 (file)
@@ -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;
index 8e50a81b975f3e0b0820e0691ac351707dc6cdcd..ee8b0b3de827fbf9a5e77ba9e242b0e54a693d77 100644 (file)
@@ -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);
 }
index de5183c113af161de35b2775a6f16342e6a89c92..2df07db26d3acc7f6736647ee306fc260ef2b835 100644 (file)
@@ -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);
+}
index 51b8f20dbcc2868d38bb7b5bf3c8068d83d46a59..1ecd9ffea434af76c1751a766b74b7f08d201a7a 100644 (file)
@@ -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);
index 87d1794a741784acb6ecbb0dd8d01e494a9d11f6..9b7f7f9ba2034c5d93ccd8fbf6e0edca7f43755f 100644 (file)
@@ -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);
index aed9c5c1cdbf295b3b5dbe3f65a1dd6cd4dd3f88..1c7f16c4d2ac7403b0770a906ca5ca2691ed4ddd 100644 (file)
@@ -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");
 
index 6bc3f15def54810c0f2a9fd61d7cc350181548be..a697b5c4e7bb25325e83621f8f34bdaad5a645ec 100644 (file)
@@ -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);
 }
index 34e129413e5706757d5e6d50256bfe8eb5bea471..13a39829e97a0e84a9263d1570bf19e4295070da 100644 (file)
@@ -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);
+}
index 3e9f6a3df309987fcb98fdfd3ed8ca27d7357aa0..407de0af5e3c8c0279a417f237d35098b149c53f 100644 (file)
@@ -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;
 
index dc86b04b8316896ee42bafaee24a6ca253765526..ef164b3942ba7fed66523f4d9eb4a69bc4b5ad7f 100644 (file)
@@ -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 */
index 6735a7a363a656b6ea23862b8e45e3c8456a3c32..0c5bb3d0c4250f3693ef9ee21f8e0b9e107676ce 100644 (file)
@@ -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);
 
index 848e5e867c7017d428a693ee60e338cff9e97735..dd55360ee5fa505e6a20f6058c1e30bf53aa52c0 100644 (file)
@@ -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);
index 40c1fd053269a96e7850892949c394adcbf23fb0..50345b7b1e3f28bc4023d96bddbf8acff05b4e66 100644 (file)
@@ -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);                                    \
index cad4aa56eca3bb848509e1ab03252809e008e38a..e9d501955c533d476e33afbdc1e5520bf5ff0511 100644 (file)
@@ -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);
         }
index 9529b09b3f3ef56a5275d423889203c103c77dab..1e09c256b0fad944549c6a9003ff8e0c84168b48 100644 (file)
@@ -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) {