[Precise SRU PATCH] eCryptfs: Unlink lower inode when ecryptfs_create() fails
Stefan Bader
stefan.bader at canonical.com
Tue Aug 7 16:58:31 UTC 2012
I am having dejavus... and not yet had any beers...
On 07.08.2012 18:40, Tim Gardner wrote:
> From: Tyler Hicks <tyhicks at canonical.com>
>
> BugLink: http://bugs.launchpad.net/bugs/872905
>
> ecryptfs_create() creates a lower inode, allocates an eCryptfs inode,
> initializes the eCryptfs inode and cryptographic metadata attached to
> the inode, and then writes the metadata to the header of the file.
>
> If an error was to occur after the lower inode was created, an empty
> lower file would be left in the lower filesystem. This is a problem
> because ecryptfs_open() refuses to open any lower files which do not
> have the appropriate metadata in the file header.
>
> This patch properly unlinks the lower inode when an error occurs in the
> later stages of ecryptfs_create(), reducing the chance that an empty
> lower file will be left in the lower filesystem.
>
> https://launchpad.net/bugs/872905
>
> Signed-off-by: Tyler Hicks <tyhicks at canonical.com>
> Cc: John Johansen <john.johansen at canonical.com>
> Cc: Colin Ian King <colin.king at canonical.com>
> (cherry picked from commit 8bc2d3cf612994a960c2e8eaea37f6676f67082a)
>
> Signed-off-by: Tim Gardner <tim.gardner at canonical.com>
> ---
> fs/ecryptfs/inode.c | 55 ++++++++++++++++++++++++++++++---------------------
> 1 file changed, 32 insertions(+), 23 deletions(-)
>
> diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
> index af11098..06f55bc 100644
> --- a/fs/ecryptfs/inode.c
> +++ b/fs/ecryptfs/inode.c
> @@ -143,6 +143,31 @@ static int ecryptfs_interpose(struct dentry *lower_dentry,
> return 0;
> }
>
> +static int ecryptfs_do_unlink(struct inode *dir, struct dentry *dentry,
> + struct inode *inode)
> +{
> + struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
> + struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir);
> + struct dentry *lower_dir_dentry;
> + int rc;
> +
> + dget(lower_dentry);
> + lower_dir_dentry = lock_parent(lower_dentry);
> + rc = vfs_unlink(lower_dir_inode, lower_dentry);
> + if (rc) {
> + printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc);
> + goto out_unlock;
> + }
> + fsstack_copy_attr_times(dir, lower_dir_inode);
> + set_nlink(inode, ecryptfs_inode_to_lower(inode)->i_nlink);
> + inode->i_ctime = dir->i_ctime;
> + d_drop(dentry);
> +out_unlock:
> + unlock_dir(lower_dir_dentry);
> + dput(lower_dentry);
> + return rc;
> +}
> +
> /**
> * ecryptfs_create_underlying_file
> * @lower_dir_inode: inode of the parent in the lower fs of the new file
> @@ -201,8 +226,10 @@ ecryptfs_do_create(struct inode *directory_inode,
> }
> inode = __ecryptfs_get_inode(lower_dentry->d_inode,
> directory_inode->i_sb);
> - if (IS_ERR(inode))
> + if (IS_ERR(inode)) {
> + vfs_unlink(lower_dir_dentry->d_inode, lower_dentry);
> goto out_lock;
> + }
> fsstack_copy_attr_times(directory_inode, lower_dir_dentry->d_inode);
> fsstack_copy_inode_size(directory_inode, lower_dir_dentry->d_inode);
> out_lock:
> @@ -284,7 +311,9 @@ ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry,
> * that this on disk file is prepared to be an ecryptfs file */
> rc = ecryptfs_initialize_file(ecryptfs_dentry, ecryptfs_inode);
> if (rc) {
> - drop_nlink(ecryptfs_inode);
> + ecryptfs_do_unlink(directory_inode, ecryptfs_dentry,
> + ecryptfs_inode);
> + make_bad_inode(ecryptfs_inode);
> unlock_new_inode(ecryptfs_inode);
> iput(ecryptfs_inode);
> goto out;
> @@ -496,27 +525,7 @@ out_lock:
>
> static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry)
> {
> - int rc = 0;
> - struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
> - struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir);
> - struct dentry *lower_dir_dentry;
> -
> - dget(lower_dentry);
> - lower_dir_dentry = lock_parent(lower_dentry);
> - rc = vfs_unlink(lower_dir_inode, lower_dentry);
> - if (rc) {
> - printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc);
> - goto out_unlock;
> - }
> - fsstack_copy_attr_times(dir, lower_dir_inode);
> - set_nlink(dentry->d_inode,
> - ecryptfs_inode_to_lower(dentry->d_inode)->i_nlink);
> - dentry->d_inode->i_ctime = dir->i_ctime;
> - d_drop(dentry);
> -out_unlock:
> - unlock_dir(lower_dir_dentry);
> - dput(lower_dentry);
> - return rc;
> + return ecryptfs_do_unlink(dir, dentry, dentry->d_inode);
> }
>
> static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry,
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 900 bytes
Desc: OpenPGP digital signature
URL: <https://lists.ubuntu.com/archives/kernel-team/attachments/20120807/c7ac75bd/attachment.sig>
More information about the kernel-team
mailing list