]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core/mount: replace invalid UTF-8 code points in "what" and "options"
authorMichal Sekletar <msekleta@redhat.com>
Fri, 5 May 2023 10:50:15 +0000 (12:50 +0200)
committerLuca Boccassi <luca.boccassi@gmail.com>
Tue, 9 May 2023 23:01:32 +0000 (00:01 +0100)
Previously, these strings were copied w/o any modification. However, if
mount table contained e.g. remote fs mount like NFS or CIFS that was
mounted from server running with non UTF-8 locale then those strings
might have contained some non UTF-8 characters.

If then client asked about status of such mount unit we tried to forward
these non UTF-8 strings over D-Bus. That is the violation of the
protocol and we ended up kicked from the bus.

src/core/mount.c

index 549d7dbf986f76ec3c2febbea2ca8b9aa71cffda..b87b57b7ad2f1e081d8b2bab3064edcd5df6510a 100644 (file)
@@ -34,6 +34,7 @@
 #include "strv.h"
 #include "unit-name.h"
 #include "unit.h"
+#include "utf8.h"
 
 #define RETRY_UMOUNT_MAX 32
 
@@ -274,13 +275,35 @@ static int update_parameters_proc_self_mountinfo(
 
         p = &m->parameters_proc_self_mountinfo;
 
-        r = free_and_strdup(&p->what, what);
-        if (r < 0)
-                return r;
+        if (what && !utf8_is_valid(what)) {
+                _cleanup_free_ char *what_escaped = NULL;
 
-        q = free_and_strdup(&p->options, options);
-        if (q < 0)
-                return q;
+                what_escaped = utf8_escape_invalid(what);
+                if (!what_escaped)
+                        return -ENOMEM;
+
+                r = !streq_ptr(p->what, what_escaped);
+                free_and_replace(p->what, what_escaped);
+        } else {
+                r = free_and_strdup(&p->what, what);
+                if (r < 0)
+                        return r;
+        }
+
+        if (options && !utf8_is_valid(options)) {
+                _cleanup_free_ char *options_escaped = NULL;
+
+                options_escaped = utf8_escape_invalid(options);
+                if (!options_escaped)
+                        return -ENOMEM;
+
+                q = !streq_ptr(p->options, options_escaped);
+                free_and_replace(p->options, options_escaped);
+        } else {
+                q = free_and_strdup(&p->options, options);
+                if (q < 0)
+                        return q;
+        }
 
         w = free_and_strdup(&p->fstype, fstype);
         if (w < 0)