Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0be260f1 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "dm-default-key, f2fs, ICE: support dm-default-key with f2fs/ICE"

parents e3e5e5cb 191db760
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -583,8 +583,12 @@ EXPORT_SYMBOL(bio_phys_segments);
static inline void bio_clone_crypt_key(struct bio *dst, const struct bio *src)
{
#ifdef CONFIG_PFK
	dst->bi_crypt_key = src->bi_crypt_key;
	dst->bi_iter.bi_dun = src->bi_iter.bi_dun;
#ifdef CONFIG_DM_DEFAULT_KEY
	dst->bi_crypt_key = src->bi_crypt_key;
	dst->bi_crypt_skip = src->bi_crypt_skip;
#endif
	dst->bi_dio_inode = src->bi_dio_inode;
#endif
}

+0 −9
Original line number Diff line number Diff line
@@ -54,15 +54,6 @@ static inline void queue_lockdep_assert_held(struct request_queue *q)
		lockdep_assert_held(q->queue_lock);
}

static inline void queue_flag_clear_unlocked(unsigned int flag,
					     struct request_queue *q)
{
	if (test_bit(QUEUE_FLAG_INIT_DONE, &q->queue_flags) &&
	    kref_read(&q->kobj.kref))
		lockdep_assert_held(q->queue_lock);
	__clear_bit(flag, &q->queue_flags);
}

static inline int queue_flag_test_and_clear(unsigned int flag,
					    struct request_queue *q)
{
+17 −0
Original line number Diff line number Diff line
@@ -294,6 +294,23 @@ config DM_CRYPT

	  If unsure, say N.

config DM_DEFAULT_KEY
	tristate "Default-key crypt target support"
	depends on BLK_DEV_DM
	depends on PFK
	---help---
	  This (currently Android-specific) device-mapper target allows you to
	  create a device that assigns a default encryption key to bios that
	  don't already have one.  This can sit between inline cryptographic
	  acceleration hardware and filesystems that use it.  This ensures a
	  default key is used when the filesystem doesn't explicitly specify a
	  key, such as for filesystem metadata, leaving no sectors unencrypted.

	  To compile this code as a module, choose M here: the module will be
	  called dm-default-key.

	  If unsure, say N.

config DM_SNAPSHOT
       tristate "Snapshot target"
       depends on BLK_DEV_DM
+1 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ obj-$(CONFIG_DM_UNSTRIPED) += dm-unstripe.o
obj-$(CONFIG_DM_BUFIO)		+= dm-bufio.o
obj-$(CONFIG_DM_BIO_PRISON)	+= dm-bio-prison.o
obj-$(CONFIG_DM_CRYPT)		+= dm-crypt.o
obj-$(CONFIG_DM_DEFAULT_KEY)	+= dm-default-key.o
obj-$(CONFIG_DM_DELAY)		+= dm-delay.o
obj-$(CONFIG_DM_FLAKEY)		+= dm-flakey.o
obj-$(CONFIG_DM_MULTIPATH)	+= dm-multipath.o dm-round-robin.o
+224 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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/device-mapper.h>
#include <linux/module.h>
#include <linux/pfk.h>

#define DM_MSG_PREFIX "default-key"

struct default_key_c {
	struct dm_dev *dev;
	sector_t start;
	struct blk_encryption_key key;
};

static void default_key_dtr(struct dm_target *ti)
{
	struct default_key_c *dkc = ti->private;

	if (dkc->dev)
		dm_put_device(ti, dkc->dev);
	kzfree(dkc);
}

/*
 * Construct a default-key mapping: <mode> <key> <dev_path> <start>
 */
static int default_key_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
	struct default_key_c *dkc;
	size_t key_size;
	unsigned long long tmp;
	char dummy;
	int err;

	if (argc != 4) {
		ti->error = "Invalid argument count";
		return -EINVAL;
	}

	dkc = kzalloc(sizeof(*dkc), GFP_KERNEL);
	if (!dkc) {
		ti->error = "Out of memory";
		return -ENOMEM;
	}
	ti->private = dkc;

	if (strcmp(argv[0], "AES-256-XTS") != 0) {
		ti->error = "Unsupported encryption mode";
		err = -EINVAL;
		goto bad;
	}

	key_size = strlen(argv[1]);
	if (key_size != 2 * BLK_ENCRYPTION_KEY_SIZE_AES_256_XTS) {
		ti->error = "Unsupported key size";
		err = -EINVAL;
		goto bad;
	}
	key_size /= 2;

	if (hex2bin(dkc->key.raw, argv[1], key_size) != 0) {
		ti->error = "Malformed key string";
		err = -EINVAL;
		goto bad;
	}

	err = dm_get_device(ti, argv[2], dm_table_get_mode(ti->table),
			    &dkc->dev);
	if (err) {
		ti->error = "Device lookup failed";
		goto bad;
	}

	if (sscanf(argv[3], "%llu%c", &tmp, &dummy) != 1) {
		ti->error = "Invalid start sector";
		err = -EINVAL;
		goto bad;
	}
	dkc->start = tmp;

	if (!blk_queue_inlinecrypt(bdev_get_queue(dkc->dev->bdev))) {
		ti->error = "Device does not support inline encryption";
		err = -EINVAL;
		goto bad;
	}

	/* Pass flush requests through to the underlying device. */
	ti->num_flush_bios = 1;

	/*
	 * We pass discard requests through to the underlying device, although
	 * the discarded blocks will be zeroed, which leaks information about
	 * unused blocks.  It's also impossible for dm-default-key to know not
	 * to decrypt discarded blocks, so they will not be read back as zeroes
	 * and we must set discard_zeroes_data_unsupported.
	 */
	ti->num_discard_bios = 1;

	/*
	 * It's unclear whether WRITE_SAME would work with inline encryption; it
	 * would depend on whether the hardware duplicates the data before or
	 * after encryption.  But since the internal storage in some  devices
	 * (MSM8998-based) doesn't claim to support WRITE_SAME anyway, we don't
	 * currently have a way to test it.  Leave it disabled it for now.
	 */
	/*ti->num_write_same_bios = 1;*/

	return 0;

bad:
	default_key_dtr(ti);
	return err;
}

static int default_key_map(struct dm_target *ti, struct bio *bio)
{
	const struct default_key_c *dkc = ti->private;

	bio_set_dev(bio, dkc->dev->bdev);
	if (bio_sectors(bio)) {
		bio->bi_iter.bi_sector = dkc->start +
			dm_target_offset(ti, bio->bi_iter.bi_sector);
	}

	if (!bio->bi_crypt_key)
		bio->bi_crypt_key = &dkc->key;

	return DM_MAPIO_REMAPPED;
}

static void default_key_status(struct dm_target *ti, status_type_t type,
			       unsigned int status_flags, char *result,
			       unsigned int maxlen)
{
	const struct default_key_c *dkc = ti->private;
	unsigned int sz = 0;

	switch (type) {
	case STATUSTYPE_INFO:
		result[0] = '\0';
		break;

	case STATUSTYPE_TABLE:

		/* encryption mode */
		DMEMIT("AES-256-XTS");

		/* reserved for key; dm-crypt shows it, but we don't for now */
		DMEMIT(" -");

		/* name of underlying device, and the start sector in it */
		DMEMIT(" %s %llu", dkc->dev->name,
		       (unsigned long long)dkc->start);
		break;
	}
}

static int default_key_prepare_ioctl(struct dm_target *ti,
				     struct block_device **bdev)
{
	struct default_key_c *dkc = ti->private;
	struct dm_dev *dev = dkc->dev;

	*bdev = dev->bdev;

	/*
	 * Only pass ioctls through if the device sizes match exactly.
	 */
	if (dkc->start ||
	    ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
		return 1;
	return 0;
}

static int default_key_iterate_devices(struct dm_target *ti,
				       iterate_devices_callout_fn fn,
				       void *data)
{
	struct default_key_c *dkc = ti->private;

	return fn(ti, dkc->dev, dkc->start, ti->len, data);
}

static struct target_type default_key_target = {
	.name   = "default-key",
	.version = {1, 0, 0},
	.module = THIS_MODULE,
	.ctr    = default_key_ctr,
	.dtr    = default_key_dtr,
	.map    = default_key_map,
	.status = default_key_status,
	.prepare_ioctl = default_key_prepare_ioctl,
	.iterate_devices = default_key_iterate_devices,
};

static int __init dm_default_key_init(void)
{
	return dm_register_target(&default_key_target);
}

static void __exit dm_default_key_exit(void)
{
	dm_unregister_target(&default_key_target);
}

module_init(dm_default_key_init);
module_exit(dm_default_key_exit);

MODULE_AUTHOR("Paul Lawrence <paullawrence@google.com>");
MODULE_AUTHOR("Paul Crowley <paulcrowley@google.com>");
MODULE_AUTHOR("Eric Biggers <ebiggers@google.com>");
MODULE_DESCRIPTION(DM_NAME " target for encrypting filesystem metadata");
MODULE_LICENSE("GPL v2");
Loading