diff --git a/block/bio.c b/block/bio.c index a4c8c99351da..a44b52572540 100644 --- a/block/bio.c +++ b/block/bio.c @@ -568,8 +568,11 @@ 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 } diff --git a/drivers/md/dm-default-key.c b/drivers/md/dm-default-key.c index 7cc7ea7f5748..ca50de11b6d0 100644 --- a/drivers/md/dm-default-key.c +++ b/drivers/md/dm-default-key.c @@ -133,7 +133,7 @@ static int default_key_map(struct dm_target *ti, struct bio *bio) dm_target_offset(ti, bio->bi_iter.bi_sector); } - if (!bio->bi_crypt_key) + if (!bio->bi_crypt_key && !bio->bi_crypt_skip) bio->bi_crypt_key = &dkc->key; return DM_MAPIO_REMAPPED; diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 2763adffefbc..6b7b4ddd2e99 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -1495,6 +1495,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) { @@ -1615,6 +1625,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); /* diff --git a/fs/crypto/fscrypt_ice.c b/fs/crypto/fscrypt_ice.c index a76fecfbf18d..cd8446949f60 100644 --- a/fs/crypto/fscrypt_ice.c +++ b/fs/crypto/fscrypt_ice.c @@ -157,16 +157,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; diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 2a4a4fb8bbb2..f7f2c1373615 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -450,7 +450,8 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio) 1, is_read_io(fio->op), fio->type, fio->temp); if (f2fs_may_encrypt_bio(inode, fio)) - fscrypt_set_ice_dun(inode, bio, PG_DUN(inode, fio->page)); + 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 @@ void 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; f2fs_bug_on(sbi, is_read_io(fio->op)); @@ -498,6 +500,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 */ @@ -511,7 +514,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: @@ -527,7 +530,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; } diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 42ad6b5de619..a14967198d60 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -78,6 +78,9 @@ struct bio { */ struct inode *bi_dio_inode; #endif +#ifdef CONFIG_DM_DEFAULT_KEY + int bi_crypt_skip; +#endif unsigned short bi_vcnt; /* how many bio_vec's */ diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 1e036141ab4d..f5371c2ce84b 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -257,7 +257,9 @@ static inline int fscrypt_encrypt_symlink(struct inode *inode, 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 bool fscrypt_mergeable_bio(struct bio *bio, u64 dun, bool bio_encrypted, + int bi_crypt_skip); +extern void fscrypt_set_ice_skip(struct bio *bio, int bi_crypt_skip); #else static inline int fscrypt_using_hardware_encryption(const struct inode *inode) { @@ -270,8 +272,12 @@ static inline void fscrypt_set_ice_dun(const struct inode *inode, return; } +static inline void fscrypt_set_ice_skip(struct bio *bio, int bi_crypt_skip) +{ +} + static inline bool fscrypt_mergeable_bio(struct bio *bio, - u64 dun, bool bio_encrypted) + u64 dun, bool bio_encrypted, int bi_crypt_skip) { return true; } diff --git a/security/pfe/pfk.c b/security/pfe/pfk.c index 0cdfd306417f..8b0b9cef83b5 100644 --- a/security/pfe/pfk.c +++ b/security/pfe/pfk.c @@ -286,8 +286,8 @@ 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; char *s_type = NULL; + const struct blk_encryption_key *key = NULL; inode = pfk_bio_get_inode(bio); which_pfe = pfk_get_pfe_type(inode); @@ -310,7 +310,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; @@ -472,13 +474,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;