Loading block/blk-merge.c +12 −4 Original line number Diff line number Diff line Loading @@ -6,7 +6,8 @@ #include <linux/bio.h> #include <linux/blkdev.h> #include <linux/scatterlist.h> #include <linux/security.h> #include <linux/pfk.h> #include <linux/pft.h> #include "blk.h" Loading Loading @@ -729,6 +730,12 @@ static void blk_account_io_merge(struct request *req) } } static bool crypto_not_mergeable(const struct bio *bio, const struct bio *nxt) { return (!pft_allow_merge_bio(bio, nxt) || !pfk_allow_merge_bio(bio, nxt)); } /* * Has to be called with the request spinlock acquired */ Loading Loading @@ -756,6 +763,9 @@ static int attempt_merge(struct request_queue *q, struct request *req, !blk_write_same_mergeable(req->bio, next->bio)) return 0; if (crypto_not_mergeable(req->bio, next->bio)) return 0; /* * If we are allowed to merge, then append bio list * from next to rq and release next. merge_requests_fn Loading Loading @@ -860,11 +870,9 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio) !blk_write_same_mergeable(rq->bio, bio)) return false; /* Don't merge bios of files with different encryption */ if (!security_allow_merge_bio(rq->bio, bio)) if (crypto_not_mergeable(rq->bio, bio)) return false; return true; } Loading fs/ext4/Kconfig +8 −2 Original line number Diff line number Diff line Loading @@ -117,10 +117,16 @@ config EXT4_ENCRYPTION decrypted pages in the page cache. config EXT4_FS_ENCRYPTION bool default y bool "Ext4 FS Encryption" default n depends on EXT4_ENCRYPTION config EXT4_FS_ICE_ENCRYPTION bool "Ext4 Encryption with ICE support" default n depends on EXT4_FS_ENCRYPTION depends on PFK config EXT4_DEBUG bool "EXT4 debugging support" depends on EXT4_FS Loading fs/ext4/Makefile +2 −0 Original line number Diff line number Diff line Loading @@ -14,3 +14,5 @@ ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o ext4-$(CONFIG_EXT4_FS_SECURITY) += xattr_security.o ext4-$(CONFIG_EXT4_FS_ENCRYPTION) += crypto_policy.o crypto.o \ crypto_key.o crypto_fname.o ext4-$(CONFIG_EXT4_FS_ICE_ENCRYPTION) += ext4_ice.o fs/ext4/crypto.c +2 −1 Original line number Diff line number Diff line Loading @@ -458,7 +458,8 @@ errout: bool ext4_valid_contents_enc_mode(uint32_t mode) { return (mode == EXT4_ENCRYPTION_MODE_AES_256_XTS); return (mode == EXT4_ENCRYPTION_MODE_AES_256_XTS || mode == EXT4_ENCRYPTION_MODE_PRIVATE); } /** Loading fs/ext4/crypto_key.c +46 −26 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include <uapi/linux/keyctl.h> #include "ext4.h" #include "ext4_ice.h" #include "xattr.h" static void derive_crypt_complete(struct crypto_async_request *req, int rc) Loading Loading @@ -111,6 +112,12 @@ void ext4_free_encryption_info(struct inode *inode, ext4_free_crypt_info(ci); } static int ext4_default_data_encryption_mode(void) { return ext4_is_ice_enabled() ? EXT4_ENCRYPTION_MODE_PRIVATE : EXT4_ENCRYPTION_MODE_AES_256_XTS; } int _ext4_get_encryption_info(struct inode *inode) { struct ext4_inode_info *ei = EXT4_I(inode); Loading @@ -124,8 +131,8 @@ int _ext4_get_encryption_info(struct inode *inode) struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); struct crypto_ablkcipher *ctfm; const char *cipher_str; char raw_key[EXT4_MAX_KEY_SIZE]; char mode; int for_fname = 0; int mode; int res; if (!ext4_read_workqueue) { Loading @@ -150,7 +157,8 @@ retry: if (res < 0) { if (!DUMMY_ENCRYPTION_ENABLED(sbi)) return res; ctx.contents_encryption_mode = EXT4_ENCRYPTION_MODE_AES_256_XTS; ctx.contents_encryption_mode = ext4_default_data_encryption_mode(); ctx.filenames_encryption_mode = EXT4_ENCRYPTION_MODE_AES_256_CTS; ctx.flags = 0; Loading @@ -169,12 +177,12 @@ retry: crypt_info->ci_keyring_key = NULL; memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor, sizeof(crypt_info->ci_master_key)); if (S_ISREG(inode->i_mode)) mode = crypt_info->ci_data_mode; else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) mode = crypt_info->ci_filename_mode; else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) for_fname = 1; else if (!S_ISREG(inode->i_mode)) BUG(); mode = for_fname ? crypt_info->ci_filename_mode : crypt_info->ci_data_mode; switch (mode) { case EXT4_ENCRYPTION_MODE_AES_256_XTS: cipher_str = "xts(aes)"; Loading @@ -182,6 +190,9 @@ retry: case EXT4_ENCRYPTION_MODE_AES_256_CTS: cipher_str = "cts(cbc(aes))"; break; case EXT4_ENCRYPTION_MODE_PRIVATE: cipher_str = "bugon"; break; default: printk_once(KERN_WARNING "ext4: unsupported key mode %d (ino %u)\n", Loading @@ -190,7 +201,7 @@ retry: goto out; } if (DUMMY_ENCRYPTION_ENABLED(sbi)) { memset(raw_key, 0x42, EXT4_AES_256_XTS_KEY_SIZE); memset(crypt_info->ci_raw_key, 0x42, EXT4_AES_256_XTS_KEY_SIZE); goto got_key; } memcpy(full_key_descriptor, EXT4_KEY_DESC_PREFIX, Loading Loading @@ -232,16 +243,17 @@ retry: goto out; } res = ext4_derive_key_aes(ctx.nonce, master_key->raw, raw_key); crypt_info->ci_raw_key); up_read(&keyring_key->sem); if (res) goto out; got_key: if (for_fname || (crypt_info->ci_data_mode != EXT4_ENCRYPTION_MODE_PRIVATE)) { ctfm = crypto_alloc_ablkcipher(cipher_str, 0, 0); if (!ctfm || IS_ERR(ctfm)) { res = ctfm ? PTR_ERR(ctfm) : -ENOMEM; printk(KERN_DEBUG "%s: error %d (inode %u) allocating crypto tfm\n", pr_debug("%s: error %d (inode %u) allocating crypto tfm\n", __func__, res, (unsigned) inode->i_ino); goto out; } Loading @@ -249,11 +261,18 @@ got_key: crypto_ablkcipher_clear_flags(ctfm, ~0); crypto_tfm_set_flags(crypto_ablkcipher_tfm(ctfm), CRYPTO_TFM_REQ_WEAK_KEY); res = crypto_ablkcipher_setkey(ctfm, raw_key, res = crypto_ablkcipher_setkey(ctfm, crypt_info->ci_raw_key, ext4_encryption_key_size(mode)); if (res) goto out; memzero_explicit(raw_key, sizeof(raw_key)); memzero_explicit(crypt_info->ci_raw_key, sizeof(crypt_info->ci_raw_key)); } else if (!ext4_is_ice_enabled()) { pr_warn("%s: ICE support not available\n", __func__); res = -EINVAL; goto out; } if (cmpxchg(&ei->i_crypt_info, NULL, crypt_info) != NULL) { ext4_free_crypt_info(crypt_info); goto retry; Loading @@ -263,8 +282,9 @@ got_key: out: if (res == -ENOKEY) res = 0; memzero_explicit(crypt_info->ci_raw_key, sizeof(crypt_info->ci_raw_key)); ext4_free_crypt_info(crypt_info); memzero_explicit(raw_key, sizeof(raw_key)); return res; } Loading Loading
block/blk-merge.c +12 −4 Original line number Diff line number Diff line Loading @@ -6,7 +6,8 @@ #include <linux/bio.h> #include <linux/blkdev.h> #include <linux/scatterlist.h> #include <linux/security.h> #include <linux/pfk.h> #include <linux/pft.h> #include "blk.h" Loading Loading @@ -729,6 +730,12 @@ static void blk_account_io_merge(struct request *req) } } static bool crypto_not_mergeable(const struct bio *bio, const struct bio *nxt) { return (!pft_allow_merge_bio(bio, nxt) || !pfk_allow_merge_bio(bio, nxt)); } /* * Has to be called with the request spinlock acquired */ Loading Loading @@ -756,6 +763,9 @@ static int attempt_merge(struct request_queue *q, struct request *req, !blk_write_same_mergeable(req->bio, next->bio)) return 0; if (crypto_not_mergeable(req->bio, next->bio)) return 0; /* * If we are allowed to merge, then append bio list * from next to rq and release next. merge_requests_fn Loading Loading @@ -860,11 +870,9 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio) !blk_write_same_mergeable(rq->bio, bio)) return false; /* Don't merge bios of files with different encryption */ if (!security_allow_merge_bio(rq->bio, bio)) if (crypto_not_mergeable(rq->bio, bio)) return false; return true; } Loading
fs/ext4/Kconfig +8 −2 Original line number Diff line number Diff line Loading @@ -117,10 +117,16 @@ config EXT4_ENCRYPTION decrypted pages in the page cache. config EXT4_FS_ENCRYPTION bool default y bool "Ext4 FS Encryption" default n depends on EXT4_ENCRYPTION config EXT4_FS_ICE_ENCRYPTION bool "Ext4 Encryption with ICE support" default n depends on EXT4_FS_ENCRYPTION depends on PFK config EXT4_DEBUG bool "EXT4 debugging support" depends on EXT4_FS Loading
fs/ext4/Makefile +2 −0 Original line number Diff line number Diff line Loading @@ -14,3 +14,5 @@ ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o ext4-$(CONFIG_EXT4_FS_SECURITY) += xattr_security.o ext4-$(CONFIG_EXT4_FS_ENCRYPTION) += crypto_policy.o crypto.o \ crypto_key.o crypto_fname.o ext4-$(CONFIG_EXT4_FS_ICE_ENCRYPTION) += ext4_ice.o
fs/ext4/crypto.c +2 −1 Original line number Diff line number Diff line Loading @@ -458,7 +458,8 @@ errout: bool ext4_valid_contents_enc_mode(uint32_t mode) { return (mode == EXT4_ENCRYPTION_MODE_AES_256_XTS); return (mode == EXT4_ENCRYPTION_MODE_AES_256_XTS || mode == EXT4_ENCRYPTION_MODE_PRIVATE); } /** Loading
fs/ext4/crypto_key.c +46 −26 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include <uapi/linux/keyctl.h> #include "ext4.h" #include "ext4_ice.h" #include "xattr.h" static void derive_crypt_complete(struct crypto_async_request *req, int rc) Loading Loading @@ -111,6 +112,12 @@ void ext4_free_encryption_info(struct inode *inode, ext4_free_crypt_info(ci); } static int ext4_default_data_encryption_mode(void) { return ext4_is_ice_enabled() ? EXT4_ENCRYPTION_MODE_PRIVATE : EXT4_ENCRYPTION_MODE_AES_256_XTS; } int _ext4_get_encryption_info(struct inode *inode) { struct ext4_inode_info *ei = EXT4_I(inode); Loading @@ -124,8 +131,8 @@ int _ext4_get_encryption_info(struct inode *inode) struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); struct crypto_ablkcipher *ctfm; const char *cipher_str; char raw_key[EXT4_MAX_KEY_SIZE]; char mode; int for_fname = 0; int mode; int res; if (!ext4_read_workqueue) { Loading @@ -150,7 +157,8 @@ retry: if (res < 0) { if (!DUMMY_ENCRYPTION_ENABLED(sbi)) return res; ctx.contents_encryption_mode = EXT4_ENCRYPTION_MODE_AES_256_XTS; ctx.contents_encryption_mode = ext4_default_data_encryption_mode(); ctx.filenames_encryption_mode = EXT4_ENCRYPTION_MODE_AES_256_CTS; ctx.flags = 0; Loading @@ -169,12 +177,12 @@ retry: crypt_info->ci_keyring_key = NULL; memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor, sizeof(crypt_info->ci_master_key)); if (S_ISREG(inode->i_mode)) mode = crypt_info->ci_data_mode; else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) mode = crypt_info->ci_filename_mode; else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) for_fname = 1; else if (!S_ISREG(inode->i_mode)) BUG(); mode = for_fname ? crypt_info->ci_filename_mode : crypt_info->ci_data_mode; switch (mode) { case EXT4_ENCRYPTION_MODE_AES_256_XTS: cipher_str = "xts(aes)"; Loading @@ -182,6 +190,9 @@ retry: case EXT4_ENCRYPTION_MODE_AES_256_CTS: cipher_str = "cts(cbc(aes))"; break; case EXT4_ENCRYPTION_MODE_PRIVATE: cipher_str = "bugon"; break; default: printk_once(KERN_WARNING "ext4: unsupported key mode %d (ino %u)\n", Loading @@ -190,7 +201,7 @@ retry: goto out; } if (DUMMY_ENCRYPTION_ENABLED(sbi)) { memset(raw_key, 0x42, EXT4_AES_256_XTS_KEY_SIZE); memset(crypt_info->ci_raw_key, 0x42, EXT4_AES_256_XTS_KEY_SIZE); goto got_key; } memcpy(full_key_descriptor, EXT4_KEY_DESC_PREFIX, Loading Loading @@ -232,16 +243,17 @@ retry: goto out; } res = ext4_derive_key_aes(ctx.nonce, master_key->raw, raw_key); crypt_info->ci_raw_key); up_read(&keyring_key->sem); if (res) goto out; got_key: if (for_fname || (crypt_info->ci_data_mode != EXT4_ENCRYPTION_MODE_PRIVATE)) { ctfm = crypto_alloc_ablkcipher(cipher_str, 0, 0); if (!ctfm || IS_ERR(ctfm)) { res = ctfm ? PTR_ERR(ctfm) : -ENOMEM; printk(KERN_DEBUG "%s: error %d (inode %u) allocating crypto tfm\n", pr_debug("%s: error %d (inode %u) allocating crypto tfm\n", __func__, res, (unsigned) inode->i_ino); goto out; } Loading @@ -249,11 +261,18 @@ got_key: crypto_ablkcipher_clear_flags(ctfm, ~0); crypto_tfm_set_flags(crypto_ablkcipher_tfm(ctfm), CRYPTO_TFM_REQ_WEAK_KEY); res = crypto_ablkcipher_setkey(ctfm, raw_key, res = crypto_ablkcipher_setkey(ctfm, crypt_info->ci_raw_key, ext4_encryption_key_size(mode)); if (res) goto out; memzero_explicit(raw_key, sizeof(raw_key)); memzero_explicit(crypt_info->ci_raw_key, sizeof(crypt_info->ci_raw_key)); } else if (!ext4_is_ice_enabled()) { pr_warn("%s: ICE support not available\n", __func__); res = -EINVAL; goto out; } if (cmpxchg(&ei->i_crypt_info, NULL, crypt_info) != NULL) { ext4_free_crypt_info(crypt_info); goto retry; Loading @@ -263,8 +282,9 @@ got_key: out: if (res == -ENOKEY) res = 0; memzero_explicit(crypt_info->ci_raw_key, sizeof(crypt_info->ci_raw_key)); ext4_free_crypt_info(crypt_info); memzero_explicit(raw_key, sizeof(raw_key)); return res; } Loading