Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fscrypt: new helper function - fscrypt_prepare_lookup_partial()

This patch introduces a new helper function which can be used both in
lookups and in atomic_open operations by filesystems that want to handle
filename encryption and no-key dentries themselves.

The reason for this function to be used in atomic open is that this
operation can act as a lookup if handed a dentry that is negative. And in
this case we may need to set DCACHE_NOKEY_NAME.

Signed-off-by: Luís Henriques <lhenriques@suse.de>
Tested-by: Xiubo Li <xiubli@redhat.com>
Reviewed-by: Xiubo Li <xiubli@redhat.com>
[ebiggers: improved the function comment, and moved the function to just
below __fscrypt_prepare_lookup()]
Link: https://lore.kernel.org/r/20230320220149.21863-1-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@google.com>

authored by

Luís Henriques and committed by
Eric Biggers
6f2656ea 9c7fb7f7

+37
+30
fs/crypto/hooks.c
··· 111 111 } 112 112 EXPORT_SYMBOL_GPL(__fscrypt_prepare_lookup); 113 113 114 + /** 115 + * fscrypt_prepare_lookup_partial() - prepare lookup without filename setup 116 + * @dir: the encrypted directory being searched 117 + * @dentry: the dentry being looked up in @dir 118 + * 119 + * This function should be used by the ->lookup and ->atomic_open methods of 120 + * filesystems that handle filename encryption and no-key name encoding 121 + * themselves and thus can't use fscrypt_prepare_lookup(). Like 122 + * fscrypt_prepare_lookup(), this will try to set up the directory's encryption 123 + * key and will set DCACHE_NOKEY_NAME on the dentry if the key is unavailable. 124 + * However, this function doesn't set up a struct fscrypt_name for the filename. 125 + * 126 + * Return: 0 on success; -errno on error. Note that the encryption key being 127 + * unavailable is not considered an error. It is also not an error if 128 + * the encryption policy is unsupported by this kernel; that is treated 129 + * like the key being unavailable, so that files can still be deleted. 130 + */ 131 + int fscrypt_prepare_lookup_partial(struct inode *dir, struct dentry *dentry) 132 + { 133 + int err = fscrypt_get_encryption_info(dir, true); 134 + 135 + if (!err && !fscrypt_has_encryption_key(dir)) { 136 + spin_lock(&dentry->d_lock); 137 + dentry->d_flags |= DCACHE_NOKEY_NAME; 138 + spin_unlock(&dentry->d_lock); 139 + } 140 + return err; 141 + } 142 + EXPORT_SYMBOL_GPL(fscrypt_prepare_lookup_partial); 143 + 114 144 int __fscrypt_prepare_readdir(struct inode *dir) 115 145 { 116 146 return fscrypt_get_encryption_info(dir, true);
+7
include/linux/fscrypt.h
··· 359 359 unsigned int flags); 360 360 int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry, 361 361 struct fscrypt_name *fname); 362 + int fscrypt_prepare_lookup_partial(struct inode *dir, struct dentry *dentry); 362 363 int __fscrypt_prepare_readdir(struct inode *dir); 363 364 int __fscrypt_prepare_setattr(struct dentry *dentry, struct iattr *attr); 364 365 int fscrypt_prepare_setflags(struct inode *inode, ··· 670 669 static inline int __fscrypt_prepare_lookup(struct inode *dir, 671 670 struct dentry *dentry, 672 671 struct fscrypt_name *fname) 672 + { 673 + return -EOPNOTSUPP; 674 + } 675 + 676 + static inline int fscrypt_prepare_lookup_partial(struct inode *dir, 677 + struct dentry *dentry) 673 678 { 674 679 return -EOPNOTSUPP; 675 680 }