eCryptfs: Fix metadata in xattr feature regression
authorTyler Hicks <tyhicks@linux.vnet.ibm.com>
Thu, 11 Feb 2010 13:10:38 +0000 (07:10 -0600)
committerTyler Hicks <tyhicks@linux.vnet.ibm.com>
Tue, 23 Mar 2010 17:29:49 +0000 (12:29 -0500)
Fixes regression in 8faece5f906725c10e7a1f6caf84452abadbdc7b

When using the ecryptfs_xattr_metadata mount option, eCryptfs stores the
metadata (normally stored at the front of the file) in the user.ecryptfs
xattr.  This causes ecryptfs_crypt_stat.num_header_bytes_at_front to be
0, since there is no header data at the front of the file.  This results
in too much memory being requested and ENOMEM being returned from
ecryptfs_write_metadata().

This patch fixes the problem by using the num_header_bytes_at_front
variable for specifying the max size of the metadata, despite whether it
is stored in the header or xattr.

Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
fs/ecryptfs/crypto.c
fs/ecryptfs/ecryptfs_kernel.h
fs/ecryptfs/inode.c
fs/ecryptfs/mmap.c

index 7cb0a59f4b9d2e7e6576be83d4787e599f9dd834..c907f6f493511c4bbeff3ca1669911c52b36e5a9 100644 (file)
@@ -381,8 +381,8 @@ out:
 static void ecryptfs_lower_offset_for_extent(loff_t *offset, loff_t extent_num,
                                             struct ecryptfs_crypt_stat *crypt_stat)
 {
-       (*offset) = (crypt_stat->num_header_bytes_at_front
-                    + (crypt_stat->extent_size * extent_num));
+       (*offset) = ecryptfs_lower_header_size(crypt_stat)
+                   + (crypt_stat->extent_size * extent_num);
 }
 
 /**
@@ -834,7 +834,8 @@ void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat)
        set_extent_mask_and_shift(crypt_stat);
        crypt_stat->iv_bytes = ECRYPTFS_DEFAULT_IV_BYTES;
        if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
-               crypt_stat->num_header_bytes_at_front = 0;
+               crypt_stat->num_header_bytes_at_front =
+                                       ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE;
        else {
                if (PAGE_CACHE_SIZE <= ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)
                        crypt_stat->num_header_bytes_at_front =
index 542f625312f30a424023e07b7146af58e9b57144..8456f70606ade5c486cf82f946b1e6658e0dfa46 100644 (file)
@@ -464,6 +464,14 @@ struct ecryptfs_daemon {
 
 extern struct mutex ecryptfs_daemon_hash_mux;
 
+static inline size_t
+ecryptfs_lower_header_size(struct ecryptfs_crypt_stat *crypt_stat)
+{
+       if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
+               return 0;
+       return crypt_stat->num_header_bytes_at_front;
+}
+
 static inline struct ecryptfs_file_info *
 ecryptfs_file_to_private(struct file *file)
 {
index 4a430ab4115c056851a9a98788417a44751e6205..1a739531b0dde3796732b54bb0dea007a5fa5529 100644 (file)
@@ -768,7 +768,7 @@ upper_size_to_lower_size(struct ecryptfs_crypt_stat *crypt_stat,
 {
        loff_t lower_size;
 
-       lower_size = crypt_stat->num_header_bytes_at_front;
+       lower_size = ecryptfs_lower_header_size(crypt_stat);
        if (upper_size != 0) {
                loff_t num_extents;
 
index df4ce99d0597bb2743dfd3c6b2fccfc807ec55d7..5a30e01547f1e8aebf23c4545006f2d2e95e8174 100644 (file)
@@ -97,19 +97,6 @@ out:
  *                        (big-endian)
  *     Octet  26:         Begin RFC 2440 authentication token packet set
  */
-static void set_header_info(char *page_virt,
-                           struct ecryptfs_crypt_stat *crypt_stat)
-{
-       size_t written;
-       size_t save_num_header_bytes_at_front =
-               crypt_stat->num_header_bytes_at_front;
-
-       crypt_stat->num_header_bytes_at_front =
-               ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE;
-       ecryptfs_write_header_metadata(page_virt + 20, crypt_stat, &written);
-       crypt_stat->num_header_bytes_at_front =
-               save_num_header_bytes_at_front;
-}
 
 /**
  * ecryptfs_copy_up_encrypted_with_header
@@ -146,9 +133,13 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
                        memset(page_virt, 0, PAGE_CACHE_SIZE);
                        /* TODO: Support more than one header extent */
                        if (view_extent_num == 0) {
+                               size_t written;
+
                                rc = ecryptfs_read_xattr_region(
                                        page_virt, page->mapping->host);
-                               set_header_info(page_virt, crypt_stat);
+                               ecryptfs_write_header_metadata(page_virt + 20,
+                                                              crypt_stat,
+                                                              &written);
                        }
                        kunmap_atomic(page_virt, KM_USER0);
                        flush_dcache_page(page);