eCryptfs: Ensure i_size is set in ecryptfs_getattr()

If the eCryptfs inode size was not set in the ecryptfs_lookup() path, we
need to force another read in ecryptfs_getattr() so that userspace gets a
valid st_size.

This could happen if stat was called on an eCryptfs inode that had not
yet been initialized. If the read of the eCryptfs metadata during
ecryptfs_lookup() was interrupted, it would result in an inode with an
i_size equal to that of the lower file (the ECRYPTFS_I_SIZE_INITIALIZED
flag would also not be set). ecryptfs_getattr() would then fill the
kstat using the bad i_size. If the file was then opened, a full parsing
of the metadata occurred and i_size would be properly set. But the
amount of readable data would not match what was reported earlier in the
flawed stat.

The fix is to check for the ECRYPTFS_I_SIZE_INITIALIZED flag and if it
is not set, make sure that the lower file is an eCryptfs-encrypted file
and then read the decrypted i_size from the metdata.

ecryptfs_i_size_read() was changed to return errors if there was a
problem reading the decrypted i_size from the metadata. It previously
ignored those errors because ecryptfs_lookup_interpose() was the
only caller and it needed to ignore the errors so that non-eCryptfs
files in the lower filesystem could be looked up.

https://launchpad.net/bugs/842647

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index ab35b11..6900c1d 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -299,11 +299,11 @@
 	ecryptfs_put_lower_file(inode);
 	if (rc) {
 		rc = ecryptfs_read_and_validate_xattr_region(dentry, inode);
-		if (!rc)
-			crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;
+		if (rc)
+			return -EINVAL;
+		crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;
 	}
 
-	/* Must return 0 to allow non-eCryptfs files to be looked up, too */
 	return 0;
 }
 
@@ -349,11 +349,8 @@
 		return PTR_ERR(inode);
 	}
 	if (S_ISREG(inode->i_mode)) {
-		rc = ecryptfs_i_size_read(dentry, inode);
-		if (rc) {
-			make_bad_inode(inode);
-			return rc;
-		}
+		/* Errors ignored so non-eCryptfs files can be looked up, too */
+		ecryptfs_i_size_read(dentry, inode);
 	}
 
 	if (inode->i_state & I_NEW)
@@ -1057,15 +1054,30 @@
 int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
 		     struct kstat *stat)
 {
+	struct inode *inode = dentry->d_inode;
 	struct kstat lower_stat;
 	int rc;
 
+	if (S_ISREG(inode->i_mode)) {
+		struct ecryptfs_crypt_stat *crypt_stat;
+
+		crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
+		mutex_lock(&crypt_stat->cs_mutex);
+		if (!(crypt_stat->flags & ECRYPTFS_I_SIZE_INITIALIZED)) {
+			rc = ecryptfs_i_size_read(dentry, inode);
+			if (rc) {
+				mutex_unlock(&crypt_stat->cs_mutex);
+				return rc;
+			}
+		}
+		mutex_unlock(&crypt_stat->cs_mutex);
+	}
+
 	rc = vfs_getattr(ecryptfs_dentry_to_lower_mnt(dentry),
 			 ecryptfs_dentry_to_lower(dentry), &lower_stat);
 	if (!rc) {
-		fsstack_copy_attr_all(dentry->d_inode,
-				      ecryptfs_inode_to_lower(dentry->d_inode));
-		generic_fillattr(dentry->d_inode, stat);
+		fsstack_copy_attr_all(inode, ecryptfs_inode_to_lower(inode));
+		generic_fillattr(inode, stat);
 		stat->blocks = lower_stat.blocks;
 	}
 	return rc;