You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
5.7 KiB
165 lines
5.7 KiB
6 years ago
|
From 078ed81d14904f48a6237646050ba5eb74d702b7 Mon Sep 17 00:00:00 2001
|
||
|
From: Ondrej Kozina <okozina@redhat.com>
|
||
|
Date: Wed, 4 Jul 2018 15:58:09 +0200
|
||
|
Subject: [PATCH 2/6] Make LUKS2 auto-recovery aware of device signatures.
|
||
|
|
||
|
auto-recovery triggers any time when only single correct LUKS2
|
||
|
header instance was found. That may be dangerous.
|
||
|
|
||
|
We should suppress auto-recovery in case blkid decided the
|
||
|
device is no longer LUKS device. For example if secondary (intact)
|
||
|
LUKS2 header was left behind and blkid declares the device is LVM2
|
||
|
member.
|
||
|
|
||
|
Moreover if at least one header instance is corrupted and blkid
|
||
|
declares device non-empty and non-LUKS in the same time, header load
|
||
|
operation will be aborted with error.
|
||
|
---
|
||
|
lib/internal.h | 1 +
|
||
|
lib/luks2/luks2_disk_metadata.c | 61 ++++++++++++++++++++++++++++++++++++++++-
|
||
|
lib/luks2/luks2_internal.h | 2 +-
|
||
|
lib/luks2/luks2_json_metadata.c | 4 +--
|
||
|
4 files changed, 64 insertions(+), 4 deletions(-)
|
||
|
|
||
|
diff --git a/lib/internal.h b/lib/internal.h
|
||
|
index 07a1a08..e6d2323 100644
|
||
|
--- a/lib/internal.h
|
||
|
+++ b/lib/internal.h
|
||
|
@@ -32,6 +32,7 @@
|
||
|
|
||
|
#include "nls.h"
|
||
|
#include "bitops.h"
|
||
|
+#include "utils_blkid.h"
|
||
|
#include "utils_crypt.h"
|
||
|
#include "utils_loop.h"
|
||
|
#include "utils_dm.h"
|
||
|
diff --git a/lib/luks2/luks2_disk_metadata.c b/lib/luks2/luks2_disk_metadata.c
|
||
|
index 4d9bce2..6ca9d5e 100644
|
||
|
--- a/lib/luks2/luks2_disk_metadata.c
|
||
|
+++ b/lib/luks2/luks2_disk_metadata.c
|
||
|
@@ -531,12 +531,59 @@ static json_object *parse_and_validate_json(const char *json_area, int length)
|
||
|
return jobj;
|
||
|
}
|
||
|
|
||
|
+static int detect_device_signatures(const char *path)
|
||
|
+{
|
||
|
+ blk_probe_status prb_state;
|
||
|
+ int r;
|
||
|
+ struct blkid_handle *h;
|
||
|
+
|
||
|
+ if (!blk_supported()) {
|
||
|
+ log_dbg("Blkid probing of device signatures disabled.");
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ if ((r = blk_init_by_path(&h, path))) {
|
||
|
+ log_dbg("Failed to initialize blkid_handle by path.");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* We don't care about details. Be fast. */
|
||
|
+ blk_set_chains_for_fast_detection(h);
|
||
|
+
|
||
|
+ /* Filter out crypto_LUKS. we don't care now */
|
||
|
+ blk_superblocks_filter_luks(h);
|
||
|
+
|
||
|
+ prb_state = blk_safeprobe(h);
|
||
|
+
|
||
|
+ switch (prb_state) {
|
||
|
+ case PRB_AMBIGUOUS:
|
||
|
+ log_dbg("Blkid probe couldn't decide device type unambiguously.");
|
||
|
+ /* fall through */
|
||
|
+ case PRB_FAIL:
|
||
|
+ log_dbg("Blkid probe failed.");
|
||
|
+ r = -EINVAL;
|
||
|
+ break;
|
||
|
+ case PRB_OK: /* crypto_LUKS type is filtered out */
|
||
|
+ r = -EINVAL;
|
||
|
+
|
||
|
+ if (blk_is_partition(h))
|
||
|
+ log_dbg("Blkid probe detected partition type '%s'", blk_get_partition_type(h));
|
||
|
+ else if (blk_is_superblock(h))
|
||
|
+ log_dbg("blkid probe detected superblock type '%s'", blk_get_superblock_type(h));
|
||
|
+ break;
|
||
|
+ case PRB_EMPTY:
|
||
|
+ log_dbg("Blkid probe detected no foreign device signature.");
|
||
|
+ }
|
||
|
+ blk_free(h);
|
||
|
+ return r;
|
||
|
+}
|
||
|
+
|
||
|
/*
|
||
|
* Read and convert on-disk LUKS2 header to in-memory representation..
|
||
|
* Try to do recovery if on-disk state is not consistent.
|
||
|
*/
|
||
|
int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr,
|
||
|
- struct device *device, int do_recovery)
|
||
|
+ struct device *device, int do_recovery, int do_blkprobe)
|
||
|
{
|
||
|
enum { HDR_OK, HDR_OBSOLETE, HDR_FAIL, HDR_FAIL_IO } state_hdr1, state_hdr2;
|
||
|
struct luks2_hdr_disk hdr_disk1, hdr_disk2;
|
||
|
@@ -616,6 +663,12 @@ int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr,
|
||
|
if (state_hdr1 == HDR_OK && state_hdr2 != HDR_OK) {
|
||
|
log_dbg("Secondary LUKS2 header requires recovery.");
|
||
|
|
||
|
+ if (do_blkprobe && (r = detect_device_signatures(device_path(device)))) {
|
||
|
+ log_err(cd, _("Device contains ambiguous signatures, cannot auto-recover LUKS2.\n"
|
||
|
+ "Please run \"cryptsetup repair\" for recovery."));
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+
|
||
|
if (do_recovery) {
|
||
|
memcpy(&hdr_disk2, &hdr_disk1, LUKS2_HDR_BIN_LEN);
|
||
|
r = crypt_random_get(NULL, (char*)hdr_disk2.salt, sizeof(hdr_disk2.salt), CRYPT_RND_SALT);
|
||
|
@@ -631,6 +684,12 @@ int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr,
|
||
|
} else if (state_hdr1 != HDR_OK && state_hdr2 == HDR_OK) {
|
||
|
log_dbg("Primary LUKS2 header requires recovery.");
|
||
|
|
||
|
+ if (do_blkprobe && (r = detect_device_signatures(device_path(device)))) {
|
||
|
+ log_err(cd, _("Device contains ambiguous signatures, cannot auto-recover LUKS2.\n"
|
||
|
+ "Please run \"cryptsetup repair\" for recovery."));
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+
|
||
|
if (do_recovery) {
|
||
|
memcpy(&hdr_disk1, &hdr_disk2, LUKS2_HDR_BIN_LEN);
|
||
|
r = crypt_random_get(NULL, (char*)hdr_disk1.salt, sizeof(hdr_disk1.salt), CRYPT_RND_SALT);
|
||
|
diff --git a/lib/luks2/luks2_internal.h b/lib/luks2/luks2_internal.h
|
||
|
index e9beab8..dcabed7 100644
|
||
|
--- a/lib/luks2/luks2_internal.h
|
||
|
+++ b/lib/luks2/luks2_internal.h
|
||
|
@@ -42,7 +42,7 @@
|
||
|
* On-disk access function prototypes
|
||
|
*/
|
||
|
int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr,
|
||
|
- struct device *device, int do_recovery);
|
||
|
+ struct device *device, int do_recovery, int do_blkprobe);
|
||
|
int LUKS2_disk_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr,
|
||
|
struct device *device);
|
||
|
|
||
|
diff --git a/lib/luks2/luks2_json_metadata.c b/lib/luks2/luks2_json_metadata.c
|
||
|
index 362388e..125cad9 100644
|
||
|
--- a/lib/luks2/luks2_json_metadata.c
|
||
|
+++ b/lib/luks2/luks2_json_metadata.c
|
||
|
@@ -853,7 +853,7 @@ int LUKS2_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr)
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
- r = LUKS2_disk_hdr_read(cd, hdr, crypt_metadata_device(cd), 1);
|
||
|
+ r = LUKS2_disk_hdr_read(cd, hdr, crypt_metadata_device(cd), 1, 1);
|
||
|
if (r == -EAGAIN) {
|
||
|
/* unlikely: auto-recovery is required and failed due to read lock being held */
|
||
|
device_read_unlock(crypt_metadata_device(cd));
|
||
|
@@ -865,7 +865,7 @@ int LUKS2_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr)
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
- r = LUKS2_disk_hdr_read(cd, hdr, crypt_metadata_device(cd), 1);
|
||
|
+ r = LUKS2_disk_hdr_read(cd, hdr, crypt_metadata_device(cd), 1, 1);
|
||
|
|
||
|
device_write_unlock(crypt_metadata_device(cd));
|
||
|
} else
|
||
|
--
|
||
|
1.8.3.1
|
||
|
|