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.
164 lines
5.7 KiB
164 lines
5.7 KiB
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 |
|
|
|
|