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.
This commit is contained in:
Lennart Poettering 2016-12-23 17:38:12 +01:00
parent 78ebe98061
commit 41488e1f7a
2 changed files with 29 additions and 17 deletions

View File

@ -257,9 +257,13 @@
<listitem><para>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 <filename>.roothash</filename> suffix is found next to the image file, bearing otherwise the same name the
root hash is read from it and automatically used.</para></listitem>
formatted hexadecimal characters) long (in case of SHA256 for example). If this option is not specified, but
the image file carries the <literal>user.verity.roothash</literal> extended file attribute (see <citerefentry
project='man-pages'><refentrytitle>xattr</refentrytitle><manvolnum>7</manvolnum></citerefentry>), 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 <filename>.roothash</filename> 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).</para></listitem>
</varlistentry>
<varlistentry>

View File

@ -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)