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

c31bd2
From c18dcfaa0b91eb48006232fbfadce9e6a9b4a790 Mon Sep 17 00:00:00 2001
c31bd2
From: Ondrej Kozina <okozina@redhat.com>
c31bd2
Date: Fri, 2 Dec 2022 15:39:36 +0100
c31bd2
Subject: [PATCH 2/2] Abort encryption when header and data devices are same.
c31bd2
c31bd2
If data device reduction is not requsted this led
c31bd2
to data corruption since LUKS metadata was written
c31bd2
over the data device.
c31bd2
---
c31bd2
 src/utils_reencrypt.c          | 42 ++++++++++++++++++++++++++++++----
c31bd2
 tests/luks2-reencryption-test  | 16 +++++++++++++
c31bd2
 tests/reencryption-compat-test | 20 +++++++++++++---
c31bd2
 3 files changed, 70 insertions(+), 8 deletions(-)
c31bd2
c31bd2
diff --git a/src/utils_tools.c b/src/utils_tools.c
c31bd2
--- a/src/utils_tools.c
c31bd2
+++ b/src/utils_tools.c
c31bd2
@@ -624,3 +624,23 @@ int tools_reencrypt_progress(uint64_t si
c31bd2
 
c31bd2
 	return r;
c31bd2
 }
c31bd2
+
c31bd2
+int reencrypt_is_header_detached(const char *header_device, const char *data_device)
c31bd2
+{
c31bd2
+	int r;
c31bd2
+	struct stat st;
c31bd2
+	struct crypt_device *cd;
c31bd2
+
c31bd2
+	if (!header_device)
c31bd2
+		return 0;
c31bd2
+
c31bd2
+	if (header_device && stat(header_device, &st) < 0 && errno == ENOENT)
c31bd2
+		return 1;
c31bd2
+
c31bd2
+	if ((r = crypt_init_data_device(&cd, header_device, data_device)))
c31bd2
+		return r;
c31bd2
+
c31bd2
+	r = crypt_get_metadata_device_name(cd) && crypt_get_device_name(cd) && strcmp(crypt_get_metadata_device_name(cd), crypt_get_device_name(cd));
c31bd2
+	crypt_free(cd);
c31bd2
+	return r;
c31bd2
+}
c31bd2
diff --git a/src/cryptsetup.h b/src/cryptsetup.h
c31bd2
--- a/src/cryptsetup.h
c31bd2
+++ b/src/cryptsetup.h
c31bd2
@@ -103,6 +103,7 @@ void tools_clear_line(void);
c31bd2
 
c31bd2
 int tools_wipe_progress(uint64_t size, uint64_t offset, void *usrptr);
c31bd2
 int tools_reencrypt_progress(uint64_t size, uint64_t offset, void *usrptr);
c31bd2
+int reencrypt_is_header_detached(const char *header_device, const char *data_device);
c31bd2
 
c31bd2
 int tools_read_mk(const char *file, char **key, int keysize);
c31bd2
 int tools_write_mk(const char *file, const char *key, int keysize);
c31bd2
diff --git a/src/cryptsetup.c b/src/cryptsetup.c
c31bd2
--- a/src/cryptsetup.c
c31bd2
+++ b/src/cryptsetup.c
c31bd2
@@ -2892,6 +2892,16 @@ static int action_encrypt_luks2(struct c
c31bd2
 		return -ENOTSUP;
c31bd2
 	}
c31bd2
 
c31bd2
+	if (!opt_data_shift) {
c31bd2
+	       r = reencrypt_is_header_detached(opt_header_device, action_argv[0]);
c31bd2
+	       if (r < 0)
c31bd2
+		       return r;
c31bd2
+	       if (!r) {
c31bd2
+		       log_err(_("Encryption without detached header (--header) is not possible without data device size reduction (--reduce-device-size)."));
c31bd2
+		       return -ENOTSUP;
c31bd2
+	       }
c31bd2
+	}
c31bd2
+
c31bd2
 	if (!opt_header_device && opt_offset && opt_data_shift && (opt_offset > (imaxabs(opt_data_shift) / (2 * SECTOR_SIZE)))) {
c31bd2
 		log_err(_("Requested data offset must be less than or equal to half of --reduce-device-size parameter."));
c31bd2
 		return -EINVAL;
c31bd2
diff --git a/src/cryptsetup_reencrypt.c b/src/cryptsetup_reencrypt.c
c31bd2
--- a/src/cryptsetup_reencrypt.c
c31bd2
+++ b/src/cryptsetup_reencrypt.c
c31bd2
@@ -1553,6 +1553,17 @@ static int run_reencrypt(const char *dev
c31bd2
 		goto out;
c31bd2
 	}
c31bd2
c31bd2
+	if (rc.reencrypt_mode == ENCRYPT) {
c31bd2
+		r = reencrypt_is_header_detached(opt_header_device, action_argv[0]);
c31bd2
+		if (r < 0)
c31bd2
+			goto out;
c31bd2
+		if (!r && !opt_reduce_size) {
c31bd2
+			log_err(_("Encryption without detached header (--header) is not possible without data device size reduction (--reduce-device-size)."));
c31bd2
+			r = -ENOTSUP;
c31bd2
+			goto out;
c31bd2
+		}
c31bd2
+	}
c31bd2
+
c31bd2
 	log_dbg("Running reencryption.");
c31bd2
c31bd2
 	if (!rc.in_progress) {
c31bd2
diff --git a/tests/luks2-reencryption-test b/tests/luks2-reencryption-test
c31bd2
index bab54353..a647a8c2 100755
c31bd2
--- a/tests/luks2-reencryption-test
c31bd2
+++ b/tests/luks2-reencryption-test
c31bd2
@@ -1080,6 +1080,15 @@ $CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 || fail
c31bd2
 $CRYPTSETUP close $DEV_NAME
c31bd2
 echo $PWD1 | $CRYPTSETUP open --header $IMG_HDR $DEV --test-passphrase || fail
c31bd2
 
c31bd2
+# Encrypt without size reduction must not allow header device same as data device
c31bd2
+wipe_dev_head $DEV 1
c31bd2
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --type luks2 --encrypt --header $DEV -q $FAST_PBKDF_ARGON 2>/dev/null && fail
c31bd2
+$CRYPTSETUP isLUKS $DEV 2>/dev/null && fail
c31bd2
+
c31bd2
+dd if=/dev/zero of=$IMG bs=4k count=1 >/dev/null 2>&1
c31bd2
+echo $PWD1 | $CRYPTSETUP reencrypt $IMG --type luks2 --encrypt --header $IMG -q $FAST_PBKDF_ARGON 2>/dev/null && fail
c31bd2
+$CRYPTSETUP isLUKS $IMG 2>/dev/null && fail
c31bd2
+
c31bd2
 echo "[4] Reencryption with detached header"
c31bd2
 wipe $PWD1 $IMG_HDR
c31bd2
 echo $PWD1 | $CRYPTSETUP reencrypt -c aes-cbc-essiv:sha256 -s 128 --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
c31bd2
diff --git a/tests/reencryption-compat-test b/tests/reencryption-compat-test
c31bd2
index f6a84137..453831d1 100755
c31bd2
--- a/tests/reencryption-compat-test
c31bd2
+++ b/tests/reencryption-compat-test
c31bd2
@@ -11,5 +11,6 @@ IMG=reenc-data
c31bd2
 IMG_HDR=$IMG.hdr
c31bd2
 ORIG_IMG=reenc-data-orig
c31bd2
+DEV_LINK="reenc-test-link"
c31bd2
 KEY1=key1
c31bd2
 PWD1="93R4P4pIqAH8"
c31bd2
 PWD2="1cND4319812f"
c31bd2
@@ -40,7 +41,7 @@ function remove_mapping()
c31bd2
 	[ -b /dev/mapper/$DEV_NAME2 ] && dmsetup remove --retry $DEV_NAME2
c31bd2
 	[ -b /dev/mapper/$DEV_NAME ] && dmsetup remove --retry $DEV_NAME
c31bd2
 	[ ! -z "$LOOPDEV1" ] && losetup -d $LOOPDEV1 >/dev/null 2>&1
c31bd2
-	rm -f $IMG $IMG_HDR $ORIG_IMG $KEY1 >/dev/null 2>&1
c31bd2
+	rm -f $IMG $IMG_HDR $ORIG_IMG $KEY1 $DEV_LINK >/dev/null 2>&1
c31bd2
 	umount $MNT_DIR > /dev/null 2>&1
c31bd2
 	rmdir $MNT_DIR > /dev/null 2>&1
c31bd2
 	LOOPDEV1=""
c31bd2
@@ -265,10 +265,16 @@ $REENC $LOOPDEV1 -d $KEY1 $FAST_PBKDF -q
c31bd2
 # FIXME echo $PWD1 | $REENC ...
c31bd2
 
c31bd2
 echo "[4] Encryption of not yet encrypted device"
c31bd2
+# Encrypt without size reduction must not allow header device same as data device
c31bd2
+wipe_dev $LOOPDEV1
c31bd2
+echo $PWD1 | $REENC $LOOPDEV1 --type luks1 --new --header $LOOPDEV1 -q $FAST_PBKDF_ARGON 2>/dev/null && fail
c31bd2
+$CRYPTSETUP isLUKS $LOOPDEV1 2>/dev/null && fail
c31bd2
+echo $PWD1 | $REENC $IMG --type luks1 --new --header $IMG -q $FAST_PBKDF_ARGON 2>/dev/null && fail
c31bd2
+$CRYPTSETUP isLUKS $IMG 2>/dev/null && fail
c31bd2
+
c31bd2
 # well, movin' zeroes :-)
c31bd2
 OFFSET=2048
c31bd2
 SIZE=$(blockdev --getsz $LOOPDEV1)
c31bd2
-wipe_dev $LOOPDEV1
c31bd2
 dmsetup create $DEV_NAME2 --table "0 $(($SIZE - $OFFSET)) linear $LOOPDEV1 0" || fail
c31bd2
 check_hash_dev /dev/mapper/$DEV_NAME2 $HASH3
c31bd2
 dmsetup remove --retry $DEV_NAME2 || fail
c31bd2
-- 
c31bd2
2.38.1
c31bd2