/*
 * Copyright (C) 2015 Google, Inc.
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#include <linux/buffer_head.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/device-mapper.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/fcntl.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/key.h>
#include <linux/module.h>
#include <linux/mount.h>
#include <linux/namei.h>
#include <linux/of.h>
#include <linux/reboot.h>
#include <linux/string.h>
#include <linux/vmalloc.h>

#include <asm/setup.h>
#include <crypto/hash.h>
#include <crypto/public_key.h>
#include <crypto/sha.h>
#include <keys/asymmetric-type.h>
#include <keys/system_keyring.h>

#include "dm-verity.h"
#include "dm-android-verity.h"

static char verifiedbootstate[VERITY_COMMANDLINE_PARAM_LENGTH];
static char veritymode[VERITY_COMMANDLINE_PARAM_LENGTH];
static char veritykeyid[VERITY_DEFAULT_KEY_ID_LENGTH];
static char buildvariant[BUILD_VARIANT];

static bool target_added;
static bool verity_enabled = true;
struct dentry *debug_dir;
static int android_verity_ctr(struct dm_target *ti, unsigned argc, char **argv);

static struct target_type android_verity_target = {
	.name                   = "android-verity",
	.version                = {1, 0, 0},
	.module                 = THIS_MODULE,
	.ctr                    = android_verity_ctr,
	.dtr                    = verity_dtr,
	.map                    = verity_map,
	.status                 = verity_status,
	.prepare_ioctl          = verity_prepare_ioctl,
	.iterate_devices        = verity_iterate_devices,
	.io_hints               = verity_io_hints,
};

static int __init verified_boot_state_param(char *line)
{
	strlcpy(verifiedbootstate, line, sizeof(verifiedbootstate));
	return 1;
}

__setup("androidboot.verifiedbootstate=", verified_boot_state_param);

static int __init verity_mode_param(char *line)
{
	strlcpy(veritymode, line, sizeof(veritymode));
	return 1;
}

__setup("androidboot.veritymode=", verity_mode_param);

static int __init verity_keyid_param(char *line)
{
	strlcpy(veritykeyid, line, sizeof(veritykeyid));
	return 1;
}

__setup("veritykeyid=", verity_keyid_param);

static int __init verity_buildvariant(char *line)
{
	strlcpy(buildvariant, line, sizeof(buildvariant));
	return 1;
}

__setup("buildvariant=", verity_buildvariant);

static inline bool default_verity_key_id(void)
{
	return veritykeyid[0] != '\0';
}

static inline bool is_eng(void)
{
	static const char typeeng[]  = "eng";

	return !strncmp(buildvariant, typeeng, sizeof(typeeng));
}

static inline bool is_userdebug(void)
{
	static const char typeuserdebug[]  = "userdebug";

	return !strncmp(buildvariant, typeuserdebug, sizeof(typeuserdebug));
}

static inline bool is_unlocked(void)
{
	static const char unlocked[] = "orange";

	return !strncmp(verifiedbootstate, unlocked, sizeof(unlocked));
}

static int table_extract_mpi_array(struct public_key_signature *pks,
				const void *data, size_t len)
{
	MPI mpi = mpi_read_raw_data(data, len);

	if (!mpi) {
		DMERR("Error while allocating mpi array");
		return -ENOMEM;
	}

	pks->mpi[0] = mpi;
	pks->nr_mpi = 1;
	return 0;
}

static struct public_key_signature *table_make_digest(
						enum hash_algo hash,
						const void *table,
						unsigned long table_len)
{
	struct public_key_signature *pks = NULL;
	struct crypto_shash *tfm;
	struct shash_desc *desc;
	size_t digest_size, desc_size;
	int ret;

	/* Allocate the hashing algorithm we're going to need and find out how
	 * big the hash operational data will be.
	 */
	tfm = crypto_alloc_shash(hash_algo_name[hash], 0, 0);
	if (IS_ERR(tfm))
		return ERR_CAST(tfm);

	desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
	digest_size = crypto_shash_digestsize(tfm);

	/* We allocate the hash operational data storage on the end of out
	 * context data and the digest output buffer on the end of that.
	 */
	ret = -ENOMEM;
	pks = kzalloc(digest_size + sizeof(*pks) + desc_size, GFP_KERNEL);
	if (!pks)
		goto error;

	pks->pkey_hash_algo = hash;
	pks->digest = (u8 *)pks + sizeof(*pks) + desc_size;
	pks->digest_size = digest_size;

	desc = (struct shash_desc *)(pks + 1);
	desc->tfm = tfm;
	desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;

	ret = crypto_shash_init(desc);
	if (ret < 0)
		goto error;

	ret = crypto_shash_finup(desc, table, table_len, pks->digest);
	if (ret < 0)
		goto error;

	crypto_free_shash(tfm);
	return pks;

error:
	kfree(pks);
	crypto_free_shash(tfm);
	return ERR_PTR(ret);
}

static int read_block_dev(struct bio_read *payload, struct block_device *bdev,
		sector_t offset, int length)
{
	struct bio *bio;
	int err = 0, i;

	payload->number_of_pages = DIV_ROUND_UP(length, PAGE_SIZE);

	bio = bio_alloc(GFP_KERNEL, payload->number_of_pages);
	if (!bio) {
		DMERR("Error while allocating bio");
		return -ENOMEM;
	}

	bio->bi_bdev = bdev;
	bio->bi_iter.bi_sector = offset;

	payload->page_io = kzalloc(sizeof(struct page *) *
		payload->number_of_pages, GFP_KERNEL);
	if (!payload->page_io) {
		DMERR("page_io array alloc failed");
		err = -ENOMEM;
		goto free_bio;
	}

	for (i = 0; i < payload->number_of_pages; i++) {
		payload->page_io[i] = alloc_page(GFP_KERNEL);
		if (!payload->page_io[i]) {
			DMERR("alloc_page failed");
			err = -ENOMEM;
			goto free_pages;
		}
		if (!bio_add_page(bio, payload->page_io[i], PAGE_SIZE, 0)) {
			DMERR("bio_add_page error");
			err = -EIO;
			goto free_pages;
		}
	}

	if (!submit_bio_wait(READ, bio))
		/* success */
		goto free_bio;
	DMERR("bio read failed");
	err = -EIO;

free_pages:
	for (i = 0; i < payload->number_of_pages; i++)
		if (payload->page_io[i])
			__free_page(payload->page_io[i]);
	kfree(payload->page_io);
free_bio:
	bio_put(bio);
	return err;
}

static inline u64 fec_div_round_up(u64 x, u64 y)
{
	u64 remainder;

	return div64_u64_rem(x, y, &remainder) +
		(remainder > 0 ? 1 : 0);
}

static inline void populate_fec_metadata(struct fec_header *header,
				struct fec_ecc_metadata *ecc)
{
	ecc->blocks = fec_div_round_up(le64_to_cpu(header->inp_size),
			FEC_BLOCK_SIZE);
	ecc->roots = le32_to_cpu(header->roots);
	ecc->start = le64_to_cpu(header->inp_size);
}

static inline int validate_fec_header(struct fec_header *header, u64 offset)
{
	/* move offset to make the sanity check work for backup header
	 * as well. */
	offset -= offset % FEC_BLOCK_SIZE;
	if (le32_to_cpu(header->magic) != FEC_MAGIC ||
		le32_to_cpu(header->version) != FEC_VERSION ||
		le32_to_cpu(header->size) != sizeof(struct fec_header) ||
		le32_to_cpu(header->roots) == 0 ||
		le32_to_cpu(header->roots) >= FEC_RSM)
		return -EINVAL;

	return 0;
}

static int extract_fec_header(dev_t dev, struct fec_header *fec,
				struct fec_ecc_metadata *ecc)
{
	u64 device_size;
	struct bio_read payload;
	int i, err = 0;
	struct block_device *bdev;

	bdev = blkdev_get_by_dev(dev, FMODE_READ, NULL);

	if (IS_ERR_OR_NULL(bdev)) {
		DMERR("bdev get error");
		return PTR_ERR(bdev);
	}

	device_size = i_size_read(bdev->bd_inode);

	/* fec metadata size is a power of 2 and PAGE_SIZE
	 * is a power of 2 as well.
	 */
	BUG_ON(FEC_BLOCK_SIZE > PAGE_SIZE);
	/* 512 byte sector alignment */
	BUG_ON(((device_size - FEC_BLOCK_SIZE) % (1 << SECTOR_SHIFT)) != 0);

	err = read_block_dev(&payload, bdev, (device_size -
		FEC_BLOCK_SIZE) / (1 << SECTOR_SHIFT), FEC_BLOCK_SIZE);
	if (err) {
		DMERR("Error while reading verity metadata");
		goto error;
	}

	BUG_ON(sizeof(struct fec_header) > PAGE_SIZE);
	memcpy(fec, page_address(payload.page_io[0]),
			sizeof(*fec));

	ecc->valid = true;
	if (validate_fec_header(fec, device_size - FEC_BLOCK_SIZE)) {
		/* Try the backup header */
		memcpy(fec, page_address(payload.page_io[0]) + FEC_BLOCK_SIZE
			- sizeof(*fec) ,
			sizeof(*fec));
		if (validate_fec_header(fec, device_size -
			sizeof(struct fec_header)))
			ecc->valid = false;
	}

	if (ecc->valid)
		populate_fec_metadata(fec, ecc);

	for (i = 0; i < payload.number_of_pages; i++)
		__free_page(payload.page_io[i]);
	kfree(payload.page_io);

error:
	blkdev_put(bdev, FMODE_READ);
	return err;
}
static void find_metadata_offset(struct fec_header *fec,
		struct block_device *bdev, u64 *metadata_offset)
{
	u64 device_size;

	device_size = i_size_read(bdev->bd_inode);

	if (le32_to_cpu(fec->magic) == FEC_MAGIC)
		*metadata_offset = le64_to_cpu(fec->inp_size) -
					VERITY_METADATA_SIZE;
	else
		*metadata_offset = device_size - VERITY_METADATA_SIZE;
}

static int find_size(dev_t dev, u64 *device_size)
{
	struct block_device *bdev;

	bdev = blkdev_get_by_dev(dev, FMODE_READ, NULL);
	if (IS_ERR_OR_NULL(bdev)) {
		DMERR("blkdev_get_by_dev failed");
		return PTR_ERR(bdev);
	}

	*device_size = i_size_read(bdev->bd_inode);
	*device_size >>= SECTOR_SHIFT;

	DMINFO("blkdev size in sectors: %llu", *device_size);
	blkdev_put(bdev, FMODE_READ);
	return 0;
}

static int verify_header(struct android_metadata_header *header)
{
	int retval = -EINVAL;

	if (is_userdebug() && le32_to_cpu(header->magic_number) ==
			VERITY_METADATA_MAGIC_DISABLE)
		return VERITY_STATE_DISABLE;

	if (!(le32_to_cpu(header->magic_number) ==
			VERITY_METADATA_MAGIC_NUMBER) ||
			(le32_to_cpu(header->magic_number) ==
			VERITY_METADATA_MAGIC_DISABLE)) {
		DMERR("Incorrect magic number");
		return retval;
	}

	if (le32_to_cpu(header->protocol_version) !=
			VERITY_METADATA_VERSION) {
		DMERR("Unsupported version %u",
			le32_to_cpu(header->protocol_version));
		return retval;
	}

	return 0;
}

static int extract_metadata(dev_t dev, struct fec_header *fec,
				struct android_metadata **metadata,
				bool *verity_enabled)
{
	struct block_device *bdev;
	struct android_metadata_header *header;
	int i;
	u32 table_length, copy_length, offset;
	u64 metadata_offset;
	struct bio_read payload;
	int err = 0;

	bdev = blkdev_get_by_dev(dev, FMODE_READ, NULL);

	if (IS_ERR_OR_NULL(bdev)) {
		DMERR("blkdev_get_by_dev failed");
		return -ENODEV;
	}

	find_metadata_offset(fec, bdev, &metadata_offset);

	/* Verity metadata size is a power of 2 and PAGE_SIZE
	 * is a power of 2 as well.
	 * PAGE_SIZE is also a multiple of 512 bytes.
	*/
	if (VERITY_METADATA_SIZE > PAGE_SIZE)
		BUG_ON(VERITY_METADATA_SIZE % PAGE_SIZE != 0);
	/* 512 byte sector alignment */
	BUG_ON(metadata_offset % (1 << SECTOR_SHIFT) != 0);

	err = read_block_dev(&payload, bdev, metadata_offset /
		(1 << SECTOR_SHIFT), VERITY_METADATA_SIZE);
	if (err) {
		DMERR("Error while reading verity metadata");
		goto blkdev_release;
	}

	header = kzalloc(sizeof(*header), GFP_KERNEL);
	if (!header) {
		DMERR("kzalloc failed for header");
		err = -ENOMEM;
		goto free_payload;
	}

	memcpy(header, page_address(payload.page_io[0]),
		sizeof(*header));

	DMINFO("bio magic_number:%u protocol_version:%d table_length:%u",
		le32_to_cpu(header->magic_number),
		le32_to_cpu(header->protocol_version),
		le32_to_cpu(header->table_length));

	err = verify_header(header);

	if (err == VERITY_STATE_DISABLE) {
		DMERR("Mounting root with verity disabled");
		*verity_enabled = false;
		/* we would still have to read the metadata to figure out
		 * the data blocks size. Or may be could map the entire
		 * partition similar to mounting the device.
		 *
		 * Reset error as well as the verity_enabled flag is changed.
		 */
		err = 0;
	} else if (err)
		goto free_header;

	*metadata = kzalloc(sizeof(**metadata), GFP_KERNEL);
	if (!*metadata) {
		DMERR("kzalloc for metadata failed");
		err = -ENOMEM;
		goto free_header;
	}

	(*metadata)->header = header;
	table_length = le32_to_cpu(header->table_length);

	if (table_length == 0 ||
		table_length > (VERITY_METADATA_SIZE -
			sizeof(struct android_metadata_header))) {
		DMERR("table_length too long");
		err = -EINVAL;
		goto free_metadata;
	}

	(*metadata)->verity_table = kzalloc(table_length + 1, GFP_KERNEL);

	if (!(*metadata)->verity_table) {
		DMERR("kzalloc verity_table failed");
		err = -ENOMEM;
		goto free_metadata;
	}

	if (sizeof(struct android_metadata_header) +
			table_length <= PAGE_SIZE) {
		memcpy((*metadata)->verity_table,
			page_address(payload.page_io[0])
			+ sizeof(struct android_metadata_header),
			table_length);
	} else {
		copy_length = PAGE_SIZE -
			sizeof(struct android_metadata_header);
		memcpy((*metadata)->verity_table,
			page_address(payload.page_io[0])
			+ sizeof(struct android_metadata_header),
			copy_length);
		table_length -= copy_length;
		offset = copy_length;
		i = 1;
		while (table_length != 0) {
			if (table_length > PAGE_SIZE) {
				memcpy((*metadata)->verity_table + offset,
					page_address(payload.page_io[i]),
					PAGE_SIZE);
				offset += PAGE_SIZE;
				table_length -= PAGE_SIZE;
			} else {
				memcpy((*metadata)->verity_table + offset,
					page_address(payload.page_io[i]),
					table_length);
				table_length = 0;
			}
			i++;
		}
	}
	(*metadata)->verity_table[table_length] = '\0';

	DMINFO("verity_table: %s", (*metadata)->verity_table);
	goto free_payload;

free_metadata:
	kfree(*metadata);
free_header:
	kfree(header);
free_payload:
	for (i = 0; i < payload.number_of_pages; i++)
		if (payload.page_io[i])
			__free_page(payload.page_io[i]);
	kfree(payload.page_io);
blkdev_release:
	blkdev_put(bdev, FMODE_READ);
	return err;
}

/* helper functions to extract properties from dts */
const char *find_dt_value(const char *name)
{
	struct device_node *firmware;
	const char *value;

	firmware = of_find_node_by_path("/firmware/android");
	if (!firmware)
		return NULL;
	value = of_get_property(firmware, name, NULL);
	of_node_put(firmware);

	return value;
}

static int verity_mode(void)
{
	static const char enforcing[] = "enforcing";
	static const char verified_mode_prop[] = "veritymode";
	const char *value;

	value = find_dt_value(verified_mode_prop);
	if (!value)
		value = veritymode;
	if (!strncmp(value, enforcing, sizeof(enforcing) - 1))
		return DM_VERITY_MODE_RESTART;

	return DM_VERITY_MODE_EIO;
}

static int verify_verity_signature(char *key_id,
		struct android_metadata *metadata)
{
	key_ref_t key_ref;
	struct key *key;
	struct public_key_signature *pks = NULL;
	int retval = -EINVAL;

	key_ref = keyring_search(make_key_ref(system_trusted_keyring, 1),
		&key_type_asymmetric, key_id);

	if (IS_ERR(key_ref)) {
		DMERR("keyring: key not found");
		return -ENOKEY;
	}

	key = key_ref_to_ptr(key_ref);

	pks = table_make_digest(HASH_ALGO_SHA256,
			(const void *)metadata->verity_table,
			le32_to_cpu(metadata->header->table_length));

	if (IS_ERR(pks)) {
		DMERR("hashing failed");
		retval = PTR_ERR(pks);
		pks = NULL;
		goto error;
	}

	retval = table_extract_mpi_array(pks, &metadata->header->signature[0],
				RSANUMBYTES);
	if (retval < 0) {
		DMERR("Error extracting mpi %d", retval);
		goto error;
	}

	retval = verify_signature(key, pks);
	mpi_free(pks->rsa.s);
error:
	kfree(pks);
	key_put(key);

	return retval;
}

static void handle_error(void)
{
	int mode = verity_mode();
	if (mode == DM_VERITY_MODE_RESTART) {
		DMERR("triggering restart");
		kernel_restart("dm-verity device corrupted");
	} else {
		DMERR("Mounting verity root failed");
	}
}

static inline bool test_mult_overflow(sector_t a, u32 b)
{
	sector_t r = (sector_t)~0ULL;

	sector_div(r, b);
	return a > r;
}

static int add_as_linear_device(struct dm_target *ti, char *dev)
{
	/*Move to linear mapping defines*/
	char *linear_table_args[DM_LINEAR_ARGS] = {dev,
					DM_LINEAR_TARGET_OFFSET};
	int err = 0;

	android_verity_target.dtr = dm_linear_dtr,
	android_verity_target.map = dm_linear_map,
	android_verity_target.status = dm_linear_status,
	android_verity_target.prepare_ioctl = dm_linear_prepare_ioctl,
	android_verity_target.iterate_devices = dm_linear_iterate_devices,
	android_verity_target.io_hints = NULL;

	set_disk_ro(dm_disk(dm_table_get_md(ti->table)), 0);

	err = dm_linear_ctr(ti, DM_LINEAR_ARGS, linear_table_args);

	if (!err) {
		DMINFO("Added android-verity as a linear target");
		target_added = true;
	} else
		DMERR("Failed to add android-verity as linear target");

	return err;
}

static int create_linear_device(struct dm_target *ti, dev_t dev,
				char *target_device)
{
	u64 device_size = 0;
	int err = find_size(dev, &device_size);

	if (err) {
		DMERR("error finding bdev size");
		handle_error();
		return err;
	}

	ti->len = device_size;
	err = add_as_linear_device(ti, target_device);
	if (err) {
		handle_error();
		return err;
	}
	verity_enabled = false;
	return 0;
}

/*
 * Target parameters:
 *	<key id>	Key id of the public key in the system keyring.
 *			Verity metadata's signature would be verified against
 *			this. If the key id contains spaces, replace them
 *			with '#'.
 *	<block device>	The block device for which dm-verity is being setup.
 */
static int android_verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
{
	dev_t uninitialized_var(dev);
	struct android_metadata *metadata = NULL;
	int err = 0, i, mode;
	char *key_id, *table_ptr, dummy, *target_device,
	*verity_table_args[VERITY_TABLE_ARGS + 2 + VERITY_TABLE_OPT_FEC_ARGS];
	/* One for specifying number of opt args and one for mode */
	sector_t data_sectors;
	u32 data_block_size;
	unsigned int no_of_args = VERITY_TABLE_ARGS + 2 + VERITY_TABLE_OPT_FEC_ARGS;
	struct fec_header uninitialized_var(fec);
	struct fec_ecc_metadata uninitialized_var(ecc);
	char buf[FEC_ARG_LENGTH], *buf_ptr;
	unsigned long long tmpll;

	if (argc == 1) {
		/* Use the default keyid */
		if (default_verity_key_id())
			key_id = veritykeyid;
		else if (!is_eng()) {
			DMERR("veritykeyid= is not set");
			handle_error();
			return -EINVAL;
		}
	} else if (argc == 2)
		key_id = argv[1];
	else {
		DMERR("Incorrect number of arguments");
		handle_error();
		return -EINVAL;
	}

	target_device = argv[0];

	dev = name_to_dev_t(target_device);
	if (!dev) {
		DMERR("no dev found for %s", target_device);
		handle_error();
		return -EINVAL;
	}

	if (is_eng())
		return create_linear_device(ti, dev, target_device);

	strreplace(key_id, '#', ' ');

	DMINFO("key:%s dev:%s", key_id, target_device);

	if (extract_fec_header(dev, &fec, &ecc)) {
		DMERR("Error while extracting fec header");
		handle_error();
		return -EINVAL;
	}

	err = extract_metadata(dev, &fec, &metadata, &verity_enabled);

	if (err) {
		/* Allow invalid metadata when the device is unlocked */
		if (is_unlocked()) {
			DMWARN("Allow invalid metadata when unlocked");
			return create_linear_device(ti, dev, target_device);
		}
		DMERR("Error while extracting metadata");
		handle_error();
		goto free_metadata;
	}

	if (verity_enabled) {
		err = verify_verity_signature(key_id, metadata);

		if (err) {
			DMERR("Signature verification failed");
			handle_error();
			goto free_metadata;
		} else
			DMINFO("Signature verification success");
	}

	table_ptr = metadata->verity_table;

	for (i = 0; i < VERITY_TABLE_ARGS; i++) {
		verity_table_args[i] = strsep(&table_ptr, " ");
		if (verity_table_args[i] == NULL)
			break;
	}

	if (i != VERITY_TABLE_ARGS) {
		DMERR("Verity table not in the expected format");
		err = -EINVAL;
		handle_error();
		goto free_metadata;
	}

	if (sscanf(verity_table_args[5], "%llu%c", &tmpll, &dummy)
							!= 1) {
		DMERR("Verity table not in the expected format");
		handle_error();
		err = -EINVAL;
		goto free_metadata;
	}

	if (tmpll > ULONG_MAX) {
		DMERR("<num_data_blocks> too large. Forgot to turn on CONFIG_LBDAF?");
		handle_error();
		err = -EINVAL;
		goto free_metadata;
	}

	data_sectors = tmpll;

	if (sscanf(verity_table_args[3], "%u%c", &data_block_size, &dummy)
								!= 1) {
		DMERR("Verity table not in the expected format");
		handle_error();
		err = -EINVAL;
		goto free_metadata;
	}

	if (test_mult_overflow(data_sectors, data_block_size >>
							SECTOR_SHIFT)) {
		DMERR("data_sectors too large");
		handle_error();
		err = -EOVERFLOW;
		goto free_metadata;
	}

	data_sectors *= data_block_size >> SECTOR_SHIFT;
	DMINFO("Data sectors %llu", (unsigned long long)data_sectors);

	/* update target length */
	ti->len = data_sectors;

	/* Setup linear target and free */
	if (!verity_enabled) {
		err = add_as_linear_device(ti, target_device);
		goto free_metadata;
	}

	/*substitute data_dev and hash_dev*/
	verity_table_args[1] = target_device;
	verity_table_args[2] = target_device;

	mode = verity_mode();

	if (ecc.valid && IS_BUILTIN(CONFIG_DM_VERITY_FEC)) {
		if (mode) {
			err = snprintf(buf, FEC_ARG_LENGTH,
				"%u %s " VERITY_TABLE_OPT_FEC_FORMAT,
				1 + VERITY_TABLE_OPT_FEC_ARGS,
				mode == DM_VERITY_MODE_RESTART ?
					VERITY_TABLE_OPT_RESTART :
					VERITY_TABLE_OPT_LOGGING,
				target_device,
				ecc.start / FEC_BLOCK_SIZE, ecc.blocks,
				ecc.roots);
		} else {
			err = snprintf(buf, FEC_ARG_LENGTH,
				"%u " VERITY_TABLE_OPT_FEC_FORMAT,
				VERITY_TABLE_OPT_FEC_ARGS, target_device,
				ecc.start / FEC_BLOCK_SIZE, ecc.blocks,
				ecc.roots);
		}
	} else if (mode) {
		err = snprintf(buf, FEC_ARG_LENGTH,
			"2 " VERITY_TABLE_OPT_IGNZERO " %s",
			mode == DM_VERITY_MODE_RESTART ?
			VERITY_TABLE_OPT_RESTART : VERITY_TABLE_OPT_LOGGING);
	} else {
		err = snprintf(buf, FEC_ARG_LENGTH, "1 %s",
				 "ignore_zero_blocks");
	}

	if (err < 0 || err >= FEC_ARG_LENGTH)
		goto free_metadata;

	buf_ptr = buf;

	for (i = VERITY_TABLE_ARGS; i < (VERITY_TABLE_ARGS +
		VERITY_TABLE_OPT_FEC_ARGS + 2); i++) {
		verity_table_args[i] = strsep(&buf_ptr, " ");
		if (verity_table_args[i] == NULL) {
			no_of_args = i;
			break;
		}
	}

	err = verity_ctr(ti, no_of_args, verity_table_args);

	if (err)
		DMERR("android-verity failed to mount as verity target");
	else {
		target_added = true;
		DMINFO("android-verity mounted as verity target");
	}

free_metadata:
	if (metadata) {
		kfree(metadata->header);
		kfree(metadata->verity_table);
	}
	kfree(metadata);
	return err;
}

static int __init dm_android_verity_init(void)
{
	int r;
	struct dentry *file;

	r = dm_register_target(&android_verity_target);
	if (r < 0)
		DMERR("register failed %d", r);

	/* Tracks the status of the last added target */
	debug_dir = debugfs_create_dir("android_verity", NULL);

	if (IS_ERR_OR_NULL(debug_dir)) {
		DMERR("Cannot create android_verity debugfs directory: %ld",
			PTR_ERR(debug_dir));
		goto end;
	}

	file = debugfs_create_bool("target_added", S_IRUGO, debug_dir,
				&target_added);

	if (IS_ERR_OR_NULL(file)) {
		DMERR("Cannot create android_verity debugfs directory: %ld",
			PTR_ERR(debug_dir));
		debugfs_remove_recursive(debug_dir);
		goto end;
	}

	file = debugfs_create_bool("verity_enabled", S_IRUGO, debug_dir,
				&verity_enabled);

	if (IS_ERR_OR_NULL(file)) {
		DMERR("Cannot create android_verity debugfs directory: %ld",
			PTR_ERR(debug_dir));
		debugfs_remove_recursive(debug_dir);
	}

end:
	return r;
}

static void __exit dm_android_verity_exit(void)
{
	if (!IS_ERR_OR_NULL(debug_dir))
		debugfs_remove_recursive(debug_dir);

	dm_unregister_target(&android_verity_target);
}

module_init(dm_android_verity_init);
module_exit(dm_android_verity_exit);
