mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-31 16:38:12 +00:00
case-insensitive updates for 6.9
- Patch case-insensitive lookup by trying the case-exact comparison first, before falling back to costly utf8 casefolded comparison. - Fix to forbid using a case-insensitive directory as part of an overlayfs mount. - Patchset to ensure d_op are set at d_alloc time for fscrypt and casefold volumes, ensuring filesystem dentries will all have the correct ops, whether they come from a lookup or not. -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQRIEdicmeMNCZKVCdo6u2Upsdk6RAUCZedXSQAKCRA6u2Upsdk6 RILBAQDXBwZjsdW4DM9CW1HYBKl7gx0rYOBI7HhlMd63ndHxvwD+N9kMWHCS+ERh QdYPEK5q44NYKTLeRE9lILjLsUCM9Q0= =dovM -----END PGP SIGNATURE----- gpgsig -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQRAhzRXHqcMeLMyaSiRxhvAZXjcogUCZemdjgAKCRCRxhvAZXjc opLhAP9/oVGFQViYR7rAr8v/uh9yQYbRJwq5O1HRCBlwSR5/qgD/e8QVP+MYfgSb /tKX+8n5rRnQlrieEsWFKfDtk6FvAQo= =Nbke -----END PGP SIGNATURE----- Merge tag 'for-next-6.9' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/krisman/unicode into vfs.misc Merge case-insensitive updates from Gabriel Krisman Bertazi: - Patch case-insensitive lookup by trying the case-exact comparison first, before falling back to costly utf8 casefolded comparison. - Fix to forbid using a case-insensitive directory as part of an overlayfs mount. - Patchset to ensure d_op are set at d_alloc time for fscrypt and casefold volumes, ensuring filesystem dentries will all have the correct ops, whether they come from a lookup or not. * tag 'for-next-6.9' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/krisman/unicode: libfs: Drop generic_set_encrypted_ci_d_ops ubifs: Configure dentry operations at dentry-creation time f2fs: Configure dentry operations at dentry-creation time ext4: Configure dentry operations at dentry-creation time libfs: Add helper to choose dentry operations at mount-time libfs: Merge encrypted_ci_dentry_ops and ci_dentry_ops fscrypt: Drop d_revalidate once the key is added fscrypt: Drop d_revalidate for valid dentries during lookup fscrypt: Factor out a helper to configure the lookup dentry ovl: Always reject mounting over case-insensitive directories libfs: Attempt exact-match comparison first during casefolded lookup Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
commit
09406ad8e5
11 changed files with 128 additions and 86 deletions
|
@ -102,11 +102,8 @@ int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry,
|
||||||
if (err && err != -ENOENT)
|
if (err && err != -ENOENT)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (fname->is_nokey_name) {
|
fscrypt_prepare_dentry(dentry, fname->is_nokey_name);
|
||||||
spin_lock(&dentry->d_lock);
|
|
||||||
dentry->d_flags |= DCACHE_NOKEY_NAME;
|
|
||||||
spin_unlock(&dentry->d_lock);
|
|
||||||
}
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__fscrypt_prepare_lookup);
|
EXPORT_SYMBOL_GPL(__fscrypt_prepare_lookup);
|
||||||
|
@ -131,12 +128,10 @@ EXPORT_SYMBOL_GPL(__fscrypt_prepare_lookup);
|
||||||
int fscrypt_prepare_lookup_partial(struct inode *dir, struct dentry *dentry)
|
int fscrypt_prepare_lookup_partial(struct inode *dir, struct dentry *dentry)
|
||||||
{
|
{
|
||||||
int err = fscrypt_get_encryption_info(dir, true);
|
int err = fscrypt_get_encryption_info(dir, true);
|
||||||
|
bool is_nokey_name = (!err && !fscrypt_has_encryption_key(dir));
|
||||||
|
|
||||||
|
fscrypt_prepare_dentry(dentry, is_nokey_name);
|
||||||
|
|
||||||
if (!err && !fscrypt_has_encryption_key(dir)) {
|
|
||||||
spin_lock(&dentry->d_lock);
|
|
||||||
dentry->d_flags |= DCACHE_NOKEY_NAME;
|
|
||||||
spin_unlock(&dentry->d_lock);
|
|
||||||
}
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(fscrypt_prepare_lookup_partial);
|
EXPORT_SYMBOL_GPL(fscrypt_prepare_lookup_partial);
|
||||||
|
|
|
@ -1762,7 +1762,6 @@ static struct buffer_head *ext4_lookup_entry(struct inode *dir,
|
||||||
struct buffer_head *bh;
|
struct buffer_head *bh;
|
||||||
|
|
||||||
err = ext4_fname_prepare_lookup(dir, dentry, &fname);
|
err = ext4_fname_prepare_lookup(dir, dentry, &fname);
|
||||||
generic_set_encrypted_ci_d_ops(dentry);
|
|
||||||
if (err == -ENOENT)
|
if (err == -ENOENT)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (err)
|
if (err)
|
||||||
|
|
|
@ -5484,6 +5484,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
|
||||||
goto failed_mount4;
|
goto failed_mount4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
generic_set_sb_d_ops(sb);
|
||||||
sb->s_root = d_make_root(root);
|
sb->s_root = d_make_root(root);
|
||||||
if (!sb->s_root) {
|
if (!sb->s_root) {
|
||||||
ext4_msg(sb, KERN_ERR, "get root dentry failed");
|
ext4_msg(sb, KERN_ERR, "get root dentry failed");
|
||||||
|
|
|
@ -531,7 +531,6 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = f2fs_prepare_lookup(dir, dentry, &fname);
|
err = f2fs_prepare_lookup(dir, dentry, &fname);
|
||||||
generic_set_encrypted_ci_d_ops(dentry);
|
|
||||||
if (err == -ENOENT)
|
if (err == -ENOENT)
|
||||||
goto out_splice;
|
goto out_splice;
|
||||||
if (err)
|
if (err)
|
||||||
|
|
|
@ -4660,6 +4660,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
goto free_node_inode;
|
goto free_node_inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
generic_set_sb_d_ops(sb);
|
||||||
sb->s_root = d_make_root(root); /* allocate root dentry */
|
sb->s_root = d_make_root(root); /* allocate root dentry */
|
||||||
if (!sb->s_root) {
|
if (!sb->s_root) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
|
|
102
fs/libfs.c
102
fs/libfs.c
|
@ -1738,16 +1738,28 @@ bool is_empty_dir_inode(struct inode *inode)
|
||||||
static int generic_ci_d_compare(const struct dentry *dentry, unsigned int len,
|
static int generic_ci_d_compare(const struct dentry *dentry, unsigned int len,
|
||||||
const char *str, const struct qstr *name)
|
const char *str, const struct qstr *name)
|
||||||
{
|
{
|
||||||
const struct dentry *parent = READ_ONCE(dentry->d_parent);
|
const struct dentry *parent;
|
||||||
const struct inode *dir = READ_ONCE(parent->d_inode);
|
const struct inode *dir;
|
||||||
const struct super_block *sb = dentry->d_sb;
|
|
||||||
const struct unicode_map *um = sb->s_encoding;
|
|
||||||
struct qstr qstr = QSTR_INIT(str, len);
|
|
||||||
char strbuf[DNAME_INLINE_LEN];
|
char strbuf[DNAME_INLINE_LEN];
|
||||||
int ret;
|
struct qstr qstr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attempt a case-sensitive match first. It is cheaper and
|
||||||
|
* should cover most lookups, including all the sane
|
||||||
|
* applications that expect a case-sensitive filesystem.
|
||||||
|
*
|
||||||
|
* This comparison is safe under RCU because the caller
|
||||||
|
* guarantees the consistency between str and len. See
|
||||||
|
* __d_lookup_rcu_op_compare() for details.
|
||||||
|
*/
|
||||||
|
if (len == name->len && !memcmp(str, name->name, len))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
parent = READ_ONCE(dentry->d_parent);
|
||||||
|
dir = READ_ONCE(parent->d_inode);
|
||||||
if (!dir || !IS_CASEFOLDED(dir))
|
if (!dir || !IS_CASEFOLDED(dir))
|
||||||
goto fallback;
|
return 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the dentry name is stored in-line, then it may be concurrently
|
* If the dentry name is stored in-line, then it may be concurrently
|
||||||
* modified by a rename. If this happens, the VFS will eventually retry
|
* modified by a rename. If this happens, the VFS will eventually retry
|
||||||
|
@ -1758,20 +1770,14 @@ static int generic_ci_d_compare(const struct dentry *dentry, unsigned int len,
|
||||||
if (len <= DNAME_INLINE_LEN - 1) {
|
if (len <= DNAME_INLINE_LEN - 1) {
|
||||||
memcpy(strbuf, str, len);
|
memcpy(strbuf, str, len);
|
||||||
strbuf[len] = 0;
|
strbuf[len] = 0;
|
||||||
qstr.name = strbuf;
|
str = strbuf;
|
||||||
/* prevent compiler from optimizing out the temporary buffer */
|
/* prevent compiler from optimizing out the temporary buffer */
|
||||||
barrier();
|
barrier();
|
||||||
}
|
}
|
||||||
ret = utf8_strncasecmp(um, name, &qstr);
|
qstr.len = len;
|
||||||
if (ret >= 0)
|
qstr.name = str;
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (sb_has_strict_encoding(sb))
|
return utf8_strncasecmp(dentry->d_sb->s_encoding, name, &qstr);
|
||||||
return -EINVAL;
|
|
||||||
fallback:
|
|
||||||
if (len != name->len)
|
|
||||||
return 1;
|
|
||||||
return !!memcmp(str, name->name, len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1800,6 +1806,9 @@ static int generic_ci_d_hash(const struct dentry *dentry, struct qstr *str)
|
||||||
static const struct dentry_operations generic_ci_dentry_ops = {
|
static const struct dentry_operations generic_ci_dentry_ops = {
|
||||||
.d_hash = generic_ci_d_hash,
|
.d_hash = generic_ci_d_hash,
|
||||||
.d_compare = generic_ci_d_compare,
|
.d_compare = generic_ci_d_compare,
|
||||||
|
#ifdef CONFIG_FS_ENCRYPTION
|
||||||
|
.d_revalidate = fscrypt_d_revalidate,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1809,64 +1818,33 @@ static const struct dentry_operations generic_encrypted_dentry_ops = {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_FS_ENCRYPTION) && IS_ENABLED(CONFIG_UNICODE)
|
|
||||||
static const struct dentry_operations generic_encrypted_ci_dentry_ops = {
|
|
||||||
.d_hash = generic_ci_d_hash,
|
|
||||||
.d_compare = generic_ci_d_compare,
|
|
||||||
.d_revalidate = fscrypt_d_revalidate,
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* generic_set_encrypted_ci_d_ops - helper for setting d_ops for given dentry
|
* generic_set_sb_d_ops - helper for choosing the set of
|
||||||
* @dentry: dentry to set ops on
|
* filesystem-wide dentry operations for the enabled features
|
||||||
|
* @sb: superblock to be configured
|
||||||
*
|
*
|
||||||
* Casefolded directories need d_hash and d_compare set, so that the dentries
|
* Filesystems supporting casefolding and/or fscrypt can call this
|
||||||
* contained in them are handled case-insensitively. Note that these operations
|
* helper at mount-time to configure sb->s_d_op to best set of dentry
|
||||||
* are needed on the parent directory rather than on the dentries in it, and
|
* operations required for the enabled features. The helper must be
|
||||||
* while the casefolding flag can be toggled on and off on an empty directory,
|
* called after these have been configured, but before the root dentry
|
||||||
* dentry_operations can't be changed later. As a result, if the filesystem has
|
* is created.
|
||||||
* casefolding support enabled at all, we have to give all dentries the
|
|
||||||
* casefolding operations even if their inode doesn't have the casefolding flag
|
|
||||||
* currently (and thus the casefolding ops would be no-ops for now).
|
|
||||||
*
|
|
||||||
* Encryption works differently in that the only dentry operation it needs is
|
|
||||||
* d_revalidate, which it only needs on dentries that have the no-key name flag.
|
|
||||||
* The no-key flag can't be set "later", so we don't have to worry about that.
|
|
||||||
*
|
|
||||||
* Finally, to maximize compatibility with overlayfs (which isn't compatible
|
|
||||||
* with certain dentry operations) and to avoid taking an unnecessary
|
|
||||||
* performance hit, we use custom dentry_operations for each possible
|
|
||||||
* combination rather than always installing all operations.
|
|
||||||
*/
|
*/
|
||||||
void generic_set_encrypted_ci_d_ops(struct dentry *dentry)
|
void generic_set_sb_d_ops(struct super_block *sb)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_FS_ENCRYPTION
|
|
||||||
bool needs_encrypt_ops = dentry->d_flags & DCACHE_NOKEY_NAME;
|
|
||||||
#endif
|
|
||||||
#if IS_ENABLED(CONFIG_UNICODE)
|
#if IS_ENABLED(CONFIG_UNICODE)
|
||||||
bool needs_ci_ops = dentry->d_sb->s_encoding;
|
if (sb->s_encoding) {
|
||||||
#endif
|
sb->s_d_op = &generic_ci_dentry_ops;
|
||||||
#if defined(CONFIG_FS_ENCRYPTION) && IS_ENABLED(CONFIG_UNICODE)
|
|
||||||
if (needs_encrypt_ops && needs_ci_ops) {
|
|
||||||
d_set_d_op(dentry, &generic_encrypted_ci_dentry_ops);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_FS_ENCRYPTION
|
#ifdef CONFIG_FS_ENCRYPTION
|
||||||
if (needs_encrypt_ops) {
|
if (sb->s_cop) {
|
||||||
d_set_d_op(dentry, &generic_encrypted_dentry_ops);
|
sb->s_d_op = &generic_encrypted_dentry_ops;
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if IS_ENABLED(CONFIG_UNICODE)
|
|
||||||
if (needs_ci_ops) {
|
|
||||||
d_set_d_op(dentry, &generic_ci_dentry_ops);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(generic_set_encrypted_ci_d_ops);
|
EXPORT_SYMBOL(generic_set_sb_d_ops);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* inode_maybe_inc_iversion - increments i_version
|
* inode_maybe_inc_iversion - increments i_version
|
||||||
|
|
|
@ -280,12 +280,20 @@ static int ovl_mount_dir_check(struct fs_context *fc, const struct path *path,
|
||||||
{
|
{
|
||||||
struct ovl_fs_context *ctx = fc->fs_private;
|
struct ovl_fs_context *ctx = fc->fs_private;
|
||||||
|
|
||||||
if (ovl_dentry_weird(path->dentry))
|
|
||||||
return invalfc(fc, "filesystem on %s not supported", name);
|
|
||||||
|
|
||||||
if (!d_is_dir(path->dentry))
|
if (!d_is_dir(path->dentry))
|
||||||
return invalfc(fc, "%s is not a directory", name);
|
return invalfc(fc, "%s is not a directory", name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Root dentries of case-insensitive capable filesystems might
|
||||||
|
* not have the dentry operations set, but still be incompatible
|
||||||
|
* with overlayfs. Check explicitly to prevent post-mount
|
||||||
|
* failures.
|
||||||
|
*/
|
||||||
|
if (sb_has_encoding(path->mnt->mnt_sb))
|
||||||
|
return invalfc(fc, "case-insensitive capable filesystem on %s not supported", name);
|
||||||
|
|
||||||
|
if (ovl_dentry_weird(path->dentry))
|
||||||
|
return invalfc(fc, "filesystem on %s not supported", name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check whether upper path is read-only here to report failures
|
* Check whether upper path is read-only here to report failures
|
||||||
|
|
|
@ -205,7 +205,6 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
|
||||||
dbg_gen("'%pd' in dir ino %lu", dentry, dir->i_ino);
|
dbg_gen("'%pd' in dir ino %lu", dentry, dir->i_ino);
|
||||||
|
|
||||||
err = fscrypt_prepare_lookup(dir, dentry, &nm);
|
err = fscrypt_prepare_lookup(dir, dentry, &nm);
|
||||||
generic_set_encrypted_ci_d_ops(dentry);
|
|
||||||
if (err == -ENOENT)
|
if (err == -ENOENT)
|
||||||
return d_splice_alias(NULL, dentry);
|
return d_splice_alias(NULL, dentry);
|
||||||
if (err)
|
if (err)
|
||||||
|
|
|
@ -2239,6 +2239,7 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
goto out_umount;
|
goto out_umount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
generic_set_sb_d_ops(sb);
|
||||||
sb->s_root = d_make_root(root);
|
sb->s_root = d_make_root(root);
|
||||||
if (!sb->s_root) {
|
if (!sb->s_root) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
|
|
|
@ -3310,7 +3310,16 @@ extern int generic_file_fsync(struct file *, loff_t, loff_t, int);
|
||||||
|
|
||||||
extern int generic_check_addressable(unsigned, u64);
|
extern int generic_check_addressable(unsigned, u64);
|
||||||
|
|
||||||
extern void generic_set_encrypted_ci_d_ops(struct dentry *dentry);
|
extern void generic_set_sb_d_ops(struct super_block *sb);
|
||||||
|
|
||||||
|
static inline bool sb_has_encoding(const struct super_block *sb)
|
||||||
|
{
|
||||||
|
#if IS_ENABLED(CONFIG_UNICODE)
|
||||||
|
return !!sb->s_encoding;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int may_setattr(struct mnt_idmap *idmap, struct inode *inode,
|
int may_setattr(struct mnt_idmap *idmap, struct inode *inode,
|
||||||
unsigned int ia_valid);
|
unsigned int ia_valid);
|
||||||
|
|
|
@ -192,6 +192,8 @@ struct fscrypt_operations {
|
||||||
unsigned int *num_devs);
|
unsigned int *num_devs);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags);
|
||||||
|
|
||||||
static inline struct fscrypt_inode_info *
|
static inline struct fscrypt_inode_info *
|
||||||
fscrypt_get_inode_info(const struct inode *inode)
|
fscrypt_get_inode_info(const struct inode *inode)
|
||||||
{
|
{
|
||||||
|
@ -221,15 +223,29 @@ static inline bool fscrypt_needs_contents_encryption(const struct inode *inode)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When d_splice_alias() moves a directory's no-key alias to its plaintext alias
|
* When d_splice_alias() moves a directory's no-key alias to its
|
||||||
* as a result of the encryption key being added, DCACHE_NOKEY_NAME must be
|
* plaintext alias as a result of the encryption key being added,
|
||||||
* cleared. Note that we don't have to support arbitrary moves of this flag
|
* DCACHE_NOKEY_NAME must be cleared and there might be an opportunity
|
||||||
* because fscrypt doesn't allow no-key names to be the source or target of a
|
* to disable d_revalidate. Note that we don't have to support the
|
||||||
* rename().
|
* inverse operation because fscrypt doesn't allow no-key names to be
|
||||||
|
* the source or target of a rename().
|
||||||
*/
|
*/
|
||||||
static inline void fscrypt_handle_d_move(struct dentry *dentry)
|
static inline void fscrypt_handle_d_move(struct dentry *dentry)
|
||||||
{
|
{
|
||||||
dentry->d_flags &= ~DCACHE_NOKEY_NAME;
|
/*
|
||||||
|
* VFS calls fscrypt_handle_d_move even for non-fscrypt
|
||||||
|
* filesystems.
|
||||||
|
*/
|
||||||
|
if (dentry->d_flags & DCACHE_NOKEY_NAME) {
|
||||||
|
dentry->d_flags &= ~DCACHE_NOKEY_NAME;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Other filesystem features might be handling dentry
|
||||||
|
* revalidation, in which case it cannot be disabled.
|
||||||
|
*/
|
||||||
|
if (dentry->d_op->d_revalidate == fscrypt_d_revalidate)
|
||||||
|
dentry->d_flags &= ~DCACHE_OP_REVALIDATE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -261,6 +277,35 @@ static inline bool fscrypt_is_nokey_name(const struct dentry *dentry)
|
||||||
return dentry->d_flags & DCACHE_NOKEY_NAME;
|
return dentry->d_flags & DCACHE_NOKEY_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void fscrypt_prepare_dentry(struct dentry *dentry,
|
||||||
|
bool is_nokey_name)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This code tries to only take ->d_lock when necessary to write
|
||||||
|
* to ->d_flags. We shouldn't be peeking on d_flags for
|
||||||
|
* DCACHE_OP_REVALIDATE unlocked, but in the unlikely case
|
||||||
|
* there is a race, the worst it can happen is that we fail to
|
||||||
|
* unset DCACHE_OP_REVALIDATE and pay the cost of an extra
|
||||||
|
* d_revalidate.
|
||||||
|
*/
|
||||||
|
if (is_nokey_name) {
|
||||||
|
spin_lock(&dentry->d_lock);
|
||||||
|
dentry->d_flags |= DCACHE_NOKEY_NAME;
|
||||||
|
spin_unlock(&dentry->d_lock);
|
||||||
|
} else if (dentry->d_flags & DCACHE_OP_REVALIDATE &&
|
||||||
|
dentry->d_op->d_revalidate == fscrypt_d_revalidate) {
|
||||||
|
/*
|
||||||
|
* Unencrypted dentries and encrypted dentries where the
|
||||||
|
* key is available are always valid from fscrypt
|
||||||
|
* perspective. Avoid the cost of calling
|
||||||
|
* fscrypt_d_revalidate unnecessarily.
|
||||||
|
*/
|
||||||
|
spin_lock(&dentry->d_lock);
|
||||||
|
dentry->d_flags &= ~DCACHE_OP_REVALIDATE;
|
||||||
|
spin_unlock(&dentry->d_lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* crypto.c */
|
/* crypto.c */
|
||||||
void fscrypt_enqueue_decrypt_work(struct work_struct *);
|
void fscrypt_enqueue_decrypt_work(struct work_struct *);
|
||||||
|
|
||||||
|
@ -368,7 +413,6 @@ int fscrypt_fname_disk_to_usr(const struct inode *inode,
|
||||||
bool fscrypt_match_name(const struct fscrypt_name *fname,
|
bool fscrypt_match_name(const struct fscrypt_name *fname,
|
||||||
const u8 *de_name, u32 de_name_len);
|
const u8 *de_name, u32 de_name_len);
|
||||||
u64 fscrypt_fname_siphash(const struct inode *dir, const struct qstr *name);
|
u64 fscrypt_fname_siphash(const struct inode *dir, const struct qstr *name);
|
||||||
int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags);
|
|
||||||
|
|
||||||
/* bio.c */
|
/* bio.c */
|
||||||
bool fscrypt_decrypt_bio(struct bio *bio);
|
bool fscrypt_decrypt_bio(struct bio *bio);
|
||||||
|
@ -425,6 +469,11 @@ static inline bool fscrypt_is_nokey_name(const struct dentry *dentry)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void fscrypt_prepare_dentry(struct dentry *dentry,
|
||||||
|
bool is_nokey_name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/* crypto.c */
|
/* crypto.c */
|
||||||
static inline void fscrypt_enqueue_decrypt_work(struct work_struct *work)
|
static inline void fscrypt_enqueue_decrypt_work(struct work_struct *work)
|
||||||
{
|
{
|
||||||
|
@ -982,6 +1031,9 @@ static inline int fscrypt_prepare_lookup(struct inode *dir,
|
||||||
fname->usr_fname = &dentry->d_name;
|
fname->usr_fname = &dentry->d_name;
|
||||||
fname->disk_name.name = (unsigned char *)dentry->d_name.name;
|
fname->disk_name.name = (unsigned char *)dentry->d_name.name;
|
||||||
fname->disk_name.len = dentry->d_name.len;
|
fname->disk_name.len = dentry->d_name.len;
|
||||||
|
|
||||||
|
fscrypt_prepare_dentry(dentry, false);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue