mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-17 05:40:13 +01:00
Detect broken LUKS metadata in-before encryption.
We should abort LUKS device in-place encryption when target data device or metadata device contain broken LUKS metadata (any version). Filed crypt_load() call was not good enough check because the call fails also when a device contains LUKS metadata overlapping with other superblock (e.g. LVM2 PV signature). Let blkid decide if device contains broken LUKS metadata or not. Fixes: #723.
This commit is contained in:
committed by
Milan Broz
parent
412de7dc25
commit
d56ccc97b8
@@ -112,7 +112,8 @@ int tools_write_json_file(const char *file, const char *json);
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PRB_FILTER_NONE = 0,
|
PRB_FILTER_NONE = 0,
|
||||||
PRB_FILTER_LUKS
|
PRB_FILTER_LUKS,
|
||||||
|
PRB_ONLY_LUKS
|
||||||
} tools_probe_filter_info;
|
} tools_probe_filter_info;
|
||||||
|
|
||||||
int tools_detect_signatures(const char *device, tools_probe_filter_info filter, size_t *count, bool batch_mode);
|
int tools_detect_signatures(const char *device, tools_probe_filter_info filter, size_t *count, bool batch_mode);
|
||||||
|
|||||||
@@ -220,11 +220,22 @@ int tools_detect_signatures(const char *device, tools_probe_filter_info filter,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
blk_set_chains_for_full_print(h);
|
switch (filter) {
|
||||||
|
case PRB_FILTER_LUKS:
|
||||||
if (filter == PRB_FILTER_LUKS && blk_superblocks_filter_luks(h)) {
|
if (blk_superblocks_filter_luks(h)) {
|
||||||
r = -EINVAL;
|
r = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
/* fall-through */
|
||||||
|
case PRB_FILTER_NONE:
|
||||||
|
blk_set_chains_for_full_print(h);
|
||||||
|
break;
|
||||||
|
case PRB_ONLY_LUKS:
|
||||||
|
blk_set_chains_for_fast_detection(h);
|
||||||
|
if (blk_superblocks_only_luks(h)) {
|
||||||
|
r = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((pr = blk_probe(h)) < PRB_EMPTY) {
|
while ((pr = blk_probe(h)) < PRB_EMPTY) {
|
||||||
|
|||||||
@@ -252,7 +252,6 @@ static enum device_status_info load_luks(struct crypt_device **r_cd, const char
|
|||||||
if (crypt_init_data_device(&cd, uuid_or_device(header_device ?: data_device), data_device))
|
if (crypt_init_data_device(&cd, uuid_or_device(header_device ?: data_device), data_device))
|
||||||
return DEVICE_INVALID;
|
return DEVICE_INVALID;
|
||||||
|
|
||||||
/* TODO: LUKS2 load may fail when header is damaged and blkid reports ambiguous/other signatures */
|
|
||||||
if ((r = crypt_load(cd, CRYPT_LUKS, NULL))) {
|
if ((r = crypt_load(cd, CRYPT_LUKS, NULL))) {
|
||||||
crypt_free(cd);
|
crypt_free(cd);
|
||||||
|
|
||||||
@@ -924,10 +923,27 @@ static int reencrypt_luks2_resume(struct crypt_device *cd)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int check_broken_luks_signature(const char *device)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
size_t count;
|
||||||
|
|
||||||
|
r = tools_detect_signatures(device, PRB_ONLY_LUKS, &count, ARG_SET(OPT_BATCH_MODE_ID));
|
||||||
|
if (r < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
if (count) {
|
||||||
|
log_err(_("Device %s contains broken LUKS metadata. Aborting operation."), device);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int _encrypt(struct crypt_device *cd, const char *type, enum device_status_info dev_st, int action_argc, const char **action_argv)
|
static int _encrypt(struct crypt_device *cd, const char *type, enum device_status_info dev_st, int action_argc, const char **action_argv)
|
||||||
{
|
{
|
||||||
const char *data_device;
|
const char *device_ptr;
|
||||||
enum device_status_info data_dev_st;
|
enum device_status_info data_dev_st;
|
||||||
|
struct stat st;
|
||||||
struct crypt_device *encrypt_cd = NULL;
|
struct crypt_device *encrypt_cd = NULL;
|
||||||
int r = -EINVAL;
|
int r = -EINVAL;
|
||||||
|
|
||||||
@@ -937,24 +953,37 @@ static int _encrypt(struct crypt_device *cd, const char *type, enum device_statu
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dev_st == DEVICE_NOT_LUKS &&
|
||||||
|
(!ARG_SET(OPT_HEADER_ID) || !stat(ARG_STR(OPT_HEADER_ID), &st))) {
|
||||||
|
device_ptr = ARG_SET(OPT_HEADER_ID) ? ARG_STR(OPT_HEADER_ID) : action_argv[0];
|
||||||
|
r = check_broken_luks_signature(device_ptr);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/* check data device type/state */
|
/* check data device type/state */
|
||||||
if (ARG_SET(OPT_HEADER_ID)) {
|
if (ARG_SET(OPT_HEADER_ID)) {
|
||||||
data_device = cd ? crypt_get_device_name(cd) : action_argv[0];
|
device_ptr = cd ? crypt_get_device_name(cd) : action_argv[0];
|
||||||
data_dev_st = check_luks_device(data_device);
|
data_dev_st = check_luks_device(device_ptr);
|
||||||
|
|
||||||
if (data_dev_st == DEVICE_INVALID)
|
if (data_dev_st == DEVICE_INVALID)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (data_dev_st == DEVICE_LUKS2 || data_dev_st == DEVICE_LUKS1) {
|
if (data_dev_st == DEVICE_LUKS2 || data_dev_st == DEVICE_LUKS1) {
|
||||||
log_err(_("Device %s is already LUKS device. Aborting operation."),
|
log_err(_("Device %s is already LUKS device. Aborting operation."),
|
||||||
data_device);
|
device_ptr);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data_dev_st == DEVICE_LUKS2_REENCRYPT || data_dev_st == DEVICE_LUKS1_UNUSABLE) {
|
if (data_dev_st == DEVICE_LUKS2_REENCRYPT || data_dev_st == DEVICE_LUKS1_UNUSABLE) {
|
||||||
log_err(_("Device %s is already in LUKS reencryption. Aborting operation."),
|
log_err(_("Device %s is already in LUKS reencryption. Aborting operation."),
|
||||||
data_device);
|
device_ptr);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r = check_broken_luks_signature(device_ptr);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!type)
|
if (!type)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ DEV_NAME=reenc9768
|
|||||||
DEV_NAME2=reenc97682
|
DEV_NAME2=reenc97682
|
||||||
IMG=reenc-data
|
IMG=reenc-data
|
||||||
IMG_HDR=$IMG.hdr
|
IMG_HDR=$IMG.hdr
|
||||||
|
HEADER_LUKS2_PV=blkid-luks2-pv.img
|
||||||
KEY1=key1
|
KEY1=key1
|
||||||
VKEY1=vkey1
|
VKEY1=vkey1
|
||||||
PWD1="93R4P4pIqAH8"
|
PWD1="93R4P4pIqAH8"
|
||||||
@@ -98,7 +99,7 @@ function remove_mapping()
|
|||||||
[ -b /dev/mapper/$OVRDEV-err ] && dmsetup remove --retry $OVRDEV-err 2>/dev/null
|
[ -b /dev/mapper/$OVRDEV-err ] && dmsetup remove --retry $OVRDEV-err 2>/dev/null
|
||||||
[ -n "$LOOPDEV" ] && losetup -d $LOOPDEV
|
[ -n "$LOOPDEV" ] && losetup -d $LOOPDEV
|
||||||
unset LOOPDEV
|
unset LOOPDEV
|
||||||
rm -f $IMG $IMG_HDR $KEY1 $VKEY1 $DEVBIG $DEV_LINK >/dev/null 2>&1
|
rm -f $IMG $IMG_HDR $KEY1 $VKEY1 $DEVBIG $DEV_LINK $HEADER_LUKS2_PV >/dev/null 2>&1
|
||||||
rmmod scsi_debug >/dev/null 2>&1
|
rmmod scsi_debug >/dev/null 2>&1
|
||||||
scsi_debug_teardown $DEV
|
scsi_debug_teardown $DEV
|
||||||
}
|
}
|
||||||
@@ -1708,5 +1709,20 @@ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --header $IMG_HDR $FAST_PBKD
|
|||||||
echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --decrypt --header $IMG_HDR --init-only $FAST_PBKDF_ARGON || fail
|
echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --decrypt --header $IMG_HDR --init-only $FAST_PBKDF_ARGON || fail
|
||||||
echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --header $IMG_HDR $DEV -q $FAST_PBKDF_ARGON 2> /dev/null && fail
|
echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --header $IMG_HDR $DEV -q $FAST_PBKDF_ARGON 2> /dev/null && fail
|
||||||
|
|
||||||
|
echo "[30] Prevent nested encryption of broken LUKS device"
|
||||||
|
rm -f $IMG_HDR
|
||||||
|
xz -dk $HEADER_LUKS2_PV.xz
|
||||||
|
wipe_dev $DEV
|
||||||
|
|
||||||
|
# broken header
|
||||||
|
echo $PWD1 | $CRYPTSETUP reencrypt -q --header $HEADER_LUKS2_PV $DEV $FAST_PBKDF --encrypt --type luks2 2>/dev/null && fail
|
||||||
|
$CRYPTSETUP isLuks $HEADER_LUKS2_PV && fail
|
||||||
|
# broken device
|
||||||
|
echo $PWD1 | $CRYPTSETUP reencrypt -q $HEADER_LUKS2_PV $FAST_PBKDF --encrypt --force-offline-reencrypt --type luks2 --reduce-device-size 8m 2>/dev/null && fail
|
||||||
|
$CRYPTSETUP isLuks $HEADER_LUKS2_PV && fail
|
||||||
|
# broken data device only
|
||||||
|
echo $PWD1 | $CRYPTSETUP reencrypt -q --header $IMG_HDR $HEADER_LUKS2_PV $FAST_PBKDF --encrypt --force-offline-reencrypt --type luks2 2>/dev/null && fail
|
||||||
|
test -f $IMG_HDR && fail
|
||||||
|
|
||||||
remove_mapping
|
remove_mapping
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ DEV_NAME=reenc9768
|
|||||||
DEV_NAME2=reenc1273
|
DEV_NAME2=reenc1273
|
||||||
IMG=reenc-data
|
IMG=reenc-data
|
||||||
IMG_HDR=$IMG.hdr
|
IMG_HDR=$IMG.hdr
|
||||||
|
HEADER_LUKS2_PV=blkid-luks2-pv.img
|
||||||
ORIG_IMG=reenc-data-orig
|
ORIG_IMG=reenc-data-orig
|
||||||
KEY1=key1
|
KEY1=key1
|
||||||
PWD1="93R4P4pIqAH8"
|
PWD1="93R4P4pIqAH8"
|
||||||
@@ -30,7 +31,7 @@ function remove_mapping()
|
|||||||
[ -b /dev/mapper/$DEV_NAME2 ] && dmsetup remove --retry $DEV_NAME2
|
[ -b /dev/mapper/$DEV_NAME2 ] && dmsetup remove --retry $DEV_NAME2
|
||||||
[ -b /dev/mapper/$DEV_NAME ] && dmsetup remove --retry $DEV_NAME
|
[ -b /dev/mapper/$DEV_NAME ] && dmsetup remove --retry $DEV_NAME
|
||||||
[ ! -z "$LOOPDEV1" ] && losetup -d $LOOPDEV1 >/dev/null 2>&1
|
[ ! -z "$LOOPDEV1" ] && losetup -d $LOOPDEV1 >/dev/null 2>&1
|
||||||
rm -f $IMG $IMG_HDR $ORIG_IMG $KEY1 >/dev/null 2>&1
|
rm -f $IMG $IMG_HDR $ORIG_IMG $KEY1 $HEADER_LUKS2_PV >/dev/null 2>&1
|
||||||
umount $MNT_DIR > /dev/null 2>&1
|
umount $MNT_DIR > /dev/null 2>&1
|
||||||
rmdir $MNT_DIR > /dev/null 2>&1
|
rmdir $MNT_DIR > /dev/null 2>&1
|
||||||
LOOPDEV1=""
|
LOOPDEV1=""
|
||||||
@@ -416,5 +417,20 @@ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 --header $IMG_HDR $FAST_PBKD
|
|||||||
echo $PWD1 | $REENC $LOOPDEV1 -q $FAST_PBKDF --new --type luks1 --header $IMG_HDR 2>/dev/null && fail
|
echo $PWD1 | $REENC $LOOPDEV1 -q $FAST_PBKDF --new --type luks1 --header $IMG_HDR 2>/dev/null && fail
|
||||||
echo $PWD1 | $REENC $LOOPDEV1 -q $FAST_PBKDF --new --type luks2 --header $IMG_HDR 2>/dev/null && fail
|
echo $PWD1 | $REENC $LOOPDEV1 -q $FAST_PBKDF --new --type luks2 --header $IMG_HDR 2>/dev/null && fail
|
||||||
|
|
||||||
|
echo "[13] Prevent nested encryption of broken LUKS device"
|
||||||
|
rm -f $IMG_HDR
|
||||||
|
wipe_dev $LOOPDEV1
|
||||||
|
xz -dk $HEADER_LUKS2_PV.xz
|
||||||
|
|
||||||
|
# broken header
|
||||||
|
echo $PWD1 | $REENC --header $HEADER_LUKS2_PV $LOOPDEV1 -q $FAST_PBKDF --new --type luks1 2>/dev/null && fail
|
||||||
|
$CRYPTSETUP isLuks $HEADER_LUKS2_PV && fail
|
||||||
|
# broken device
|
||||||
|
echo $PWD1 | $REENC $HEADER_LUKS2_PV -q $FAST_PBKDF --new --type luks1 --reduce-device-size 1024S 2>/dev/null && fail
|
||||||
|
$CRYPTSETUP isLuks $HEADER_LUKS2_PV && fail
|
||||||
|
# broken data device only
|
||||||
|
echo $PWD1 | $REENC --header $IMG_HDR $HEADER_LUKS2_PV -q $FAST_PBKDF --new --type luks1 2>/dev/null && fail
|
||||||
|
test -f $IMG_HDR && fail
|
||||||
|
|
||||||
remove_mapping
|
remove_mapping
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
Reference in New Issue
Block a user