X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=fs%2Fecryptfs%2Fmmap.c;h=6df1debdccce14aabbf0e63193b66ec0c8366d3e;hb=62429f434091586d54b37b8dd46076e7c08b27b9;hp=32c5711d79a320593e9a536590f3b347905055bd;hpb=eba0e319c12fb098d66316a8eafbaaa9174a07c3;p=linux-2.6 diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 32c5711d79..6df1debdcc 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -34,8 +34,6 @@ #include #include "ecryptfs_kernel.h" -struct kmem_cache *ecryptfs_lower_page_cache; - /** * ecryptfs_get_locked_page * @@ -102,13 +100,14 @@ static void set_header_info(char *page_virt, struct ecryptfs_crypt_stat *crypt_stat) { size_t written; - int save_num_header_extents_at_front = - crypt_stat->num_header_extents_at_front; + size_t save_num_header_bytes_at_front = + crypt_stat->num_header_bytes_at_front; - crypt_stat->num_header_extents_at_front = 1; + 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_extents_at_front = - save_num_header_extents_at_front; + crypt_stat->num_header_bytes_at_front = + save_num_header_bytes_at_front; } /** @@ -134,8 +133,11 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page, loff_t view_extent_num = ((((loff_t)page->index) * num_extents_per_page) + extent_num_in_page); + size_t num_header_extents_at_front = + (crypt_stat->num_header_bytes_at_front + / crypt_stat->extent_size); - if (view_extent_num < crypt_stat->num_header_extents_at_front) { + if (view_extent_num < num_header_extents_at_front) { /* This is a header extent */ char *page_virt; @@ -157,9 +159,8 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page, } else { /* This is an encrypted data extent */ loff_t lower_offset = - ((view_extent_num - - crypt_stat->num_header_extents_at_front) - * crypt_stat->extent_size); + ((view_extent_num * crypt_stat->extent_size) + - crypt_stat->num_header_bytes_at_front); rc = ecryptfs_read_lower_page_segment( page, (lower_offset >> PAGE_CACHE_SHIFT), @@ -257,58 +258,107 @@ static int fill_zeros_to_end_of_page(struct page *page, unsigned int to) end_byte_in_page = i_size_read(inode) % PAGE_CACHE_SIZE; if (to > end_byte_in_page) end_byte_in_page = to; - zero_user_page(page, end_byte_in_page, - PAGE_CACHE_SIZE - end_byte_in_page, KM_USER0); + zero_user_segment(page, end_byte_in_page, PAGE_CACHE_SIZE); out: return 0; } -/* This function must zero any hole we create */ +/** + * ecryptfs_prepare_write + * @file: The eCryptfs file + * @page: The eCryptfs page + * @from: The start byte from which we will write + * @to: The end byte to which we will write + * + * This function must zero any hole we create + * + * Returns zero on success; non-zero otherwise + */ static int ecryptfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to) { - int rc = 0; loff_t prev_page_end_size; + int rc = 0; if (!PageUptodate(page)) { - rc = ecryptfs_read_lower_page_segment(page, page->index, 0, - PAGE_CACHE_SIZE, - page->mapping->host); - if (rc) { - printk(KERN_ERR "%s: Error attemping to read lower " - "page segment; rc = [%d]\n", __FUNCTION__, rc); - ClearPageUptodate(page); - goto out; - } else + struct ecryptfs_crypt_stat *crypt_stat = + &ecryptfs_inode_to_private( + file->f_path.dentry->d_inode)->crypt_stat; + + if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED) + || (crypt_stat->flags & ECRYPTFS_NEW_FILE)) { + rc = ecryptfs_read_lower_page_segment( + page, page->index, 0, PAGE_CACHE_SIZE, + page->mapping->host); + if (rc) { + printk(KERN_ERR "%s: Error attemping to read " + "lower page segment; rc = [%d]\n", + __FUNCTION__, rc); + ClearPageUptodate(page); + goto out; + } else + SetPageUptodate(page); + } else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) { + if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) { + rc = ecryptfs_copy_up_encrypted_with_header( + page, crypt_stat); + if (rc) { + printk(KERN_ERR "%s: Error attempting " + "to copy the encrypted content " + "from the lower file whilst " + "inserting the metadata from " + "the xattr into the header; rc " + "= [%d]\n", __FUNCTION__, rc); + ClearPageUptodate(page); + goto out; + } + SetPageUptodate(page); + } else { + rc = ecryptfs_read_lower_page_segment( + page, page->index, 0, PAGE_CACHE_SIZE, + page->mapping->host); + if (rc) { + printk(KERN_ERR "%s: Error reading " + "page; rc = [%d]\n", + __FUNCTION__, rc); + ClearPageUptodate(page); + goto out; + } + SetPageUptodate(page); + } + } else { + rc = ecryptfs_decrypt_page(page); + if (rc) { + printk(KERN_ERR "%s: Error decrypting page " + "at index [%ld]; rc = [%d]\n", + __FUNCTION__, page->index, rc); + ClearPageUptodate(page); + goto out; + } SetPageUptodate(page); + } } - prev_page_end_size = ((loff_t)page->index << PAGE_CACHE_SHIFT); - - /* - * If creating a page or more of holes, zero them out via truncate. - * Note, this will increase i_size. - */ + /* If creating a page or more of holes, zero them out via truncate. + * Note, this will increase i_size. */ if (page->index != 0) { if (prev_page_end_size > i_size_read(page->mapping->host)) { rc = ecryptfs_truncate(file->f_path.dentry, prev_page_end_size); if (rc) { - printk(KERN_ERR "Error on attempt to " + printk(KERN_ERR "%s: Error on attempt to " "truncate to (higher) offset [%lld];" - " rc = [%d]\n", prev_page_end_size, rc); + " rc = [%d]\n", __FUNCTION__, + prev_page_end_size, rc); goto out; } } } - /* - * Writing to a new page, and creating a small hole from start of page? - * Zero it out. - */ - if ((i_size_read(page->mapping->host) == prev_page_end_size) && - (from != 0)) { - zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0); - } + /* Writing to a new page, and creating a small hole from start + * of page? Zero it out. */ + if ((i_size_read(page->mapping->host) == prev_page_end_size) + && (from != 0)) + zero_user(page, 0, PAGE_CACHE_SIZE); out: return rc; }