[dm-devel] [PATCH v2 2/2] dm: verity support data device offset (Linux 3.4.7)

Wesley Miaw wmiaw at netflix.com
Thu Aug 9 00:40:23 UTC 2012


On Aug 8, 2012, at 1:56 PM, Milan Broz wrote:

> On 08/08/2012 10:46 PM, Wesley Miaw wrote:
> 
>> I did modify veritysetup on my own so the format and verify commands will work with regular files on disk instead of having to mount through loop devices.
> 
> Which veritysetup? In upstream (cryptsetup repository) it allocates loop automatically.
> (And for userspace verification it doesn't need loop at all.)
> 
> Anyway, please send a patch for userspace as well then ;-)

This isn't as polished because I pretty much just added support to do what I needed. I'm not sure if the LKML is the right place to post, so let me know if I should send this somewhere else.

Your previous email implied that veritysetup would need a way to determine if the data offset option is supported; I did not modify veritysetup to support this idea as I didn't need it.

Thanks.

From: Wesley Miaw <wmiaw at netflix.com>

Allow veritysetup format and verify commands to directly operate on regular
files instead of requiring mounts through loop devices.

Signed-off-by: Wesley Miaw <wmiaw at netflix.com>
---
 cryptsetup/lib/internal.h        |    1 
 cryptsetup/lib/libcryptsetup.h   |   22 ++++
 cryptsetup/lib/libcryptsetup.sym |    2 
 cryptsetup/lib/setup.c           |  133 ++++++++++++++++++++++++++++-
 cryptsetup/lib/utils.c           |   12 ++
 cryptsetup/src/veritysetup.c     |   23 +++--
 6 files changed, 183 insertions(+), 10 deletions(-)
--- a/cryptsetup/lib/internal.h	2012-08-08 17:11:20.366392301 -0700
+++ b/cryptsetup/lib/internal.h	2012-08-06 16:17:35.154719491 -0700
@@ -76,6 +76,7 @@ ssize_t read_blockwise(int fd, void *_bu
 ssize_t write_lseek_blockwise(int fd, char *buf, size_t count, off_t offset);
 int device_ready(struct crypt_device *cd, const char *device, int mode);
 int device_size(const char *device, uint64_t *size);
+int file_size(const char *filename, uint64_t *size);
 
 unsigned crypt_getpagesize(void);
 
--- a/cryptsetup/lib/libcryptsetup.h	2012-08-08 17:11:20.375392929 -0700
+++ b/cryptsetup/lib/libcryptsetup.h	2012-08-06 16:17:35.159720699 -0700
@@ -56,6 +57,19 @@ struct crypt_device; /* crypt device han
 int crypt_init(struct crypt_device **cd, const char *device);
 
 /**
+ * Initial crypt device handle from a file and check if provided file exists.
+ *
+ * @param cd Returns pointer to crypt device handle.
+ * @param filename Path to the backing file.
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ *
+ * @note Note that logging is not initialized here, possible messages uses
+ *       default log function.
+ */
+int crypt_initfile(struct crypt_device **cd, const char *filename);
+
+/**
  * Initialize crypt device handle from provided active device name,
  * and, optionally, from separate metadata (header) device
  * and check if provided device exists.
@@ -237,6 +251,15 @@ void crypt_set_password_verify(struct cr
 int crypt_set_data_device(struct crypt_device *cd, const char *device);
 
 /**
+ * Set data file
+ * For VERITY it is data file when hash device is separated.
+ *
+ * @param cd crypt device handle
+ * @param filename path to data file
+ */
+int crypt_set_data_file(struct crypt_device *cd, const char *device);
+
+/**
  * @defgroup rng "Cryptsetup RNG"
  *
  * @addtogroup rng
--- a/cryptsetup/lib/libcryptsetup.sym	2012-08-08 17:11:20.375392930 -0700
+++ b/cryptsetup/lib/libcryptsetup.sym	2012-08-06 16:17:35.160720941 -0700
@@ -1,6 +1,7 @@
 CRYPTSETUP_1.0 {
 	global:
 		crypt_init;
+		crypt_initfile;
 		crypt_init_by_name;
 		crypt_init_by_name_and_header;
 		crypt_set_log_callback;
@@ -13,6 +14,7 @@ CRYPTSETUP_1.0 {
 		crypt_set_password_verify;
 		crypt_set_uuid;
 		crypt_set_data_device;
+		crypt_set_data_file;
 
 		crypt_memory_lock;
 		crypt_format;
--- a/cryptsetup/lib/setup.c	2012-08-08 17:11:20.428396640 -0700
+++ b/cryptsetup/lib/setup.c	2012-08-06 16:17:35.192728669 -0700
@@ -25,6 +25,8 @@
 #include <stdarg.h>
 #include <fcntl.h>
 #include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 #include "libcryptsetup.h"
 #include "luks.h"
@@ -585,6 +587,56 @@ bad:
 	return r;
 }
 
+int crypt_initfile(struct crypt_device **cd, const char *filename)
+{
+	struct crypt_device *h = NULL;
+	int fd;
+	struct stat st;
+	int r;
+
+	if (!cd)
+		return -EINVAL;
+
+	if (stat(filename, &st) < 0) {
+		log_err(NULL, _("File %s doesn't exist or access denied.\n"), filename);
+		return -EINVAL;
+	}
+
+	log_dbg("Trying to open and write file %s.", filename);
+	fd = open(filename, O_RDWR);
+	if (fd < 0) {
+		log_err(NULL, _("Cannot open file %s for writeable access.\n"), filename);
+		return -EINVAL;
+	}
+	close(fd);
+
+	log_dbg("Allocating crypt device %s context.", filename);
+
+	if (!(h = malloc(sizeof(struct crypt_device))))
+		return -ENOMEM;
+
+	memset(h, 0, sizeof(*h));
+	h->loop_device_fd = -1;
+	h->loop_metadata_device_fd = -1;
+	h->device = strdup(filename);
+	if (!h->device) {
+		r = -ENOMEM;
+		goto bad;
+	}
+	h->iteration_time = 1000;
+	h->password_verify = 0;
+	h->tries = 3;
+	h->rng_type = crypt_random_default_key_rng();
+	*cd = h;
+	return 0;
+bad:
+	if (h) {
+		free(h->device);
+	}
+	free(h);
+	return r;
+}
+
 static int crypt_check_data_device_size(struct crypt_device *cd)
 {
 	int r;
@@ -606,6 +658,27 @@ static int crypt_check_data_device_size(
 	return r;
 }
 
+static int crypt_check_data_file_size(struct crypt_device *cd)
+{
+	int r;
+	uint64_t size, size_min;
+
+	/* Check data device size, require at least one sector */
+	size_min = crypt_get_data_offset(cd) << SECTOR_SHIFT ?: SECTOR_SIZE;
+
+	r = file_size(crypt_get_device_name(cd), &size);
+	if (r < 0)
+		return r;
+
+	if (size < size_min) {
+		log_err(cd, _("Header detected but device %s is too small.\n"),
+			crypt_get_device_name(cd));
+		return -EINVAL;
+	}
+
+	return r;
+}
+
 int crypt_set_data_device(struct crypt_device *cd, const char *device)
 {
 	char *data_device = NULL;
@@ -641,6 +714,52 @@ int crypt_set_data_device(struct crypt_d
 	return crypt_check_data_device_size(cd);
 }
 
+int crypt_set_data_file(struct crypt_device *cd, const char *filename)
+{
+	int fd;
+	struct stat st;
+
+	log_dbg("Setting ciphertext data file to %s.", filename ?: "(none");
+
+	if (!isVERITY(cd->type)) {
+		log_err(cd, _("This operation is not supported for this device type.\n"));
+		return  -EINVAL;
+	}
+
+	/* metadata device must be set */
+	if (!cd->device || !filename)
+		return -EINVAL;
+
+	if (stat(filename, &st) < 0) {
+		log_err(NULL, _("File %s doesn't exist or access denied.\n"), filename);
+		return -EINVAL;
+	}
+
+	log_dbg("Trying to open and read file %s.", filename);
+	fd = open(filename, O_RDONLY);
+	if (fd < 0) {
+		log_err(NULL, _("Cannot open file %s for read access.\n"), filename);
+		return -EINVAL;
+	}
+	close(fd);
+
+	if (!cd->metadata_device) {
+		cd->metadata_device = cd->device;
+		cd->loop_metadata_device_fd = cd->loop_device_fd;
+	} else {
+		free(cd->device);
+		if (cd->loop_device_fd != -1)
+			close(cd->loop_device_fd);
+	}
+
+	cd->device = strdup(filename);
+	if (!cd->device)
+		return -ENOMEM;
+	cd->loop_device_fd = -1;
+
+	return crypt_check_data_file_size(cd);
+}
+
 static int _crypt_load_luks1(struct crypt_device *cd, int require_header, int repair)
 {
 	struct luks_phdr hdr;
@@ -1080,12 +1199,18 @@ static int _crypt_format_verity(struct c
 		return -ENOMEM;
 
 	r = crypt_set_data_device(cd, params->data_device);
-	if (r)
-		return r;
+	if (r) {
+		r = crypt_set_data_file(cd, params->data_device);
+		if (r)
+			return r;
+	}
 	if (!params->data_size) {
 		r = device_size(cd->device, &data_device_size);
-		if (r < 0)
-			return r;
+		if (r < 0) {
+			r = file_size(cd->device, &data_device_size);
+			if (r < 0)
+				return r;
+		}
 
 		cd->verity_hdr.data_size = data_device_size / params->data_block_size;
 	} else
--- a/cryptsetup/lib/utils.c	2012-08-08 17:11:20.433396990 -0700
+++ b/cryptsetup/lib/utils.c	2012-08-06 16:17:35.202731084 -0700
@@ -316,6 +316,18 @@ int device_size(const char *device, uint
 	return r;
 }
 
+int file_size(const char *filename, uint64_t *size)
+{
+	struct stat st;
+
+	if (stat(filename, &st) < 0)
+		return -EINVAL;
+
+	*size = (uint64_t)st.st_size;
+
+	return 0;
+}
+
 static int get_device_infos(const char *device, enum devcheck device_check,
 			    int *readonly, uint64_t *size)
 {
--- a/cryptsetup/src/veritysetup.c	2012-08-08 17:11:20.942432624 -0700
+++ b/cryptsetup/src/veritysetup.c	2012-08-06 16:17:35.235739053 -0700
@@ -142,8 +142,12 @@ static int action_format(int arg)
 	uint32_t flags = CRYPT_VERITY_CREATE_HASH;
 	int r;
 
-	if ((r = crypt_init(&cd, action_argv[1])))
-		goto out;
+	r = crypt_init(&cd, action_argv[1]);
+	if (r < 0) {
+		r = crypt_initfile(&cd, action_argv[1]);
+		if (r < 0)
+			goto out;
+	}
 
 	if (!use_superblock)
 		flags |= CRYPT_VERITY_NO_HEADER;
@@ -174,8 +178,12 @@ static int _activate(const char *dm_devi
 	ssize_t hash_size;
 	int r;
 
-	if ((r = crypt_init(&cd, hash_device)))
-		goto out;
+	r = crypt_init(&cd, hash_device);
+	if (r < 0) {
+		r = crypt_initfile(&cd, hash_device);
+		if (r < 0)
+			goto out;
+	}
 
 	if (use_superblock) {
 		params.flags = flags;
@@ -190,8 +198,11 @@ static int _activate(const char *dm_devi
 	if (r < 0)
 		goto out;
 	r = crypt_set_data_device(cd, data_device);
-	if (r < 0)
-		goto out;
+	if (r < 0) {
+		r = crypt_set_data_file(cd, data_device);
+		if (r < 0)
+			goto out;
+	}
 
 	hash_size = crypt_get_volume_key_size(cd);
 	if (crypt_hex_to_bytes(root_hash, &root_hash_bytes, 0) != hash_size) {

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 495 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <http://listman.redhat.com/archives/dm-devel/attachments/20120809/335a11d2/attachment.sig>


More information about the dm-devel mailing list