Harald Hoyer d4ee25
From 61ca2800f3a1666478bdc01fc796d36c917a5032 Mon Sep 17 00:00:00 2001
Harald Hoyer d4ee25
From: Tom Gundersen <teg@jklm.no>
Harald Hoyer d4ee25
Date: Sun, 18 Aug 2013 14:59:00 +0800
Harald Hoyer d4ee25
Subject: [PATCH] cryptsetup-generator: allow specifying options in
Harald Hoyer d4ee25
 /proc/cmdline
Harald Hoyer d4ee25
MIME-Version: 1.0
Harald Hoyer d4ee25
Content-Type: text/plain; charset=UTF-8
Harald Hoyer d4ee25
Content-Transfer-Encoding: 8bit
Harald Hoyer d4ee25
Harald Hoyer d4ee25
The main usecase for this is to make it possible to use cryptsetup in
Harald Hoyer d4ee25
the initrd without it having to include a host-specific /etc/crypttab.
Harald Hoyer d4ee25
Harald Hoyer d4ee25
Tested-by: Thomas Bächler <thomas@archlinux.org>
Harald Hoyer d4ee25
---
Harald Hoyer d4ee25
 man/systemd-cryptsetup-generator.xml  | 23 ++++++++++
Harald Hoyer d4ee25
 src/cryptsetup/cryptsetup-generator.c | 79 +++++++++++++++++++++++++++++++++--
Harald Hoyer d4ee25
 2 files changed, 98 insertions(+), 4 deletions(-)
Harald Hoyer d4ee25
Harald Hoyer d4ee25
diff --git a/man/systemd-cryptsetup-generator.xml b/man/systemd-cryptsetup-generator.xml
Harald Hoyer d4ee25
index 215ac2d..d6b7e49 100644
Harald Hoyer d4ee25
--- a/man/systemd-cryptsetup-generator.xml
Harald Hoyer d4ee25
+++ b/man/systemd-cryptsetup-generator.xml
Harald Hoyer d4ee25
@@ -137,6 +137,29 @@
Harald Hoyer d4ee25
                                 will be activated in the initrd or the real root.</para>
Harald Hoyer d4ee25
                                 </listitem>
Harald Hoyer d4ee25
                         </varlistentry>
Harald Hoyer d4ee25
+
Harald Hoyer d4ee25
+                        <varlistentry>
Harald Hoyer d4ee25
+                                <term><varname>luks.options=</varname></term>
Harald Hoyer d4ee25
+                                <term><varname>rd.luks.options=</varname></term>
Harald Hoyer d4ee25
+
Harald Hoyer d4ee25
+                                <listitem><para>Takes a LUKS super
Harald Hoyer d4ee25
+                                block UUID followed by an '=' and a string
Harald Hoyer d4ee25
+                                of options separated by commas as argument.
Harald Hoyer d4ee25
+                                This will override the options for the given
Harald Hoyer d4ee25
+                                UUID.</para>
Harald Hoyer d4ee25
+                                <para>If only a list of options, without an
Harald Hoyer d4ee25
+                                UUID, is specified, they apply to any UUIDs not
Harald Hoyer d4ee25
+                                specified elsewhere, and without an entry in
Harald Hoyer d4ee25
+                                /etc/crypttab.</para><para>
Harald Hoyer d4ee25
+                                <varname>rd.luks.options=</varname>
Harald Hoyer d4ee25
+                                is honored only by initial RAM disk
Harald Hoyer d4ee25
+                                (initrd) while
Harald Hoyer d4ee25
+                                <varname>luks.options=</varname> is
Harald Hoyer d4ee25
+                                honored by both the main system and
Harald Hoyer d4ee25
+                                the initrd.</para>
Harald Hoyer d4ee25
+                                </listitem>
Harald Hoyer d4ee25
+                        </varlistentry>
Harald Hoyer d4ee25
+
Harald Hoyer d4ee25
                         <varlistentry>
Harald Hoyer d4ee25
                                 <term><varname>luks.key=</varname></term>
Harald Hoyer d4ee25
                                 <term><varname>rd.luks.key=</varname></term>
Harald Hoyer d4ee25
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
Harald Hoyer d4ee25
index 967c5e6..ba6efa6 100644
Harald Hoyer d4ee25
--- a/src/cryptsetup/cryptsetup-generator.c
Harald Hoyer d4ee25
+++ b/src/cryptsetup/cryptsetup-generator.c
Harald Hoyer d4ee25
@@ -240,7 +240,7 @@ static int create_disk(
Harald Hoyer d4ee25
         return 0;
Harald Hoyer d4ee25
 }
Harald Hoyer d4ee25
 
Harald Hoyer d4ee25
-static int parse_proc_cmdline(char ***arg_proc_cmdline_disks, char **arg_proc_cmdline_keyfile) {
Harald Hoyer d4ee25
+static int parse_proc_cmdline(char ***arg_proc_cmdline_disks, char ***arg_proc_cmdline_options, char **arg_proc_cmdline_keyfile) {
Harald Hoyer d4ee25
         _cleanup_free_ char *line = NULL;
Harald Hoyer d4ee25
         char *w = NULL, *state = NULL;
Harald Hoyer d4ee25
         int r;
Harald Hoyer d4ee25
@@ -307,7 +307,20 @@ static int parse_proc_cmdline(char ***arg_proc_cmdline_disks, char **arg_proc_cm
Harald Hoyer d4ee25
                                         return log_oom();
Harald Hoyer d4ee25
                         }
Harald Hoyer d4ee25
 
Harald Hoyer d4ee25
+                } else if (startswith(word, "luks.options=")) {
Harald Hoyer d4ee25
+                        if (strv_extend(arg_proc_cmdline_options, word + 13) < 0)
Harald Hoyer d4ee25
+                                return log_oom();
Harald Hoyer d4ee25
+
Harald Hoyer d4ee25
+                } else if (startswith(word, "rd.luks.options=")) {
Harald Hoyer d4ee25
+
Harald Hoyer d4ee25
+                        if (in_initrd()) {
Harald Hoyer d4ee25
+                                if (strv_extend(arg_proc_cmdline_options, word + 16) < 0)
Harald Hoyer d4ee25
+                                        return log_oom();
Harald Hoyer d4ee25
+                        }
Harald Hoyer d4ee25
+
Harald Hoyer d4ee25
                 } else if (startswith(word, "luks.key=")) {
Harald Hoyer d4ee25
+                        if (*arg_proc_cmdline_keyfile)
Harald Hoyer d4ee25
+                                free(*arg_proc_cmdline_keyfile);
Harald Hoyer d4ee25
                         *arg_proc_cmdline_keyfile = strdup(word + 9);
Harald Hoyer d4ee25
                         if (!*arg_proc_cmdline_keyfile)
Harald Hoyer d4ee25
                                 return log_oom();
Harald Hoyer d4ee25
@@ -337,6 +350,7 @@ static int parse_proc_cmdline(char ***arg_proc_cmdline_disks, char **arg_proc_cm
Harald Hoyer d4ee25
 int main(int argc, char *argv[]) {
Harald Hoyer d4ee25
         _cleanup_strv_free_ char **arg_proc_cmdline_disks_done = NULL;
Harald Hoyer d4ee25
         _cleanup_strv_free_ char **arg_proc_cmdline_disks = NULL;
Harald Hoyer d4ee25
+        _cleanup_strv_free_ char **arg_proc_cmdline_options = NULL;
Harald Hoyer d4ee25
         _cleanup_free_ char *arg_proc_cmdline_keyfile = NULL;
Harald Hoyer d4ee25
         _cleanup_fclose_ FILE *f = NULL;
Harald Hoyer d4ee25
         unsigned n = 0;
Harald Hoyer d4ee25
@@ -357,7 +371,7 @@ int main(int argc, char *argv[]) {
Harald Hoyer d4ee25
 
Harald Hoyer d4ee25
         umask(0022);
Harald Hoyer d4ee25
 
Harald Hoyer d4ee25
-        if (parse_proc_cmdline(&arg_proc_cmdline_disks, &arg_proc_cmdline_keyfile) < 0)
Harald Hoyer d4ee25
+        if (parse_proc_cmdline(&arg_proc_cmdline_disks, &arg_proc_cmdline_options, &arg_proc_cmdline_keyfile) < 0)
Harald Hoyer d4ee25
                 return EXIT_FAILURE;
Harald Hoyer d4ee25
 
Harald Hoyer d4ee25
         if (!arg_enabled)
Harald Hoyer d4ee25
@@ -412,6 +426,26 @@ int main(int argc, char *argv[]) {
Harald Hoyer d4ee25
                                 continue;
Harald Hoyer d4ee25
                         }
Harald Hoyer d4ee25
 
Harald Hoyer d4ee25
+                        if (arg_proc_cmdline_options) {
Harald Hoyer d4ee25
+                                /*
Harald Hoyer d4ee25
+                                  If options are specified on the kernel commandline, let them override
Harald Hoyer d4ee25
+                                  the ones from crypttab.
Harald Hoyer d4ee25
+                                */
Harald Hoyer d4ee25
+                                STRV_FOREACH(i, arg_proc_cmdline_options) {
Harald Hoyer d4ee25
+                                        _cleanup_free_ char *proc_uuid = NULL, *proc_options = NULL;
Harald Hoyer d4ee25
+                                        const char *p = *i;
Harald Hoyer d4ee25
+
Harald Hoyer d4ee25
+                                        k = sscanf(p, "%m[0-9a-fA-F-]=%ms", &proc_uuid, &proc_options);
Harald Hoyer d4ee25
+                                        if (k == 2 && streq(proc_uuid, device + 5)) {
Harald Hoyer d4ee25
+                                                if (options)
Harald Hoyer d4ee25
+                                                        free(options);
Harald Hoyer d4ee25
+                                                options = strdup(p);
Harald Hoyer d4ee25
+                                                if (!proc_options)
Harald Hoyer d4ee25
+                                                        return log_oom();
Harald Hoyer d4ee25
+                                        }
Harald Hoyer d4ee25
+                                }
Harald Hoyer d4ee25
+                        }
Harald Hoyer d4ee25
+
Harald Hoyer d4ee25
                         if (arg_proc_cmdline_disks) {
Harald Hoyer d4ee25
                                 /*
Harald Hoyer d4ee25
                                   If luks UUIDs are specified on the kernel command line, use them as a filter
Harald Hoyer d4ee25
@@ -452,7 +486,7 @@ next:
Harald Hoyer d4ee25
                   on the kernel command line and not yet written.
Harald Hoyer d4ee25
                 */
Harald Hoyer d4ee25
 
Harald Hoyer d4ee25
-                _cleanup_free_ char *name = NULL, *device = NULL;
Harald Hoyer d4ee25
+                _cleanup_free_ char *name = NULL, *device = NULL, *options = NULL;
Harald Hoyer d4ee25
                 const char *p = *i;
Harald Hoyer d4ee25
 
Harald Hoyer d4ee25
                 if (startswith(p, "luks-"))
Harald Hoyer d4ee25
@@ -467,7 +501,44 @@ next:
Harald Hoyer d4ee25
                 if (!name || !device)
Harald Hoyer d4ee25
                         return log_oom();
Harald Hoyer d4ee25
 
Harald Hoyer d4ee25
-                if (create_disk(name, device, arg_proc_cmdline_keyfile, "timeout=0") < 0)
Harald Hoyer d4ee25
+                if (arg_proc_cmdline_options) {
Harald Hoyer d4ee25
+                        /*
Harald Hoyer d4ee25
+                          If options are specified on the kernel commandline, use them.
Harald Hoyer d4ee25
+                        */
Harald Hoyer d4ee25
+                        char **j;
Harald Hoyer d4ee25
+
Harald Hoyer d4ee25
+                        STRV_FOREACH(j, arg_proc_cmdline_options) {
Harald Hoyer d4ee25
+                                _cleanup_free_ char *proc_uuid = NULL, *proc_options = NULL;
Harald Hoyer d4ee25
+                                const char *s = *j;
Harald Hoyer d4ee25
+                                int k;
Harald Hoyer d4ee25
+
Harald Hoyer d4ee25
+                                k = sscanf(s, "%m[0-9a-fA-F-]=%ms", &proc_uuid, &proc_options);
Harald Hoyer d4ee25
+                                if (k == 2) {
Harald Hoyer d4ee25
+                                        if (streq(proc_uuid, device + 5)) {
Harald Hoyer d4ee25
+                                                if (options)
Harald Hoyer d4ee25
+                                                        free(options);
Harald Hoyer d4ee25
+                                                options = strdup(proc_options);
Harald Hoyer d4ee25
+                                                if (!options)
Harald Hoyer d4ee25
+                                                        return log_oom();
Harald Hoyer d4ee25
+                                        }
Harald Hoyer d4ee25
+                                } else if (!options) {
Harald Hoyer d4ee25
+                                        /*
Harald Hoyer d4ee25
+                                          Fall back to options without a specified UUID
Harald Hoyer d4ee25
+                                        */
Harald Hoyer d4ee25
+                                        options = strdup(s);
Harald Hoyer d4ee25
+                                        if (!options)
Harald Hoyer d4ee25
+                                                return log_oom();
Harald Hoyer d4ee25
+                                }
Harald Hoyer d4ee25
+                        }
Harald Hoyer d4ee25
+                }
Harald Hoyer d4ee25
+
Harald Hoyer d4ee25
+                if (!options) {
Harald Hoyer d4ee25
+                        options = strdup("timeout=0");
Harald Hoyer d4ee25
+                        if (!options)
Harald Hoyer d4ee25
+                                return log_oom();
Harald Hoyer d4ee25
+                }
Harald Hoyer d4ee25
+
Harald Hoyer d4ee25
+                if (create_disk(name, device, arg_proc_cmdline_keyfile, options) < 0)
Harald Hoyer d4ee25
                         r = EXIT_FAILURE;
Harald Hoyer d4ee25
         }
Harald Hoyer d4ee25