summaryrefslogtreecommitdiff
path: root/src/shared/dissect-image.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared/dissect-image.c')
-rw-r--r--src/shared/dissect-image.c161
1 files changed, 110 insertions, 51 deletions
diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c
index 8decac94b2..2c8a5d85bf 100644
--- a/src/shared/dissect-image.c
+++ b/src/shared/dissect-image.c
@@ -307,6 +307,7 @@ int dissect_image(
int fd,
const void *root_hash,
size_t root_hash_size,
+ const char *verity_data,
DissectImageFlags flags,
DissectedImage **ret) {
@@ -329,6 +330,7 @@ int dissect_image(
assert(fd >= 0);
assert(ret);
assert(root_hash || root_hash_size == 0);
+ assert(!((flags & DISSECT_IMAGE_GPT_ONLY) && (flags & DISSECT_IMAGE_NO_PARTITION_TABLE)));
/* Probes a disk image, and returns information about what it found in *ret.
*
@@ -391,8 +393,9 @@ int dissect_image(
if (r < 0)
return r;
- if (!(flags & DISSECT_IMAGE_GPT_ONLY) &&
- (flags & DISSECT_IMAGE_REQUIRE_ROOT)) {
+ if ((!(flags & DISSECT_IMAGE_GPT_ONLY) &&
+ (flags & DISSECT_IMAGE_REQUIRE_ROOT)) ||
+ (flags & DISSECT_IMAGE_NO_PARTITION_TABLE)) {
const char *usage = NULL;
(void) blkid_probe_lookup_value(b, "USAGE", &usage, NULL);
@@ -413,9 +416,13 @@ int dissect_image(
if (r < 0)
return r;
+ m->single_file_system = true;
+ m->verity = root_hash && verity_data;
+ m->can_verity = !!verity_data;
+
m->partitions[PARTITION_ROOT] = (DissectedPartition) {
.found = true,
- .rw = true,
+ .rw = !m->verity,
.partno = -1,
.architecture = _ARCHITECTURE_INVALID,
.fstype = TAKE_PTR(t),
@@ -424,11 +431,11 @@ int dissect_image(
m->encrypted = streq_ptr(fstype, "crypto_LUKS");
- if (!streq(usage, "filesystem")) {
- r = loop_wait_for_partitions_to_appear(fd, d, 0, flags, &e);
- if (r < 0)
- return r;
- }
+ /* Even on a single partition we need to wait for udev to create the
+ * /dev/block/X:Y symlink to /dev/loopZ */
+ r = loop_wait_for_partitions_to_appear(fd, d, 0, flags, &e);
+ if (r < 0)
+ return r;
*ret = TAKE_PTR(m);
return 0;
@@ -1215,6 +1222,7 @@ static int verity_partition(
DissectedPartition *v,
const void *root_hash,
size_t root_hash_size,
+ const char *verity_data,
DissectImageFlags flags,
DecryptedImage *d) {
@@ -1223,18 +1231,20 @@ static int verity_partition(
int r;
assert(m);
- assert(v);
+ assert(v || verity_data);
if (!root_hash)
return 0;
if (!m->found || !m->node || !m->fstype)
return 0;
- if (!v->found || !v->node || !v->fstype)
- return 0;
+ if (!verity_data) {
+ if (!v->found || !v->node || !v->fstype)
+ return 0;
- if (!streq(v->fstype, "DM_verity_hash"))
- return 0;
+ if (!streq(v->fstype, "DM_verity_hash"))
+ return 0;
+ }
r = make_dm_name_and_node(m->node, "-verity", &name, &node);
if (r < 0)
@@ -1243,7 +1253,7 @@ static int verity_partition(
if (!GREEDY_REALLOC0(d->decrypted, d->n_allocated, d->n_decrypted + 1))
return -ENOMEM;
- r = crypt_init(&cd, v->node);
+ r = crypt_init(&cd, verity_data ?: v->node);
if (r < 0)
return r;
@@ -1276,6 +1286,7 @@ int dissected_image_decrypt(
const char *passphrase,
const void *root_hash,
size_t root_hash_size,
+ const char *verity_data,
DissectImageFlags flags,
DecryptedImage **ret) {
@@ -1322,7 +1333,7 @@ int dissected_image_decrypt(
k = PARTITION_VERITY_OF(i);
if (k >= 0) {
- r = verity_partition(p, m->partitions + k, root_hash, root_hash_size, flags, d);
+ r = verity_partition(p, m->partitions + k, root_hash, root_hash_size, verity_data, flags, d);
if (r < 0)
return r;
}
@@ -1347,6 +1358,7 @@ int dissected_image_decrypt_interactively(
const char *passphrase,
const void *root_hash,
size_t root_hash_size,
+ const char *verity_data,
DissectImageFlags flags,
DecryptedImage **ret) {
@@ -1357,7 +1369,7 @@ int dissected_image_decrypt_interactively(
n--;
for (;;) {
- r = dissected_image_decrypt(m, passphrase, root_hash, root_hash_size, flags, ret);
+ r = dissected_image_decrypt(m, passphrase, root_hash, root_hash_size, verity_data, flags, ret);
if (r >= 0)
return r;
if (r == -EKEYREJECTED)
@@ -1409,56 +1421,85 @@ 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;
- size_t l;
+int verity_metadata_load(const char *image, void **ret_roothash, size_t *ret_roothash_size, char **ret_verity_data) {
+ _cleanup_free_ char *verity_filename = NULL;
+ _cleanup_free_ void *roothash_decoded = NULL;
+ size_t roothash_decoded_size = 0;
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;
+ if (ret_roothash)
+ *ret_roothash = NULL;
+ if (ret_roothash_size)
+ *ret_roothash_size = 0;
+ if (ret_verity_data)
+ *ret_verity_data = NULL;
return 0;
}
- r = getxattr_malloc(image, "user.verity.roothash", &text, true);
- if (r < 0) {
- char *fn, *e, *n;
-
- if (!IN_SET(r, -ENODATA, -EOPNOTSUPP, -ENOENT))
- return r;
+ if (ret_verity_data) {
+ char *e;
- fn = newa(char, strlen(image) + STRLEN(".roothash") + 1);
- n = stpcpy(fn, image);
- e = endswith(fn, ".raw");
+ verity_filename = new(char, strlen(image) + STRLEN(".verity") + 1);
+ if (!verity_filename)
+ return -ENOMEM;
+ strcpy(verity_filename, image);
+ e = endswith(verity_filename, ".raw");
if (e)
- n = e;
-
- strcpy(n, ".roothash");
+ strcpy(e, ".verity");
+ else
+ strcat(verity_filename, ".verity");
- r = read_one_line_file(fn, &text);
- if (r == -ENOENT) {
- *ret = NULL;
- *ret_size = 0;
- return 0;
+ r = access(verity_filename, F_OK);
+ if (r < 0) {
+ if (errno != ENOENT)
+ return -errno;
+ verity_filename = mfree(verity_filename);
}
- 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;
+ if (ret_roothash) {
+ _cleanup_free_ char *text = NULL;
+ assert(ret_roothash_size);
+
+ r = getxattr_malloc(image, "user.verity.roothash", &text, true);
+ if (r < 0) {
+ char *fn, *e, *n;
+
+ if (!IN_SET(r, -ENODATA, -EOPNOTSUPP, -ENOENT))
+ return r;
+
+ fn = newa(char, strlen(image) + STRLEN(".roothash") + 1);
+ n = stpcpy(fn, image);
+ e = endswith(fn, ".raw");
+ if (e)
+ n = e;
- *ret = TAKE_PTR(k);
- *ret_size = l;
+ strcpy(n, ".roothash");
+
+ r = read_one_line_file(fn, &text);
+ if (r < 0 && r != -ENOENT)
+ return r;
+ }
+
+ if (text) {
+ r = unhexmem(text, strlen(text), &roothash_decoded, &roothash_decoded_size);
+ if (r < 0)
+ return r;
+ if (roothash_decoded_size < sizeof(sd_id128_t))
+ return -EINVAL;
+ }
+ }
+
+ if (ret_roothash) {
+ *ret_roothash = TAKE_PTR(roothash_decoded);
+ *ret_roothash_size = roothash_decoded_size;
+ }
+ if (ret_verity_data)
+ *ret_verity_data = TAKE_PTR(verity_filename);
return 1;
}
@@ -1617,6 +1658,7 @@ int dissect_image_and_warn(
const char *name,
const void *root_hash,
size_t root_hash_size,
+ const char *verity_data,
DissectImageFlags flags,
DissectedImage **ret) {
@@ -1631,7 +1673,7 @@ int dissect_image_and_warn(
name = buffer;
}
- r = dissect_image(fd, root_hash, root_hash_size, flags, ret);
+ r = dissect_image(fd, root_hash, root_hash_size, verity_data, flags, ret);
switch (r) {
@@ -1661,6 +1703,23 @@ int dissect_image_and_warn(
}
}
+bool dissected_image_can_do_verity(const DissectedImage *image, unsigned partition_designator) {
+ if (image->single_file_system)
+ return partition_designator == PARTITION_ROOT && image->can_verity;
+
+ return PARTITION_VERITY_OF(partition_designator) >= 0;
+}
+
+bool dissected_image_has_verity(const DissectedImage *image, unsigned partition_designator) {
+ int k;
+
+ if (image->single_file_system)
+ return partition_designator == PARTITION_ROOT && image->verity;
+
+ k = PARTITION_VERITY_OF(partition_designator);
+ return k >= 0 && image->partitions[k].found;
+}
+
static const char *const partition_designator_table[] = {
[PARTITION_ROOT] = "root",
[PARTITION_ROOT_SECONDARY] = "root-secondary",