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