mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
Merge "defconfig: sm8150: Enable ICE metadata encryption"
This commit is contained in:
commit
9b4c05670c
@ -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
|
||||
|
2
arch/arm64/configs/vendor/sm8150_defconfig
vendored
2
arch/arm64/configs/vendor/sm8150_defconfig
vendored
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
224
drivers/md/dm-default-key.c
Normal 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");
|
@ -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);
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user