core,nspawn,dissect: make nspawn's .roothash file search reusable
authorLennart Poettering <lennart@poettering.net>
Fri, 23 Dec 2016 16:10:42 +0000 (17:10 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 7 Feb 2017 11:21:28 +0000 (12:21 +0100)
This makes nspawn's logic of automatically discovering the root hash of
an image file generic, and then reuses it in systemd-dissect and in
PID1's RootImage= logic, so that verity is automatically set up whenever
we can.

src/core/namespace.c
src/dissect/dissect.c
src/nspawn/nspawn.c
src/shared/dissect-image.c
src/shared/dissect-image.h

index 0ae5f70..75dca5b 100644 (file)
@@ -883,8 +883,11 @@ int setup_namespace(
                 DissectImageFlags dissect_image_flags) {
 
         _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
+        _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
         _cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL;
+        _cleanup_free_ void *root_hash = NULL;
         MountEntry *m, *mounts = NULL;
+        size_t root_hash_size = 0;
         bool make_slave = false;
         unsigned n_mounts;
         int r = 0;
@@ -906,7 +909,15 @@ int setup_namespace(
                 if (r < 0)
                         return r;
 
-                r = dissect_image(loop_device->fd, NULL, 0, dissect_image_flags, &dissected_image);
+                r = root_hash_load(root_image, &root_hash, &root_hash_size);
+                if (r < 0)
+                        return r;
+
+                r = dissect_image(loop_device->fd, root_hash, root_hash_size, dissect_image_flags, &dissected_image);
+                if (r < 0)
+                        return r;
+
+                r = dissected_image_decrypt(dissected_image, NULL, root_hash, root_hash_size, dissect_image_flags, &decrypted_image);
                 if (r < 0)
                         return r;
 
@@ -1038,6 +1049,10 @@ int setup_namespace(
                 if (r < 0)
                         goto finish;
 
+                r = decrypted_image_relinquish(decrypted_image);
+                if (r < 0)
+                        goto finish;
+
                 loop_device_relinquish(loop_device);
 
         } else if (root_directory) {
index fd9db5b..59bd7d9 100644 (file)
@@ -191,6 +191,14 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
+        if (!arg_root_hash) {
+                r = root_hash_load(arg_image, &arg_root_hash, &arg_root_hash_size);
+                if (r < 0) {
+                        log_error_errno(r, "Failed to read root hash file for %s: %m", arg_image);
+                        goto finish;
+                }
+        }
+
         r = dissect_image(d->fd, arg_root_hash, arg_root_hash_size, arg_flags, &m);
         if (r == -ENOPKG) {
                 log_error_errno(r, "Couldn't identify a suitable partition table or file system in %s.", arg_image);
index 5594b87..213f50f 100644 (file)
@@ -3480,53 +3480,6 @@ static int run(int master,
         return 1; /* loop again */
 }
 
-static int load_root_hash(const char *image) {
-        _cleanup_free_ char *text = NULL, *fn = NULL;
-        char *n, *e;
-        void *k;
-        size_t l;
-        int r;
-
-        assert_se(image);
-
-        /* Try to load the root hash from a file next to the image file if it exists. */
-
-        if (arg_root_hash)
-                return 0;
-
-        fn = new(char, strlen(image) + strlen(".roothash") + 1);
-        if (!fn)
-                return log_oom();
-
-        n = stpcpy(fn, image);
-        e = endswith(fn, ".raw");
-        if (e)
-                n = e;
-
-        strcpy(n, ".roothash");
-
-        r = read_one_line_file(fn, &text);
-        if (r == -ENOENT)
-                return 0;
-        if (r < 0) {
-                log_warning_errno(r, "Failed to read %s, ignoring: %m", fn);
-                return 0;
-        }
-
-        r = unhexmem(text, strlen(text), &k, &l);
-        if (r < 0)
-                return log_error_errno(r, "Invalid root hash: %s", text);
-        if (l < sizeof(sd_id128_t)) {
-                free(k);
-                return log_error_errno(r, "Root hash too short: %s", text);
-        }
-
-        arg_root_hash = k;
-        arg_root_hash_size = l;
-
-        return 0;
-}
-
 int main(int argc, char *argv[]) {
 
         _cleanup_free_ char *console = NULL;
@@ -3742,9 +3695,13 @@ int main(int argc, char *argv[]) {
                                 goto finish;
                         }
 
-                        r = load_root_hash(arg_image);
-                        if (r < 0)
-                                goto finish;
+                        if (!arg_root_hash) {
+                                r = root_hash_load(arg_image, &arg_root_hash, &arg_root_hash_size);
+                                if (r < 0) {
+                                        log_error_errno(r, "Failed to load root hash file for %s: %m", arg_image);
+                                        goto finish;
+                                }
+                        }
                 }
 
                 if (!mkdtemp(tmprootdir)) {
index 5fc2ce2..f3cd663 100644 (file)
 #include "blkid-util.h"
 #include "dissect-image.h"
 #include "fd-util.h"
+#include "fileio.h"
 #include "fs-util.h"
 #include "gpt.h"
+#include "hexdecoct.h"
 #include "mount-util.h"
 #include "path-util.h"
 #include "stat-util.h"
@@ -1087,6 +1089,55 @@ int decrypted_image_relinquish(DecryptedImage *d) {
         return 0;
 }
 
+int root_hash_load(const char *image, void **ret, size_t *ret_size) {
+        _cleanup_free_ char *text = NULL;
+        _cleanup_free_ void *k = NULL;
+        char *fn, *e, *n;
+        size_t l;
+        int r;
+
+        assert(image);
+        assert(ret);
+        assert(ret_size);
+
+        if (is_device_path(image)) {
+                /* If we are asked to load the root hash for a device node, exit early */
+                *ret = NULL;
+                *ret_size = 0;
+                return 0;
+        }
+
+        fn = newa(char, strlen(image) + strlen(".roothash") + 1);
+        n = stpcpy(fn, image);
+        e = endswith(fn, ".raw");
+        if (e)
+                n = e;
+
+        strcpy(n, ".roothash");
+
+        r = read_one_line_file(fn, &text);
+        if (r == -ENOENT) {
+                *ret = NULL;
+                *ret_size = 0;
+                return 0;
+        }
+        if (r < 0)
+                return r;
+
+        r = unhexmem(text, strlen(text), &k, &l);
+        if (r < 0)
+                return r;
+        if (l < sizeof(sd_id128_t))
+                return -EINVAL;
+
+        *ret = k;
+        *ret_size = l;
+
+        k = NULL;
+
+        return 1;
+}
+
 static const char *const partition_designator_table[] = {
         [PARTITION_ROOT] = "root",
         [PARTITION_ROOT_SECONDARY] = "root-secondary",
index 26319bd..cdb083b 100644 (file)
@@ -94,3 +94,5 @@ int decrypted_image_relinquish(DecryptedImage *d);
 
 const char* partition_designator_to_string(int i) _const_;
 int partition_designator_from_string(const char *name) _pure_;
+
+int root_hash_load(const char *image, void **ret, size_t *ret_size);