11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2688a9f7cSLee Jones /* 3237fead6SMichael Halcrow * eCryptfs: Linux filesystem encryption layer 4237fead6SMichael Halcrow * This is where eCryptfs coordinates the symmetric encryption and 5237fead6SMichael Halcrow * decryption of the file data as it passes between the lower 6237fead6SMichael Halcrow * encrypted file and the upper decrypted file. 7237fead6SMichael Halcrow * 8237fead6SMichael Halcrow * Copyright (C) 1997-2003 Erez Zadok 9237fead6SMichael Halcrow * Copyright (C) 2001-2003 Stony Brook University 10dd2a3b7aSMichael Halcrow * Copyright (C) 2004-2007 International Business Machines Corp. 11237fead6SMichael Halcrow * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> 12237fead6SMichael Halcrow */ 13237fead6SMichael Halcrow 14237fead6SMichael Halcrow #include <linux/pagemap.h> 15237fead6SMichael Halcrow #include <linux/writeback.h> 16237fead6SMichael Halcrow #include <linux/page-flags.h> 17237fead6SMichael Halcrow #include <linux/mount.h> 18237fead6SMichael Halcrow #include <linux/file.h> 19237fead6SMichael Halcrow #include <linux/scatterlist.h> 205a0e3ad6STejun Heo #include <linux/slab.h> 215d6c3191SAndreas Gruenbacher #include <linux/xattr.h> 220a688ad7SHarvey Harrison #include <asm/unaligned.h> 23237fead6SMichael Halcrow #include "ecryptfs_kernel.h" 24237fead6SMichael Halcrow 25688a9f7cSLee Jones /* 2616a72c45SMichael Halcrow * ecryptfs_get_locked_page 27237fead6SMichael Halcrow * 28237fead6SMichael Halcrow * Get one page from cache or lower f/s, return error otherwise. 29237fead6SMichael Halcrow * 3016a72c45SMichael Halcrow * Returns locked and up-to-date page (if ok), with increased 31237fead6SMichael Halcrow * refcnt. 32237fead6SMichael Halcrow */ 3302bd9799SAl Viro struct page *ecryptfs_get_locked_page(struct inode *inode, loff_t index) 34237fead6SMichael Halcrow { 3502bd9799SAl Viro struct page *page = read_mapping_page(inode->i_mapping, index, NULL); 3616a72c45SMichael Halcrow if (!IS_ERR(page)) 3716a72c45SMichael Halcrow lock_page(page); 3816a72c45SMichael Halcrow return page; 39237fead6SMichael Halcrow } 40237fead6SMichael Halcrow 41237fead6SMichael Halcrow /** 42237fead6SMichael Halcrow * ecryptfs_writepage 43237fead6SMichael Halcrow * @page: Page that is locked before this call is made 44688a9f7cSLee Jones * @wbc: Write-back control structure 45237fead6SMichael Halcrow * 46237fead6SMichael Halcrow * Returns zero on success; non-zero otherwise 471589cb1aSLi Wang * 481589cb1aSLi Wang * This is where we encrypt the data and pass the encrypted data to 491589cb1aSLi Wang * the lower filesystem. In OpenPGP-compatible mode, we operate on 501589cb1aSLi Wang * entire underlying packets. 51237fead6SMichael Halcrow */ 52237fead6SMichael Halcrow static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc) 53237fead6SMichael Halcrow { 54237fead6SMichael Halcrow int rc; 55237fead6SMichael Halcrow 560216f7f7SMichael Halcrow rc = ecryptfs_encrypt_page(page); 57237fead6SMichael Halcrow if (rc) { 58237fead6SMichael Halcrow ecryptfs_printk(KERN_WARNING, "Error encrypting " 59888d57bbSJoe Perches "page (upper index [0x%.16lx])\n", page->index); 60237fead6SMichael Halcrow ClearPageUptodate(page); 61237fead6SMichael Halcrow goto out; 62237fead6SMichael Halcrow } 63237fead6SMichael Halcrow SetPageUptodate(page); 64237fead6SMichael Halcrow out: 6557db4e8dSThieu Le unlock_page(page); 66237fead6SMichael Halcrow return rc; 67237fead6SMichael Halcrow } 68237fead6SMichael Halcrow 69f4e60e6bSTyler Hicks static void strip_xattr_flag(char *page_virt, 70f4e60e6bSTyler Hicks struct ecryptfs_crypt_stat *crypt_stat) 71f4e60e6bSTyler Hicks { 72f4e60e6bSTyler Hicks if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) { 73f4e60e6bSTyler Hicks size_t written; 74f4e60e6bSTyler Hicks 75f4e60e6bSTyler Hicks crypt_stat->flags &= ~ECRYPTFS_METADATA_IN_XATTR; 76f4e60e6bSTyler Hicks ecryptfs_write_crypt_stat_flags(page_virt, crypt_stat, 77f4e60e6bSTyler Hicks &written); 78f4e60e6bSTyler Hicks crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; 79f4e60e6bSTyler Hicks } 80f4e60e6bSTyler Hicks } 81f4e60e6bSTyler Hicks 82688a9f7cSLee Jones /* 83e77a56ddSMichael Halcrow * Header Extent: 84e77a56ddSMichael Halcrow * Octets 0-7: Unencrypted file size (big-endian) 85e77a56ddSMichael Halcrow * Octets 8-15: eCryptfs special marker 86e77a56ddSMichael Halcrow * Octets 16-19: Flags 87e77a56ddSMichael Halcrow * Octet 16: File format version number (between 0 and 255) 88e77a56ddSMichael Halcrow * Octets 17-18: Reserved 89e77a56ddSMichael Halcrow * Octet 19: Bit 1 (lsb): Reserved 90e77a56ddSMichael Halcrow * Bit 2: Encrypted? 91e77a56ddSMichael Halcrow * Bits 3-8: Reserved 92e77a56ddSMichael Halcrow * Octets 20-23: Header extent size (big-endian) 93e77a56ddSMichael Halcrow * Octets 24-25: Number of header extents at front of file 94e77a56ddSMichael Halcrow * (big-endian) 95e77a56ddSMichael Halcrow * Octet 26: Begin RFC 2440 authentication token packet set 96e77a56ddSMichael Halcrow */ 97237fead6SMichael Halcrow 98237fead6SMichael Halcrow /** 99bf12be1cSMichael Halcrow * ecryptfs_copy_up_encrypted_with_header 100bf12be1cSMichael Halcrow * @page: Sort of a ``virtual'' representation of the encrypted lower 101bf12be1cSMichael Halcrow * file. The actual lower file does not have the metadata in 102bf12be1cSMichael Halcrow * the header. This is locked. 103bf12be1cSMichael Halcrow * @crypt_stat: The eCryptfs inode's cryptographic context 104237fead6SMichael Halcrow * 105bf12be1cSMichael Halcrow * The ``view'' is the version of the file that userspace winds up 106bf12be1cSMichael Halcrow * seeing, with the header information inserted. 107237fead6SMichael Halcrow */ 108bf12be1cSMichael Halcrow static int 109bf12be1cSMichael Halcrow ecryptfs_copy_up_encrypted_with_header(struct page *page, 110bf12be1cSMichael Halcrow struct ecryptfs_crypt_stat *crypt_stat) 111237fead6SMichael Halcrow { 112bf12be1cSMichael Halcrow loff_t extent_num_in_page = 0; 11309cbfeafSKirill A. Shutemov loff_t num_extents_per_page = (PAGE_SIZE 114bf12be1cSMichael Halcrow / crypt_stat->extent_size); 115237fead6SMichael Halcrow int rc = 0; 116237fead6SMichael Halcrow 117bf12be1cSMichael Halcrow while (extent_num_in_page < num_extents_per_page) { 118d6a13c17SMichael Halcrow loff_t view_extent_num = ((((loff_t)page->index) 119d6a13c17SMichael Halcrow * num_extents_per_page) 120bf12be1cSMichael Halcrow + extent_num_in_page); 121cc11beffSMichael Halcrow size_t num_header_extents_at_front = 122fa3ef1cbSTyler Hicks (crypt_stat->metadata_size / crypt_stat->extent_size); 123e77a56ddSMichael Halcrow 124cc11beffSMichael Halcrow if (view_extent_num < num_header_extents_at_front) { 125bf12be1cSMichael Halcrow /* This is a header extent */ 126e77a56ddSMichael Halcrow char *page_virt; 127e77a56ddSMichael Halcrow 128465c9343SCong Wang page_virt = kmap_atomic(page); 12909cbfeafSKirill A. Shutemov memset(page_virt, 0, PAGE_SIZE); 130bf12be1cSMichael Halcrow /* TODO: Support more than one header extent */ 131bf12be1cSMichael Halcrow if (view_extent_num == 0) { 132157f1071STyler Hicks size_t written; 133157f1071STyler Hicks 134e77a56ddSMichael Halcrow rc = ecryptfs_read_xattr_region( 135d7cdc5feSMichael Halcrow page_virt, page->mapping->host); 136f4e60e6bSTyler Hicks strip_xattr_flag(page_virt + 16, crypt_stat); 137157f1071STyler Hicks ecryptfs_write_header_metadata(page_virt + 20, 138157f1071STyler Hicks crypt_stat, 139157f1071STyler Hicks &written); 140e77a56ddSMichael Halcrow } 141465c9343SCong Wang kunmap_atomic(page_virt); 1420a9ac382SMichael Halcrow flush_dcache_page(page); 143e77a56ddSMichael Halcrow if (rc) { 144bf12be1cSMichael Halcrow printk(KERN_ERR "%s: Error reading xattr " 14518d1dbf1SHarvey Harrison "region; rc = [%d]\n", __func__, rc); 146e77a56ddSMichael Halcrow goto out; 147e77a56ddSMichael Halcrow } 148e77a56ddSMichael Halcrow } else { 149bf12be1cSMichael Halcrow /* This is an encrypted data extent */ 150bf12be1cSMichael Halcrow loff_t lower_offset = 151cc11beffSMichael Halcrow ((view_extent_num * crypt_stat->extent_size) 152fa3ef1cbSTyler Hicks - crypt_stat->metadata_size); 153bf12be1cSMichael Halcrow 154bf12be1cSMichael Halcrow rc = ecryptfs_read_lower_page_segment( 15509cbfeafSKirill A. Shutemov page, (lower_offset >> PAGE_SHIFT), 15609cbfeafSKirill A. Shutemov (lower_offset & ~PAGE_MASK), 157bf12be1cSMichael Halcrow crypt_stat->extent_size, page->mapping->host); 158e77a56ddSMichael Halcrow if (rc) { 159bf12be1cSMichael Halcrow printk(KERN_ERR "%s: Error attempting to read " 160bf12be1cSMichael Halcrow "extent at offset [%lld] in the lower " 16118d1dbf1SHarvey Harrison "file; rc = [%d]\n", __func__, 162bf12be1cSMichael Halcrow lower_offset, rc); 163e77a56ddSMichael Halcrow goto out; 164e77a56ddSMichael Halcrow } 165e77a56ddSMichael Halcrow } 166bf12be1cSMichael Halcrow extent_num_in_page++; 167bf12be1cSMichael Halcrow } 168bf12be1cSMichael Halcrow out: 169bf12be1cSMichael Halcrow return rc; 170bf12be1cSMichael Halcrow } 171bf12be1cSMichael Halcrow 172bf12be1cSMichael Halcrow /** 173bf12be1cSMichael Halcrow * ecryptfs_readpage 174bf12be1cSMichael Halcrow * @file: An eCryptfs file 175bf12be1cSMichael Halcrow * @page: Page from eCryptfs inode mapping into which to stick the read data 176bf12be1cSMichael Halcrow * 177bf12be1cSMichael Halcrow * Read in a page, decrypting if necessary. 178bf12be1cSMichael Halcrow * 179bf12be1cSMichael Halcrow * Returns zero on success; non-zero on error. 180bf12be1cSMichael Halcrow */ 181bf12be1cSMichael Halcrow static int ecryptfs_readpage(struct file *file, struct page *page) 182bf12be1cSMichael Halcrow { 183bf12be1cSMichael Halcrow struct ecryptfs_crypt_stat *crypt_stat = 184bef5bc24SAl Viro &ecryptfs_inode_to_private(page->mapping->host)->crypt_stat; 185bf12be1cSMichael Halcrow int rc = 0; 186bf12be1cSMichael Halcrow 187fed8859bSTyler Hicks if (!crypt_stat || !(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { 188bf12be1cSMichael Halcrow rc = ecryptfs_read_lower_page_segment(page, page->index, 0, 18909cbfeafSKirill A. Shutemov PAGE_SIZE, 190bf12be1cSMichael Halcrow page->mapping->host); 191bf12be1cSMichael Halcrow } else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) { 192bf12be1cSMichael Halcrow if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) { 193bf12be1cSMichael Halcrow rc = ecryptfs_copy_up_encrypted_with_header(page, 194bf12be1cSMichael Halcrow crypt_stat); 195bf12be1cSMichael Halcrow if (rc) { 196bf12be1cSMichael Halcrow printk(KERN_ERR "%s: Error attempting to copy " 197bf12be1cSMichael Halcrow "the encrypted content from the lower " 198bf12be1cSMichael Halcrow "file whilst inserting the metadata " 199bf12be1cSMichael Halcrow "from the xattr into the header; rc = " 20018d1dbf1SHarvey Harrison "[%d]\n", __func__, rc); 201bf12be1cSMichael Halcrow goto out; 202bf12be1cSMichael Halcrow } 203bf12be1cSMichael Halcrow 204e77a56ddSMichael Halcrow } else { 205bf12be1cSMichael Halcrow rc = ecryptfs_read_lower_page_segment( 20609cbfeafSKirill A. Shutemov page, page->index, 0, PAGE_SIZE, 207bf12be1cSMichael Halcrow page->mapping->host); 208e77a56ddSMichael Halcrow if (rc) { 209e77a56ddSMichael Halcrow printk(KERN_ERR "Error reading page; rc = " 210e77a56ddSMichael Halcrow "[%d]\n", rc); 211e77a56ddSMichael Halcrow goto out; 212e77a56ddSMichael Halcrow } 213e77a56ddSMichael Halcrow } 214237fead6SMichael Halcrow } else { 2150216f7f7SMichael Halcrow rc = ecryptfs_decrypt_page(page); 216237fead6SMichael Halcrow if (rc) { 217237fead6SMichael Halcrow ecryptfs_printk(KERN_ERR, "Error decrypting page; " 218237fead6SMichael Halcrow "rc = [%d]\n", rc); 219237fead6SMichael Halcrow goto out; 220237fead6SMichael Halcrow } 221237fead6SMichael Halcrow } 222237fead6SMichael Halcrow out: 22316a72c45SMichael Halcrow if (rc) 22416a72c45SMichael Halcrow ClearPageUptodate(page); 22516a72c45SMichael Halcrow else 22616a72c45SMichael Halcrow SetPageUptodate(page); 227888d57bbSJoe Perches ecryptfs_printk(KERN_DEBUG, "Unlocking page with index = [0x%.16lx]\n", 228237fead6SMichael Halcrow page->index); 229237fead6SMichael Halcrow unlock_page(page); 230237fead6SMichael Halcrow return rc; 231237fead6SMichael Halcrow } 232237fead6SMichael Halcrow 233688a9f7cSLee Jones /* 234dd2a3b7aSMichael Halcrow * Called with lower inode mutex held. 235dd2a3b7aSMichael Halcrow */ 236237fead6SMichael Halcrow static int fill_zeros_to_end_of_page(struct page *page, unsigned int to) 237237fead6SMichael Halcrow { 238237fead6SMichael Halcrow struct inode *inode = page->mapping->host; 239237fead6SMichael Halcrow int end_byte_in_page; 240237fead6SMichael Halcrow 24109cbfeafSKirill A. Shutemov if ((i_size_read(inode) / PAGE_SIZE) != page->index) 2429d8b8ce5SMichael Halcrow goto out; 24309cbfeafSKirill A. Shutemov end_byte_in_page = i_size_read(inode) % PAGE_SIZE; 244237fead6SMichael Halcrow if (to > end_byte_in_page) 245237fead6SMichael Halcrow end_byte_in_page = to; 24609cbfeafSKirill A. Shutemov zero_user_segment(page, end_byte_in_page, PAGE_SIZE); 247237fead6SMichael Halcrow out: 2489d8b8ce5SMichael Halcrow return 0; 249237fead6SMichael Halcrow } 250237fead6SMichael Halcrow 251e4465fdaSMichael Halcrow /** 252807b7ebeSBadari Pulavarty * ecryptfs_write_begin 253e4465fdaSMichael Halcrow * @file: The eCryptfs file 254807b7ebeSBadari Pulavarty * @mapping: The eCryptfs object 255807b7ebeSBadari Pulavarty * @pos: The file offset at which to start writing 256807b7ebeSBadari Pulavarty * @len: Length of the write 257807b7ebeSBadari Pulavarty * @flags: Various flags 258807b7ebeSBadari Pulavarty * @pagep: Pointer to return the page 259807b7ebeSBadari Pulavarty * @fsdata: Pointer to return fs data (unused) 260e4465fdaSMichael Halcrow * 261e4465fdaSMichael Halcrow * This function must zero any hole we create 262e4465fdaSMichael Halcrow * 263e4465fdaSMichael Halcrow * Returns zero on success; non-zero otherwise 264e4465fdaSMichael Halcrow */ 265807b7ebeSBadari Pulavarty static int ecryptfs_write_begin(struct file *file, 266807b7ebeSBadari Pulavarty struct address_space *mapping, 267807b7ebeSBadari Pulavarty loff_t pos, unsigned len, unsigned flags, 268807b7ebeSBadari Pulavarty struct page **pagep, void **fsdata) 26953a2731fSMichael Halcrow { 27009cbfeafSKirill A. Shutemov pgoff_t index = pos >> PAGE_SHIFT; 271807b7ebeSBadari Pulavarty struct page *page; 2727a3f595cSEric Sandeen loff_t prev_page_end_size; 273e4465fdaSMichael Halcrow int rc = 0; 27453a2731fSMichael Halcrow 27554566b2cSNick Piggin page = grab_cache_page_write_begin(mapping, index, flags); 276807b7ebeSBadari Pulavarty if (!page) 277807b7ebeSBadari Pulavarty return -ENOMEM; 278807b7ebeSBadari Pulavarty *pagep = page; 279807b7ebeSBadari Pulavarty 28009cbfeafSKirill A. Shutemov prev_page_end_size = ((loff_t)index << PAGE_SHIFT); 28116a72c45SMichael Halcrow if (!PageUptodate(page)) { 282e4465fdaSMichael Halcrow struct ecryptfs_crypt_stat *crypt_stat = 283bef5bc24SAl Viro &ecryptfs_inode_to_private(mapping->host)->crypt_stat; 284e4465fdaSMichael Halcrow 285fed8859bSTyler Hicks if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { 286e4465fdaSMichael Halcrow rc = ecryptfs_read_lower_page_segment( 28709cbfeafSKirill A. Shutemov page, index, 0, PAGE_SIZE, mapping->host); 28816a72c45SMichael Halcrow if (rc) { 289971bd8faSMasanari Iida printk(KERN_ERR "%s: Error attempting to read " 290e4465fdaSMichael Halcrow "lower page segment; rc = [%d]\n", 29118d1dbf1SHarvey Harrison __func__, rc); 29216a72c45SMichael Halcrow ClearPageUptodate(page); 29316a72c45SMichael Halcrow goto out; 29416a72c45SMichael Halcrow } else 29516a72c45SMichael Halcrow SetPageUptodate(page); 296e4465fdaSMichael Halcrow } else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) { 297e4465fdaSMichael Halcrow if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) { 298e4465fdaSMichael Halcrow rc = ecryptfs_copy_up_encrypted_with_header( 299e4465fdaSMichael Halcrow page, crypt_stat); 300e4465fdaSMichael Halcrow if (rc) { 301e4465fdaSMichael Halcrow printk(KERN_ERR "%s: Error attempting " 302e4465fdaSMichael Halcrow "to copy the encrypted content " 303e4465fdaSMichael Halcrow "from the lower file whilst " 304e4465fdaSMichael Halcrow "inserting the metadata from " 305e4465fdaSMichael Halcrow "the xattr into the header; rc " 30618d1dbf1SHarvey Harrison "= [%d]\n", __func__, rc); 307e4465fdaSMichael Halcrow ClearPageUptodate(page); 308e4465fdaSMichael Halcrow goto out; 30916a72c45SMichael Halcrow } 310e4465fdaSMichael Halcrow SetPageUptodate(page); 311e4465fdaSMichael Halcrow } else { 312e4465fdaSMichael Halcrow rc = ecryptfs_read_lower_page_segment( 31309cbfeafSKirill A. Shutemov page, index, 0, PAGE_SIZE, 314807b7ebeSBadari Pulavarty mapping->host); 315e4465fdaSMichael Halcrow if (rc) { 316e4465fdaSMichael Halcrow printk(KERN_ERR "%s: Error reading " 317e4465fdaSMichael Halcrow "page; rc = [%d]\n", 31818d1dbf1SHarvey Harrison __func__, rc); 319e4465fdaSMichael Halcrow ClearPageUptodate(page); 320e4465fdaSMichael Halcrow goto out; 321e4465fdaSMichael Halcrow } 322e4465fdaSMichael Halcrow SetPageUptodate(page); 323e4465fdaSMichael Halcrow } 324e4465fdaSMichael Halcrow } else { 32524562486SFrank Swiderski if (prev_page_end_size 32624562486SFrank Swiderski >= i_size_read(page->mapping->host)) { 32709cbfeafSKirill A. Shutemov zero_user(page, 0, PAGE_SIZE); 328e4bc6522SLi Wang SetPageUptodate(page); 32909cbfeafSKirill A. Shutemov } else if (len < PAGE_SIZE) { 330e4465fdaSMichael Halcrow rc = ecryptfs_decrypt_page(page); 331e4465fdaSMichael Halcrow if (rc) { 33224562486SFrank Swiderski printk(KERN_ERR "%s: Error decrypting " 33324562486SFrank Swiderski "page at index [%ld]; " 33424562486SFrank Swiderski "rc = [%d]\n", 33518d1dbf1SHarvey Harrison __func__, page->index, rc); 336e4465fdaSMichael Halcrow ClearPageUptodate(page); 337e4465fdaSMichael Halcrow goto out; 338e4465fdaSMichael Halcrow } 339e4465fdaSMichael Halcrow SetPageUptodate(page); 340e4465fdaSMichael Halcrow } 341e4465fdaSMichael Halcrow } 342e4bc6522SLi Wang } 343e4465fdaSMichael Halcrow /* If creating a page or more of holes, zero them out via truncate. 344e4465fdaSMichael Halcrow * Note, this will increase i_size. */ 345807b7ebeSBadari Pulavarty if (index != 0) { 3467a3f595cSEric Sandeen if (prev_page_end_size > i_size_read(page->mapping->host)) { 347240e2df5SMichael Halcrow rc = ecryptfs_truncate(file->f_path.dentry, 3487a3f595cSEric Sandeen prev_page_end_size); 34953a2731fSMichael Halcrow if (rc) { 350e4465fdaSMichael Halcrow printk(KERN_ERR "%s: Error on attempt to " 35153a2731fSMichael Halcrow "truncate to (higher) offset [%lld];" 35218d1dbf1SHarvey Harrison " rc = [%d]\n", __func__, 353e4465fdaSMichael Halcrow prev_page_end_size, rc); 35453a2731fSMichael Halcrow goto out; 35553a2731fSMichael Halcrow } 35653a2731fSMichael Halcrow } 3577a3f595cSEric Sandeen } 358e4465fdaSMichael Halcrow /* Writing to a new page, and creating a small hole from start 359e4465fdaSMichael Halcrow * of page? Zero it out. */ 360807b7ebeSBadari Pulavarty if ((i_size_read(mapping->host) == prev_page_end_size) 361807b7ebeSBadari Pulavarty && (pos != 0)) 36209cbfeafSKirill A. Shutemov zero_user(page, 0, PAGE_SIZE); 36353a2731fSMichael Halcrow out: 36450f198aeSTyler Hicks if (unlikely(rc)) { 36550f198aeSTyler Hicks unlock_page(page); 36609cbfeafSKirill A. Shutemov put_page(page); 36750f198aeSTyler Hicks *pagep = NULL; 36850f198aeSTyler Hicks } 36953a2731fSMichael Halcrow return rc; 37053a2731fSMichael Halcrow } 37153a2731fSMichael Halcrow 372688a9f7cSLee Jones /* 373237fead6SMichael Halcrow * ecryptfs_write_inode_size_to_header 374237fead6SMichael Halcrow * 375237fead6SMichael Halcrow * Writes the lower file size to the first 8 bytes of the header. 376237fead6SMichael Halcrow * 377237fead6SMichael Halcrow * Returns zero on success; non-zero on error. 378237fead6SMichael Halcrow */ 3790216f7f7SMichael Halcrow static int ecryptfs_write_inode_size_to_header(struct inode *ecryptfs_inode) 380237fead6SMichael Halcrow { 3810216f7f7SMichael Halcrow char *file_size_virt; 3820216f7f7SMichael Halcrow int rc; 383237fead6SMichael Halcrow 3840216f7f7SMichael Halcrow file_size_virt = kmalloc(sizeof(u64), GFP_KERNEL); 3850216f7f7SMichael Halcrow if (!file_size_virt) { 3860216f7f7SMichael Halcrow rc = -ENOMEM; 387237fead6SMichael Halcrow goto out; 388237fead6SMichael Halcrow } 3890a688ad7SHarvey Harrison put_unaligned_be64(i_size_read(ecryptfs_inode), file_size_virt); 3900216f7f7SMichael Halcrow rc = ecryptfs_write_lower(ecryptfs_inode, file_size_virt, 0, 3910216f7f7SMichael Halcrow sizeof(u64)); 3920216f7f7SMichael Halcrow kfree(file_size_virt); 39396a7b9c2STyler Hicks if (rc < 0) 3940216f7f7SMichael Halcrow printk(KERN_ERR "%s: Error writing file size to header; " 39518d1dbf1SHarvey Harrison "rc = [%d]\n", __func__, rc); 39696a7b9c2STyler Hicks else 39796a7b9c2STyler Hicks rc = 0; 398237fead6SMichael Halcrow out: 399237fead6SMichael Halcrow return rc; 400237fead6SMichael Halcrow } 401237fead6SMichael Halcrow 4020216f7f7SMichael Halcrow struct kmem_cache *ecryptfs_xattr_cache; 4030216f7f7SMichael Halcrow 4040216f7f7SMichael Halcrow static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode) 405dd2a3b7aSMichael Halcrow { 406dd2a3b7aSMichael Halcrow ssize_t size; 407dd2a3b7aSMichael Halcrow void *xattr_virt; 4080216f7f7SMichael Halcrow struct dentry *lower_dentry = 409b583043eSAl Viro ecryptfs_inode_to_private(ecryptfs_inode)->lower_file->f_path.dentry; 4102b0143b5SDavid Howells struct inode *lower_inode = d_inode(lower_dentry); 411dd2a3b7aSMichael Halcrow int rc; 412dd2a3b7aSMichael Halcrow 4135d6c3191SAndreas Gruenbacher if (!(lower_inode->i_opflags & IOP_XATTR)) { 4140216f7f7SMichael Halcrow printk(KERN_WARNING 4150216f7f7SMichael Halcrow "No support for setting xattr in lower filesystem\n"); 4160216f7f7SMichael Halcrow rc = -ENOSYS; 4170216f7f7SMichael Halcrow goto out; 4180216f7f7SMichael Halcrow } 419dd2a3b7aSMichael Halcrow xattr_virt = kmem_cache_alloc(ecryptfs_xattr_cache, GFP_KERNEL); 420dd2a3b7aSMichael Halcrow if (!xattr_virt) { 421dd2a3b7aSMichael Halcrow rc = -ENOMEM; 422dd2a3b7aSMichael Halcrow goto out; 423dd2a3b7aSMichael Halcrow } 4245955102cSAl Viro inode_lock(lower_inode); 4255d6c3191SAndreas Gruenbacher size = __vfs_getxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME, 42609cbfeafSKirill A. Shutemov xattr_virt, PAGE_SIZE); 427dd2a3b7aSMichael Halcrow if (size < 0) 428dd2a3b7aSMichael Halcrow size = 8; 4290a688ad7SHarvey Harrison put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt); 430c7c7a1a1STycho Andersen rc = __vfs_setxattr(&init_user_ns, lower_dentry, lower_inode, 431c7c7a1a1STycho Andersen ECRYPTFS_XATTR_NAME, xattr_virt, size, 0); 4325955102cSAl Viro inode_unlock(lower_inode); 433dd2a3b7aSMichael Halcrow if (rc) 434dd2a3b7aSMichael Halcrow printk(KERN_ERR "Error whilst attempting to write inode size " 435dd2a3b7aSMichael Halcrow "to lower file xattr; rc = [%d]\n", rc); 436dd2a3b7aSMichael Halcrow kmem_cache_free(ecryptfs_xattr_cache, xattr_virt); 437dd2a3b7aSMichael Halcrow out: 438dd2a3b7aSMichael Halcrow return rc; 439dd2a3b7aSMichael Halcrow } 440dd2a3b7aSMichael Halcrow 4410216f7f7SMichael Halcrow int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode) 442dd2a3b7aSMichael Halcrow { 443dd2a3b7aSMichael Halcrow struct ecryptfs_crypt_stat *crypt_stat; 444dd2a3b7aSMichael Halcrow 4450216f7f7SMichael Halcrow crypt_stat = &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; 44613a791b4STyler Hicks BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)); 447dd2a3b7aSMichael Halcrow if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) 4480216f7f7SMichael Halcrow return ecryptfs_write_inode_size_to_xattr(ecryptfs_inode); 449dd2a3b7aSMichael Halcrow else 4500216f7f7SMichael Halcrow return ecryptfs_write_inode_size_to_header(ecryptfs_inode); 451dd2a3b7aSMichael Halcrow } 452dd2a3b7aSMichael Halcrow 453237fead6SMichael Halcrow /** 454807b7ebeSBadari Pulavarty * ecryptfs_write_end 455237fead6SMichael Halcrow * @file: The eCryptfs file object 456807b7ebeSBadari Pulavarty * @mapping: The eCryptfs object 457807b7ebeSBadari Pulavarty * @pos: The file position 458807b7ebeSBadari Pulavarty * @len: The length of the data (unused) 459807b7ebeSBadari Pulavarty * @copied: The amount of data copied 460237fead6SMichael Halcrow * @page: The eCryptfs page 461807b7ebeSBadari Pulavarty * @fsdata: The fsdata (unused) 462237fead6SMichael Halcrow */ 463807b7ebeSBadari Pulavarty static int ecryptfs_write_end(struct file *file, 464807b7ebeSBadari Pulavarty struct address_space *mapping, 465807b7ebeSBadari Pulavarty loff_t pos, unsigned len, unsigned copied, 466807b7ebeSBadari Pulavarty struct page *page, void *fsdata) 467237fead6SMichael Halcrow { 46809cbfeafSKirill A. Shutemov pgoff_t index = pos >> PAGE_SHIFT; 46909cbfeafSKirill A. Shutemov unsigned from = pos & (PAGE_SIZE - 1); 470807b7ebeSBadari Pulavarty unsigned to = from + copied; 471807b7ebeSBadari Pulavarty struct inode *ecryptfs_inode = mapping->host; 472bf12be1cSMichael Halcrow struct ecryptfs_crypt_stat *crypt_stat = 473bef5bc24SAl Viro &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; 474237fead6SMichael Halcrow int rc; 475237fead6SMichael Halcrow 476237fead6SMichael Halcrow ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page" 477888d57bbSJoe Perches "(page w/ index = [0x%.16lx], to = [%d])\n", index, to); 47813a791b4STyler Hicks if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { 47913a791b4STyler Hicks rc = ecryptfs_write_lower_page_segment(ecryptfs_inode, page, 0, 48013a791b4STyler Hicks to); 48113a791b4STyler Hicks if (!rc) { 48213a791b4STyler Hicks rc = copied; 48313a791b4STyler Hicks fsstack_copy_inode_size(ecryptfs_inode, 48413a791b4STyler Hicks ecryptfs_inode_to_lower(ecryptfs_inode)); 48513a791b4STyler Hicks } 48613a791b4STyler Hicks goto out; 48713a791b4STyler Hicks } 488e4bc6522SLi Wang if (!PageUptodate(page)) { 48909cbfeafSKirill A. Shutemov if (copied < PAGE_SIZE) { 490e4bc6522SLi Wang rc = 0; 491e4bc6522SLi Wang goto out; 492e4bc6522SLi Wang } 493e4bc6522SLi Wang SetPageUptodate(page); 494e4bc6522SLi Wang } 495bf12be1cSMichael Halcrow /* Fills in zeros if 'to' goes beyond inode size */ 496237fead6SMichael Halcrow rc = fill_zeros_to_end_of_page(page, to); 497237fead6SMichael Halcrow if (rc) { 498237fead6SMichael Halcrow ecryptfs_printk(KERN_WARNING, "Error attempting to fill " 499888d57bbSJoe Perches "zeros in page with index = [0x%.16lx]\n", index); 500237fead6SMichael Halcrow goto out; 501237fead6SMichael Halcrow } 502821f7494STyler Hicks rc = ecryptfs_encrypt_page(page); 503821f7494STyler Hicks if (rc) { 504821f7494STyler Hicks ecryptfs_printk(KERN_WARNING, "Error encrypting page (upper " 505821f7494STyler Hicks "index [0x%.16lx])\n", index); 506821f7494STyler Hicks goto out; 507821f7494STyler Hicks } 508807b7ebeSBadari Pulavarty if (pos + copied > i_size_read(ecryptfs_inode)) { 509807b7ebeSBadari Pulavarty i_size_write(ecryptfs_inode, pos + copied); 510237fead6SMichael Halcrow ecryptfs_printk(KERN_DEBUG, "Expanded file size to " 511888d57bbSJoe Perches "[0x%.16llx]\n", 512888d57bbSJoe Perches (unsigned long long)i_size_read(ecryptfs_inode)); 513821f7494STyler Hicks } 514bf12be1cSMichael Halcrow rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode); 515821f7494STyler Hicks if (rc) 516dd2a3b7aSMichael Halcrow printk(KERN_ERR "Error writing inode size to metadata; " 517dd2a3b7aSMichael Halcrow "rc = [%d]\n", rc); 518821f7494STyler Hicks else 519807b7ebeSBadari Pulavarty rc = copied; 520237fead6SMichael Halcrow out: 521807b7ebeSBadari Pulavarty unlock_page(page); 52209cbfeafSKirill A. Shutemov put_page(page); 523237fead6SMichael Halcrow return rc; 524237fead6SMichael Halcrow } 525237fead6SMichael Halcrow 526237fead6SMichael Halcrow static sector_t ecryptfs_bmap(struct address_space *mapping, sector_t block) 527237fead6SMichael Halcrow { 528569d2056SCarlos Maiolino struct inode *lower_inode = ecryptfs_inode_to_lower(mapping->host); 529569d2056SCarlos Maiolino int ret = bmap(lower_inode, &block); 530237fead6SMichael Halcrow 531569d2056SCarlos Maiolino if (ret) 532569d2056SCarlos Maiolino return 0; 533569d2056SCarlos Maiolino return block; 534237fead6SMichael Halcrow } 535237fead6SMichael Halcrow 536*0af57378SChristoph Hellwig #include <linux/buffer_head.h> 537*0af57378SChristoph Hellwig 5387f09410bSAlexey Dobriyan const struct address_space_operations ecryptfs_aops = { 539*0af57378SChristoph Hellwig /* 540*0af57378SChristoph Hellwig * XXX: This is pretty broken for multiple reasons: ecryptfs does not 541*0af57378SChristoph Hellwig * actually use buffer_heads, and ecryptfs will crash without 542*0af57378SChristoph Hellwig * CONFIG_BLOCK. But it matches the behavior before the default for 543*0af57378SChristoph Hellwig * address_space_operations without the ->set_page_dirty method was 544*0af57378SChristoph Hellwig * cleaned up, so this is the best we can do without maintainer 545*0af57378SChristoph Hellwig * feedback. 546*0af57378SChristoph Hellwig */ 547*0af57378SChristoph Hellwig #ifdef CONFIG_BLOCK 548*0af57378SChristoph Hellwig .set_page_dirty = __set_page_dirty_buffers, 549*0af57378SChristoph Hellwig #endif 550237fead6SMichael Halcrow .writepage = ecryptfs_writepage, 551237fead6SMichael Halcrow .readpage = ecryptfs_readpage, 552807b7ebeSBadari Pulavarty .write_begin = ecryptfs_write_begin, 553807b7ebeSBadari Pulavarty .write_end = ecryptfs_write_end, 554237fead6SMichael Halcrow .bmap = ecryptfs_bmap, 555237fead6SMichael Halcrow }; 556