diff options
author | Tyler Hicks <tyhicks@linux.vnet.ibm.com> | 2011-03-15 15:54:00 -0400 |
---|---|---|
committer | Tyler Hicks <tyhicks@linux.vnet.ibm.com> | 2011-04-25 19:45:06 -0400 |
commit | 3aeb86ea4cd15f728147a3bd5469a205ada8c767 (patch) | |
tree | 6219c664f7938fa8e5e8a2efa93aab7bcc38c12f /fs/ecryptfs/inode.c | |
parent | 332ab16f830f59e7621ae8eb2c353dc135a316f6 (diff) |
eCryptfs: Handle failed metadata read in lookup
When failing to read the lower file's crypto metadata during a lookup,
eCryptfs must continue on without throwing an error. For example, there
may be a plaintext file in the lower mount point that the user wants to
delete through the eCryptfs mount.
If an error is encountered while reading the metadata in lookup(), the
eCryptfs inode's size could be incorrect. We must be sure to reread the
plaintext inode size from the metadata when performing an open() or
setattr(). The metadata is already being read in those paths, so this
adds minimal performance overhead.
This patch introduces a flag which will track whether or not the
plaintext inode size has been read so that an incorrect i_size can be
fixed in the open() or setattr() paths.
https://bugs.launchpad.net/bugs/509180
Cc: <stable@kernel.org>
Signed-off-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
Diffstat (limited to 'fs/ecryptfs/inode.c')
-rw-r--r-- | fs/ecryptfs/inode.c | 18 |
1 files changed, 3 insertions, 15 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index f6b388638c3d..2c19d362d2d4 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -225,10 +225,8 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, | |||
225 | struct dentry *lower_dir_dentry; | 225 | struct dentry *lower_dir_dentry; |
226 | struct vfsmount *lower_mnt; | 226 | struct vfsmount *lower_mnt; |
227 | struct inode *lower_inode; | 227 | struct inode *lower_inode; |
228 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat; | ||
229 | struct ecryptfs_crypt_stat *crypt_stat; | 228 | struct ecryptfs_crypt_stat *crypt_stat; |
230 | char *page_virt = NULL; | 229 | char *page_virt = NULL; |
231 | u64 file_size; | ||
232 | int put_lower = 0, rc = 0; | 230 | int put_lower = 0, rc = 0; |
233 | 231 | ||
234 | lower_dir_dentry = lower_dentry->d_parent; | 232 | lower_dir_dentry = lower_dentry->d_parent; |
@@ -302,18 +300,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, | |||
302 | } | 300 | } |
303 | crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; | 301 | crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; |
304 | } | 302 | } |
305 | mount_crypt_stat = &ecryptfs_superblock_to_private( | 303 | ecryptfs_i_size_init(page_virt, ecryptfs_dentry->d_inode); |
306 | ecryptfs_dentry->d_sb)->mount_crypt_stat; | ||
307 | if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) { | ||
308 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) | ||
309 | file_size = (crypt_stat->metadata_size | ||
310 | + i_size_read(lower_dentry->d_inode)); | ||
311 | else | ||
312 | file_size = i_size_read(lower_dentry->d_inode); | ||
313 | } else { | ||
314 | file_size = get_unaligned_be64(page_virt); | ||
315 | } | ||
316 | i_size_write(ecryptfs_dentry->d_inode, (loff_t)file_size); | ||
317 | out_free_kmem: | 304 | out_free_kmem: |
318 | kmem_cache_free(ecryptfs_header_cache_2, page_virt); | 305 | kmem_cache_free(ecryptfs_header_cache_2, page_virt); |
319 | goto out; | 306 | goto out; |
@@ -937,7 +924,8 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) | |||
937 | goto out; | 924 | goto out; |
938 | } | 925 | } |
939 | rc = 0; | 926 | rc = 0; |
940 | crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); | 927 | crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED |
928 | | ECRYPTFS_ENCRYPTED); | ||
941 | } | 929 | } |
942 | } | 930 | } |
943 | mutex_unlock(&crypt_stat->cs_mutex); | 931 | mutex_unlock(&crypt_stat->cs_mutex); |