Zbigniew Jędrzejewski-Szmek a52f67
From 08ad3cb42d0c075d5b51127e9f867907b42fccbb Mon Sep 17 00:00:00 2001
Zbigniew Jędrzejewski-Szmek ca73a2
From: Goffredo Baroncelli <kreijack@libero.it>
Zbigniew Jędrzejewski-Szmek ca73a2
Date: Thu, 6 Feb 2014 19:09:59 +0100
Zbigniew Jędrzejewski-Szmek ca73a2
Subject: [PATCH] core: fix crashes if locale.conf contains invalid utf-8
Zbigniew Jędrzejewski-Szmek ca73a2
 string
Zbigniew Jędrzejewski-Szmek ca73a2
Zbigniew Jędrzejewski-Szmek ca73a2
In the parse_env_file_push() and load_env_file_push() functions, there
Zbigniew Jędrzejewski-Szmek ca73a2
are two assert() call to check if the key or value parameters are utf8 valid.
Zbigniew Jędrzejewski-Szmek ca73a2
Zbigniew Jędrzejewski-Szmek ca73a2
If the strings aren't utf8 valid, assert does abort.
Zbigniew Jędrzejewski-Szmek ca73a2
Zbigniew Jędrzejewski-Szmek ca73a2
These function are used early by systemd to parse some files. For
Zbigniew Jędrzejewski-Szmek ca73a2
example '/etc/locale.conf'. In my case this file contained a not utf8
Zbigniew Jędrzejewski-Szmek ca73a2
sequence, which is bad, but systemd crashed during the boot, which
Zbigniew Jędrzejewski-Szmek ca73a2
is even worse!
Zbigniew Jędrzejewski-Szmek ca73a2
Zbigniew Jędrzejewski-Szmek ca73a2
The enclosed patch removes the assert and return -EINVAL if the
Zbigniew Jędrzejewski-Szmek ca73a2
sequence is invalid. This is possible because the caller of these
Zbigniew Jędrzejewski-Szmek ca73a2
function [1] checks the errors.
Zbigniew Jędrzejewski-Szmek ca73a2
So the check of an invalid utf8 sequence is still performed, but
Zbigniew Jędrzejewski-Szmek ca73a2
systemd doesn't crash anymore and logs the error.
Zbigniew Jędrzejewski-Szmek ca73a2
Zbigniew Jędrzejewski-Szmek ca73a2
[1] parse_env_file_internal(), invoked by load_env_file() and
Zbigniew Jędrzejewski-Szmek ca73a2
parse_env_file()
Zbigniew Jędrzejewski-Szmek a52f67
Zbigniew Jędrzejewski-Szmek a52f67
(cherry picked from commit f27f0e2177ac0a4b96585aed7db3a080e27a2f00)
Zbigniew Jędrzejewski-Szmek ca73a2
---
Zbigniew Jędrzejewski-Szmek ca73a2
 src/shared/fileio.c | 77 ++++++++++++++++++++++++++++++-----------------------
Zbigniew Jędrzejewski-Szmek ca73a2
 1 file changed, 43 insertions(+), 34 deletions(-)
Zbigniew Jędrzejewski-Szmek ca73a2
Zbigniew Jędrzejewski-Szmek ca73a2
diff --git a/src/shared/fileio.c b/src/shared/fileio.c
Zbigniew Jędrzejewski-Szmek 1cc3df
index 733b320388..d28e38a621 100644
Zbigniew Jędrzejewski-Szmek ca73a2
--- a/src/shared/fileio.c
Zbigniew Jędrzejewski-Szmek ca73a2
+++ b/src/shared/fileio.c
Zbigniew Jędrzejewski-Szmek ca73a2
@@ -462,35 +462,39 @@ fail:
Zbigniew Jędrzejewski-Szmek ca73a2
 
Zbigniew Jędrzejewski-Szmek ca73a2
 static int parse_env_file_push(const char *filename, unsigned line,
Zbigniew Jędrzejewski-Szmek ca73a2
                                const char *key, char *value, void *userdata) {
Zbigniew Jędrzejewski-Szmek ca73a2
-        assert(utf8_is_valid(key));
Zbigniew Jędrzejewski-Szmek ca73a2
 
Zbigniew Jędrzejewski-Szmek ca73a2
-        if (value && !utf8_is_valid(value))
Zbigniew Jędrzejewski-Szmek ca73a2
+        const char *k;
Zbigniew Jędrzejewski-Szmek ca73a2
+        va_list aq, *ap = userdata;
Zbigniew Jędrzejewski-Szmek ca73a2
+
Zbigniew Jędrzejewski-Szmek ca73a2
+        if (!utf8_is_valid(key)) {
Zbigniew Jędrzejewski-Szmek ca73a2
+                log_error("%s:%u: invalid UTF-8 for key '%s', ignoring.",
Zbigniew Jędrzejewski-Szmek ca73a2
+                          filename, line, key);
Zbigniew Jędrzejewski-Szmek ca73a2
+                return -EINVAL;
Zbigniew Jędrzejewski-Szmek ca73a2
+        }
Zbigniew Jędrzejewski-Szmek ca73a2
+
Zbigniew Jędrzejewski-Szmek ca73a2
+        if (value && !utf8_is_valid(value)) {
Zbigniew Jędrzejewski-Szmek ca73a2
                 /* FIXME: filter UTF-8 */
Zbigniew Jędrzejewski-Szmek ca73a2
-                log_error("%s:%u: invalid UTF-8 for key %s: '%s', ignoring.",
Zbigniew Jędrzejewski-Szmek ca73a2
+                log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.",
Zbigniew Jędrzejewski-Szmek ca73a2
                           filename, line, key, value);
Zbigniew Jędrzejewski-Szmek ca73a2
-        else {
Zbigniew Jędrzejewski-Szmek ca73a2
-                const char *k;
Zbigniew Jędrzejewski-Szmek ca73a2
-                va_list* ap = (va_list*) userdata;
Zbigniew Jędrzejewski-Szmek ca73a2
-                va_list aq;
Zbigniew Jędrzejewski-Szmek ca73a2
+                return -EINVAL;
Zbigniew Jędrzejewski-Szmek ca73a2
+        }
Zbigniew Jędrzejewski-Szmek ca73a2
 
Zbigniew Jędrzejewski-Szmek ca73a2
-                va_copy(aq, *ap);
Zbigniew Jędrzejewski-Szmek ca73a2
+        va_copy(aq, *ap);
Zbigniew Jędrzejewski-Szmek ca73a2
 
Zbigniew Jędrzejewski-Szmek ca73a2
-                while ((k = va_arg(aq, const char *))) {
Zbigniew Jędrzejewski-Szmek ca73a2
-                        char **v;
Zbigniew Jędrzejewski-Szmek ca73a2
+        while ((k = va_arg(aq, const char *))) {
Zbigniew Jędrzejewski-Szmek ca73a2
+                char **v;
Zbigniew Jędrzejewski-Szmek ca73a2
 
Zbigniew Jędrzejewski-Szmek ca73a2
-                        v = va_arg(aq, char **);
Zbigniew Jędrzejewski-Szmek ca73a2
+                v = va_arg(aq, char **);
Zbigniew Jędrzejewski-Szmek ca73a2
 
Zbigniew Jędrzejewski-Szmek ca73a2
-                        if (streq(key, k)) {
Zbigniew Jędrzejewski-Szmek ca73a2
-                                va_end(aq);
Zbigniew Jędrzejewski-Szmek ca73a2
-                                free(*v);
Zbigniew Jędrzejewski-Szmek ca73a2
-                                *v = value;
Zbigniew Jędrzejewski-Szmek ca73a2
-                                return 1;
Zbigniew Jędrzejewski-Szmek ca73a2
-                        }
Zbigniew Jędrzejewski-Szmek ca73a2
+                if (streq(key, k)) {
Zbigniew Jędrzejewski-Szmek ca73a2
+                        va_end(aq);
Zbigniew Jędrzejewski-Szmek ca73a2
+                        free(*v);
Zbigniew Jędrzejewski-Szmek ca73a2
+                        *v = value;
Zbigniew Jędrzejewski-Szmek ca73a2
+                        return 1;
Zbigniew Jędrzejewski-Szmek ca73a2
                 }
Zbigniew Jędrzejewski-Szmek ca73a2
-
Zbigniew Jędrzejewski-Szmek ca73a2
-                va_end(aq);
Zbigniew Jędrzejewski-Szmek ca73a2
         }
Zbigniew Jędrzejewski-Szmek ca73a2
 
Zbigniew Jędrzejewski-Szmek ca73a2
+        va_end(aq);
Zbigniew Jędrzejewski-Szmek ca73a2
         free(value);
Zbigniew Jędrzejewski-Szmek ca73a2
         return 0;
Zbigniew Jędrzejewski-Szmek ca73a2
 }
Zbigniew Jędrzejewski-Szmek ca73a2
@@ -514,26 +518,31 @@ int parse_env_file(
Zbigniew Jędrzejewski-Szmek ca73a2
 
Zbigniew Jędrzejewski-Szmek ca73a2
 static int load_env_file_push(const char *filename, unsigned line,
Zbigniew Jędrzejewski-Szmek ca73a2
                               const char *key, char *value, void *userdata) {
Zbigniew Jędrzejewski-Szmek ca73a2
-        assert(utf8_is_valid(key));
Zbigniew Jędrzejewski-Szmek ca73a2
+        char ***m = userdata;
Zbigniew Jędrzejewski-Szmek ca73a2
+        char *p;
Zbigniew Jędrzejewski-Szmek ca73a2
+        int r;
Zbigniew Jędrzejewski-Szmek ca73a2
 
Zbigniew Jędrzejewski-Szmek ca73a2
-        if (value && !utf8_is_valid(value))
Zbigniew Jędrzejewski-Szmek ca73a2
+        if (!utf8_is_valid(key)) {
Zbigniew Jędrzejewski-Szmek ca73a2
+                log_error("%s:%u: invalid UTF-8 for key '%s', ignoring.",
Zbigniew Jędrzejewski-Szmek ca73a2
+                          filename, line, key);
Zbigniew Jędrzejewski-Szmek ca73a2
+                return -EINVAL;
Zbigniew Jędrzejewski-Szmek ca73a2
+        }
Zbigniew Jędrzejewski-Szmek ca73a2
+
Zbigniew Jędrzejewski-Szmek ca73a2
+        if (value && !utf8_is_valid(value)) {
Zbigniew Jędrzejewski-Szmek ca73a2
                 /* FIXME: filter UTF-8 */
Zbigniew Jędrzejewski-Szmek ca73a2
-                log_error("%s:%u: invalid UTF-8 for key %s: '%s', ignoring.",
Zbigniew Jędrzejewski-Szmek ca73a2
+                log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.",
Zbigniew Jędrzejewski-Szmek ca73a2
                           filename, line, key, value);
Zbigniew Jędrzejewski-Szmek ca73a2
-        else {
Zbigniew Jędrzejewski-Szmek ca73a2
-                char ***m = userdata;
Zbigniew Jędrzejewski-Szmek ca73a2
-                char *p;
Zbigniew Jędrzejewski-Szmek ca73a2
-                int r;
Zbigniew Jędrzejewski-Szmek ca73a2
+                return -EINVAL;
Zbigniew Jędrzejewski-Szmek ca73a2
+        }
Zbigniew Jędrzejewski-Szmek ca73a2
 
Zbigniew Jędrzejewski-Szmek ca73a2
-                p = strjoin(key, "=", strempty(value), NULL);
Zbigniew Jędrzejewski-Szmek ca73a2
-                if (!p)
Zbigniew Jędrzejewski-Szmek ca73a2
-                        return -ENOMEM;
Zbigniew Jędrzejewski-Szmek ca73a2
+        p = strjoin(key, "=", strempty(value), NULL);
Zbigniew Jędrzejewski-Szmek ca73a2
+        if (!p)
Zbigniew Jędrzejewski-Szmek ca73a2
+                return -ENOMEM;
Zbigniew Jędrzejewski-Szmek ca73a2
 
Zbigniew Jędrzejewski-Szmek ca73a2
-                r = strv_push(m, p);
Zbigniew Jędrzejewski-Szmek ca73a2
-                if (r < 0) {
Zbigniew Jędrzejewski-Szmek ca73a2
-                        free(p);
Zbigniew Jędrzejewski-Szmek ca73a2
-                        return r;
Zbigniew Jędrzejewski-Szmek ca73a2
-                }
Zbigniew Jędrzejewski-Szmek ca73a2
+        r = strv_push(m, p);
Zbigniew Jędrzejewski-Szmek ca73a2
+        if (r < 0) {
Zbigniew Jędrzejewski-Szmek ca73a2
+                free(p);
Zbigniew Jędrzejewski-Szmek ca73a2
+                return r;
Zbigniew Jędrzejewski-Szmek ca73a2
         }
Zbigniew Jędrzejewski-Szmek ca73a2
 
Zbigniew Jędrzejewski-Szmek ca73a2
         free(value);