From 0babec3ad8b0f4f77960f80fbca4965443c503ff Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Wed, 23 Feb 2011 18:45:28 -0600 Subject: [PATCH] eCryptfs: Fix error paths when failing to read metadata When failing to read the lower file's crypto metadata during a lookup, eCryptfs wasn't throwing an error. Instead, it acted like the lookup was successful, resulting in an eCryptfs inode with the wrong i_size. Some users were seeing this problem when vfs_read() returned -EINTR during the read of the lower metadata during a lookup. This caused the decrypted file to typically have 8-12 kB of zeroes tacked onto the end of the file. However, the on-disk, lower file was correct. This patch also allows the errors returned from ecryptfs_read_metadata() to be returned by ecryptfs_open(). Any error code was being masked by -EIO, which isn't mentioned in the open(2) man page. Signed-off-by: Tyler Hicks --- fs/ecryptfs/file.c | 5 ++--- fs/ecryptfs/inode.c | 28 ++++++++++++++-------------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index 7d1050e..148774d 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -225,12 +225,11 @@ static int ecryptfs_open(struct inode *inode, struct file *file) "Valid headers not found\n"); if (!(mount_crypt_stat->flags & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { - rc = -EIO; printk(KERN_WARNING "Either the lower file " "is not in a valid eCryptfs format, " - "or the key could not be retrieved. " + "or the key could not be retrieved.\n" "Plaintext passthrough mode is not " - "enabled; returning -EIO\n"); + "enabled\n"); mutex_unlock(&crypt_stat->cs_mutex); goto out_free; } diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index f99051b..ef52bb4 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -246,7 +246,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, printk(KERN_ERR "%s: Out of memory whilst attempting " "to allocate ecryptfs_dentry_info struct\n", __func__); - goto out_put; + goto out; } ecryptfs_set_dentry_lower(ecryptfs_dentry, lower_dentry); ecryptfs_set_dentry_lower_mnt(ecryptfs_dentry, lower_mnt); @@ -283,7 +283,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, "the persistent file for the dentry with name " "[%s]; rc = [%d]\n", __func__, ecryptfs_dentry->d_name.name, rc); - goto out_free_kmem; + goto out; } crypt_stat = &ecryptfs_inode_to_private( ecryptfs_dentry->d_inode)->crypt_stat; @@ -296,10 +296,8 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, memset(page_virt, 0, PAGE_CACHE_SIZE); rc = ecryptfs_read_and_validate_xattr_region(page_virt, ecryptfs_dentry); - if (rc) { - rc = 0; - goto out_free_kmem; - } + if (rc) + goto out; crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; } mount_crypt_stat = &ecryptfs_superblock_to_private( @@ -314,14 +312,14 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, file_size = get_unaligned_be64(page_virt); } i_size_write(ecryptfs_dentry->d_inode, (loff_t)file_size); -out_free_kmem: - kmem_cache_free(ecryptfs_header_cache_2, page_virt); - goto out; -out_put: - dput(lower_dentry); - mntput(lower_mnt); - d_drop(ecryptfs_dentry); out: + if (page_virt) + kmem_cache_free(ecryptfs_header_cache_2, page_virt); + if (rc) { + ecryptfs_set_dentry_lower(ecryptfs_dentry, NULL); + ecryptfs_set_dentry_lower_mnt(ecryptfs_dentry, NULL); + mntput(lower_mnt); + } return rc; } @@ -395,7 +393,9 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, lookup_and_interpose: rc = ecryptfs_lookup_and_interpose_lower(ecryptfs_dentry, lower_dentry, ecryptfs_dir_inode); - goto out; + if (!rc) + goto out; + dput(lower_dentry); out_d_drop: d_drop(ecryptfs_dentry); out: -- 1.7.4