diff --git a/block/bio.c b/block/bio.c index 02c4d9bf1590..d55eb8306e70 100644 --- a/block/bio.c +++ b/block/bio.c @@ -562,6 +562,13 @@ inline int bio_phys_segments(struct request_queue *q, struct bio *bio) } 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; +#endif +} + /** * __bio_clone_fast - clone a bio that shares the original bio's biovec * @bio: destination bio @@ -588,6 +595,8 @@ void __bio_clone_fast(struct bio *bio, struct bio *bio_src) bio->bi_io_vec = bio_src->bi_io_vec; bio->bi_dio_inode = bio_src->bi_dio_inode; + bio_clone_crypt_key(bio, bio_src); + bio_clone_blkcg_association(bio, bio_src); } EXPORT_SYMBOL(__bio_clone_fast); @@ -694,6 +703,8 @@ integrity_clone: } } + bio_clone_crypt_key(bio, bio_src); + bio_clone_blkcg_association(bio, bio_src); return bio; diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 6d73a04d0150..148ee951f3ed 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -98,6 +98,11 @@ struct bio { #endif }; +#ifdef CONFIG_PFK + /* Encryption key to use (NULL if none) */ + const struct blk_encryption_key *bi_crypt_key; +#endif + unsigned short bi_vcnt; /* how many bio_vec's */ /* diff --git a/include/linux/pfk.h b/include/linux/pfk.h index 82ee74199752..d308e02a0b35 100644 --- a/include/linux/pfk.h +++ b/include/linux/pfk.h @@ -17,6 +17,19 @@ struct ice_crypto_setting; +/* + * Default key for inline encryption. + * + * For now only AES-256-XTS is supported, so this is a fixed length. But if + * ever needed, this should be made variable-length with a 'mode' and 'size'. + * (Remember to update pfk_allow_merge_bio() when doing so!) + */ +#define BLK_ENCRYPTION_KEY_SIZE_AES_256_XTS 64 + +struct blk_encryption_key { + u8 raw[BLK_ENCRYPTION_KEY_SIZE_AES_256_XTS]; +}; + #ifdef CONFIG_PFK int pfk_load_key_start(const struct bio *bio, diff --git a/security/pfe/pfk.c b/security/pfe/pfk.c index 2e5aa2fb6688..8f6a97604bba 100644 --- a/security/pfe/pfk.c +++ b/security/pfe/pfk.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -151,28 +152,6 @@ static enum pfe_type pfk_get_pfe_type(const struct inode *inode) return INVALID_PFE; } -/** - * inode_to_filename() - get the filename from inode pointer. - * @inode: inode pointer - * - * it is used for debug prints. - * - * Return: filename string or "unknown". - */ -char *inode_to_filename(const struct inode *inode) -{ - struct dentry *dentry = NULL; - char *filename = NULL; - - if (hlist_empty(&inode->i_dentry)) - return "unknown"; - - dentry = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias); - filename = dentry->d_iname; - - return filename; -} - /** * pfk_is_ready() - driver is initialized and ready. * @@ -271,6 +250,59 @@ bool pfe_is_inode_filesystem_type(const struct inode *inode, return (strcmp(inode->i_sb->s_type->name, fs_type) == 0); } +/** + * pfk_get_key_for_bio() - get the encryption key to be used for a bio + * + * @bio: pointer to the BIO + * @key_info: pointer to the key information which will be filled in + * @algo_mode: optional pointer to the algorithm identifier which will be set + * @is_pfe: will be set to false if the BIO should be left unencrypted + * + * Return: 0 if a key is being used, otherwise a -errno value + */ +static int pfk_get_key_for_bio(const struct bio *bio, + struct pfk_key_info *key_info, + enum ice_cryto_algo_mode *algo_mode, + bool *is_pfe) +{ + const struct inode *inode; + enum pfe_type which_pfe; + const struct blk_encryption_key *key; + + inode = pfk_bio_get_inode(bio); + which_pfe = pfk_get_pfe_type(inode); + + if (which_pfe != INVALID_PFE) { + /* Encrypted file; override ->bi_crypt_key */ + pr_debug("parsing inode %lu with PFE type %d\n", + inode->i_ino, which_pfe); + return (*(pfk_parse_inode_ftable[which_pfe])) + (bio, inode, key_info, algo_mode, is_pfe); + } + + /* + * bio is not for an encrypted file. Use ->bi_crypt_key if it was set. + * Otherwise, don't encrypt/decrypt the bio. + */ + + key = bio->bi_crypt_key; + if (!key) { + *is_pfe = false; + return -EINVAL; + } + + /* Note: the "salt" is really just the second half of the XTS key. */ + BUILD_BUG_ON(sizeof(key->raw) != + PFK_SUPPORTED_KEY_SIZE + PFK_SUPPORTED_SALT_SIZE); + key_info->key = &key->raw[0]; + key_info->key_size = PFK_SUPPORTED_KEY_SIZE; + key_info->salt = &key->raw[PFK_SUPPORTED_KEY_SIZE]; + key_info->salt_size = PFK_SUPPORTED_SALT_SIZE; + if (algo_mode) + *algo_mode = ICE_CRYPTO_ALGO_MODE_AES_XTS; + return 0; +} + /** * pfk_load_key_start() - loads PFE encryption key to the ICE @@ -300,8 +332,6 @@ int pfk_load_key_start(const struct bio *bio, enum ice_cryto_algo_mode algo_mode = ICE_CRYPTO_ALGO_MODE_AES_XTS; enum ice_crpto_key_size key_size_type = 0; u32 key_index = 0; - struct inode *inode = NULL; - enum pfe_type which_pfe = INVALID_PFE; if (!is_pfe) { pr_err("is_pfe is NULL\n"); @@ -323,23 +353,7 @@ int pfk_load_key_start(const struct bio *bio, return -EINVAL; } - inode = pfk_bio_get_inode(bio); - if (!inode) { - *is_pfe = false; - return -EINVAL; - } - - which_pfe = pfk_get_pfe_type(inode); - if (which_pfe == INVALID_PFE) { - *is_pfe = false; - return -EPERM; - } - - pr_debug("parsing file %s with PFE %d\n", - inode_to_filename(inode), which_pfe); - - ret = (*(pfk_parse_inode_ftable[which_pfe])) - (bio, inode, &key_info, &algo_mode, is_pfe); + ret = pfk_get_key_for_bio(bio, &key_info, &algo_mode, is_pfe); if (ret != 0) return ret; @@ -363,9 +377,6 @@ int pfk_load_key_start(const struct bio *bio, ice_setting->key_mode = ICE_CRYPTO_USE_LUT_SW_KEY; ice_setting->key_index = key_index; - pr_debug("loaded key for file %s key_index %d\n", - inode_to_filename(inode), key_index); - return 0; } @@ -384,8 +395,6 @@ int pfk_load_key_end(const struct bio *bio, bool *is_pfe) { int ret = 0; struct pfk_key_info key_info = {0}; - enum pfe_type which_pfe = INVALID_PFE; - struct inode *inode = NULL; if (!is_pfe) { pr_err("is_pfe is NULL\n"); @@ -401,29 +410,13 @@ int pfk_load_key_end(const struct bio *bio, bool *is_pfe) if (!pfk_is_ready()) return -ENODEV; - inode = pfk_bio_get_inode(bio); - if (!inode) { - *is_pfe = false; - return -EINVAL; - } - - which_pfe = pfk_get_pfe_type(inode); - if (which_pfe == INVALID_PFE) { - *is_pfe = false; - return -EPERM; - } - - ret = (*(pfk_parse_inode_ftable[which_pfe])) - (bio, inode, &key_info, NULL, is_pfe); + ret = pfk_get_key_for_bio(bio, &key_info, NULL, is_pfe); if (ret != 0) return ret; pfk_kc_load_key_end(key_info.key, key_info.key_size, key_info.salt, key_info.salt_size); - pr_debug("finished using key for file %s\n", - inode_to_filename(inode)); - return 0; } @@ -444,10 +437,12 @@ 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) { - struct inode *inode1 = NULL; - struct inode *inode2 = NULL; - enum pfe_type which_pfe1 = INVALID_PFE; - enum pfe_type which_pfe2 = INVALID_PFE; + const struct blk_encryption_key *key1 = bio1->bi_crypt_key; + const struct blk_encryption_key *key2 = bio2->bi_crypt_key; + const struct inode *inode1; + const struct inode *inode2; + enum pfe_type which_pfe1; + enum pfe_type which_pfe2; if (!pfk_is_ready()) return false; @@ -465,17 +460,29 @@ bool pfk_allow_merge_bio(const struct bio *bio1, const struct bio *bio2) which_pfe1 = pfk_get_pfe_type(inode1); which_pfe2 = pfk_get_pfe_type(inode2); - /* nodes with different encryption, do not merge */ + /* + * If one bio is for an encrypted file and the other is for a different + * type of encrypted file or for blocks that are not part of an + * encrypted file, do not merge. + */ if (which_pfe1 != which_pfe2) return false; - /* both nodes do not have encryption, allow merge */ - if (which_pfe1 == INVALID_PFE) - return true; + if (which_pfe1 != INVALID_PFE) { + /* Both bios are for the same type of encrypted file. */ + return (*(pfk_allow_merge_bio_ftable[which_pfe1]))(bio1, bio2, + inode1, inode2); + } - return (*(pfk_allow_merge_bio_ftable[which_pfe1]))(bio1, bio2, - inode1, inode2); + /* + * Neither bio is for an encrypted file. Merge only if the default keys + * are the same (or both are NULL). + */ + return key1 == key2 || + (key1 && key2 && + !crypto_memneq(key1->raw, key2->raw, sizeof(key1->raw))); } + /** * Flush key table on storage core reset. During core reset key configuration * is lost in ICE. We need to flash the cache, so that the keys will be diff --git a/security/pfe/pfk_internal.h b/security/pfe/pfk_internal.h index abdd0b325b39..5342fd555832 100644 --- a/security/pfe/pfk_internal.h +++ b/security/pfe/pfk_internal.h @@ -29,6 +29,4 @@ int pfk_key_size_to_key_type(size_t key_size, bool pfe_is_inode_filesystem_type(const struct inode *inode, const char *fs_type); -char *inode_to_filename(const struct inode *inode); - #endif /* _PFK_INTERNAL_H_ */