b9a53a
From 9040e15cd3cba546b47aeae0ea133afa1a6ad292 Mon Sep 17 00:00:00 2001
b9a53a
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
b9a53a
Date: Wed, 13 Nov 2019 10:32:30 +0100
b9a53a
Subject: [PATCH] cryptsetup-generator: guess whether the keyfile argument is
b9a53a
 two items or one
b9a53a
b9a53a
Fixes #13615.
b9a53a
b9a53a
See the inline comment for documentation.
b9a53a
b9a53a
(cherry picked from commit 32c6237a7c2e697d2fc4f3403319db16858fb8e3)
b9a53a
b9a53a
Related: #1763155
b9a53a
---
b9a53a
 src/cryptsetup/cryptsetup-generator.c | 45 ++++++++++++++++++---------
b9a53a
 1 file changed, 30 insertions(+), 15 deletions(-)
b9a53a
b9a53a
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
b9a53a
index a09983b576..4117930925 100644
b9a53a
--- a/src/cryptsetup/cryptsetup-generator.c
b9a53a
+++ b/src/cryptsetup/cryptsetup-generator.c
b9a53a
@@ -54,17 +54,36 @@ static int split_keyspec(const char *keyspec, char **ret_keyfile, char **ret_key
b9a53a
 
b9a53a
         c = strrchr(keyspec, ':');
b9a53a
         if (c) {
b9a53a
-                keyfile = strndup(keyspec, c-keyspec);
b9a53a
-                keydev = strdup(c + 1);
b9a53a
-                if (!keyfile || !keydev)
b9a53a
+                /* The keydev part has to be either an absolute path to device node (/dev/something,
b9a53a
+                 * /dev/foo/something, or even possibly /dev/foo/something:part), or a fstab device
b9a53a
+                 * specification starting with LABEL= or similar. The keyfile part has the same syntax.
b9a53a
+                 *
b9a53a
+                 * Let's try to guess if the second part looks like a keydev specification, or just part of a
b9a53a
+                 * filename with a colon. fstab_node_to_udev_node() will convert the fstab device syntax to
b9a53a
+                 * an absolute path. If we didn't get an absolute path, assume that it is just part of the
b9a53a
+                 * first keyfile argument. */
b9a53a
+
b9a53a
+                keydev = fstab_node_to_udev_node(c + 1);
b9a53a
+                if (!keydev)
b9a53a
                         return log_oom();
b9a53a
-        } else {
b9a53a
+
b9a53a
+                if (path_is_absolute(keydev))
b9a53a
+                        keyfile = strndup(keyspec, c-keyspec);
b9a53a
+                else {
b9a53a
+                        log_debug("Keyspec argument contains a colon, but \"%s\" doesn't look like a device specification.\n"
b9a53a
+                                  "Assuming that \"%s\" is a single device specification.",
b9a53a
+                                  c + 1, keyspec);
b9a53a
+                        keydev = mfree(keydev);
b9a53a
+                        c = NULL;
b9a53a
+                }
b9a53a
+        }
b9a53a
+
b9a53a
+        if (!c)
b9a53a
                 /* No keydev specified */
b9a53a
                 keyfile = strdup(keyspec);
b9a53a
-                keydev = NULL;
b9a53a
-                if (!keyfile)
b9a53a
-                        return log_oom();
b9a53a
-        }
b9a53a
+
b9a53a
+        if (!keyfile)
b9a53a
+                return log_oom();
b9a53a
 
b9a53a
         *ret_keyfile = TAKE_PTR(keyfile);
b9a53a
         *ret_keydev = TAKE_PTR(keydev);
b9a53a
@@ -73,7 +92,7 @@ static int split_keyspec(const char *keyspec, char **ret_keyfile, char **ret_key
b9a53a
 }
b9a53a
 
b9a53a
 static int generate_keydev_mount(const char *name, const char *keydev, const char *keydev_timeout, bool canfail, char **unit, char **mount) {
b9a53a
-        _cleanup_free_ char *u = NULL, *what = NULL, *where = NULL, *name_escaped = NULL, *device_unit = NULL;
b9a53a
+        _cleanup_free_ char *u = NULL, *where = NULL, *name_escaped = NULL, *device_unit = NULL;
b9a53a
         _cleanup_fclose_ FILE *f = NULL;
b9a53a
         int r;
b9a53a
         usec_t timeout_us;
b9a53a
@@ -111,22 +130,18 @@ static int generate_keydev_mount(const char *name, const char *keydev, const cha
b9a53a
         if (r < 0)
b9a53a
                 return r;
b9a53a
 
b9a53a
-        what = fstab_node_to_udev_node(keydev);
b9a53a
-        if (!what)
b9a53a
-                return -ENOMEM;
b9a53a
-
b9a53a
         fprintf(f,
b9a53a
                 "[Unit]\n"
b9a53a
                 "DefaultDependencies=no\n\n"
b9a53a
                 "[Mount]\n"
b9a53a
                 "What=%s\n"
b9a53a
                 "Where=%s\n"
b9a53a
-                "Options=ro%s\n", what, where, canfail ? ",nofail" : "");
b9a53a
+                "Options=ro%s\n", keydev, where, canfail ? ",nofail" : "");
b9a53a
 
b9a53a
         if (keydev_timeout) {
b9a53a
                 r = parse_sec_fix_0(keydev_timeout, &timeout_us);
b9a53a
                 if (r >= 0) {
b9a53a
-                        r = unit_name_from_path(what, ".device", &device_unit);
b9a53a
+                        r = unit_name_from_path(keydev, ".device", &device_unit);
b9a53a
                         if (r < 0)
b9a53a
                                 return log_error_errno(r, "Failed to generate unit name: %m");
b9a53a