36e8a3
From 2a4d58bb2ab9ba5487785cc167932440a4f0c13d Mon Sep 17 00:00:00 2001
36e8a3
From: Michal Sekletar <msekleta@redhat.com>
36e8a3
Date: Tue, 4 Sep 2018 20:03:34 +0200
36e8a3
Subject: [PATCH] cryptsetup-generator: allow whitespace characters in keydev
36e8a3
 specification
36e8a3
36e8a3
For example, <luks.uuid>=/keyfile:LABEL="KEYFILE FS" previously wouldn't
36e8a3
work, because we truncated label at the first whitespace character,
36e8a3
i.e. LABEL="KEYFILE".
36e8a3
36e8a3
(cherry-picked from commit 7949dfa73a44ae6524779689483d12243dfbcfdf)
36e8a3
36e8a3
Related: #1656869
36e8a3
---
36e8a3
 src/cryptsetup/cryptsetup-generator.c | 64 ++++++++++++++++++---------
36e8a3
 1 file changed, 43 insertions(+), 21 deletions(-)
36e8a3
36e8a3
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
4bff0a
index 03c513c26e..52c1262728 100644
36e8a3
--- a/src/cryptsetup/cryptsetup-generator.c
36e8a3
+++ b/src/cryptsetup/cryptsetup-generator.c
36e8a3
@@ -5,11 +5,13 @@
36e8a3
 
36e8a3
 #include "alloc-util.h"
36e8a3
 #include "dropin.h"
36e8a3
+#include "escape.h"
36e8a3
 #include "fd-util.h"
36e8a3
 #include "fileio.h"
36e8a3
 #include "fstab-util.h"
36e8a3
 #include "generator.h"
36e8a3
 #include "hashmap.h"
36e8a3
+#include "id128-util.h"
36e8a3
 #include "log.h"
36e8a3
 #include "mkdir.h"
36e8a3
 #include "parse-util.h"
36e8a3
@@ -39,7 +41,7 @@ static char *arg_default_options = NULL;
36e8a3
 static char *arg_default_keyfile = NULL;
36e8a3
 
36e8a3
 static int generate_keydev_mount(const char *name, const char *keydev, char **unit, char **mount) {
36e8a3
-        _cleanup_free_ char *u = NULL, *what = NULL, *where = NULL;
36e8a3
+        _cleanup_free_ char *u = NULL, *what = NULL, *where = NULL, *name_escaped = NULL;
36e8a3
         _cleanup_fclose_ FILE *f = NULL;
36e8a3
         int r;
36e8a3
 
36e8a3
@@ -56,7 +58,11 @@ static int generate_keydev_mount(const char *name, const char *keydev, char **un
36e8a3
         if (r < 0 && errno != EEXIST)
36e8a3
                 return -errno;
36e8a3
 
36e8a3
-        where = strjoin("/run/systemd/cryptsetup/keydev-", name);
36e8a3
+        name_escaped = cescape(name);
36e8a3
+        if (!name_escaped)
36e8a3
+                return -ENOMEM;
36e8a3
+
36e8a3
+        where = strjoin("/run/systemd/cryptsetup/keydev-", name_escaped);
36e8a3
         if (!where)
36e8a3
                 return -ENOMEM;
36e8a3
 
36e8a3
@@ -386,36 +392,52 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
36e8a3
                         return log_oom();
36e8a3
 
36e8a3
         } else if (streq(key, "luks.key")) {
36e8a3
+                size_t n;
36e8a3
+                _cleanup_free_ char *keyfile = NULL, *keydev = NULL;
36e8a3
+                char *c;
36e8a3
+                const char *keyspec;
36e8a3
 
36e8a3
                 if (proc_cmdline_value_missing(key, value))
36e8a3
                         return 0;
36e8a3
 
36e8a3
-                r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value);
36e8a3
-                if (r == 2) {
36e8a3
-                        char *c;
36e8a3
-                        _cleanup_free_ char *keyfile = NULL, *keydev = NULL;
36e8a3
+                n = strspn(value, LETTERS DIGITS "-");
36e8a3
+                if (value[n] != '=') {
36e8a3
+                        if (free_and_strdup(&arg_default_keyfile, value) < 0)
36e8a3
+                                 return log_oom();
36e8a3
+                        return 0;
36e8a3
+                }
36e8a3
 
36e8a3
-                        d = get_crypto_device(uuid);
36e8a3
-                        if (!d)
36e8a3
-                                return log_oom();
36e8a3
+                uuid = strndup(value, n);
36e8a3
+                if (!uuid)
36e8a3
+                        return log_oom();
36e8a3
 
36e8a3
-                        c = strrchr(uuid_value, ':');
36e8a3
-                        if (!c)
36e8a3
-                                /* No keydev specified */
36e8a3
-                                return free_and_replace(d->keyfile, uuid_value);
36e8a3
+                if (!id128_is_valid(uuid)) {
36e8a3
+                        log_warning("Failed to parse luks.key= kernel command line switch. UUID is invalid, ignoring.");
36e8a3
+                        return 0;
36e8a3
+                }
36e8a3
+
36e8a3
+                d = get_crypto_device(uuid);
36e8a3
+                if (!d)
36e8a3
+                        return log_oom();
36e8a3
 
36e8a3
-                        *c = '\0';
36e8a3
-                        keyfile = strdup(uuid_value);
36e8a3
-                        keydev = strdup(++c);
36e8a3
+                keyspec = value + n + 1;
36e8a3
+                c = strrchr(keyspec, ':');
36e8a3
+                if (c) {
36e8a3
+                         *c = '\0';
36e8a3
+                        keyfile = strdup(keyspec);
36e8a3
+                        keydev = strdup(c + 1);
36e8a3
 
36e8a3
                         if (!keyfile || !keydev)
36e8a3
                                 return log_oom();
36e8a3
+                } else {
36e8a3
+                        /* No keydev specified */
36e8a3
+                        keyfile = strdup(keyspec);
36e8a3
+                        if (!keyfile)
36e8a3
+                                return log_oom();
36e8a3
+                }
36e8a3
 
36e8a3
-                        free_and_replace(d->keyfile, keyfile);
36e8a3
-                        free_and_replace(d->keydev, keydev);
36e8a3
-                } else if (free_and_strdup(&arg_default_keyfile, value) < 0)
36e8a3
-                        return log_oom();
36e8a3
-
36e8a3
+                free_and_replace(d->keyfile, keyfile);
36e8a3
+                free_and_replace(d->keydev, keydev);
36e8a3
         } else if (streq(key, "luks.name")) {
36e8a3
 
36e8a3
                 if (proc_cmdline_value_missing(key, value))