Merge tag 'fscrypt_for_linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt
Pull fscrypt updates from Ted Ts'o: "Clean up fscrypt's dcache revalidation support, and other miscellaneous cleanups" * tag 'fscrypt_for_linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt: fscrypt: cache decrypted symlink target in ->i_link vfs: use READ_ONCE() to access ->i_link fscrypt: fix race where ->lookup() marks plaintext dentry as ciphertext fscrypt: only set dentry_operations on ciphertext dentries fs, fscrypt: clear DCACHE_ENCRYPTED_NAME when unaliasing directory fscrypt: fix race allowing rename() and link() of ciphertext dentries fscrypt: clean up and improve dentry revalidation fscrypt: use READ_ONCE() to access ->i_crypt_info fscrypt: remove WARN_ON_ONCE() when decryption fails fscrypt: drop inode argument from fscrypt_get_ctx()
此提交包含在:
@@ -36,12 +36,10 @@ static void __fscrypt_decrypt_bio(struct bio *bio, bool done)
|
||||
int ret = fscrypt_decrypt_page(page->mapping->host, page,
|
||||
PAGE_SIZE, 0, page->index);
|
||||
|
||||
if (ret) {
|
||||
WARN_ON_ONCE(1);
|
||||
if (ret)
|
||||
SetPageError(page);
|
||||
} else if (done) {
|
||||
else if (done)
|
||||
SetPageUptodate(page);
|
||||
}
|
||||
if (done)
|
||||
unlock_page(page);
|
||||
}
|
||||
@@ -103,7 +101,7 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
|
||||
|
||||
BUG_ON(inode->i_sb->s_blocksize != PAGE_SIZE);
|
||||
|
||||
ctx = fscrypt_get_ctx(inode, GFP_NOFS);
|
||||
ctx = fscrypt_get_ctx(GFP_NOFS);
|
||||
if (IS_ERR(ctx))
|
||||
return PTR_ERR(ctx);
|
||||
|
||||
|
@@ -87,23 +87,17 @@ EXPORT_SYMBOL(fscrypt_release_ctx);
|
||||
|
||||
/**
|
||||
* fscrypt_get_ctx() - Gets an encryption context
|
||||
* @inode: The inode for which we are doing the crypto
|
||||
* @gfp_flags: The gfp flag for memory allocation
|
||||
*
|
||||
* Allocates and initializes an encryption context.
|
||||
*
|
||||
* Return: An allocated and initialized encryption context on success; error
|
||||
* value or NULL otherwise.
|
||||
* Return: A new encryption context on success; an ERR_PTR() otherwise.
|
||||
*/
|
||||
struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *inode, gfp_t gfp_flags)
|
||||
struct fscrypt_ctx *fscrypt_get_ctx(gfp_t gfp_flags)
|
||||
{
|
||||
struct fscrypt_ctx *ctx = NULL;
|
||||
struct fscrypt_info *ci = inode->i_crypt_info;
|
||||
struct fscrypt_ctx *ctx;
|
||||
unsigned long flags;
|
||||
|
||||
if (ci == NULL)
|
||||
return ERR_PTR(-ENOKEY);
|
||||
|
||||
/*
|
||||
* We first try getting the ctx from a free list because in
|
||||
* the common case the ctx will have an allocated and
|
||||
@@ -258,9 +252,9 @@ struct page *fscrypt_encrypt_page(const struct inode *inode,
|
||||
|
||||
BUG_ON(!PageLocked(page));
|
||||
|
||||
ctx = fscrypt_get_ctx(inode, gfp_flags);
|
||||
ctx = fscrypt_get_ctx(gfp_flags);
|
||||
if (IS_ERR(ctx))
|
||||
return (struct page *)ctx;
|
||||
return ERR_CAST(ctx);
|
||||
|
||||
/* The encryption operation will require a bounce page. */
|
||||
ciphertext_page = fscrypt_alloc_bounce_page(ctx, gfp_flags);
|
||||
@@ -313,45 +307,47 @@ int fscrypt_decrypt_page(const struct inode *inode, struct page *page,
|
||||
EXPORT_SYMBOL(fscrypt_decrypt_page);
|
||||
|
||||
/*
|
||||
* Validate dentries for encrypted directories to make sure we aren't
|
||||
* potentially caching stale data after a key has been added or
|
||||
* removed.
|
||||
* Validate dentries in encrypted directories to make sure we aren't potentially
|
||||
* caching stale dentries after a key has been added.
|
||||
*/
|
||||
static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags)
|
||||
{
|
||||
struct dentry *dir;
|
||||
int dir_has_key, cached_with_key;
|
||||
int err;
|
||||
int valid;
|
||||
|
||||
/*
|
||||
* Plaintext names are always valid, since fscrypt doesn't support
|
||||
* reverting to ciphertext names without evicting the directory's inode
|
||||
* -- which implies eviction of the dentries in the directory.
|
||||
*/
|
||||
if (!(dentry->d_flags & DCACHE_ENCRYPTED_NAME))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Ciphertext name; valid if the directory's key is still unavailable.
|
||||
*
|
||||
* Although fscrypt forbids rename() on ciphertext names, we still must
|
||||
* use dget_parent() here rather than use ->d_parent directly. That's
|
||||
* because a corrupted fs image may contain directory hard links, which
|
||||
* the VFS handles by moving the directory's dentry tree in the dcache
|
||||
* each time ->lookup() finds the directory and it already has a dentry
|
||||
* elsewhere. Thus ->d_parent can be changing, and we must safely grab
|
||||
* a reference to some ->d_parent to prevent it from being freed.
|
||||
*/
|
||||
|
||||
if (flags & LOOKUP_RCU)
|
||||
return -ECHILD;
|
||||
|
||||
dir = dget_parent(dentry);
|
||||
if (!IS_ENCRYPTED(d_inode(dir))) {
|
||||
dput(dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
spin_lock(&dentry->d_lock);
|
||||
cached_with_key = dentry->d_flags & DCACHE_ENCRYPTED_WITH_KEY;
|
||||
spin_unlock(&dentry->d_lock);
|
||||
dir_has_key = (d_inode(dir)->i_crypt_info != NULL);
|
||||
err = fscrypt_get_encryption_info(d_inode(dir));
|
||||
valid = !fscrypt_has_encryption_key(d_inode(dir));
|
||||
dput(dir);
|
||||
|
||||
/*
|
||||
* If the dentry was cached without the key, and it is a
|
||||
* negative dentry, it might be a valid name. We can't check
|
||||
* if the key has since been made available due to locking
|
||||
* reasons, so we fail the validation so ext4_lookup() can do
|
||||
* this check.
|
||||
*
|
||||
* We also fail the validation if the dentry was created with
|
||||
* the key present, but we no longer have the key, or vice versa.
|
||||
*/
|
||||
if ((!cached_with_key && d_is_negative(dentry)) ||
|
||||
(!cached_with_key && dir_has_key) ||
|
||||
(cached_with_key && !dir_has_key))
|
||||
return 0;
|
||||
return 1;
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
const struct dentry_operations fscrypt_d_ops = {
|
||||
|
@@ -269,7 +269,7 @@ int fscrypt_fname_disk_to_usr(struct inode *inode,
|
||||
if (iname->len < FS_CRYPTO_BLOCK_SIZE)
|
||||
return -EUCLEAN;
|
||||
|
||||
if (inode->i_crypt_info)
|
||||
if (fscrypt_has_encryption_key(inode))
|
||||
return fname_decrypt(inode, iname, oname);
|
||||
|
||||
if (iname->len <= FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE) {
|
||||
@@ -336,7 +336,7 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (dir->i_crypt_info) {
|
||||
if (fscrypt_has_encryption_key(dir)) {
|
||||
if (!fscrypt_fname_encrypted_size(dir, iname->len,
|
||||
dir->i_sb->s_cop->max_namelen,
|
||||
&fname->crypto_buf.len))
|
||||
@@ -356,6 +356,7 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname,
|
||||
}
|
||||
if (!lookup)
|
||||
return -ENOKEY;
|
||||
fname->is_ciphertext_name = true;
|
||||
|
||||
/*
|
||||
* We don't have the key and we are doing a lookup; decode the
|
||||
|
@@ -49,7 +49,8 @@ int fscrypt_file_open(struct inode *inode, struct file *filp)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fscrypt_file_open);
|
||||
|
||||
int __fscrypt_prepare_link(struct inode *inode, struct inode *dir)
|
||||
int __fscrypt_prepare_link(struct inode *inode, struct inode *dir,
|
||||
struct dentry *dentry)
|
||||
{
|
||||
int err;
|
||||
|
||||
@@ -57,6 +58,10 @@ int __fscrypt_prepare_link(struct inode *inode, struct inode *dir)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* ... in case we looked up ciphertext name before key was added */
|
||||
if (dentry->d_flags & DCACHE_ENCRYPTED_NAME)
|
||||
return -ENOKEY;
|
||||
|
||||
if (!fscrypt_has_permitted_context(dir, inode))
|
||||
return -EXDEV;
|
||||
|
||||
@@ -78,6 +83,11 @@ int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* ... in case we looked up ciphertext name(s) before key was added */
|
||||
if ((old_dentry->d_flags | new_dentry->d_flags) &
|
||||
DCACHE_ENCRYPTED_NAME)
|
||||
return -ENOKEY;
|
||||
|
||||
if (old_dir != new_dir) {
|
||||
if (IS_ENCRYPTED(new_dir) &&
|
||||
!fscrypt_has_permitted_context(new_dir,
|
||||
@@ -94,21 +104,21 @@ int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__fscrypt_prepare_rename);
|
||||
|
||||
int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry)
|
||||
int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry,
|
||||
struct fscrypt_name *fname)
|
||||
{
|
||||
int err = fscrypt_get_encryption_info(dir);
|
||||
int err = fscrypt_setup_filename(dir, &dentry->d_name, 1, fname);
|
||||
|
||||
if (err)
|
||||
if (err && err != -ENOENT)
|
||||
return err;
|
||||
|
||||
if (fscrypt_has_encryption_key(dir)) {
|
||||
if (fname->is_ciphertext_name) {
|
||||
spin_lock(&dentry->d_lock);
|
||||
dentry->d_flags |= DCACHE_ENCRYPTED_WITH_KEY;
|
||||
dentry->d_flags |= DCACHE_ENCRYPTED_NAME;
|
||||
spin_unlock(&dentry->d_lock);
|
||||
d_set_d_op(dentry, &fscrypt_d_ops);
|
||||
}
|
||||
|
||||
d_set_d_op(dentry, &fscrypt_d_ops);
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__fscrypt_prepare_lookup);
|
||||
|
||||
@@ -179,11 +189,9 @@ int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
|
||||
sd->len = cpu_to_le16(ciphertext_len);
|
||||
|
||||
err = fname_encrypt(inode, &iname, sd->encrypted_path, ciphertext_len);
|
||||
if (err) {
|
||||
if (!disk_link->name)
|
||||
kfree(sd);
|
||||
return err;
|
||||
}
|
||||
if (err)
|
||||
goto err_free_sd;
|
||||
|
||||
/*
|
||||
* Null-terminating the ciphertext doesn't make sense, but we still
|
||||
* count the null terminator in the length, so we might as well
|
||||
@@ -191,9 +199,20 @@ int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
|
||||
*/
|
||||
sd->encrypted_path[ciphertext_len] = '\0';
|
||||
|
||||
/* Cache the plaintext symlink target for later use by get_link() */
|
||||
err = -ENOMEM;
|
||||
inode->i_link = kmemdup(target, len + 1, GFP_NOFS);
|
||||
if (!inode->i_link)
|
||||
goto err_free_sd;
|
||||
|
||||
if (!disk_link->name)
|
||||
disk_link->name = (unsigned char *)sd;
|
||||
return 0;
|
||||
|
||||
err_free_sd:
|
||||
if (!disk_link->name)
|
||||
kfree(sd);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__fscrypt_encrypt_symlink);
|
||||
|
||||
@@ -202,7 +221,7 @@ EXPORT_SYMBOL_GPL(__fscrypt_encrypt_symlink);
|
||||
* @inode: the symlink inode
|
||||
* @caddr: the on-disk contents of the symlink
|
||||
* @max_size: size of @caddr buffer
|
||||
* @done: if successful, will be set up to free the returned target
|
||||
* @done: if successful, will be set up to free the returned target if needed
|
||||
*
|
||||
* If the symlink's encryption key is available, we decrypt its target.
|
||||
* Otherwise, we encode its target for presentation.
|
||||
@@ -217,12 +236,18 @@ const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
|
||||
{
|
||||
const struct fscrypt_symlink_data *sd;
|
||||
struct fscrypt_str cstr, pstr;
|
||||
bool has_key;
|
||||
int err;
|
||||
|
||||
/* This is for encrypted symlinks only */
|
||||
if (WARN_ON(!IS_ENCRYPTED(inode)))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/* If the decrypted target is already cached, just return it. */
|
||||
pstr.name = READ_ONCE(inode->i_link);
|
||||
if (pstr.name)
|
||||
return pstr.name;
|
||||
|
||||
/*
|
||||
* Try to set up the symlink's encryption key, but we can continue
|
||||
* regardless of whether the key is available or not.
|
||||
@@ -230,6 +255,7 @@ const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
|
||||
err = fscrypt_get_encryption_info(inode);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
has_key = fscrypt_has_encryption_key(inode);
|
||||
|
||||
/*
|
||||
* For historical reasons, encrypted symlink targets are prefixed with
|
||||
@@ -261,7 +287,17 @@ const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
|
||||
goto err_kfree;
|
||||
|
||||
pstr.name[pstr.len] = '\0';
|
||||
set_delayed_call(done, kfree_link, pstr.name);
|
||||
|
||||
/*
|
||||
* Cache decrypted symlink targets in i_link for later use. Don't cache
|
||||
* symlink targets encoded without the key, since those become outdated
|
||||
* once the key is added. This pairs with the READ_ONCE() above and in
|
||||
* the VFS path lookup code.
|
||||
*/
|
||||
if (!has_key ||
|
||||
cmpxchg_release(&inode->i_link, NULL, pstr.name) != NULL)
|
||||
set_delayed_call(done, kfree_link, pstr.name);
|
||||
|
||||
return pstr.name;
|
||||
|
||||
err_kfree:
|
||||
|
@@ -508,7 +508,7 @@ int fscrypt_get_encryption_info(struct inode *inode)
|
||||
u8 *raw_key = NULL;
|
||||
int res;
|
||||
|
||||
if (inode->i_crypt_info)
|
||||
if (fscrypt_has_encryption_key(inode))
|
||||
return 0;
|
||||
|
||||
res = fscrypt_initialize(inode->i_sb->s_cop->flags);
|
||||
@@ -572,7 +572,7 @@ int fscrypt_get_encryption_info(struct inode *inode)
|
||||
if (res)
|
||||
goto out;
|
||||
|
||||
if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) == NULL)
|
||||
if (cmpxchg_release(&inode->i_crypt_info, NULL, crypt_info) == NULL)
|
||||
crypt_info = NULL;
|
||||
out:
|
||||
if (res == -ENOKEY)
|
||||
@@ -583,9 +583,30 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL(fscrypt_get_encryption_info);
|
||||
|
||||
/**
|
||||
* fscrypt_put_encryption_info - free most of an inode's fscrypt data
|
||||
*
|
||||
* Free the inode's fscrypt_info. Filesystems must call this when the inode is
|
||||
* being evicted. An RCU grace period need not have elapsed yet.
|
||||
*/
|
||||
void fscrypt_put_encryption_info(struct inode *inode)
|
||||
{
|
||||
put_crypt_info(inode->i_crypt_info);
|
||||
inode->i_crypt_info = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(fscrypt_put_encryption_info);
|
||||
|
||||
/**
|
||||
* fscrypt_free_inode - free an inode's fscrypt data requiring RCU delay
|
||||
*
|
||||
* Free the inode's cached decrypted symlink target, if any. Filesystems must
|
||||
* call this after an RCU grace period, just before they free the inode.
|
||||
*/
|
||||
void fscrypt_free_inode(struct inode *inode)
|
||||
{
|
||||
if (IS_ENCRYPTED(inode) && S_ISLNK(inode->i_mode)) {
|
||||
kfree(inode->i_link);
|
||||
inode->i_link = NULL;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(fscrypt_free_inode);
|
||||
|
@@ -194,8 +194,8 @@ int fscrypt_has_permitted_context(struct inode *parent, struct inode *child)
|
||||
res = fscrypt_get_encryption_info(child);
|
||||
if (res)
|
||||
return 0;
|
||||
parent_ci = parent->i_crypt_info;
|
||||
child_ci = child->i_crypt_info;
|
||||
parent_ci = READ_ONCE(parent->i_crypt_info);
|
||||
child_ci = READ_ONCE(child->i_crypt_info);
|
||||
|
||||
if (parent_ci && child_ci) {
|
||||
return memcmp(parent_ci->ci_master_key_descriptor,
|
||||
@@ -246,7 +246,7 @@ int fscrypt_inherit_context(struct inode *parent, struct inode *child,
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
ci = parent->i_crypt_info;
|
||||
ci = READ_ONCE(parent->i_crypt_info);
|
||||
if (ci == NULL)
|
||||
return -ENOKEY;
|
||||
|
||||
|
新增問題並參考
封鎖使用者