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>

+28 -16
+21
fs/ecryptfs/crypto.c
··· 1452 crypt_stat->metadata_size = ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE; 1453 } 1454 1455 /** 1456 * ecryptfs_read_headers_virt 1457 * @page_virt: The virtual address into which to read the headers ··· 1501 rc = -EINVAL; 1502 goto out; 1503 } 1504 offset += MAGIC_ECRYPTFS_MARKER_SIZE_BYTES; 1505 rc = ecryptfs_process_flags(crypt_stat, (page_virt + offset), 1506 &bytes_read);
··· 1452 crypt_stat->metadata_size = ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE; 1453 } 1454 1455 + void ecryptfs_i_size_init(const char *page_virt, struct inode *inode) 1456 + { 1457 + struct ecryptfs_mount_crypt_stat *mount_crypt_stat; 1458 + struct ecryptfs_crypt_stat *crypt_stat; 1459 + u64 file_size; 1460 + 1461 + crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; 1462 + mount_crypt_stat = 1463 + &ecryptfs_superblock_to_private(inode->i_sb)->mount_crypt_stat; 1464 + if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) { 1465 + file_size = i_size_read(ecryptfs_inode_to_lower(inode)); 1466 + if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) 1467 + file_size += crypt_stat->metadata_size; 1468 + } else 1469 + file_size = get_unaligned_be64(page_virt); 1470 + i_size_write(inode, (loff_t)file_size); 1471 + crypt_stat->flags |= ECRYPTFS_I_SIZE_INITIALIZED; 1472 + } 1473 + 1474 /** 1475 * ecryptfs_read_headers_virt 1476 * @page_virt: The virtual address into which to read the headers ··· 1482 rc = -EINVAL; 1483 goto out; 1484 } 1485 + if (!(crypt_stat->flags & ECRYPTFS_I_SIZE_INITIALIZED)) 1486 + ecryptfs_i_size_init(page_virt, ecryptfs_dentry->d_inode); 1487 offset += MAGIC_ECRYPTFS_MARKER_SIZE_BYTES; 1488 rc = ecryptfs_process_flags(crypt_stat, (page_virt + offset), 1489 &bytes_read);
+2
fs/ecryptfs/ecryptfs_kernel.h
··· 269 #define ECRYPTFS_ENCFN_USE_MOUNT_FNEK 0x00000800 270 #define ECRYPTFS_ENCFN_USE_FEK 0x00001000 271 #define ECRYPTFS_UNLINK_SIGS 0x00002000 272 u32 flags; 273 unsigned int file_version; 274 size_t iv_bytes; ··· 629 int ecryptfs_interpose(struct dentry *hidden_dentry, 630 struct dentry *this_dentry, struct super_block *sb, 631 u32 flags); 632 int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, 633 struct dentry *lower_dentry, 634 struct inode *ecryptfs_dir_inode);
··· 269 #define ECRYPTFS_ENCFN_USE_MOUNT_FNEK 0x00000800 270 #define ECRYPTFS_ENCFN_USE_FEK 0x00001000 271 #define ECRYPTFS_UNLINK_SIGS 0x00002000 272 + #define ECRYPTFS_I_SIZE_INITIALIZED 0x00004000 273 u32 flags; 274 unsigned int file_version; 275 size_t iv_bytes; ··· 628 int ecryptfs_interpose(struct dentry *hidden_dentry, 629 struct dentry *this_dentry, struct super_block *sb, 630 u32 flags); 631 + void ecryptfs_i_size_init(const char *page_virt, struct inode *inode); 632 int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, 633 struct dentry *lower_dentry, 634 struct inode *ecryptfs_dir_inode);
+2 -1
fs/ecryptfs/file.c
··· 235 goto out_put; 236 } 237 rc = 0; 238 - crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); 239 mutex_unlock(&crypt_stat->cs_mutex); 240 goto out; 241 }
··· 235 goto out_put; 236 } 237 rc = 0; 238 + crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED 239 + | ECRYPTFS_ENCRYPTED); 240 mutex_unlock(&crypt_stat->cs_mutex); 241 goto out; 242 }
+3 -15
fs/ecryptfs/inode.c
··· 225 struct dentry *lower_dir_dentry; 226 struct vfsmount *lower_mnt; 227 struct inode *lower_inode; 228 - struct ecryptfs_mount_crypt_stat *mount_crypt_stat; 229 struct ecryptfs_crypt_stat *crypt_stat; 230 char *page_virt = NULL; 231 - u64 file_size; 232 int put_lower = 0, rc = 0; 233 234 lower_dir_dentry = lower_dentry->d_parent; ··· 300 } 301 crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; 302 } 303 - mount_crypt_stat = &ecryptfs_superblock_to_private( 304 - ecryptfs_dentry->d_sb)->mount_crypt_stat; 305 - if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) { 306 - if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) 307 - file_size = (crypt_stat->metadata_size 308 - + i_size_read(lower_dentry->d_inode)); 309 - else 310 - file_size = i_size_read(lower_dentry->d_inode); 311 - } else { 312 - file_size = get_unaligned_be64(page_virt); 313 - } 314 - i_size_write(ecryptfs_dentry->d_inode, (loff_t)file_size); 315 out_free_kmem: 316 kmem_cache_free(ecryptfs_header_cache_2, page_virt); 317 goto out; ··· 924 goto out; 925 } 926 rc = 0; 927 - crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); 928 } 929 } 930 mutex_unlock(&crypt_stat->cs_mutex);
··· 225 struct dentry *lower_dir_dentry; 226 struct vfsmount *lower_mnt; 227 struct inode *lower_inode; 228 struct ecryptfs_crypt_stat *crypt_stat; 229 char *page_virt = NULL; 230 int put_lower = 0, rc = 0; 231 232 lower_dir_dentry = lower_dentry->d_parent; ··· 302 } 303 crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; 304 } 305 + ecryptfs_i_size_init(page_virt, ecryptfs_dentry->d_inode); 306 out_free_kmem: 307 kmem_cache_free(ecryptfs_header_cache_2, page_virt); 308 goto out; ··· 937 goto out; 938 } 939 rc = 0; 940 + crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED 941 + | ECRYPTFS_ENCRYPTED); 942 } 943 } 944 mutex_unlock(&crypt_stat->cs_mutex);