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