aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ecryptfs/inode.c
diff options
context:
space:
mode:
authorTyler Hicks <tyhicks@linux.vnet.ibm.com>2011-03-15 15:54:00 -0400
committerTyler Hicks <tyhicks@linux.vnet.ibm.com>2011-04-25 19:45:06 -0400
commit3aeb86ea4cd15f728147a3bd5469a205ada8c767 (patch)
tree6219c664f7938fa8e5e8a2efa93aab7bcc38c12f /fs/ecryptfs/inode.c
parent332ab16f830f59e7621ae8eb2c353dc135a316f6 (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.c18
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);
317out_free_kmem: 304out_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);