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