Merge "defconfig: sm8150: Enable ICE metadata encryption"

This commit is contained in:
qctecmdr Service 2018-08-24 12:24:03 -07:00 committed by Gerrit - the friendly Code Review server
commit 9b4c05670c
13 changed files with 309 additions and 11 deletions

View File

@ -273,6 +273,7 @@ CONFIG_SCSI_UFS_QCOM=y
CONFIG_SCSI_UFS_QCOM_ICE=y
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
CONFIG_DM_DEFAULT_KEY=y
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_FEC=y
@ -649,6 +650,7 @@ CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0
CONFIG_CORESIGHT_TGU=y
CONFIG_CORESIGHT_EVENT=y
CONFIG_PFK=y
CONFIG_PFK_WRAPPED_KEY_SUPPORTED=y
CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
CONFIG_SECURITY=y
CONFIG_HARDENED_USERCOPY=y

View File

@ -286,6 +286,7 @@ CONFIG_SCSI_UFS_QCOM_ICE=y
CONFIG_SCSI_UFSHCD_CMD_LOGGING=y
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
CONFIG_DM_DEFAULT_KEY=y
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_FEC=y
@ -729,6 +730,7 @@ CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0
CONFIG_CORESIGHT_TGU=y
CONFIG_CORESIGHT_EVENT=y
CONFIG_PFK=y
CONFIG_PFK_WRAPPED_KEY_SUPPORTED=y
CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
CONFIG_SECURITY=y
CONFIG_HARDENED_USERCOPY=y

View File

@ -580,8 +580,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
}

View File

@ -286,6 +286,24 @@ 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 that
where the filesystem doesn't explicitly specify a key, such as for
filesystem metadata, a default key will be used instead, 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

View File

@ -43,6 +43,7 @@ obj-$(CONFIG_BLK_DEV_DM_BUILTIN) += dm-builtin.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
drivers/md/dm-default-key.c Normal file
View File

@ -0,0 +1,224 @@
/*
* 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_skip)
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, fmode_t *mode)
{
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");

View File

@ -1686,6 +1686,16 @@ static int queue_supports_sg_merge(struct dm_target *ti, struct dm_dev *dev,
return q && !test_bit(QUEUE_FLAG_NO_SG_MERGE, &q->queue_flags);
}
static int queue_supports_inline_encryption(struct dm_target *ti,
struct dm_dev *dev,
sector_t start, sector_t len,
void *data)
{
struct request_queue *q = bdev_get_queue(dev->bdev);
return q && blk_queue_inlinecrypt(q);
}
static bool dm_table_all_devices_attribute(struct dm_table *t,
iterate_devices_callout_fn func)
{
@ -1836,6 +1846,11 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
else
queue_flag_set_unlocked(QUEUE_FLAG_NO_SG_MERGE, q);
if (dm_table_all_devices_attribute(t, queue_supports_inline_encryption))
queue_flag_set_unlocked(QUEUE_FLAG_INLINECRYPT, q);
else
queue_flag_clear_unlocked(QUEUE_FLAG_INLINECRYPT, q);
dm_table_verify_integrity(t);
/*

View File

@ -126,16 +126,29 @@ void fscrypt_set_ice_dun(const struct inode *inode, struct bio *bio, u64 dun)
}
EXPORT_SYMBOL(fscrypt_set_ice_dun);
void fscrypt_set_ice_skip(struct bio *bio, int bi_crypt_skip)
{
#ifdef CONFIG_DM_DEFAULT_KEY
bio->bi_crypt_skip = bi_crypt_skip;
#endif
}
EXPORT_SYMBOL(fscrypt_set_ice_skip);
/*
* This function will be used for filesystem when deciding to merge bios.
* Basic assumption is, if inline_encryption is set, single bio has to
* guarantee consecutive LBAs as well as ino|pg->index.
*/
bool fscrypt_mergeable_bio(struct bio *bio, u64 dun, bool bio_encrypted)
bool fscrypt_mergeable_bio(struct bio *bio, u64 dun, bool bio_encrypted,
int bi_crypt_skip)
{
if (!bio)
return true;
#ifdef CONFIG_DM_DEFAULT_KEY
if (bi_crypt_skip != bio->bi_crypt_skip)
return false;
#endif
/* if both of them are not encrypted, no further check is needed */
if (!bio_dun(bio) && !bio_encrypted)
return true;

View File

@ -451,6 +451,7 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
if (f2fs_may_encrypt_bio(inode, fio))
fscrypt_set_ice_dun(inode, bio, PG_DUN(inode, fio->page));
fscrypt_set_ice_skip(bio, fio->encrypted_page ? 1 : 0);
if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
bio_put(bio);
@ -473,6 +474,7 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
struct page *bio_page;
struct inode *inode;
bool bio_encrypted;
int bi_crypt_skip;
u64 dun;
int err = 0;
@ -499,6 +501,7 @@ next:
bio_page = fio->encrypted_page ? fio->encrypted_page : fio->page;
inode = fio->page->mapping->host;
dun = PG_DUN(inode, fio->page);
bi_crypt_skip = fio->encrypted_page ? 1 : 0;
bio_encrypted = f2fs_may_encrypt_bio(inode, fio);
/* set submitted = true as a return value */
@ -512,7 +515,7 @@ next:
__submit_merged_bio(io);
/* ICE support */
if (!fscrypt_mergeable_bio(io->bio, dun, bio_encrypted))
if (!fscrypt_mergeable_bio(io->bio, dun, bio_encrypted, bi_crypt_skip))
__submit_merged_bio(io);
alloc_new:
@ -528,7 +531,7 @@ alloc_new:
fio->type, fio->temp);
if (bio_encrypted)
fscrypt_set_ice_dun(inode, io->bio, dun);
fscrypt_set_ice_skip(io->bio, bi_crypt_skip);
io->fio = *fio;
}
@ -1539,7 +1542,7 @@ submit_and_realloc:
dun = PG_DUN(inode, page);
bio_encrypted = f2fs_may_encrypt_bio(inode, NULL);
if (!fscrypt_mergeable_bio(bio, dun, bio_encrypted)) {
if (!fscrypt_mergeable_bio(bio, dun, bio_encrypted, 0)) {
__submit_bio(F2FS_I_SB(inode), bio, DATA);
bio = NULL;
}

View File

@ -104,6 +104,9 @@ struct bio {
/* Encryption key to use (NULL if none) */
const struct blk_encryption_key *bi_crypt_key;
#endif
#ifdef CONFIG_DM_DEFAULT_KEY
int bi_crypt_skip;
#endif
unsigned short bi_vcnt; /* how many bio_vec's */

View File

@ -193,8 +193,13 @@ static inline int fscrypt_using_hardware_encryption(const struct inode *inode)
static inline void fscrypt_set_ice_dun(const struct inode *inode,
struct bio *bio, u64 dun){}
static inline void fscrypt_set_ice_skip(struct bio *bio, int bi_crypt_skip)
{
return;
}
static inline bool fscrypt_mergeable_bio(struct bio *bio,
sector_t iv_block, bool bio_encrypted)
sector_t iv_block, bool bio_encrypted, int bi_crypt_skip)
{
return true;
}

View File

@ -201,8 +201,9 @@ extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t,
extern int fscrypt_using_hardware_encryption(const struct inode *inode);
extern void fscrypt_set_ice_dun(const struct inode *inode,
struct bio *bio, u64 dun);
extern bool fscrypt_mergeable_bio(struct bio *bio, u64 dun, bool bio_encrypted);
extern void fscrypt_set_ice_skip(struct bio *bio, int bi_crypt_skip);
extern bool fscrypt_mergeable_bio(struct bio *bio, u64 dun, bool bio_encrypted,
int bi_crypt_skip);
/* hooks.c */
extern int fscrypt_file_open(struct inode *inode, struct file *filp);

View File

@ -288,7 +288,7 @@ static int pfk_get_key_for_bio(const struct bio *bio,
{
const struct inode *inode;
enum pfe_type which_pfe;
const struct blk_encryption_key *key;
const struct blk_encryption_key *key = NULL;
inode = pfk_bio_get_inode(bio);
which_pfe = pfk_get_pfe_type(inode);
@ -305,7 +305,9 @@ static int pfk_get_key_for_bio(const struct bio *bio,
* bio is not for an encrypted file. Use ->bi_crypt_key if it was set.
* Otherwise, don't encrypt/decrypt the bio.
*/
#ifdef CONFIG_DM_DEFAULT_KEY
key = bio->bi_crypt_key;
#endif
if (!key) {
*is_pfe = false;
return -EINVAL;
@ -464,13 +466,18 @@ int pfk_load_key_end(const struct bio *bio, bool *is_pfe)
*/
bool pfk_allow_merge_bio(const struct bio *bio1, const struct bio *bio2)
{
const struct blk_encryption_key *key1;
const struct blk_encryption_key *key2;
const struct blk_encryption_key *key1 = NULL;
const struct blk_encryption_key *key2 = NULL;
const struct inode *inode1;
const struct inode *inode2;
enum pfe_type which_pfe1;
enum pfe_type which_pfe2;
#ifdef CONFIG_DM_DEFAULT_KEY
key1 = bio1->bi_crypt_key;
key2 = bio2->bi_crypt_key;
#endif
if (!pfk_is_ready())
return false;