From: Lennart Poettering Date: Fri, 23 Dec 2016 16:38:12 +0000 (+0100) Subject: dissect: try to read roothash value off user.verity.roothash xattr of image file X-Git-Tag: v233~134^2~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=41488e1f7acf5f4b5e11ff992a05ee1baa537d54;p=thirdparty%2Fsystemd.git dissect: try to read roothash value off user.verity.roothash xattr of image file This slightly extends the roothash loading logic to first check for a user.verity.roothash extended attribute on the image file. If it exists, it is used as Verity root hash and the ".roothash" file is not used. This should improve the chance that the roothash is retained when the file is moved around, as the data snippet is attached directly to the image file. The field is still detached from the file payload however, in order to make sure it may be trusted independently. This does not replace the ".roothash" file loading, it simply adds a second way to retrieve the data. Extended attributes are often a poor choice for storing metadata like this as it is usually difficult to discover for admins and users, and hard to fix if it ever gets out of sync. However, in this case I think it's safe as verity implies read-only access, and thus there's little chance of it to get out of sync. --- diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml index f6b3f57fc77..b8cae62818d 100644 --- a/man/systemd-nspawn.xml +++ b/man/systemd-nspawn.xml @@ -257,9 +257,13 @@ Takes a data integrity (dm-verity) root hash specified in hexadecimal. This option enables data integrity checks using dm-verity, if the used image contains the appropriate integrity data (see above). The specified hash must match the root hash of integrity data, and is usually at least 256bits (and hence 64 - hexadecimal characters) long (in case of SHA256 for example). If this option is not specified, but a file with - the .roothash suffix is found next to the image file, bearing otherwise the same name the - root hash is read from it and automatically used. + formatted hexadecimal characters) long (in case of SHA256 for example). If this option is not specified, but + the image file carries the user.verity.roothash extended file attribute (see xattr7), then the root + hash is read from it, also as formatted hexadecimal characters. If the extended file attribute is not found (or + not supported by the underlying file system), but a file with the .roothash suffix is + found next to the image file, bearing otherwise the same name the root hash is read from it and automatically + used (again, as formatted hexadecimal characters). diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index f3cd663602c..66ddf3a8721 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -40,6 +40,7 @@ #include "string-util.h" #include "strv.h" #include "udev-util.h" +#include "xattr-util.h" static int probe_filesystem(const char *node, char **ret_fstype) { #ifdef HAVE_BLKID @@ -1092,7 +1093,6 @@ int decrypted_image_relinquish(DecryptedImage *d) { 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; @@ -1107,22 +1107,30 @@ int root_hash_load(const char *image, void **ret, size_t *ret_size) { return 0; } - fn = newa(char, strlen(image) + strlen(".roothash") + 1); - n = stpcpy(fn, image); - e = endswith(fn, ".raw"); - if (e) - n = e; + r = getxattr_malloc(image, "user.verity.roothash", &text, true); + if (r < 0) { + char *fn, *e, *n; - strcpy(n, ".roothash"); + if (!IN_SET(r, -ENODATA, -EOPNOTSUPP, -ENOENT)) + return r; - r = read_one_line_file(fn, &text); - if (r == -ENOENT) { - *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; } - if (r < 0) - return r; r = unhexmem(text, strlen(text), &k, &l); if (r < 0)