Patch "ext4 crypto: revalidate dentry after adding or removing the key" has been added to the 4.4-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
ext4 crypto: revalidate dentry after adding or removing the key
to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
ext4-crypto-revalidate-dentry-after-adding-or-removing-the-key.patch
and it can be found in the queue-4.4 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
28b4c263961c47da84ed8b5be0b5116bad1133ebMon Sep 17 00:00:00 2001
From: Theodore Ts'o <[email protected]>
Date: Sun, 7 Feb 2016 19:35:05 -0500
Subject: ext4 crypto: revalidate dentry after adding or removing the key
From: Theodore Ts'o <[email protected]>
commit 28b4c263961c47da84ed8b5be0b5116bad1133eb upstream.
Add a validation check for dentries for encrypted directory to make sure we're not caching stale data after a key has been added or removed.
Also check to make sure that status of the encryption key is updated when readdir(2) is executed.
--- fs/ext4/crypto.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ fs/ext4/dir.c | 6 ++++++ fs/ext4/ext4.h | 1 + fs/ext4/namei.c | 18 ++++++++++++++++++ 4 files changed, 75 insertions(+)
fs/ext4/crypto.c +50 -0
@@ -469,3 +469,53 @@ uint32_t ext4_validate_encryption_key_sireturn size;return 0 ; } + +/* +* Validate dentries for encrypted directories to make sure we aren't +* potentially caching stale data after a key has been added or +* removed. +*/ +static int ext4_d_revalidate (struct dentry *dentry,unsigned int flags) +{ +struct inode *dir =d_inode (dentry->d_parent); +struct ext4_crypt_info *ci =EXT4_I (dir)->i_crypt_info; +int dir_has_key, cached_with_key; + +if (!ext4_encrypted_inode (dir)) +return 0 ; + +/* this should eventually be an flag in d_flags */ + cached_with_key = dentry->d_fsdata !=NULL ; + dir_has_key = (ci !=NULL ); + +/* +* 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)) { +#if 0 /* Revalidation debug */ +char buf[80 ]; +char *cp =simple_dname (dentry, buf,sizeof (buf)); + +if (IS_ERR (cp)) + cp = (char *)"???" ; +pr_err ("revalidate: %s %p %d %d %d\n" , cp, dentry->d_fsdata, + cached_with_key,d_is_negative (dentry), + dir_has_key); +#endif +return 0 ; + } +return 1 ; +} + +const struct dentry_operations ext4_encrypted_d_ops = { + .d_revalidate = ext4_d_revalidate, +};
fs/ext4/dir.c +6 -0
@@ -111,6 +111,12 @@ static int ext4_readdir(struct file *filint dir_has_error =0 ;struct ext4_str fname_crypto_str = {.name =NULL , .len =0 }; +if (ext4_encrypted_inode (inode)) { + err =ext4_get_encryption_info (inode); +if (err && err != -ENOKEY ) +return err; + } +if (is_dx_dir (inode)) { err =ext4_dx_readdir (file, ctx);if (err !=ERR_BAD_DX_DIR ) {
fs/ext4/ext4.h +1 -0
@@ -2268,6 +2268,7 @@ struct page *ext4_encrypt(struct inode * struct page *plaintext_page);int ext4_decrypt (struct page *page);int ext4_encrypted_zeroout (struct inode *inode,struct ext4_extent *ex); +extern const struct dentry_operations ext4_encrypted_d_ops;#ifdef CONFIG_EXT4_FS_ENCRYPTION int ext4_init_crypto (void );
fs/ext4/namei.c +18 -0
@@ -1557,6 +1557,24 @@ static struct dentry *ext4_lookup(structstruct ext4_dir_entry_2 *de;struct buffer_head *bh; +if (ext4_encrypted_inode (dir)) { +int res =ext4_get_encryption_info (dir); + +/* +* This should be a properly defined flag for +* dentry->d_flags when we uplift this to the VFS. +* d_fsdata is set to (void *) 1 if if the dentry is +* created while the directory was encrypted and we +* don't have access to the key. +*/ + dentry->d_fsdata =NULL ; +if (ext4_encryption_info (dir)) + dentry->d_fsdata = (void *)1 ; +d_set_d_op (dentry, &ext4_encrypted_d_ops); +if (res && res != -ENOKEY ) +return ERR_PTR (res); + } +if (dentry->d_name.len >EXT4_NAME_LEN )return ERR_PTR (-ENAMETOOLONG );
Patches currently in stable-queue which might be from [email protected] are
queue-4.4/ext4-fscrypto-avoid-rcu-lookup-in-d_revalidate.patch queue-4.4/ext4-crypto-revalidate-dentry-after-adding-or-removing-the-key.patch queue-4.4/ext4-crypto-use-dget_parent-in-ext4_d_revalidate.patch queue-4.4/ext4-require-encryption-feature-for-ext4_ioc_set_encryption_policy.patch