Blame SOURCES/cryptsetup-2.6.1-Abort-encryption-when-header-and-data-devices-are-sa.patch

0b2424
From c18dcfaa0b91eb48006232fbfadce9e6a9b4a790 Mon Sep 17 00:00:00 2001
0b2424
From: Ondrej Kozina <okozina@redhat.com>
0b2424
Date: Fri, 2 Dec 2022 15:39:36 +0100
0b2424
Subject: [PATCH 2/2] Abort encryption when header and data devices are same.
0b2424
0b2424
If data device reduction is not requsted this led
0b2424
to data corruption since LUKS metadata was written
0b2424
over the data device.
0b2424
---
0b2424
 src/utils_reencrypt.c          | 42 ++++++++++++++++++++++++++++++----
0b2424
 tests/luks2-reencryption-test  | 16 +++++++++++++
0b2424
 tests/reencryption-compat-test | 20 +++++++++++++---
0b2424
 3 files changed, 70 insertions(+), 8 deletions(-)
0b2424
0b2424
diff --git a/src/utils_reencrypt.c b/src/utils_reencrypt.c
0b2424
index 87ead680..73e0bca8 100644
0b2424
--- a/src/utils_reencrypt.c
0b2424
+++ b/src/utils_reencrypt.c
0b2424
@@ -467,6 +467,26 @@ static int reencrypt_check_active_device_sb_block_size(const char *active_device
0b2424
 	return reencrypt_check_data_sb_block_size(dm_device, new_sector_size);
0b2424
 }
0b2424
 
0b2424
+static int reencrypt_is_header_detached(const char *header_device, const char *data_device)
0b2424
+{
0b2424
+	int r;
0b2424
+	struct stat st;
0b2424
+	struct crypt_device *cd;
0b2424
+
0b2424
+	if (!header_device)
0b2424
+		return 0;
0b2424
+
0b2424
+	if (header_device && stat(header_device, &st) < 0 && errno == ENOENT)
0b2424
+		return 1;
0b2424
+
0b2424
+	if ((r = crypt_init_data_device(&cd, header_device, data_device)))
0b2424
+		return r;
0b2424
+
0b2424
+	r = crypt_header_is_detached(cd);
0b2424
+	crypt_free(cd);
0b2424
+	return r;
0b2424
+}
0b2424
+
0b2424
 static int encrypt_luks2_init(struct crypt_device **cd, const char *data_device, const char *device_name)
0b2424
 {
0b2424
 	int keyslot, r, fd;
0b2424
@@ -490,9 +510,14 @@ static int encrypt_luks2_init(struct crypt_device **cd, const char *data_device,
0b2424
 
0b2424
 	_set_reencryption_flags(&params.flags);
0b2424
 
0b2424
-	if (!data_shift && !ARG_SET(OPT_HEADER_ID)) {
0b2424
-		log_err(_("Encryption without detached header (--header) is not possible without data device size reduction (--reduce-device-size)."));
0b2424
-		return -ENOTSUP;
0b2424
+	if (!data_shift) {
0b2424
+		r = reencrypt_is_header_detached(ARG_STR(OPT_HEADER_ID), data_device);
0b2424
+		if (r < 0)
0b2424
+			return r;
0b2424
+		if (!r) {
0b2424
+			log_err(_("Encryption without detached header (--header) is not possible without data device size reduction (--reduce-device-size)."));
0b2424
+			return -ENOTSUP;
0b2424
+		}
0b2424
 	}
0b2424
 
0b2424
 	if (!ARG_SET(OPT_HEADER_ID) && ARG_UINT64(OPT_OFFSET_ID) &&
0b2424
@@ -1358,9 +1383,16 @@ static int _encrypt(struct crypt_device *cd, const char *type, enum device_statu
0b2424
 	if (!type)
0b2424
 		type = crypt_get_default_type();
0b2424
 
0b2424
-	if (dev_st == DEVICE_LUKS1_UNUSABLE || isLUKS1(type))
0b2424
+	if (dev_st == DEVICE_LUKS1_UNUSABLE || isLUKS1(type)) {
0b2424
+		r = reencrypt_is_header_detached(ARG_STR(OPT_HEADER_ID), action_argv[0]);
0b2424
+		if (r < 0)
0b2424
+			return r;
0b2424
+		if (!r && !ARG_SET(OPT_REDUCE_DEVICE_SIZE_ID)) {
0b2424
+			log_err(_("Encryption without detached header (--header) is not possible without data device size reduction (--reduce-device-size)."));
0b2424
+			return -ENOTSUP;
0b2424
+		}
0b2424
 		return reencrypt_luks1(action_argv[0]);
0b2424
-	else if (dev_st == DEVICE_NOT_LUKS) {
0b2424
+	} else if (dev_st == DEVICE_NOT_LUKS) {
0b2424
 		r = encrypt_luks2_init(&encrypt_cd, action_argv[0], action_argc > 1 ? action_argv[1] : NULL);
0b2424
 		if (r < 0 || ARG_SET(OPT_INIT_ONLY_ID)) {
0b2424
 			crypt_free(encrypt_cd);
0b2424
diff --git a/tests/luks2-reencryption-test b/tests/luks2-reencryption-test
0b2424
index bab54353..a647a8c2 100755
0b2424
--- a/tests/luks2-reencryption-test
0b2424
+++ b/tests/luks2-reencryption-test
0b2424
@@ -1080,6 +1080,22 @@ $CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 || fail
0b2424
 $CRYPTSETUP close $DEV_NAME
0b2424
 echo $PWD1 | $CRYPTSETUP open --header $IMG_HDR $DEV --test-passphrase || fail
0b2424
 
0b2424
+# Encrypt without size reduction must not allow header device same as data device
0b2424
+wipe_dev_head $DEV 1
0b2424
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --type luks2 --encrypt --header $DEV -q $FAST_PBKDF_ARGON 2>/dev/null && fail
0b2424
+$CRYPTSETUP isLUKS $DEV 2>/dev/null && fail
0b2424
+ln -s $DEV $DEV_LINK || fail
0b2424
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --type luks2 --encrypt --header $DEV_LINK -q $FAST_PBKDF_ARGON 2>/dev/null && fail
0b2424
+$CRYPTSETUP isLUKS $DEV 2>/dev/null && fail
0b2424
+rm -f $DEV_LINK || fail
0b2424
+
0b2424
+dd if=/dev/zero of=$IMG bs=4k count=1 >/dev/null 2>&1
0b2424
+echo $PWD1 | $CRYPTSETUP reencrypt $IMG --type luks2 --encrypt --header $IMG -q $FAST_PBKDF_ARGON 2>/dev/null && fail
0b2424
+$CRYPTSETUP isLUKS $IMG 2>/dev/null && fail
0b2424
+ln -s $IMG $DEV_LINK || fail
0b2424
+echo $PWD1 | $CRYPTSETUP reencrypt $IMG --type luks2 --encrypt --header $DEV_LINK -q $FAST_PBKDF_ARGON 2>/dev/null && fail
0b2424
+$CRYPTSETUP isLUKS $IMG 2>/dev/null && fail
0b2424
+
0b2424
 echo "[4] Reencryption with detached header"
0b2424
 wipe $PWD1 $IMG_HDR
0b2424
 echo $PWD1 | $CRYPTSETUP reencrypt -c aes-cbc-essiv:sha256 -s 128 --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
0b2424
diff --git a/tests/reencryption-compat-test b/tests/reencryption-compat-test
0b2424
index f6a84137..453831d1 100755
0b2424
--- a/tests/reencryption-compat-test
0b2424
+++ b/tests/reencryption-compat-test
0b2424
@@ -15,6 +15,7 @@ IMG=reenc-data
0b2424
 IMG_HDR=$IMG.hdr
0b2424
 HEADER_LUKS2_PV=blkid-luks2-pv.img
0b2424
 ORIG_IMG=reenc-data-orig
0b2424
+DEV_LINK="reenc-test-link"
0b2424
 KEY1=key1
0b2424
 PWD1="93R4P4pIqAH8"
0b2424
 PWD2="1cND4319812f"
0b2424
@@ -40,7 +41,7 @@ function remove_mapping()
0b2424
 	[ -b /dev/mapper/$DEV_NAME2 ] && dmsetup remove --retry $DEV_NAME2
0b2424
 	[ -b /dev/mapper/$DEV_NAME ] && dmsetup remove --retry $DEV_NAME
0b2424
 	[ ! -z "$LOOPDEV1" ] && losetup -d $LOOPDEV1 >/dev/null 2>&1
0b2424
-	rm -f $IMG $IMG_HDR $ORIG_IMG $KEY1 $HEADER_LUKS2_PV >/dev/null 2>&1
0b2424
+	rm -f $IMG $IMG_HDR $ORIG_IMG $KEY1 $HEADER_LUKS2_PV $DEV_LINK >/dev/null 2>&1
0b2424
 	umount $MNT_DIR > /dev/null 2>&1
0b2424
 	rmdir $MNT_DIR > /dev/null 2>&1
0b2424
 	LOOPDEV1=""
0b2424
@@ -302,12 +303,25 @@ check_slot 0 || fail "Only keyslot 0 expected to be enabled"
0b2424
 $REENC $LOOPDEV1 -d $KEY1 $FAST_PBKDF -q || fail
0b2424
 # FIXME echo $PWD1 | $REENC ...
0b2424
 
0b2424
-if [ ! fips_mode ]; then
0b2424
 echo "[4] Encryption of not yet encrypted device"
0b2424
+# Encrypt without size reduction must not allow header device same as data device
0b2424
+wipe_dev $LOOPDEV1
0b2424
+echo $PWD1 | $REENC $LOOPDEV1 --type luks1 --new --header $LOOPDEV1 -q $FAST_PBKDF_ARGON 2>/dev/null && fail
0b2424
+$CRYPTSETUP isLUKS $LOOPDEV1 2>/dev/null && fail
0b2424
+ln -s $LOOPDEV1 $DEV_LINK || fail
0b2424
+echo $PWD1 | $REENC $LOOPDEV1 --type luks1 --new --header $DEV_LINK -q $FAST_PBKDF_ARGON 2>/dev/null && fail
0b2424
+$CRYPTSETUP isLUKS $LOOPDEV1 2>/dev/null && fail
0b2424
+rm -f $DEV_LINK || fail
0b2424
+echo $PWD1 | $REENC $IMG --type luks1 --new --header $IMG -q $FAST_PBKDF_ARGON 2>/dev/null && fail
0b2424
+$CRYPTSETUP isLUKS $IMG 2>/dev/null && fail
0b2424
+ln -s $IMG $DEV_LINK || fail
0b2424
+echo $PWD1 | $REENC $IMG --type luks1 --new --header $DEV_LINK -q $FAST_PBKDF_ARGON 2>/dev/null && fail
0b2424
+$CRYPTSETUP isLUKS $IMG 2>/dev/null && fail
0b2424
+
0b2424
+if [ ! fips_mode ]; then
0b2424
 # well, movin' zeroes :-)
0b2424
 OFFSET=2048
0b2424
 SIZE=$(blockdev --getsz $LOOPDEV1)
0b2424
-wipe_dev $LOOPDEV1
0b2424
 dmsetup create $DEV_NAME2 --table "0 $(($SIZE - $OFFSET)) linear $LOOPDEV1 0" || fail
0b2424
 check_hash_dev /dev/mapper/$DEV_NAME2 $HASH3
0b2424
 dmsetup remove --retry $DEV_NAME2 || fail
0b2424
-- 
0b2424
2.38.1
0b2424