From c1b2212990e1567dc4a4d130e89b0f946e1c38f5 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sat, 26 Nov 2016 14:33:40 -0500 Subject: MAINTAINERS: fscrypto: recommend linux-fsdevel for fscrypto patches The filesystem level encryption support, currently used by ext4 and f2fs and proposed for ubifs, does not yet have a dedicated mailing list. Since no mailing lists were specified in MAINTAINERS, get_maintainer.pl only recommended to send patches directly to the maintainers and to linux-kernel. This patch adds linux-fsdevel as the preferred mailing list for fscrypto patches for the time being. Signed-off-by: Eric Biggers Signed-off-by: Theodore Ts'o --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 411e3b87b8c2..0774714c4e67 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5138,6 +5138,7 @@ F: include/linux/fscache*.h FS-CRYPTO: FILE SYSTEM LEVEL ENCRYPTION SUPPORT M: Theodore Y. Ts'o M: Jaegeuk Kim +L: linux-fsdevel@vger.kernel.org S: Supported F: fs/crypto/ F: include/linux/fscrypto.h -- cgit From 8048123576d1011e186b1f62478bcd06ac7cabc8 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sat, 26 Nov 2016 15:06:43 -0500 Subject: fscrypto: remove unneeded Kconfig dependencies SHA256 and ENCRYPTED_KEYS are not needed. CTR shouldn't be needed either, but I left it for now because it was intentionally added by commit 71dea01ea2ed ("ext4 crypto: require CONFIG_CRYPTO_CTR if ext4 encryption is enabled"). So it sounds like there may be a dependency problem elsewhere, which I have not been able to identify specifically, that must be solved before CTR can be removed. Signed-off-by: Eric Biggers Signed-off-by: Theodore Ts'o --- fs/crypto/Kconfig | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/crypto/Kconfig b/fs/crypto/Kconfig index 92348faf9865..f514978f6688 100644 --- a/fs/crypto/Kconfig +++ b/fs/crypto/Kconfig @@ -8,9 +8,7 @@ config FS_ENCRYPTION select CRYPTO_XTS select CRYPTO_CTS select CRYPTO_CTR - select CRYPTO_SHA256 select KEYS - select ENCRYPTED_KEYS help Enable encryption of files and directories. This feature is similar to ecryptfs, but it is more memory -- cgit From db717d8e26c2d1b0dba3e08668a1e6a7f665adde Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sat, 26 Nov 2016 19:07:49 -0500 Subject: fscrypto: move ioctl processing more fully into common code Multiple bugs were recently fixed in the "set encryption policy" ioctl. To make it clear that fscrypt_process_policy() and fscrypt_get_policy() implement ioctls and therefore their implementations must take standard security and correctness precautions, rename them to fscrypt_ioctl_set_policy() and fscrypt_ioctl_get_policy(). Make the latter take in a struct file * to make it consistent with the former. Signed-off-by: Eric Biggers Signed-off-by: Theodore Ts'o --- fs/crypto/policy.c | 34 +++++++++++++++++++++------------- fs/ext4/ext4.h | 4 ++-- fs/ext4/ioctl.c | 34 +++++----------------------------- fs/f2fs/f2fs.h | 4 ++-- fs/f2fs/file.c | 19 ++----------------- include/linux/fscrypto.h | 12 ++++++------ 6 files changed, 38 insertions(+), 69 deletions(-) diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c index 6865663aac69..b96a10e3cf78 100644 --- a/fs/crypto/policy.c +++ b/fs/crypto/policy.c @@ -93,16 +93,19 @@ static int create_encryption_context_from_policy(struct inode *inode, return inode->i_sb->s_cop->set_context(inode, &ctx, sizeof(ctx), NULL); } -int fscrypt_process_policy(struct file *filp, - const struct fscrypt_policy *policy) +int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg) { + struct fscrypt_policy policy; struct inode *inode = file_inode(filp); int ret; + if (copy_from_user(&policy, arg, sizeof(policy))) + return -EFAULT; + if (!inode_owner_or_capable(inode)) return -EACCES; - if (policy->version != 0) + if (policy.version != 0) return -EINVAL; ret = mnt_want_write_file(filp); @@ -120,9 +123,9 @@ int fscrypt_process_policy(struct file *filp, ret = -ENOTEMPTY; else ret = create_encryption_context_from_policy(inode, - policy); + &policy); } else if (!is_encryption_context_consistent_with_policy(inode, - policy)) { + &policy)) { printk(KERN_WARNING "%s: Policy inconsistent with encryption context\n", __func__); @@ -134,11 +137,13 @@ int fscrypt_process_policy(struct file *filp, mnt_drop_write_file(filp); return ret; } -EXPORT_SYMBOL(fscrypt_process_policy); +EXPORT_SYMBOL(fscrypt_ioctl_set_policy); -int fscrypt_get_policy(struct inode *inode, struct fscrypt_policy *policy) +int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg) { + struct inode *inode = file_inode(filp); struct fscrypt_context ctx; + struct fscrypt_policy policy; int res; if (!inode->i_sb->s_cop->get_context || @@ -151,15 +156,18 @@ int fscrypt_get_policy(struct inode *inode, struct fscrypt_policy *policy) if (ctx.format != FS_ENCRYPTION_CONTEXT_FORMAT_V1) return -EINVAL; - policy->version = 0; - policy->contents_encryption_mode = ctx.contents_encryption_mode; - policy->filenames_encryption_mode = ctx.filenames_encryption_mode; - policy->flags = ctx.flags; - memcpy(&policy->master_key_descriptor, ctx.master_key_descriptor, + policy.version = 0; + policy.contents_encryption_mode = ctx.contents_encryption_mode; + policy.filenames_encryption_mode = ctx.filenames_encryption_mode; + policy.flags = ctx.flags; + memcpy(policy.master_key_descriptor, ctx.master_key_descriptor, FS_KEY_DESCRIPTOR_SIZE); + + if (copy_to_user(arg, &policy, sizeof(policy))) + return -EFAULT; return 0; } -EXPORT_SYMBOL(fscrypt_get_policy); +EXPORT_SYMBOL(fscrypt_ioctl_get_policy); int fscrypt_has_permitted_context(struct inode *parent, struct inode *child) { diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 282a51b07c57..bd8bc3be93a5 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -2338,8 +2338,8 @@ static inline void ext4_fname_free_filename(struct ext4_filename *fname) { } #define fscrypt_pullback_bio_page fscrypt_notsupp_pullback_bio_page #define fscrypt_restore_control_page fscrypt_notsupp_restore_control_page #define fscrypt_zeroout_range fscrypt_notsupp_zeroout_range -#define fscrypt_process_policy fscrypt_notsupp_process_policy -#define fscrypt_get_policy fscrypt_notsupp_get_policy +#define fscrypt_ioctl_set_policy fscrypt_notsupp_ioctl_set_policy +#define fscrypt_ioctl_get_policy fscrypt_notsupp_ioctl_get_policy #define fscrypt_has_permitted_context fscrypt_notsupp_has_permitted_context #define fscrypt_inherit_context fscrypt_notsupp_inherit_context #define fscrypt_get_encryption_info fscrypt_notsupp_get_encryption_info diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index bf5ae8ebbc97..70083863ce51 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -765,22 +765,12 @@ resizefs_out: } case EXT4_IOC_PRECACHE_EXTENTS: return ext4_ext_precache(inode); - case EXT4_IOC_SET_ENCRYPTION_POLICY: { -#ifdef CONFIG_EXT4_FS_ENCRYPTION - struct fscrypt_policy policy; + case EXT4_IOC_SET_ENCRYPTION_POLICY: if (!ext4_has_feature_encrypt(sb)) return -EOPNOTSUPP; + return fscrypt_ioctl_set_policy(filp, (const void __user *)arg); - if (copy_from_user(&policy, - (struct fscrypt_policy __user *)arg, - sizeof(policy))) - return -EFAULT; - return fscrypt_process_policy(filp, &policy); -#else - return -EOPNOTSUPP; -#endif - } case EXT4_IOC_GET_ENCRYPTION_PWSALT: { int err, err2; struct ext4_sb_info *sbi = EXT4_SB(sb); @@ -817,23 +807,9 @@ resizefs_out: return -EFAULT; return 0; } - case EXT4_IOC_GET_ENCRYPTION_POLICY: { -#ifdef CONFIG_EXT4_FS_ENCRYPTION - struct fscrypt_policy policy; - int err = 0; - - if (!ext4_encrypted_inode(inode)) - return -ENOENT; - err = fscrypt_get_policy(inode, &policy); - if (err) - return err; - if (copy_to_user((void __user *)arg, &policy, sizeof(policy))) - return -EFAULT; - return 0; -#else - return -EOPNOTSUPP; -#endif - } + case EXT4_IOC_GET_ENCRYPTION_POLICY: + return fscrypt_ioctl_get_policy(filp, (void __user *)arg); + case EXT4_IOC_FSGETXATTR: { struct fsxattr fa; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 9e8de18a168a..8e94b7bda42b 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -2453,8 +2453,8 @@ static inline bool f2fs_may_encrypt(struct inode *inode) #define fscrypt_pullback_bio_page fscrypt_notsupp_pullback_bio_page #define fscrypt_restore_control_page fscrypt_notsupp_restore_control_page #define fscrypt_zeroout_range fscrypt_notsupp_zeroout_range -#define fscrypt_process_policy fscrypt_notsupp_process_policy -#define fscrypt_get_policy fscrypt_notsupp_get_policy +#define fscrypt_ioctl_set_policy fscrypt_notsupp_ioctl_set_policy +#define fscrypt_ioctl_get_policy fscrypt_notsupp_ioctl_get_policy #define fscrypt_has_permitted_context fscrypt_notsupp_has_permitted_context #define fscrypt_inherit_context fscrypt_notsupp_inherit_context #define fscrypt_get_encryption_info fscrypt_notsupp_get_encryption_info diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index c7865073cd26..f0c83f74557d 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1752,31 +1752,16 @@ static bool uuid_is_nonzero(__u8 u[16]) static int f2fs_ioc_set_encryption_policy(struct file *filp, unsigned long arg) { - struct fscrypt_policy policy; struct inode *inode = file_inode(filp); - if (copy_from_user(&policy, (struct fscrypt_policy __user *)arg, - sizeof(policy))) - return -EFAULT; - f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); - return fscrypt_process_policy(filp, &policy); + return fscrypt_ioctl_set_policy(filp, (const void __user *)arg); } static int f2fs_ioc_get_encryption_policy(struct file *filp, unsigned long arg) { - struct fscrypt_policy policy; - struct inode *inode = file_inode(filp); - int err; - - err = fscrypt_get_policy(inode, &policy); - if (err) - return err; - - if (copy_to_user((struct fscrypt_policy __user *)arg, &policy, sizeof(policy))) - return -EFAULT; - return 0; + return fscrypt_ioctl_get_policy(filp, (void __user *)arg); } static int f2fs_ioc_get_encryption_pwsalt(struct file *filp, unsigned long arg) diff --git a/include/linux/fscrypto.h b/include/linux/fscrypto.h index 98c71e973a96..be94684dc05f 100644 --- a/include/linux/fscrypto.h +++ b/include/linux/fscrypto.h @@ -259,8 +259,8 @@ extern void fscrypt_restore_control_page(struct page *); extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t, unsigned int); /* policy.c */ -extern int fscrypt_process_policy(struct file *, const struct fscrypt_policy *); -extern int fscrypt_get_policy(struct inode *, struct fscrypt_policy *); +extern int fscrypt_ioctl_set_policy(struct file *, const void __user *); +extern int fscrypt_ioctl_get_policy(struct file *, void __user *); extern int fscrypt_has_permitted_context(struct inode *, struct inode *); extern int fscrypt_inherit_context(struct inode *, struct inode *, void *, bool); @@ -334,14 +334,14 @@ static inline int fscrypt_notsupp_zeroout_range(const struct inode *i, pgoff_t p } /* policy.c */ -static inline int fscrypt_notsupp_process_policy(struct file *f, - const struct fscrypt_policy *p) +static inline int fscrypt_notsupp_ioctl_set_policy(struct file *f, + const void __user *arg) { return -EOPNOTSUPP; } -static inline int fscrypt_notsupp_get_policy(struct inode *i, - struct fscrypt_policy *p) +static inline int fscrypt_notsupp_ioctl_get_policy(struct file *f, + void __user *arg) { return -EOPNOTSUPP; } -- cgit From 3325bea5b26ac67e2521383f10e5ea0156c9a4b6 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 26 Nov 2016 20:32:46 -0500 Subject: fscrypt: rename get_crypt_info() to fscrypt_get_crypt_info() To avoid namespace collisions, rename get_crypt_info() to fscrypt_get_crypt_info(). The function is only used inside the fs/crypto directory, so declare it in the new header file, fscrypt_private.h. Signed-off-by: Theodore Ts'o Reviewed-by: Eric Biggers --- fs/crypto/fname.c | 4 ++-- fs/crypto/fscrypt_private.h | 19 +++++++++++++++++++ fs/crypto/keyinfo.c | 6 +++--- include/linux/fscrypto.h | 1 - 4 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 fs/crypto/fscrypt_private.h diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c index 6b45d9caeeb0..56ad9d195f18 100644 --- a/fs/crypto/fname.c +++ b/fs/crypto/fname.c @@ -12,7 +12,7 @@ #include #include -#include +#include "fscrypt_private.h" /** * fname_crypt_complete() - completion callback for filename crypto @@ -350,7 +350,7 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname, fname->disk_name.len = iname->len; return 0; } - ret = get_crypt_info(dir); + ret = fscrypt_get_crypt_info(dir); if (ret && ret != -EOPNOTSUPP) return ret; diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h new file mode 100644 index 000000000000..7c31108728e4 --- /dev/null +++ b/fs/crypto/fscrypt_private.h @@ -0,0 +1,19 @@ +/* + * fscrypt_private.h + * + * Copyright (C) 2015, Google, Inc. + * + * This contains encryption key functions. + * + * Written by Michael Halcrow, Ildar Muslukhov, and Uday Savagaonkar, 2015. + */ + +#ifndef _FSCRYPT_PRIVATE_H +#define _FSCRYPT_PRIVATE_H + +#include + +/* keyinfo.c */ +extern int fscrypt_get_crypt_info(struct inode *); + +#endif /* _FSCRYPT_PRIVATE_H */ diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index 67fb6d8876d0..35d3317a27b3 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -10,7 +10,7 @@ #include #include -#include +#include "fscrypt_private.h" static void derive_crypt_complete(struct crypto_async_request *req, int rc) { @@ -178,7 +178,7 @@ static void put_crypt_info(struct fscrypt_info *ci) kmem_cache_free(fscrypt_info_cachep, ci); } -int get_crypt_info(struct inode *inode) +int fscrypt_get_crypt_info(struct inode *inode) { struct fscrypt_info *crypt_info; struct fscrypt_context ctx; @@ -327,7 +327,7 @@ int fscrypt_get_encryption_info(struct inode *inode) (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) | (1 << KEY_FLAG_REVOKED) | (1 << KEY_FLAG_DEAD))))) - return get_crypt_info(inode); + return fscrypt_get_crypt_info(inode); return 0; } EXPORT_SYMBOL(fscrypt_get_encryption_info); diff --git a/include/linux/fscrypto.h b/include/linux/fscrypto.h index be94684dc05f..2f8894f0696c 100644 --- a/include/linux/fscrypto.h +++ b/include/linux/fscrypto.h @@ -265,7 +265,6 @@ extern int fscrypt_has_permitted_context(struct inode *, struct inode *); extern int fscrypt_inherit_context(struct inode *, struct inode *, void *, bool); /* keyinfo.c */ -extern int get_crypt_info(struct inode *); extern int fscrypt_get_encryption_info(struct inode *); extern void fscrypt_put_encryption_info(struct inode *, struct fscrypt_info *); -- cgit From b98701df349b7003efd52d9330acbb7be5a255c6 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 26 Nov 2016 20:43:09 -0500 Subject: fscrypt: unexport fscrypt_initialize() The fscrypt_initalize() function isn't used outside fs/crypto, so there's no point making it be an exported symbol. Signed-off-by: Theodore Ts'o Reviewed-by: Eric Biggers --- fs/crypto/crypto.c | 1 - fs/crypto/fscrypt_private.h | 3 +++ include/linux/fscrypto.h | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index b6029785714c..56f98f45cece 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -540,7 +540,6 @@ fail: mutex_unlock(&fscrypt_init_mutex); return res; } -EXPORT_SYMBOL(fscrypt_initialize); /** * fscrypt_init() - Set up for fs encryption. diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 7c31108728e4..bb92f0c0961b 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -13,6 +13,9 @@ #include +/* crypto.c */ +int fscrypt_initialize(void); + /* keyinfo.c */ extern int fscrypt_get_crypt_info(struct inode *); diff --git a/include/linux/fscrypto.h b/include/linux/fscrypto.h index 2f8894f0696c..ce2ebdee6a89 100644 --- a/include/linux/fscrypto.h +++ b/include/linux/fscrypto.h @@ -244,7 +244,6 @@ static inline void fscrypt_set_d_op(struct dentry *dentry) #if IS_ENABLED(CONFIG_FS_ENCRYPTION) /* crypto.c */ extern struct kmem_cache *fscrypt_info_cachep; -int fscrypt_initialize(void); extern struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *, gfp_t); extern void fscrypt_release_ctx(struct fscrypt_ctx *); -- cgit From cc4e0df038ddb73510c01712abf302b3f0130147 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 26 Nov 2016 22:05:18 -0500 Subject: fscrypt: move non-public structures and constants to fscrypt_private.h Signed-off-by: Theodore Ts'o Reviewed-by: Eric Biggers --- fs/crypto/crypto.c | 2 +- fs/crypto/fscrypt_private.h | 71 +++++++++++++++++++++++++++++++++++++++++++++ fs/crypto/policy.c | 2 +- include/linux/fscrypto.h | 68 ++----------------------------------------- 4 files changed, 76 insertions(+), 67 deletions(-) diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index 56f98f45cece..4d9d221b1d60 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include "fscrypt_private.h" static unsigned int num_prealloc_crypto_pages = 32; static unsigned int num_prealloc_crypto_ctxs = 128; diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index bb92f0c0961b..c98b2a7fb6d3 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -13,6 +13,77 @@ #include +#define FS_FNAME_CRYPTO_DIGEST_SIZE 32 + +/* Encryption parameters */ +#define FS_XTS_TWEAK_SIZE 16 +#define FS_AES_128_ECB_KEY_SIZE 16 +#define FS_AES_256_GCM_KEY_SIZE 32 +#define FS_AES_256_CBC_KEY_SIZE 32 +#define FS_AES_256_CTS_KEY_SIZE 32 +#define FS_AES_256_XTS_KEY_SIZE 64 +#define FS_MAX_KEY_SIZE 64 + +#define FS_KEY_DESC_PREFIX "fscrypt:" +#define FS_KEY_DESC_PREFIX_SIZE 8 + +#define FS_KEY_DERIVATION_NONCE_SIZE 16 + +/** + * Encryption context for inode + * + * Protector format: + * 1 byte: Protector format (1 = this version) + * 1 byte: File contents encryption mode + * 1 byte: File names encryption mode + * 1 byte: Flags + * 8 bytes: Master Key descriptor + * 16 bytes: Encryption Key derivation nonce + */ +struct fscrypt_context { + u8 format; + u8 contents_encryption_mode; + u8 filenames_encryption_mode; + u8 flags; + u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE]; + u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE]; +} __packed; + +#define FS_ENCRYPTION_CONTEXT_FORMAT_V1 1 + +/* This is passed in from userspace into the kernel keyring */ +struct fscrypt_key { + u32 mode; + u8 raw[FS_MAX_KEY_SIZE]; + u32 size; +} __packed; + +/* + * A pointer to this structure is stored in the file system's in-core + * representation of an inode. + */ +struct fscrypt_info { + u8 ci_data_mode; + u8 ci_filename_mode; + u8 ci_flags; + struct crypto_skcipher *ci_ctfm; + struct key *ci_keyring_key; + u8 ci_master_key[FS_KEY_DESCRIPTOR_SIZE]; +}; + +#define FS_CTX_REQUIRES_FREE_ENCRYPT_FL 0x00000001 +#define FS_WRITE_PATH_FL 0x00000002 + +struct fscrypt_completion_result { + struct completion completion; + int res; +}; + +#define DECLARE_FS_COMPLETION_RESULT(ecr) \ + struct fscrypt_completion_result ecr = { \ + COMPLETION_INITIALIZER((ecr).completion), 0 } + + /* crypto.c */ int fscrypt_initialize(void); diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c index b96a10e3cf78..6ed7c2eebeec 100644 --- a/fs/crypto/policy.c +++ b/fs/crypto/policy.c @@ -10,8 +10,8 @@ #include #include -#include #include +#include "fscrypt_private.h" static int inode_has_encryption_context(struct inode *inode) { diff --git a/include/linux/fscrypto.h b/include/linux/fscrypto.h index ce2ebdee6a89..71e8a20711ec 100644 --- a/include/linux/fscrypto.h +++ b/include/linux/fscrypto.h @@ -18,9 +18,6 @@ #include #include -#define FS_KEY_DERIVATION_NONCE_SIZE 16 -#define FS_ENCRYPTION_CONTEXT_FORMAT_V1 1 - #define FS_POLICY_FLAGS_PAD_4 0x00 #define FS_POLICY_FLAGS_PAD_8 0x01 #define FS_POLICY_FLAGS_PAD_16 0x02 @@ -35,56 +32,10 @@ #define FS_ENCRYPTION_MODE_AES_256_CBC 3 #define FS_ENCRYPTION_MODE_AES_256_CTS 4 -/** - * Encryption context for inode - * - * Protector format: - * 1 byte: Protector format (1 = this version) - * 1 byte: File contents encryption mode - * 1 byte: File names encryption mode - * 1 byte: Flags - * 8 bytes: Master Key descriptor - * 16 bytes: Encryption Key derivation nonce - */ -struct fscrypt_context { - u8 format; - u8 contents_encryption_mode; - u8 filenames_encryption_mode; - u8 flags; - u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE]; - u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE]; -} __packed; - -/* Encryption parameters */ -#define FS_XTS_TWEAK_SIZE 16 -#define FS_AES_128_ECB_KEY_SIZE 16 -#define FS_AES_256_GCM_KEY_SIZE 32 -#define FS_AES_256_CBC_KEY_SIZE 32 -#define FS_AES_256_CTS_KEY_SIZE 32 -#define FS_AES_256_XTS_KEY_SIZE 64 -#define FS_MAX_KEY_SIZE 64 - -#define FS_KEY_DESC_PREFIX "fscrypt:" -#define FS_KEY_DESC_PREFIX_SIZE 8 - -/* This is passed in from userspace into the kernel keyring */ -struct fscrypt_key { - u32 mode; - u8 raw[FS_MAX_KEY_SIZE]; - u32 size; -} __packed; - -struct fscrypt_info { - u8 ci_data_mode; - u8 ci_filename_mode; - u8 ci_flags; - struct crypto_skcipher *ci_ctfm; - struct key *ci_keyring_key; - u8 ci_master_key[FS_KEY_DESCRIPTOR_SIZE]; -}; +#define FS_CRYPTO_BLOCK_SIZE 16 -#define FS_CTX_REQUIRES_FREE_ENCRYPT_FL 0x00000001 -#define FS_WRITE_PATH_FL 0x00000002 +struct fscrypt_info; +struct fscrypt_ctx; struct fscrypt_ctx { union { @@ -102,19 +53,6 @@ struct fscrypt_ctx { u8 mode; /* Encryption mode for tfm */ }; -struct fscrypt_completion_result { - struct completion completion; - int res; -}; - -#define DECLARE_FS_COMPLETION_RESULT(ecr) \ - struct fscrypt_completion_result ecr = { \ - COMPLETION_INITIALIZER((ecr).completion), 0 } - -#define FS_FNAME_NUM_SCATTER_ENTRIES 4 -#define FS_CRYPTO_BLOCK_SIZE 16 -#define FS_FNAME_CRYPTO_DIGEST_SIZE 32 - /** * For encrypted symlinks, the ciphertext length is stored at the beginning * of the string in little-endian format. -- cgit From 41d5319af3368127b55f6587f1c747dd6a7b9b04 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 26 Nov 2016 22:18:59 -0500 Subject: fscrypt: move the policy flags and encryption mode definitions to uapi header These constants are part of the UAPI, so they belong in include/uapi/linux/fs.h instead of include/linux/fscrypto.h Signed-off-by: Theodore Ts'o Reviewed-by: Eric Biggers --- include/linux/fscrypto.h | 14 -------------- include/uapi/linux/fs.h | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/include/linux/fscrypto.h b/include/linux/fscrypto.h index 71e8a20711ec..42ef82d60790 100644 --- a/include/linux/fscrypto.h +++ b/include/linux/fscrypto.h @@ -18,20 +18,6 @@ #include #include -#define FS_POLICY_FLAGS_PAD_4 0x00 -#define FS_POLICY_FLAGS_PAD_8 0x01 -#define FS_POLICY_FLAGS_PAD_16 0x02 -#define FS_POLICY_FLAGS_PAD_32 0x03 -#define FS_POLICY_FLAGS_PAD_MASK 0x03 -#define FS_POLICY_FLAGS_VALID 0x03 - -/* Encryption algorithms */ -#define FS_ENCRYPTION_MODE_INVALID 0 -#define FS_ENCRYPTION_MODE_AES_256_XTS 1 -#define FS_ENCRYPTION_MODE_AES_256_GCM 2 -#define FS_ENCRYPTION_MODE_AES_256_CBC 3 -#define FS_ENCRYPTION_MODE_AES_256_CTS 4 - #define FS_CRYPTO_BLOCK_SIZE 16 struct fscrypt_info; diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index acb2b6152ba0..0496d37abe28 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h @@ -254,6 +254,20 @@ struct fsxattr { /* Policy provided via an ioctl on the topmost directory */ #define FS_KEY_DESCRIPTOR_SIZE 8 +#define FS_POLICY_FLAGS_PAD_4 0x00 +#define FS_POLICY_FLAGS_PAD_8 0x01 +#define FS_POLICY_FLAGS_PAD_16 0x02 +#define FS_POLICY_FLAGS_PAD_32 0x03 +#define FS_POLICY_FLAGS_PAD_MASK 0x03 +#define FS_POLICY_FLAGS_VALID 0x03 + +/* Encryption algorithms */ +#define FS_ENCRYPTION_MODE_INVALID 0 +#define FS_ENCRYPTION_MODE_AES_256_XTS 1 +#define FS_ENCRYPTION_MODE_AES_256_GCM 2 +#define FS_ENCRYPTION_MODE_AES_256_CBC 3 +#define FS_ENCRYPTION_MODE_AES_256_CTS 4 + struct fscrypt_policy { __u8 version; __u8 contents_encryption_mode; -- cgit From e550c16c8aab95c7996b0c864d5fcedc2c430a43 Mon Sep 17 00:00:00 2001 From: David Gstir Date: Tue, 6 Dec 2016 23:53:53 +0100 Subject: fscrypt: Use correct index in decrypt path. Actually use the fs-provided index instead of always using page->index which is only set for page-cache pages. Fixes: 9c4bb8a3a9b4 ("fscrypt: Let fs select encryption index/tweak") Signed-off-by: David Gstir Signed-off-by: Theodore Ts'o --- fs/crypto/crypto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index 4d9d221b1d60..d19a42f3a983 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -296,7 +296,7 @@ EXPORT_SYMBOL(fscrypt_encrypt_page); int fscrypt_decrypt_page(const struct inode *inode, struct page *page, unsigned int len, unsigned int offs, pgoff_t index) { - return do_page_crypto(inode, FS_DECRYPT, page->index, page, page, len, offs, + return do_page_crypto(inode, FS_DECRYPT, index, page, page, len, offs, GFP_NOFS); } EXPORT_SYMBOL(fscrypt_decrypt_page); -- cgit From 9e532772b4e36888584efc7a9531143bd43355b3 Mon Sep 17 00:00:00 2001 From: David Gstir Date: Tue, 6 Dec 2016 23:53:54 +0100 Subject: fscrypt: Never allocate fscrypt_ctx on in-place encryption In case of in-place encryption fscrypt_ctx was allocated but never released. Since we don't need it for in-place encryption, we skip allocating it. Fixes: 1c7dcf69eea3 ("fscrypt: Add in-place encryption mode") Signed-off-by: David Gstir Signed-off-by: Theodore Ts'o --- fs/crypto/crypto.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index d19a42f3a983..f287f76cc906 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -246,16 +246,26 @@ struct page *fscrypt_encrypt_page(const struct inode *inode, BUG_ON(plaintext_len % FS_CRYPTO_BLOCK_SIZE != 0); + if (inode->i_sb->s_cop->flags & FS_CFLG_INPLACE_ENCRYPTION) { + /* with inplace-encryption we just encrypt the page */ + err = do_page_crypto(inode, FS_ENCRYPT, index, + plaintext_page, ciphertext_page, + plaintext_len, plaintext_offset, + gfp_flags); + if (err) + return ERR_PTR(err); + + return ciphertext_page; + } + ctx = fscrypt_get_ctx(inode, gfp_flags); if (IS_ERR(ctx)) return (struct page *)ctx; - if (!(inode->i_sb->s_cop->flags & FS_CFLG_INPLACE_ENCRYPTION)) { - /* The encryption operation will require a bounce page. */ - ciphertext_page = alloc_bounce_page(ctx, gfp_flags); - if (IS_ERR(ciphertext_page)) - goto errout; - } + /* The encryption operation will require a bounce page. */ + ciphertext_page = alloc_bounce_page(ctx, gfp_flags); + if (IS_ERR(ciphertext_page)) + goto errout; ctx->w.control_page = plaintext_page; err = do_page_crypto(inode, FS_ENCRYPT, index, @@ -266,11 +276,9 @@ struct page *fscrypt_encrypt_page(const struct inode *inode, ciphertext_page = ERR_PTR(err); goto errout; } - if (!(inode->i_sb->s_cop->flags & FS_CFLG_INPLACE_ENCRYPTION)) { - SetPagePrivate(ciphertext_page); - set_page_private(ciphertext_page, (unsigned long)ctx); - lock_page(ciphertext_page); - } + SetPagePrivate(ciphertext_page); + set_page_private(ciphertext_page, (unsigned long)ctx); + lock_page(ciphertext_page); return ciphertext_page; errout: -- cgit From 1400451f04f2ff28b658b92557495e5090914aee Mon Sep 17 00:00:00 2001 From: David Gstir Date: Tue, 6 Dec 2016 23:53:55 +0100 Subject: fscrypt: Cleanup fscrypt_{decrypt,encrypt}_page() - Improve documentation - Add BUG_ON(len == 0) to avoid accidental switch of offs and len parameters - Improve variable names for readability Signed-off-by: David Gstir Signed-off-by: Theodore Ts'o --- fs/crypto/crypto.c | 93 +++++++++++++++++++++++++++--------------------- include/linux/fscrypto.h | 8 ++--- 2 files changed, 56 insertions(+), 45 deletions(-) diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index f287f76cc906..8c104e712bb2 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -147,9 +147,9 @@ typedef enum { } fscrypt_direction_t; static int do_page_crypto(const struct inode *inode, - fscrypt_direction_t rw, pgoff_t index, + fscrypt_direction_t rw, u64 lblk_num, struct page *src_page, struct page *dest_page, - unsigned int src_len, unsigned int src_offset, + unsigned int len, unsigned int offs, gfp_t gfp_flags) { struct { @@ -163,6 +163,8 @@ static int do_page_crypto(const struct inode *inode, struct crypto_skcipher *tfm = ci->ci_ctfm; int res = 0; + BUG_ON(len == 0); + req = skcipher_request_alloc(tfm, gfp_flags); if (!req) { printk_ratelimited(KERN_ERR @@ -176,14 +178,14 @@ static int do_page_crypto(const struct inode *inode, page_crypt_complete, &ecr); BUILD_BUG_ON(sizeof(xts_tweak) != FS_XTS_TWEAK_SIZE); - xts_tweak.index = cpu_to_le64(index); + xts_tweak.index = cpu_to_le64(lblk_num); memset(xts_tweak.padding, 0, sizeof(xts_tweak.padding)); sg_init_table(&dst, 1); - sg_set_page(&dst, dest_page, src_len, src_offset); + sg_set_page(&dst, dest_page, len, offs); sg_init_table(&src, 1); - sg_set_page(&src, src_page, src_len, src_offset); - skcipher_request_set_crypt(req, &src, &dst, src_len, &xts_tweak); + sg_set_page(&src, src_page, len, offs); + skcipher_request_set_crypt(req, &src, &dst, len, &xts_tweak); if (rw == FS_DECRYPT) res = crypto_skcipher_decrypt(req); else @@ -214,44 +216,53 @@ static struct page *alloc_bounce_page(struct fscrypt_ctx *ctx, gfp_t gfp_flags) /** * fscypt_encrypt_page() - Encrypts a page - * @inode: The inode for which the encryption should take place - * @plaintext_page: The page to encrypt. Must be locked. - * @plaintext_len: Length of plaintext within page - * @plaintext_offset: Offset of plaintext within page - * @index: Index for encryption. This is mainly the page index, but - * but might be different for multiple calls on same page. - * @gfp_flags: The gfp flag for memory allocation + * @inode: The inode for which the encryption should take place + * @page: The page to encrypt. Must be locked for bounce-page + * encryption. + * @len: Length of data to encrypt in @page and encrypted + * data in returned page. + * @offs: Offset of data within @page and returned + * page holding encrypted data. + * @lblk_num: Logical block number. This must be unique for multiple + * calls with same inode, except when overwriting + * previously written data. + * @gfp_flags: The gfp flag for memory allocation * - * Encrypts plaintext_page using the ctx encryption context. If - * the filesystem supports it, encryption is performed in-place, otherwise a - * new ciphertext_page is allocated and returned. + * Encrypts @page using the ctx encryption context. Performs encryption + * either in-place or into a newly allocated bounce page. + * Called on the page write path. * - * Called on the page write path. The caller must call + * Bounce page allocation is the default. + * In this case, the contents of @page are encrypted and stored in an + * allocated bounce page. @page has to be locked and the caller must call * fscrypt_restore_control_page() on the returned ciphertext page to * release the bounce buffer and the encryption context. * - * Return: An allocated page with the encrypted content on success. Else, an + * In-place encryption is used by setting the FS_CFLG_INPLACE_ENCRYPTION flag in + * fscrypt_operations. Here, the input-page is returned with its content + * encrypted. + * + * Return: A page with the encrypted content on success. Else, an * error value or NULL. */ struct page *fscrypt_encrypt_page(const struct inode *inode, - struct page *plaintext_page, - unsigned int plaintext_len, - unsigned int plaintext_offset, - pgoff_t index, gfp_t gfp_flags) + struct page *page, + unsigned int len, + unsigned int offs, + u64 lblk_num, gfp_t gfp_flags) { struct fscrypt_ctx *ctx; - struct page *ciphertext_page = plaintext_page; + struct page *ciphertext_page = page; int err; - BUG_ON(plaintext_len % FS_CRYPTO_BLOCK_SIZE != 0); + BUG_ON(len % FS_CRYPTO_BLOCK_SIZE != 0); if (inode->i_sb->s_cop->flags & FS_CFLG_INPLACE_ENCRYPTION) { /* with inplace-encryption we just encrypt the page */ - err = do_page_crypto(inode, FS_ENCRYPT, index, - plaintext_page, ciphertext_page, - plaintext_len, plaintext_offset, - gfp_flags); + err = do_page_crypto(inode, FS_ENCRYPT, lblk_num, + page, ciphertext_page, + len, offs, gfp_flags); if (err) return ERR_PTR(err); @@ -267,11 +278,10 @@ struct page *fscrypt_encrypt_page(const struct inode *inode, if (IS_ERR(ciphertext_page)) goto errout; - ctx->w.control_page = plaintext_page; - err = do_page_crypto(inode, FS_ENCRYPT, index, - plaintext_page, ciphertext_page, - plaintext_len, plaintext_offset, - gfp_flags); + ctx->w.control_page = page; + err = do_page_crypto(inode, FS_ENCRYPT, lblk_num, + page, ciphertext_page, + len, offs, gfp_flags); if (err) { ciphertext_page = ERR_PTR(err); goto errout; @@ -289,11 +299,12 @@ EXPORT_SYMBOL(fscrypt_encrypt_page); /** * fscrypt_decrypt_page() - Decrypts a page in-place - * @inode: Encrypted inode to decrypt. - * @page: The page to decrypt. Must be locked. - * @len: Number of bytes in @page to be decrypted. - * @offs: Start of data in @page. - * @index: Index for encryption. + * @inode: The corresponding inode for the page to decrypt. + * @page: The page to decrypt. Must be locked in case + * it is a writeback page. + * @len: Number of bytes in @page to be decrypted. + * @offs: Start of data in @page. + * @lblk_num: Logical block number. * * Decrypts page in-place using the ctx encryption context. * @@ -302,10 +313,10 @@ EXPORT_SYMBOL(fscrypt_encrypt_page); * Return: Zero on success, non-zero otherwise. */ int fscrypt_decrypt_page(const struct inode *inode, struct page *page, - unsigned int len, unsigned int offs, pgoff_t index) + unsigned int len, unsigned int offs, u64 lblk_num) { - return do_page_crypto(inode, FS_DECRYPT, index, page, page, len, offs, - GFP_NOFS); + return do_page_crypto(inode, FS_DECRYPT, lblk_num, page, page, len, + offs, GFP_NOFS); } EXPORT_SYMBOL(fscrypt_decrypt_page); diff --git a/include/linux/fscrypto.h b/include/linux/fscrypto.h index 42ef82d60790..2d9abfa22b94 100644 --- a/include/linux/fscrypto.h +++ b/include/linux/fscrypto.h @@ -173,9 +173,9 @@ extern struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *, gfp_t); extern void fscrypt_release_ctx(struct fscrypt_ctx *); extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *, unsigned int, unsigned int, - pgoff_t, gfp_t); + u64, gfp_t); extern int fscrypt_decrypt_page(const struct inode *, struct page *, unsigned int, - unsigned int, pgoff_t); + unsigned int, u64); extern void fscrypt_decrypt_bio_pages(struct fscrypt_ctx *, struct bio *); extern void fscrypt_pullback_bio_page(struct page **, bool); extern void fscrypt_restore_control_page(struct page *); @@ -221,14 +221,14 @@ static inline struct page *fscrypt_notsupp_encrypt_page(const struct inode *i, struct page *p, unsigned int len, unsigned int offs, - pgoff_t index, gfp_t f) + u64 lblk_num, gfp_t f) { return ERR_PTR(-EOPNOTSUPP); } static inline int fscrypt_notsupp_decrypt_page(const struct inode *i, struct page *p, unsigned int len, unsigned int offs, - pgoff_t index) + u64 lblk_num) { return -EOPNOTSUPP; } -- cgit From bd7b8290388dd58a8c0a3710b171e58ef952ca4d Mon Sep 17 00:00:00 2001 From: David Gstir Date: Tue, 6 Dec 2016 23:53:56 +0100 Subject: fscrypt: Cleanup page locking requirements for fscrypt_{decrypt,encrypt}_page() Rename the FS_CFLG_INPLACE_ENCRYPTION flag to FS_CFLG_OWN_PAGES which, when set, indicates that the fs uses pages under its own control as opposed to writeback pages which require locking and a bounce buffer for encryption. Signed-off-by: David Gstir Signed-off-by: Theodore Ts'o --- fs/crypto/crypto.c | 11 ++++++++--- fs/ext4/inode.c | 1 - fs/f2fs/data.c | 1 - include/linux/fscrypto.h | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index 8c104e712bb2..5ffc59436397 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -238,7 +238,7 @@ static struct page *alloc_bounce_page(struct fscrypt_ctx *ctx, gfp_t gfp_flags) * fscrypt_restore_control_page() on the returned ciphertext page to * release the bounce buffer and the encryption context. * - * In-place encryption is used by setting the FS_CFLG_INPLACE_ENCRYPTION flag in + * In-place encryption is used by setting the FS_CFLG_OWN_PAGES flag in * fscrypt_operations. Here, the input-page is returned with its content * encrypted. * @@ -258,7 +258,7 @@ struct page *fscrypt_encrypt_page(const struct inode *inode, BUG_ON(len % FS_CRYPTO_BLOCK_SIZE != 0); - if (inode->i_sb->s_cop->flags & FS_CFLG_INPLACE_ENCRYPTION) { + if (inode->i_sb->s_cop->flags & FS_CFLG_OWN_PAGES) { /* with inplace-encryption we just encrypt the page */ err = do_page_crypto(inode, FS_ENCRYPT, lblk_num, page, ciphertext_page, @@ -269,6 +269,8 @@ struct page *fscrypt_encrypt_page(const struct inode *inode, return ciphertext_page; } + BUG_ON(!PageLocked(page)); + ctx = fscrypt_get_ctx(inode, gfp_flags); if (IS_ERR(ctx)) return (struct page *)ctx; @@ -301,7 +303,7 @@ EXPORT_SYMBOL(fscrypt_encrypt_page); * fscrypt_decrypt_page() - Decrypts a page in-place * @inode: The corresponding inode for the page to decrypt. * @page: The page to decrypt. Must be locked in case - * it is a writeback page. + * it is a writeback page (FS_CFLG_OWN_PAGES unset). * @len: Number of bytes in @page to be decrypted. * @offs: Start of data in @page. * @lblk_num: Logical block number. @@ -315,6 +317,9 @@ EXPORT_SYMBOL(fscrypt_encrypt_page); int fscrypt_decrypt_page(const struct inode *inode, struct page *page, unsigned int len, unsigned int offs, u64 lblk_num) { + if (!(inode->i_sb->s_cop->flags & FS_CFLG_OWN_PAGES)) + BUG_ON(!PageLocked(page)); + return do_page_crypto(inode, FS_DECRYPT, lblk_num, page, page, len, offs, GFP_NOFS); } diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 1485ac273bfb..fb2b514f675b 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3744,7 +3744,6 @@ static int __ext4_block_zero_page_range(handle_t *handle, /* We expect the key to be set. */ BUG_ON(!fscrypt_has_encryption_key(inode)); BUG_ON(blocksize != PAGE_SIZE); - BUG_ON(!PageLocked(page)); WARN_ON_ONCE(fscrypt_decrypt_page(page->mapping->host, page, PAGE_SIZE, 0, page->index)); } diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 435590c4b341..9f0ba90b92e4 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1194,7 +1194,6 @@ int do_write_data_page(struct f2fs_io_info *fio) f2fs_wait_on_encrypted_page_writeback(F2FS_I_SB(inode), fio->old_blkaddr); retry_encrypt: - BUG_ON(!PageLocked(fio->page)); fio->encrypted_page = fscrypt_encrypt_page(inode, fio->page, PAGE_SIZE, 0, fio->page->index, diff --git a/include/linux/fscrypto.h b/include/linux/fscrypto.h index 2d9abfa22b94..188b4fa59cbf 100644 --- a/include/linux/fscrypto.h +++ b/include/linux/fscrypto.h @@ -80,7 +80,7 @@ struct fscrypt_name { /* * fscrypt superblock flags */ -#define FS_CFLG_INPLACE_ENCRYPTION (1U << 1) +#define FS_CFLG_OWN_PAGES (1U << 1) /* * crypto opertions for filesystems -- cgit From f32d7ac20a5864483c1f96e4970daa083e18bfd1 Mon Sep 17 00:00:00 2001 From: David Gstir Date: Tue, 6 Dec 2016 23:53:57 +0100 Subject: fscrypt: Delay bounce page pool allocation until needed Since fscrypt users can now indicated if fscrypt_encrypt_page() should use a bounce page, we can delay the bounce page pool initialization util it is really needed. That is until fscrypt_operations has no FS_CFLG_OWN_PAGES flag set. Signed-off-by: David Gstir Signed-off-by: Theodore Ts'o --- fs/crypto/crypto.c | 9 +++++++-- fs/crypto/fscrypt_private.h | 2 +- fs/crypto/keyinfo.c | 2 +- include/linux/fscrypto.h | 1 - 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index 5ffc59436397..bc1d4781b9ec 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -525,17 +525,22 @@ static void fscrypt_destroy(void) /** * fscrypt_initialize() - allocate major buffers for fs encryption. + * @cop_flags: fscrypt operations flags * * We only call this when we start accessing encrypted files, since it * results in memory getting allocated that wouldn't otherwise be used. * * Return: Zero on success, non-zero otherwise. */ -int fscrypt_initialize(void) +int fscrypt_initialize(unsigned int cop_flags) { int i, res = -ENOMEM; - if (fscrypt_bounce_page_pool) + /* + * No need to allocate a bounce page pool if there already is one or + * this FS won't use it. + */ + if (cop_flags & FS_CFLG_OWN_PAGES || fscrypt_bounce_page_pool) return 0; mutex_lock(&fscrypt_init_mutex); diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index c98b2a7fb6d3..7ba10cd45a2e 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -85,7 +85,7 @@ struct fscrypt_completion_result { /* crypto.c */ -int fscrypt_initialize(void); +int fscrypt_initialize(unsigned int cop_flags); /* keyinfo.c */ extern int fscrypt_get_crypt_info(struct inode *); diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index 35d3317a27b3..6eeea1dcba41 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -188,7 +188,7 @@ int fscrypt_get_crypt_info(struct inode *inode) u8 *raw_key = NULL; int res; - res = fscrypt_initialize(); + res = fscrypt_initialize(inode->i_sb->s_cop->flags); if (res) return res; diff --git a/include/linux/fscrypto.h b/include/linux/fscrypto.h index 188b4fa59cbf..1adc1c758d31 100644 --- a/include/linux/fscrypto.h +++ b/include/linux/fscrypto.h @@ -168,7 +168,6 @@ static inline void fscrypt_set_d_op(struct dentry *dentry) #if IS_ENABLED(CONFIG_FS_ENCRYPTION) /* crypto.c */ extern struct kmem_cache *fscrypt_info_cachep; - extern struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *, gfp_t); extern void fscrypt_release_ctx(struct fscrypt_ctx *); extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *, -- cgit From 6a34e4d2be07255cc59e6ccaf820669cfd7f815c Mon Sep 17 00:00:00 2001 From: David Gstir Date: Tue, 6 Dec 2016 23:53:58 +0100 Subject: fscrypt: Rename FS_WRITE_PATH_FL to FS_CTX_HAS_BOUNCE_BUFFER_FL ... to better explain its purpose after introducing in-place encryption without bounce buffer. Signed-off-by: David Gstir Signed-off-by: Theodore Ts'o --- fs/crypto/crypto.c | 6 +++--- fs/crypto/fscrypt_private.h | 2 +- include/linux/fscrypto.h | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index bc1d4781b9ec..ac8e4f6a3773 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -63,7 +63,7 @@ void fscrypt_release_ctx(struct fscrypt_ctx *ctx) { unsigned long flags; - if (ctx->flags & FS_WRITE_PATH_FL && ctx->w.bounce_page) { + if (ctx->flags & FS_CTX_HAS_BOUNCE_BUFFER_FL && ctx->w.bounce_page) { mempool_free(ctx->w.bounce_page, fscrypt_bounce_page_pool); ctx->w.bounce_page = NULL; } @@ -121,7 +121,7 @@ struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *inode, gfp_t gfp_flags) } else { ctx->flags &= ~FS_CTX_REQUIRES_FREE_ENCRYPT_FL; } - ctx->flags &= ~FS_WRITE_PATH_FL; + ctx->flags &= ~FS_CTX_HAS_BOUNCE_BUFFER_FL; return ctx; } EXPORT_SYMBOL(fscrypt_get_ctx); @@ -210,7 +210,7 @@ static struct page *alloc_bounce_page(struct fscrypt_ctx *ctx, gfp_t gfp_flags) ctx->w.bounce_page = mempool_alloc(fscrypt_bounce_page_pool, gfp_flags); if (ctx->w.bounce_page == NULL) return ERR_PTR(-ENOMEM); - ctx->flags |= FS_WRITE_PATH_FL; + ctx->flags |= FS_CTX_HAS_BOUNCE_BUFFER_FL; return ctx->w.bounce_page; } diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 7ba10cd45a2e..aeab032d7d35 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -72,7 +72,7 @@ struct fscrypt_info { }; #define FS_CTX_REQUIRES_FREE_ENCRYPT_FL 0x00000001 -#define FS_WRITE_PATH_FL 0x00000002 +#define FS_CTX_HAS_BOUNCE_BUFFER_FL 0x00000002 struct fscrypt_completion_result { struct completion completion; diff --git a/include/linux/fscrypto.h b/include/linux/fscrypto.h index 1adc1c758d31..c074b670aa99 100644 --- a/include/linux/fscrypto.h +++ b/include/linux/fscrypto.h @@ -21,7 +21,6 @@ #define FS_CRYPTO_BLOCK_SIZE 16 struct fscrypt_info; -struct fscrypt_ctx; struct fscrypt_ctx { union { -- cgit