[PATCH] cryptsetup: add support for the "fix_padding" option

Mikulas Patocka <[email protected]>
Newsgroups gmane.linux.kernel.device-mapper.devel,gmane.linux.kernel.device-mapper.dm-crypt
Message-ID <alpine.LRH.2.02.1911130648210.20335@file01.intranet.prod.int.rdu2.redhat.com>
This patch adds support for fixed padding to cryptsetup.

* Cryptsetup will accept superblocks version 4.
* If the dm-integrity target version is greater than 1.4, cryptsetup will 
  add a flag "fix_padding" to the dm-integrity target arguments.

There is still one quirk: if we have an old libdm without 
DM_DEVICE_GET_TARGET_VERSION and if dm-integrity module is not loaded, 
cryptsetup will not detect that it can use the "fix_padding" option.

Signed-off-by: Mikulas Patocka <[email protected]>

---
 lib/integrity/integrity.c |    7 +++----
 lib/integrity/integrity.h |    2 ++
 lib/libdevmapper.c        |   20 +++++++++++++++++++-
 lib/utils_dm.h            |    6 +++++-
 4 files changed, 29 insertions(+), 6 deletions(-)

Index: cryptsetup/lib/integrity/integrity.c
===================================================================
--- cryptsetup.orig/lib/integrity/integrity.c	2019-11-12 20:09:30.000000000 +0100
+++ cryptsetup/lib/integrity/integrity.c	2019-11-12 21:09:05.000000000 +0100
@@ -41,8 +41,7 @@ static int INTEGRITY_read_superblock(str
 	if (read_lseek_blockwise(devfd, device_block_size(cd, device),
 		device_alignment(device), sb, sizeof(*sb), offset) != sizeof(*sb) ||
 	    memcmp(sb->magic, SB_MAGIC, sizeof(sb->magic)) ||
-	    (sb->version != SB_VERSION_1 && sb->version != SB_VERSION_2 &&
-	     sb->version != SB_VERSION_3)) {
+	    sb->version < SB_VERSION_1 || sb->version > SB_VERSION_4) {
 		log_std(cd, "No integrity superblock detected on %s.\n",
 			device_path(device));
 		r = -EINVAL;
@@ -203,7 +202,7 @@ int INTEGRITY_create_dmd_device(struct c
 	if (r < 0)
 		return r;
 
-	return dm_integrity_target_set(&dmd->segment, 0, dmd->size,
+	return dm_integrity_target_set(cd, &dmd->segment, 0, dmd->size,
 			crypt_metadata_device(cd), crypt_data_device(cd),
 			crypt_get_integrity_tag_size(cd), crypt_get_data_offset(cd),
 			crypt_get_sector_size(cd), vk, journal_crypt_key,
@@ -289,7 +288,7 @@ int INTEGRITY_format(struct crypt_device
 	if (params && params->integrity_key_size)
 		vk = crypt_alloc_volume_key(params->integrity_key_size, NULL);
 
-	r = dm_integrity_target_set(tgt, 0, dmdi.size, crypt_metadata_device(cd),
+	r = dm_integrity_target_set(cd, tgt, 0, dmdi.size, crypt_metadata_device(cd),
 			crypt_data_device(cd), crypt_get_integrity_tag_size(cd),
 			crypt_get_data_offset(cd), crypt_get_sector_size(cd), vk,
 			journal_crypt_key, journal_mac_key, params);
Index: cryptsetup/lib/integrity/integrity.h
===================================================================
--- cryptsetup.orig/lib/integrity/integrity.h	2019-11-12 20:09:30.000000000 +0100
+++ cryptsetup/lib/integrity/integrity.h	2019-11-12 20:12:54.000000000 +0100
@@ -34,10 +34,12 @@ struct crypt_dm_active_device;
 #define SB_VERSION_1	1
 #define SB_VERSION_2	2
 #define SB_VERSION_3	3
+#define SB_VERSION_4	4
 
 #define SB_FLAG_HAVE_JOURNAL_MAC	(1 << 0)
 #define SB_FLAG_RECALCULATING		(1 << 1) /* V2 only */
 #define SB_FLAG_DIRTY_BITMAP		(1 << 2) /* V3 only */
+#define SB_FLAG_FIXED_PADDING		(1 << 3) /* V4 only */
 
 struct superblock {
 	uint8_t magic[8];
Index: cryptsetup/lib/libdevmapper.c
===================================================================
--- cryptsetup.orig/lib/libdevmapper.c	2019-11-12 20:09:30.000000000 +0100
+++ cryptsetup/lib/libdevmapper.c	2019-11-13 12:42:39.000000000 +0100
@@ -218,6 +218,9 @@ static void _dm_set_integrity_compat(str
 	if (_dm_satisfies_version(1, 3, 0, integrity_maj, integrity_min, integrity_patch))
 		_dm_flags |= DM_INTEGRITY_BITMAP_SUPPORTED;
 
+	if (_dm_satisfies_version(1, 4, 0, integrity_maj, integrity_min, integrity_patch))
+		_dm_flags |= DM_INTEGRITY_FIX_PADDING_SUPPORTED;
+
 	_dm_integrity_checked = true;
 }
 
@@ -866,6 +869,11 @@ static char *get_dm_integrity_params(con
 		strncat(features, feature, sizeof(features) - strlen(features) - 1);
 		crypt_safe_free(hexkey);
 	}
+	if (tgt->u.integrity.fix_padding) {
+		num_options++;
+		snprintf(feature, sizeof(feature), "fix_padding ");
+		strncat(features, feature, sizeof(features) - strlen(features) - 1);
+	}
 
 	if (flags & CRYPT_ACTIVATE_RECALCULATE) {
 		num_options++;
@@ -2334,6 +2342,8 @@ static int _dm_target_query_integrity(st
 				}
 			} else if (!strcmp(arg, "recalculate")) {
 				*act_flags |= CRYPT_ACTIVATE_RECALCULATE;
+			} else if (!strcmp(arg, "fix_padding")) {
+				tgt->u.integrity.fix_padding = true;
 			} else /* unknown option */
 				goto err;
 		}
@@ -2865,16 +2875,21 @@ int dm_verity_target_set(struct dm_targe
 	return 0;
 }
 
-int dm_integrity_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
+int dm_integrity_target_set(struct crypt_device *cd,
+			struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
 			struct device *meta_device,
 		        struct device *data_device, uint64_t tag_size, uint64_t offset,
 			uint32_t sector_size, struct volume_key *vk,
 			struct volume_key *journal_crypt_key, struct volume_key *journal_mac_key,
 			const struct crypt_params_integrity *ip)
 {
+	uint32_t dmi_flags;
+
 	if (!data_device)
 		return -EINVAL;
 
+	_dm_check_versions(cd, DM_INTEGRITY);
+
 	tgt->type = DM_INTEGRITY;
 	tgt->direction = TARGET_SET;
 	tgt->offset = seg_offset;
@@ -2890,6 +2905,9 @@ int dm_integrity_target_set(struct dm_ta
 	tgt->u.integrity.journal_crypt_key = journal_crypt_key;
 	tgt->u.integrity.journal_integrity_key = journal_mac_key;
 
+	if (!dm_flags(cd, DM_INTEGRITY, &dmi_flags) && dmi_flags & DM_INTEGRITY_FIX_PADDING_SUPPORTED)
+		tgt->u.integrity.fix_padding = true;
+
 	if (ip) {
 		tgt->u.integrity.journal_size = ip->journal_size;
 		tgt->u.integrity.journal_watermark = ip->journal_watermark;
Index: cryptsetup/lib/utils_dm.h
===================================================================
--- cryptsetup.orig/lib/utils_dm.h	2019-11-12 20:09:30.000000000 +0100
+++ cryptsetup/lib/utils_dm.h	2019-11-12 21:09:25.000000000 +0100
@@ -64,6 +64,7 @@ static inline uint32_t act2dmflags(uint3
 #define DM_INTEGRITY_RECALC_SUPPORTED (1 << 16) /* dm-integrity automatic recalculation supported */
 #define DM_INTEGRITY_BITMAP_SUPPORTED (1 << 17) /* dm-integrity bitmap mode supported */
 #define DM_GET_TARGET_VERSION_SUPPORTED (1 << 18) /* dm DM_GET_TARGET version ioctl supported */
+#define DM_INTEGRITY_FIX_PADDING_SUPPORTED (1 << 19) /* supports the parameter fix_padding that fixes a bug that caused excessive padding */
 
 typedef enum { DM_CRYPT = 0, DM_VERITY, DM_INTEGRITY, DM_LINEAR, DM_ERROR, DM_UNKNOWN } dm_target_type;
 enum tdirection { TARGET_SET = 1, TARGET_QUERY };
@@ -138,6 +139,8 @@ struct dm_target {
 		struct volume_key *journal_crypt_key;
 
 		struct device *meta_device;
+
+		bool fix_padding;
 	} integrity;
 	struct {
 		uint64_t offset;
@@ -177,7 +180,8 @@ int dm_verity_target_set(struct dm_targe
 	struct device *data_device, struct device *hash_device, struct device *fec_device,
 	const char *root_hash, uint32_t root_hash_size, uint64_t hash_offset_block,
 	uint64_t hash_blocks, struct crypt_params_verity *vp);
-int dm_integrity_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
+int dm_integrity_target_set(struct crypt_device *cd,
+	struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
 	struct device *meta_device,
 	struct device *data_device, uint64_t tag_size, uint64_t offset, uint32_t sector_size,
 	struct volume_key *vk,
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.