Blame SOURCES/cryptsetup-2.3.7-Make-reencryption-flag-and-keyslot-inseparable.patch

33f49e
From c75d740f9abd8a005975517008f780b16d103b0a Mon Sep 17 00:00:00 2001
33f49e
From: Ondrej Kozina <okozina@redhat.com>
33f49e
Date: Thu, 6 Jan 2022 12:24:26 +0100
33f49e
Subject: [PATCH 20/28] Make reencryption flag and keyslot inseparable.
33f49e
33f49e
LUKS2 validation code now requires reencrypt keyslot together with
33f49e
online-reencryption flag or none of those.
33f49e
---
33f49e
 lib/luks2/luks2_keyslot.c   | 25 +++++++++++++++++++++++++
33f49e
 lib/luks2/luks2_reencrypt.c | 17 +++++++++++------
33f49e
 2 files changed, 36 insertions(+), 6 deletions(-)
33f49e
33f49e
diff --git a/lib/luks2/luks2_keyslot.c b/lib/luks2/luks2_keyslot.c
33f49e
index 2ad5632c..d93f2dda 100644
33f49e
--- a/lib/luks2/luks2_keyslot.c
33f49e
+++ b/lib/luks2/luks2_keyslot.c
33f49e
@@ -878,10 +878,17 @@ int LUKS2_keyslots_validate(struct crypt_device *cd, json_object *hdr_jobj)
33f49e
 	const keyslot_handler *h;
33f49e
 	int keyslot;
33f49e
 	json_object *jobj_keyslots, *jobj_type;
33f49e
+	uint32_t reqs, reencrypt_count = 0;
33f49e
+	struct luks2_hdr dummy = {
33f49e
+		.jobj = hdr_jobj
33f49e
+	};
33f49e
 
33f49e
 	if (!json_object_object_get_ex(hdr_jobj, "keyslots", &jobj_keyslots))
33f49e
 		return -EINVAL;
33f49e
 
33f49e
+	if (LUKS2_config_get_requirements(cd, &dummy, &reqs))
33f49e
+		return -EINVAL;
33f49e
+
33f49e
 	json_object_object_foreach(jobj_keyslots, slot, val) {
33f49e
 		keyslot = atoi(slot);
33f49e
 		json_object_object_get_ex(val, "type", &jobj_type);
33f49e
@@ -897,6 +904,24 @@ int LUKS2_keyslots_validate(struct crypt_device *cd, json_object *hdr_jobj)
33f49e
 			log_dbg(cd, "Keyslot %d is not assigned to exactly 1 digest.", keyslot);
33f49e
 			return -EINVAL;
33f49e
 		}
33f49e
+
33f49e
+		if (!strcmp(h->name, "reencrypt"))
33f49e
+			reencrypt_count++;
33f49e
+	}
33f49e
+
33f49e
+	if ((reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT) && reencrypt_count == 0) {
33f49e
+		log_dbg(cd, "Missing reencryption keyslot.");
33f49e
+		return -EINVAL;
33f49e
+	}
33f49e
+
33f49e
+	if (!(reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT) && reencrypt_count) {
33f49e
+		log_dbg(cd, "Missing reencryption requirement flag.");
33f49e
+		return -EINVAL;
33f49e
+	}
33f49e
+
33f49e
+	if (reencrypt_count > 1) {
33f49e
+		log_dbg(cd, "Too many reencryption keyslots.");
33f49e
+		return -EINVAL;
33f49e
 	}
33f49e
 
33f49e
 	return 0;
33f49e
diff --git a/lib/luks2/luks2_reencrypt.c b/lib/luks2/luks2_reencrypt.c
33f49e
index f68675de..104871a4 100644
33f49e
--- a/lib/luks2/luks2_reencrypt.c
33f49e
+++ b/lib/luks2/luks2_reencrypt.c
33f49e
@@ -3301,15 +3301,20 @@ static int reencrypt_teardown_ok(struct crypt_device *cd, struct luks2_hdr *hdr,
33f49e
 			log_dbg(cd, "Failed to set new keyslots area size.");
33f49e
 		if (rh->digest_old >= 0 && rh->digest_new != rh->digest_old)
33f49e
 			for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++)
33f49e
-				if (LUKS2_digest_by_keyslot(hdr, i) == rh->digest_old)
33f49e
-					crypt_keyslot_destroy(cd, i);
33f49e
-		crypt_keyslot_destroy(cd, rh->reenc_keyslot);
33f49e
+				if (LUKS2_digest_by_keyslot(hdr, i) == rh->digest_old && crypt_keyslot_destroy(cd, i))
33f49e
+					log_err(cd, _("Failed to remove unused (unbound) keyslot %d."), i);
33f49e
+
33f49e
 		if (reencrypt_erase_backup_segments(cd, hdr))
33f49e
 			log_dbg(cd, "Failed to erase backup segments");
33f49e
 
33f49e
-		/* do we need atomic erase? */
33f49e
-		if (reencrypt_update_flag(cd, 0, true))
33f49e
-			log_err(cd, _("Failed to disable reencryption requirement flag."));
33f49e
+		if (reencrypt_update_flag(cd, 0, false))
33f49e
+			log_dbg(cd, "Failed to disable reencryption requirement flag.");
33f49e
+
33f49e
+		/* metadata commit point also removing reencryption flag on-disk */
33f49e
+		if (crypt_keyslot_destroy(cd, rh->reenc_keyslot)) {
33f49e
+			log_err(cd, _("Failed to remove reencryption keyslot."));
33f49e
+			return -EINVAL;
33f49e
+		}
33f49e
 	}
33f49e
 
33f49e
 	return 0;
33f49e
-- 
33f49e
2.27.0
33f49e