mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-11 19:00:02 +01:00
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.
This commit is contained in:
committed by
Milan Broz
parent
ad092a898d
commit
2c1a6e3f94
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
@@ -617,6 +664,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);
|
||||
@@ -632,6 +685,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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user