dissect-image: support activating luks+verity partitions
Let's properly activate images that have both LUKS and Verity enabled for a partition.
This commit is contained in:
+23
-11
@@ -2868,8 +2868,9 @@ static DecryptedImage* decrypted_image_free(DecryptedImage *d) {
|
||||
if (!d)
|
||||
return NULL;
|
||||
|
||||
for (size_t i = 0; i < d->n_decrypted; i++) {
|
||||
DecryptedPartition *p = d->decrypted + i;
|
||||
/* Detach in reverse order so that nested dm-verity and dm-crypt are detached in the right order. */
|
||||
for (size_t i = d->n_decrypted; i > 0; i--) {
|
||||
DecryptedPartition *p = d->decrypted + i - 1;
|
||||
|
||||
if (p->device && p->name && !p->relinquished) {
|
||||
_cleanup_free_ char *node = NULL;
|
||||
@@ -3005,6 +3006,13 @@ static int decrypt_partition(
|
||||
if (!FLAGS_SET(policy_flags, PARTITION_POLICY_ENCRYPTED))
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(ERFKILL), "Attempted to unlock partition via LUKS, but it's prohibited.");
|
||||
|
||||
/* If a dm-verity device was already set up on this partition, then the partition is both Verity
|
||||
* protected and LUKS encrypted, with Verity being the outer envelope and LUKS the inner. In that
|
||||
* case open the LUKS device on top of the verity device, so that everything we read is
|
||||
* authenticated. Since verity devices are read-only, the LUKS layer must then be read-only, too. */
|
||||
const char *source_node = m->decrypted_node ?: m->node;
|
||||
bool on_verity = !!m->decrypted_node;
|
||||
|
||||
r = dlopen_cryptsetup(LOG_DEBUG);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -3016,7 +3024,7 @@ static int decrypt_partition(
|
||||
if (!GREEDY_REALLOC0(d->decrypted, d->n_decrypted + 1))
|
||||
return -ENOMEM;
|
||||
|
||||
r = sym_crypt_init(&cd, m->node);
|
||||
r = sym_crypt_init(&cd, source_node);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to initialize dm-crypt: %m");
|
||||
|
||||
@@ -3027,8 +3035,8 @@ static int decrypt_partition(
|
||||
return log_debug_errno(r, "Failed to load LUKS metadata: %m");
|
||||
|
||||
r = sym_crypt_activate_by_passphrase(cd, name, CRYPT_ANY_SLOT, passphrase, strlen(passphrase),
|
||||
((flags & DISSECT_IMAGE_DEVICE_READ_ONLY) ? CRYPT_ACTIVATE_READONLY : 0) |
|
||||
((flags & DISSECT_IMAGE_DISCARD_ON_CRYPTO) ? CRYPT_ACTIVATE_ALLOW_DISCARDS : 0));
|
||||
((flags & DISSECT_IMAGE_DEVICE_READ_ONLY) || on_verity ? CRYPT_ACTIVATE_READONLY : 0) |
|
||||
((flags & DISSECT_IMAGE_DISCARD_ON_CRYPTO) && !on_verity ? CRYPT_ACTIVATE_ALLOW_DISCARDS : 0));
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to activate LUKS device: %m");
|
||||
return r == -EPERM ? -EKEYREJECTED : r;
|
||||
@@ -3043,7 +3051,7 @@ static int decrypt_partition(
|
||||
.device = TAKE_PTR(cd),
|
||||
};
|
||||
|
||||
m->decrypted_node = TAKE_PTR(node);
|
||||
free_and_replace(m->decrypted_node, node);
|
||||
close_and_replace(m->mount_node_fd, fd);
|
||||
|
||||
return 0;
|
||||
@@ -3542,7 +3550,7 @@ success:
|
||||
.device = TAKE_PTR(cd),
|
||||
};
|
||||
|
||||
m->decrypted_node = TAKE_PTR(node);
|
||||
free_and_replace(m->decrypted_node, node);
|
||||
close_and_replace(m->mount_node_fd, mount_node_fd);
|
||||
|
||||
return 0;
|
||||
@@ -3602,10 +3610,10 @@ int dissected_image_decrypt(
|
||||
|
||||
PartitionPolicyFlags fl = image_policy_get_exhaustively(policy, i);
|
||||
|
||||
r = decrypt_partition(m, p, passphrase, flags, fl, d);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Set up Verity first, and only then LUKS: if a partition is both Verity protected and
|
||||
* encrypted, Verity is the outer envelope and LUKS the inner, i.e. the Verity hash data
|
||||
* covers the LUKS ciphertext, and decrypt_partition() then stacks the LUKS device on top of
|
||||
* the verity device. */
|
||||
k = partition_verity_hash_of(i);
|
||||
if (k >= 0) {
|
||||
r = verity_partition(m, i, p, m->partitions + k, root, verity, flags, fl, d);
|
||||
@@ -3613,6 +3621,10 @@ int dissected_image_decrypt(
|
||||
return r;
|
||||
}
|
||||
|
||||
r = decrypt_partition(m, p, passphrase, flags, fl, d);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!p->decrypted_fstype && p->mount_node_fd >= 0 && p->decrypted_node) {
|
||||
r = probe_filesystem_full(p->mount_node_fd, p->decrypted_node, 0, UINT64_MAX, /* bool restrict_fstypes= */ true, &p->decrypted_fstype);
|
||||
if (r < 0 && r != -EUCLEAN)
|
||||
|
||||
Reference in New Issue
Block a user