Network filesystems usually don't know what inode number they'll have until after the reply to a create RPC comes in. But we do need a (blank) crypto context before that point. Break out the part of fscrypt_inherit_context that creates a new context without setting it into the new inode just yet. Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx> --- fs/crypto/policy.c | 42 ++++++++++++++++++++++++++++++----------- include/linux/fscrypt.h | 6 ++++++ 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c index 2d73fd39ad96..13e0a50157d5 100644 --- a/fs/crypto/policy.c +++ b/fs/crypto/policy.c @@ -621,19 +621,19 @@ int fscrypt_has_permitted_context(struct inode *parent, struct inode *child) EXPORT_SYMBOL(fscrypt_has_permitted_context); /** - * fscrypt_inherit_context() - Sets a child context from its parent + * fscrypt_new_context_from_parent() - generate a new fscrypt context from its parent * @parent: Parent inode from which the context is inherited. - * @child: Child inode that inherits the context from @parent. - * @fs_data: private data given by FS. - * @preload: preload child i_crypt_info if true + * @ctx: destination for new encryption context * - * Return: 0 on success, -errno on failure + * Generate a new encryption context for an inode from its parent, suitable + * for later installation into a child dentry's inode. Returns positive + * length of the new context on success, or -errno on failure. + * + * Note that the caller must ensure that it provides sufficient buffer space + * to write out the context (at least FSCRYPT_SET_CONTEXT_MAX_SIZE bytes). */ -int fscrypt_inherit_context(struct inode *parent, struct inode *child, - void *fs_data, bool preload) +int fscrypt_new_context_from_parent(struct inode *parent, void *ctx) { - union fscrypt_context ctx; - int ctxsize; struct fscrypt_info *ci; int res; @@ -645,10 +645,30 @@ int fscrypt_inherit_context(struct inode *parent, struct inode *child, if (ci == NULL) return -ENOKEY; - ctxsize = fscrypt_new_context_from_policy(&ctx, &ci->ci_policy); + return fscrypt_new_context_from_policy(ctx, &ci->ci_policy); +} +EXPORT_SYMBOL(fscrypt_new_context_from_parent); + +/** + * fscrypt_inherit_context() - Sets a child context from its parent + * @parent: Parent inode from which the context is inherited. + * @child: Child inode that inherits the context from @parent. + * @fs_data: private data given by FS. + * @preload: preload child i_crypt_info if true + * + * Return: 0 on success, -errno on failure + */ +int fscrypt_inherit_context(struct inode *parent, struct inode *child, + void *fs_data, bool preload) +{ + union fscrypt_context ctx; + int res; BUILD_BUG_ON(sizeof(ctx) != FSCRYPT_SET_CONTEXT_MAX_SIZE); - res = parent->i_sb->s_cop->set_context(child, &ctx, ctxsize, fs_data); + res = fscrypt_new_context_from_parent(parent, &ctx); + if (res < 0) + return res; + res = parent->i_sb->s_cop->set_context(child, &ctx, res, fs_data); if (res) return res; return preload ? fscrypt_get_encryption_info(child): 0; diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index eaf16eb55788..c5fe6f334a1d 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -156,6 +156,7 @@ int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg); int fscrypt_ioctl_get_policy_ex(struct file *filp, void __user *arg); int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg); int fscrypt_has_permitted_context(struct inode *parent, struct inode *child); +int fscrypt_new_context_from_parent(struct inode *parent, void *); int fscrypt_inherit_context(struct inode *parent, struct inode *child, void *fs_data, bool preload); @@ -340,6 +341,11 @@ static inline int fscrypt_has_permitted_context(struct inode *parent, return 0; } +static inline int fscrypt_new_context_from_parent(struct inode *parent, void *ctx); +{ + return -EOPNOTSUPP; +} + static inline int fscrypt_inherit_context(struct inode *parent, struct inode *child, void *fs_data, bool preload) -- 2.26.2