b7dd4d
From e3e479fc9c51e0b6f2c21087e2e78e7c6f55169c Mon Sep 17 00:00:00 2001
62b62a
From: Lennart Poettering <lennart@poettering.net>
62b62a
Date: Mon, 25 May 2020 00:34:58 +0200
62b62a
Subject: [PATCH] unit-name: tighten checks for building valid unit names
62b62a
62b62a
Let's be more thorough that whenever we build a unit name based on
62b62a
parameters, that the result is actually a valid user name. If it isn't
62b62a
fail early.
62b62a
62b62a
This should allows us to catch various issues earlier, in particular
62b62a
when we synthesize mount units from /proc/self/mountinfo: instead of
62b62a
actually attempting to allocate a mount unit we will fail much earlier
62b62a
when we build the name to synthesize the unit under. Failing early is a
62b62a
good thing generally.
62b62a
62b62a
(cherry picked from commit ab19db01ae1826efb3cbdf6dcb6a14412f8844d4)
62b62a
b7dd4d
Related: #1940973
62b62a
---
62b62a
 src/basic/unit-name.c | 61 ++++++++++++++++++++++++++++++-------------
62b62a
 1 file changed, 43 insertions(+), 18 deletions(-)
62b62a
62b62a
diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c
62b62a
index 614eb8649b..f9b3fafd4d 100644
62b62a
--- a/src/basic/unit-name.c
62b62a
+++ b/src/basic/unit-name.c
62b62a
@@ -207,8 +207,9 @@ UnitType unit_name_to_type(const char *n) {
62b62a
 }
62b62a
 
62b62a
 int unit_name_change_suffix(const char *n, const char *suffix, char **ret) {
62b62a
-        char *e, *s;
62b62a
+        _cleanup_free_ char *s = NULL;
62b62a
         size_t a, b;
62b62a
+        char *e;
62b62a
 
62b62a
         assert(n);
62b62a
         assert(suffix);
62b62a
@@ -230,8 +231,12 @@ int unit_name_change_suffix(const char *n, const char *suffix, char **ret) {
62b62a
                 return -ENOMEM;
62b62a
 
62b62a
         strcpy(mempcpy(s, n, a), suffix);
62b62a
-        *ret = s;
62b62a
 
62b62a
+        /* Make sure the name is still valid (i.e. didn't grow too large due to longer suffix) */
62b62a
+        if (!unit_name_is_valid(s, UNIT_NAME_ANY))
62b62a
+                return -EINVAL;
62b62a
+
62b62a
+        *ret = TAKE_PTR(s);
62b62a
         return 0;
62b62a
 }
62b62a
 
62b62a
@@ -253,8 +258,8 @@ int unit_name_build(const char *prefix, const char *instance, const char *suffix
62b62a
 }
62b62a
 
62b62a
 int unit_name_build_from_type(const char *prefix, const char *instance, UnitType type, char **ret) {
62b62a
+        _cleanup_free_ char *s = NULL;
62b62a
         const char *ut;
62b62a
-        char *s;
62b62a
 
62b62a
         assert(prefix);
62b62a
         assert(type >= 0);
62b62a
@@ -264,19 +269,23 @@ int unit_name_build_from_type(const char *prefix, const char *instance, UnitType
62b62a
         if (!unit_prefix_is_valid(prefix))
62b62a
                 return -EINVAL;
62b62a
 
62b62a
-        if (instance && !unit_instance_is_valid(instance))
62b62a
-                return -EINVAL;
62b62a
-
62b62a
         ut = unit_type_to_string(type);
62b62a
 
62b62a
-        if (!instance)
62b62a
-                s = strjoin(prefix, ".", ut);
62b62a
-        else
62b62a
+        if (instance) {
62b62a
+                if (!unit_instance_is_valid(instance))
62b62a
+                        return -EINVAL;
62b62a
+
62b62a
                 s = strjoin(prefix, "@", instance, ".", ut);
62b62a
+        } else
62b62a
+                s = strjoin(prefix, ".", ut);
62b62a
         if (!s)
62b62a
                 return -ENOMEM;
62b62a
 
62b62a
-        *ret = s;
62b62a
+        /* Verify that this didn't grow too large (or otherwise is invalid) */
62b62a
+        if (!unit_name_is_valid(s, instance ? UNIT_NAME_INSTANCE : UNIT_NAME_PLAIN))
62b62a
+                return -EINVAL;
62b62a
+
62b62a
+        *ret = TAKE_PTR(s);
62b62a
         return 0;
62b62a
 }
62b62a
 
62b62a
@@ -445,8 +454,8 @@ int unit_name_path_unescape(const char *f, char **ret) {
62b62a
 }
62b62a
 
62b62a
 int unit_name_replace_instance(const char *f, const char *i, char **ret) {
62b62a
+        _cleanup_free_ char *s = NULL;
62b62a
         const char *p, *e;
62b62a
-        char *s;
62b62a
         size_t a, b;
62b62a
 
62b62a
         assert(f);
62b62a
@@ -470,7 +479,11 @@ int unit_name_replace_instance(const char *f, const char *i, char **ret) {
62b62a
 
62b62a
         strcpy(mempcpy(mempcpy(s, f, a + 1), i, b), e);
62b62a
 
62b62a
-        *ret = s;
62b62a
+        /* Make sure the resulting name still is valid, i.e. didn't grow too large */
62b62a
+        if (!unit_name_is_valid(s, UNIT_NAME_INSTANCE))
62b62a
+                return -EINVAL;
62b62a
+
62b62a
+        *ret = TAKE_PTR(s);
62b62a
         return 0;
62b62a
 }
62b62a
 
62b62a
@@ -501,8 +514,7 @@ int unit_name_template(const char *f, char **ret) {
62b62a
 }
62b62a
 
62b62a
 int unit_name_from_path(const char *path, const char *suffix, char **ret) {
62b62a
-        _cleanup_free_ char *p = NULL;
62b62a
-        char *s = NULL;
62b62a
+        _cleanup_free_ char *p = NULL, *s = NULL;
62b62a
         int r;
62b62a
 
62b62a
         assert(path);
62b62a
@@ -520,7 +532,11 @@ int unit_name_from_path(const char *path, const char *suffix, char **ret) {
62b62a
         if (!s)
62b62a
                 return -ENOMEM;
62b62a
 
62b62a
-        *ret = s;
62b62a
+        /* Refuse this if this got too long or for some other reason didn't result in a valid name */
62b62a
+        if (!unit_name_is_valid(s, UNIT_NAME_PLAIN))
62b62a
+                return -EINVAL;
62b62a
+
62b62a
+        *ret = TAKE_PTR(s);
62b62a
         return 0;
62b62a
 }
62b62a
 
62b62a
@@ -548,6 +564,10 @@ int unit_name_from_path_instance(const char *prefix, const char *path, const cha
62b62a
         if (!s)
62b62a
                 return -ENOMEM;
62b62a
 
62b62a
+        /* Refuse this if this got too long or for some other reason didn't result in a valid name */
62b62a
+        if (!unit_name_is_valid(s, UNIT_NAME_INSTANCE))
62b62a
+                return -EINVAL;
62b62a
+
62b62a
         *ret = s;
62b62a
         return 0;
62b62a
 }
62b62a
@@ -601,7 +621,7 @@ static bool do_escape_mangle(const char *f, bool allow_globs, char *t) {
62b62a
  *  If @allow_globs, globs characters are preserved. Otherwise, they are escaped.
62b62a
  */
62b62a
 int unit_name_mangle_with_suffix(const char *name, UnitNameMangle flags, const char *suffix, char **ret) {
62b62a
-        char *s;
62b62a
+        _cleanup_free_ char *s = NULL;
62b62a
         int r;
62b62a
         bool mangled;
62b62a
 
62b62a
@@ -656,7 +676,12 @@ int unit_name_mangle_with_suffix(const char *name, UnitNameMangle flags, const c
62b62a
         if ((!(flags & UNIT_NAME_MANGLE_GLOB) || !string_is_glob(s)) && unit_name_to_type(s) < 0)
62b62a
                 strcat(s, suffix);
62b62a
 
62b62a
-        *ret = s;
62b62a
+        /* Make sure mangling didn't grow this too large (but don't do this check if globbing is allowed,
62b62a
+         * since globs generally do not qualify as valid unit names) */
62b62a
+        if (!FLAGS_SET(flags, UNIT_NAME_MANGLE_GLOB) && !unit_name_is_valid(s, UNIT_NAME_ANY))
62b62a
+                return -EINVAL;
62b62a
+
62b62a
+        *ret = TAKE_PTR(s);
62b62a
         return 1;
62b62a
 
62b62a
 good:
62b62a
@@ -664,7 +689,7 @@ good:
62b62a
         if (!s)
62b62a
                 return -ENOMEM;
62b62a
 
62b62a
-        *ret = s;
62b62a
+        *ret = TAKE_PTR(s);
62b62a
         return 0;
62b62a
 }
62b62a