VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
1a59d1b8e05ea (Thomas Gleixner     2019-05-27 08:55:05 +0200   1) // SPDX-License-Identifier: GPL-2.0-or-later
688a9f7cd824e (Lee Jones           2021-03-30 17:44:56 +0100   2) /*
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700   3)  * eCryptfs: Linux filesystem encryption layer
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700   4)  * This is where eCryptfs coordinates the symmetric encryption and
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700   5)  * decryption of the file data as it passes between the lower
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700   6)  * encrypted file and the upper decrypted file.
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700   7)  *
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700   8)  * Copyright (C) 1997-2003 Erez Zadok
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700   9)  * Copyright (C) 2001-2003 Stony Brook University
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800  10)  * Copyright (C) 2004-2007 International Business Machines Corp.
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  11)  *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  12)  */
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  13) 
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  14) #include <linux/pagemap.h>
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  15) #include <linux/writeback.h>
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  16) #include <linux/page-flags.h>
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  17) #include <linux/mount.h>
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  18) #include <linux/file.h>
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  19) #include <linux/scatterlist.h>
5a0e3ad6af866 (Tejun Heo           2010-03-24 17:04:11 +0900  20) #include <linux/slab.h>
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200  21) #include <linux/xattr.h>
0a688ad713949 (Harvey Harrison     2008-07-23 21:30:07 -0700  22) #include <asm/unaligned.h>
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  23) #include "ecryptfs_kernel.h"
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  24) 
688a9f7cd824e (Lee Jones           2021-03-30 17:44:56 +0100  25) /*
16a72c455a67b (Michael Halcrow     2007-10-16 01:28:14 -0700  26)  * ecryptfs_get_locked_page
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  27)  *
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  28)  * Get one page from cache or lower f/s, return error otherwise.
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  29)  *
16a72c455a67b (Michael Halcrow     2007-10-16 01:28:14 -0700  30)  * Returns locked and up-to-date page (if ok), with increased
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  31)  * refcnt.
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  32)  */
02bd97997a07a (Al Viro             2010-05-21 11:02:14 -0400  33) struct page *ecryptfs_get_locked_page(struct inode *inode, loff_t index)
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  34) {
02bd97997a07a (Al Viro             2010-05-21 11:02:14 -0400  35) 	struct page *page = read_mapping_page(inode->i_mapping, index, NULL);
16a72c455a67b (Michael Halcrow     2007-10-16 01:28:14 -0700  36) 	if (!IS_ERR(page))
16a72c455a67b (Michael Halcrow     2007-10-16 01:28:14 -0700  37) 		lock_page(page);
16a72c455a67b (Michael Halcrow     2007-10-16 01:28:14 -0700  38) 	return page;
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  39) }
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  40) 
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  41) /**
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  42)  * ecryptfs_writepage
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  43)  * @page: Page that is locked before this call is made
688a9f7cd824e (Lee Jones           2021-03-30 17:44:56 +0100  44)  * @wbc: Write-back control structure
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  45)  *
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  46)  * Returns zero on success; non-zero otherwise
1589cb1a94c38 (Li Wang             2012-01-25 15:40:31 +0800  47)  *
1589cb1a94c38 (Li Wang             2012-01-25 15:40:31 +0800  48)  * This is where we encrypt the data and pass the encrypted data to
1589cb1a94c38 (Li Wang             2012-01-25 15:40:31 +0800  49)  * the lower filesystem.  In OpenPGP-compatible mode, we operate on
1589cb1a94c38 (Li Wang             2012-01-25 15:40:31 +0800  50)  * entire underlying packets.
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  51)  */
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  52) static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc)
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  53) {
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  54) 	int rc;
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  55) 
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700  56) 	rc = ecryptfs_encrypt_page(page);
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  57) 	if (rc) {
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  58) 		ecryptfs_printk(KERN_WARNING, "Error encrypting "
888d57bbc91eb (Joe Perches         2010-11-10 15:46:16 -0800  59) 				"page (upper index [0x%.16lx])\n", page->index);
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  60) 		ClearPageUptodate(page);
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  61) 		goto out;
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  62) 	}
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  63) 	SetPageUptodate(page);
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  64) out:
57db4e8d73ef2 (Thieu Le            2011-03-08 16:26:03 -0800  65) 	unlock_page(page);
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  66) 	return rc;
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  67) }
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  68) 
f4e60e6b303bc (Tyler Hicks         2010-02-11 00:02:32 -0600  69) static void strip_xattr_flag(char *page_virt,
f4e60e6b303bc (Tyler Hicks         2010-02-11 00:02:32 -0600  70) 			     struct ecryptfs_crypt_stat *crypt_stat)
f4e60e6b303bc (Tyler Hicks         2010-02-11 00:02:32 -0600  71) {
f4e60e6b303bc (Tyler Hicks         2010-02-11 00:02:32 -0600  72) 	if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) {
f4e60e6b303bc (Tyler Hicks         2010-02-11 00:02:32 -0600  73) 		size_t written;
f4e60e6b303bc (Tyler Hicks         2010-02-11 00:02:32 -0600  74) 
f4e60e6b303bc (Tyler Hicks         2010-02-11 00:02:32 -0600  75) 		crypt_stat->flags &= ~ECRYPTFS_METADATA_IN_XATTR;
f4e60e6b303bc (Tyler Hicks         2010-02-11 00:02:32 -0600  76) 		ecryptfs_write_crypt_stat_flags(page_virt, crypt_stat,
f4e60e6b303bc (Tyler Hicks         2010-02-11 00:02:32 -0600  77) 						&written);
f4e60e6b303bc (Tyler Hicks         2010-02-11 00:02:32 -0600  78) 		crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;
f4e60e6b303bc (Tyler Hicks         2010-02-11 00:02:32 -0600  79) 	}
f4e60e6b303bc (Tyler Hicks         2010-02-11 00:02:32 -0600  80) }
f4e60e6b303bc (Tyler Hicks         2010-02-11 00:02:32 -0600  81) 
688a9f7cd824e (Lee Jones           2021-03-30 17:44:56 +0100  82) /*
e77a56ddceeec (Michael Halcrow     2007-02-12 00:53:47 -0800  83)  *   Header Extent:
e77a56ddceeec (Michael Halcrow     2007-02-12 00:53:47 -0800  84)  *     Octets 0-7:        Unencrypted file size (big-endian)
e77a56ddceeec (Michael Halcrow     2007-02-12 00:53:47 -0800  85)  *     Octets 8-15:       eCryptfs special marker
e77a56ddceeec (Michael Halcrow     2007-02-12 00:53:47 -0800  86)  *     Octets 16-19:      Flags
e77a56ddceeec (Michael Halcrow     2007-02-12 00:53:47 -0800  87)  *      Octet 16:         File format version number (between 0 and 255)
e77a56ddceeec (Michael Halcrow     2007-02-12 00:53:47 -0800  88)  *      Octets 17-18:     Reserved
e77a56ddceeec (Michael Halcrow     2007-02-12 00:53:47 -0800  89)  *      Octet 19:         Bit 1 (lsb): Reserved
e77a56ddceeec (Michael Halcrow     2007-02-12 00:53:47 -0800  90)  *                        Bit 2: Encrypted?
e77a56ddceeec (Michael Halcrow     2007-02-12 00:53:47 -0800  91)  *                        Bits 3-8: Reserved
e77a56ddceeec (Michael Halcrow     2007-02-12 00:53:47 -0800  92)  *     Octets 20-23:      Header extent size (big-endian)
e77a56ddceeec (Michael Halcrow     2007-02-12 00:53:47 -0800  93)  *     Octets 24-25:      Number of header extents at front of file
e77a56ddceeec (Michael Halcrow     2007-02-12 00:53:47 -0800  94)  *                        (big-endian)
e77a56ddceeec (Michael Halcrow     2007-02-12 00:53:47 -0800  95)  *     Octet  26:         Begin RFC 2440 authentication token packet set
e77a56ddceeec (Michael Halcrow     2007-02-12 00:53:47 -0800  96)  */
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700  97) 
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700  98) /**
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700  99)  * ecryptfs_copy_up_encrypted_with_header
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 100)  * @page: Sort of a ``virtual'' representation of the encrypted lower
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 101)  *        file. The actual lower file does not have the metadata in
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 102)  *        the header. This is locked.
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 103)  * @crypt_stat: The eCryptfs inode's cryptographic context
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 104)  *
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 105)  * The ``view'' is the version of the file that userspace winds up
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 106)  * seeing, with the header information inserted.
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 107)  */
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 108) static int
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 109) ecryptfs_copy_up_encrypted_with_header(struct page *page,
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 110) 				       struct ecryptfs_crypt_stat *crypt_stat)
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 111) {
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 112) 	loff_t extent_num_in_page = 0;
09cbfeaf1a5a6 (Kirill A. Shutemov  2016-04-01 15:29:47 +0300 113) 	loff_t num_extents_per_page = (PAGE_SIZE
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 114) 				       / crypt_stat->extent_size);
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 115) 	int rc = 0;
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 116) 
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 117) 	while (extent_num_in_page < num_extents_per_page) {
d6a13c17164fc (Michael Halcrow     2007-10-16 01:28:12 -0700 118) 		loff_t view_extent_num = ((((loff_t)page->index)
d6a13c17164fc (Michael Halcrow     2007-10-16 01:28:12 -0700 119) 					   * num_extents_per_page)
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 120) 					  + extent_num_in_page);
cc11beffdf80c (Michael Halcrow     2008-02-06 01:38:32 -0800 121) 		size_t num_header_extents_at_front =
fa3ef1cb4e6e9 (Tyler Hicks         2010-02-11 05:09:14 -0600 122) 			(crypt_stat->metadata_size / crypt_stat->extent_size);
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 123) 
cc11beffdf80c (Michael Halcrow     2008-02-06 01:38:32 -0800 124) 		if (view_extent_num < num_header_extents_at_front) {
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 125) 			/* This is a header extent */
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 126) 			char *page_virt;
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 127) 
465c9343c5b74 (Cong Wang           2012-02-10 13:39:50 +0800 128) 			page_virt = kmap_atomic(page);
09cbfeaf1a5a6 (Kirill A. Shutemov  2016-04-01 15:29:47 +0300 129) 			memset(page_virt, 0, PAGE_SIZE);
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 130) 			/* TODO: Support more than one header extent */
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 131) 			if (view_extent_num == 0) {
157f1071354db (Tyler Hicks         2010-02-11 07:10:38 -0600 132) 				size_t written;
157f1071354db (Tyler Hicks         2010-02-11 07:10:38 -0600 133) 
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 134) 				rc = ecryptfs_read_xattr_region(
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 135) 					page_virt, page->mapping->host);
f4e60e6b303bc (Tyler Hicks         2010-02-11 00:02:32 -0600 136) 				strip_xattr_flag(page_virt + 16, crypt_stat);
157f1071354db (Tyler Hicks         2010-02-11 07:10:38 -0600 137) 				ecryptfs_write_header_metadata(page_virt + 20,
157f1071354db (Tyler Hicks         2010-02-11 07:10:38 -0600 138) 							       crypt_stat,
157f1071354db (Tyler Hicks         2010-02-11 07:10:38 -0600 139) 							       &written);
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 140) 			}
465c9343c5b74 (Cong Wang           2012-02-10 13:39:50 +0800 141) 			kunmap_atomic(page_virt);
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 142) 			flush_dcache_page(page);
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 143) 			if (rc) {
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 144) 				printk(KERN_ERR "%s: Error reading xattr "
18d1dbf1d401e (Harvey Harrison     2008-04-29 00:59:48 -0700 145) 				       "region; rc = [%d]\n", __func__, rc);
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 146) 				goto out;
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 147) 			}
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 148) 		} else {
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 149) 			/* This is an encrypted data extent */
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 150) 			loff_t lower_offset =
cc11beffdf80c (Michael Halcrow     2008-02-06 01:38:32 -0800 151) 				((view_extent_num * crypt_stat->extent_size)
fa3ef1cb4e6e9 (Tyler Hicks         2010-02-11 05:09:14 -0600 152) 				 - crypt_stat->metadata_size);
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 153) 
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 154) 			rc = ecryptfs_read_lower_page_segment(
09cbfeaf1a5a6 (Kirill A. Shutemov  2016-04-01 15:29:47 +0300 155) 				page, (lower_offset >> PAGE_SHIFT),
09cbfeaf1a5a6 (Kirill A. Shutemov  2016-04-01 15:29:47 +0300 156) 				(lower_offset & ~PAGE_MASK),
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 157) 				crypt_stat->extent_size, page->mapping->host);
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 158) 			if (rc) {
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 159) 				printk(KERN_ERR "%s: Error attempting to read "
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 160) 				       "extent at offset [%lld] in the lower "
18d1dbf1d401e (Harvey Harrison     2008-04-29 00:59:48 -0700 161) 				       "file; rc = [%d]\n", __func__,
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 162) 				       lower_offset, rc);
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 163) 				goto out;
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 164) 			}
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 165) 		}
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 166) 		extent_num_in_page++;
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 167) 	}
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 168) out:
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 169) 	return rc;
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 170) }
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 171) 
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 172) /**
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 173)  * ecryptfs_readpage
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 174)  * @file: An eCryptfs file
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 175)  * @page: Page from eCryptfs inode mapping into which to stick the read data
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 176)  *
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 177)  * Read in a page, decrypting if necessary.
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 178)  *
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 179)  * Returns zero on success; non-zero on error.
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 180)  */
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 181) static int ecryptfs_readpage(struct file *file, struct page *page)
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 182) {
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 183) 	struct ecryptfs_crypt_stat *crypt_stat =
bef5bc2464517 (Al Viro             2010-05-21 10:56:12 -0400 184) 		&ecryptfs_inode_to_private(page->mapping->host)->crypt_stat;
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 185) 	int rc = 0;
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 186) 
fed8859b3ab94 (Tyler Hicks         2011-02-23 00:54:20 -0600 187) 	if (!crypt_stat || !(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 188) 		rc = ecryptfs_read_lower_page_segment(page, page->index, 0,
09cbfeaf1a5a6 (Kirill A. Shutemov  2016-04-01 15:29:47 +0300 189) 						      PAGE_SIZE,
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 190) 						      page->mapping->host);
e77a56ddceeec (Michael Halcrow     2007-02-12 00:53:47 -0800 191) 	} else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) {
e77a56ddceeec (Michael Halcrow     2007-02-12 00:53:47 -0800 192) 		if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) {
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 193) 			rc = ecryptfs_copy_up_encrypted_with_header(page,
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 194) 								    crypt_stat);
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 195) 			if (rc) {
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 196) 				printk(KERN_ERR "%s: Error attempting to copy "
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 197) 				       "the encrypted content from the lower "
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 198) 				       "file whilst inserting the metadata "
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 199) 				       "from the xattr into the header; rc = "
18d1dbf1d401e (Harvey Harrison     2008-04-29 00:59:48 -0700 200) 				       "[%d]\n", __func__, rc);
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 201) 				goto out;
e77a56ddceeec (Michael Halcrow     2007-02-12 00:53:47 -0800 202) 			}
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 203) 
e77a56ddceeec (Michael Halcrow     2007-02-12 00:53:47 -0800 204) 		} else {
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 205) 			rc = ecryptfs_read_lower_page_segment(
09cbfeaf1a5a6 (Kirill A. Shutemov  2016-04-01 15:29:47 +0300 206) 				page, page->index, 0, PAGE_SIZE,
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 207) 				page->mapping->host);
e77a56ddceeec (Michael Halcrow     2007-02-12 00:53:47 -0800 208) 			if (rc) {
e77a56ddceeec (Michael Halcrow     2007-02-12 00:53:47 -0800 209) 				printk(KERN_ERR "Error reading page; rc = "
e77a56ddceeec (Michael Halcrow     2007-02-12 00:53:47 -0800 210) 				       "[%d]\n", rc);
e77a56ddceeec (Michael Halcrow     2007-02-12 00:53:47 -0800 211) 				goto out;
e77a56ddceeec (Michael Halcrow     2007-02-12 00:53:47 -0800 212) 			}
e77a56ddceeec (Michael Halcrow     2007-02-12 00:53:47 -0800 213) 		}
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 214) 	} else {
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700 215) 		rc = ecryptfs_decrypt_page(page);
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 216) 		if (rc) {
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 217) 			ecryptfs_printk(KERN_ERR, "Error decrypting page; "
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 218) 					"rc = [%d]\n", rc);
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 219) 			goto out;
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 220) 		}
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 221) 	}
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 222) out:
16a72c455a67b (Michael Halcrow     2007-10-16 01:28:14 -0700 223) 	if (rc)
16a72c455a67b (Michael Halcrow     2007-10-16 01:28:14 -0700 224) 		ClearPageUptodate(page);
16a72c455a67b (Michael Halcrow     2007-10-16 01:28:14 -0700 225) 	else
16a72c455a67b (Michael Halcrow     2007-10-16 01:28:14 -0700 226) 		SetPageUptodate(page);
888d57bbc91eb (Joe Perches         2010-11-10 15:46:16 -0800 227) 	ecryptfs_printk(KERN_DEBUG, "Unlocking page with index = [0x%.16lx]\n",
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 228) 			page->index);
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 229) 	unlock_page(page);
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 230) 	return rc;
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 231) }
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 232) 
688a9f7cd824e (Lee Jones           2021-03-30 17:44:56 +0100 233) /*
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 234)  * Called with lower inode mutex held.
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 235)  */
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 236) static int fill_zeros_to_end_of_page(struct page *page, unsigned int to)
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 237) {
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 238) 	struct inode *inode = page->mapping->host;
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 239) 	int end_byte_in_page;
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 240) 
09cbfeaf1a5a6 (Kirill A. Shutemov  2016-04-01 15:29:47 +0300 241) 	if ((i_size_read(inode) / PAGE_SIZE) != page->index)
9d8b8ce556189 (Michael Halcrow     2007-02-12 00:53:48 -0800 242) 		goto out;
09cbfeaf1a5a6 (Kirill A. Shutemov  2016-04-01 15:29:47 +0300 243) 	end_byte_in_page = i_size_read(inode) % PAGE_SIZE;
9d8b8ce556189 (Michael Halcrow     2007-02-12 00:53:48 -0800 244) 	if (to > end_byte_in_page)
9d8b8ce556189 (Michael Halcrow     2007-02-12 00:53:48 -0800 245) 		end_byte_in_page = to;
09cbfeaf1a5a6 (Kirill A. Shutemov  2016-04-01 15:29:47 +0300 246) 	zero_user_segment(page, end_byte_in_page, PAGE_SIZE);
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 247) out:
9d8b8ce556189 (Michael Halcrow     2007-02-12 00:53:48 -0800 248) 	return 0;
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 249) }
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 250) 
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 251) /**
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 252)  * ecryptfs_write_begin
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 253)  * @file: The eCryptfs file
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 254)  * @mapping: The eCryptfs object
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 255)  * @pos: The file offset at which to start writing
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 256)  * @len: Length of the write
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 257)  * @flags: Various flags
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 258)  * @pagep: Pointer to return the page
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 259)  * @fsdata: Pointer to return fs data (unused)
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 260)  *
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 261)  * This function must zero any hole we create
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 262)  *
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 263)  * Returns zero on success; non-zero otherwise
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 264)  */
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 265) static int ecryptfs_write_begin(struct file *file,
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 266) 			struct address_space *mapping,
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 267) 			loff_t pos, unsigned len, unsigned flags,
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 268) 			struct page **pagep, void **fsdata)
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 269) {
09cbfeaf1a5a6 (Kirill A. Shutemov  2016-04-01 15:29:47 +0300 270) 	pgoff_t index = pos >> PAGE_SHIFT;
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 271) 	struct page *page;
7a3f595cc8298 (Eric Sandeen        2007-12-17 16:20:10 -0800 272) 	loff_t prev_page_end_size;
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 273) 	int rc = 0;
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 274) 
54566b2c1594c (Nicholas Piggin     2009-01-04 12:00:53 -0800 275) 	page = grab_cache_page_write_begin(mapping, index, flags);
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 276) 	if (!page)
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 277) 		return -ENOMEM;
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 278) 	*pagep = page;
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 279) 
09cbfeaf1a5a6 (Kirill A. Shutemov  2016-04-01 15:29:47 +0300 280) 	prev_page_end_size = ((loff_t)index << PAGE_SHIFT);
16a72c455a67b (Michael Halcrow     2007-10-16 01:28:14 -0700 281) 	if (!PageUptodate(page)) {
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 282) 		struct ecryptfs_crypt_stat *crypt_stat =
bef5bc2464517 (Al Viro             2010-05-21 10:56:12 -0400 283) 			&ecryptfs_inode_to_private(mapping->host)->crypt_stat;
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 284) 
fed8859b3ab94 (Tyler Hicks         2011-02-23 00:54:20 -0600 285) 		if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 286) 			rc = ecryptfs_read_lower_page_segment(
09cbfeaf1a5a6 (Kirill A. Shutemov  2016-04-01 15:29:47 +0300 287) 				page, index, 0, PAGE_SIZE, mapping->host);
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 288) 			if (rc) {
971bd8fa369a3 (Masanari Iida       2015-05-20 23:54:02 +0900 289) 				printk(KERN_ERR "%s: Error attempting to read "
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 290) 				       "lower page segment; rc = [%d]\n",
18d1dbf1d401e (Harvey Harrison     2008-04-29 00:59:48 -0700 291) 				       __func__, rc);
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 292) 				ClearPageUptodate(page);
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 293) 				goto out;
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 294) 			} else
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 295) 				SetPageUptodate(page);
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 296) 		} else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) {
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 297) 			if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) {
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 298) 				rc = ecryptfs_copy_up_encrypted_with_header(
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 299) 					page, crypt_stat);
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 300) 				if (rc) {
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 301) 					printk(KERN_ERR "%s: Error attempting "
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 302) 					       "to copy the encrypted content "
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 303) 					       "from the lower file whilst "
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 304) 					       "inserting the metadata from "
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 305) 					       "the xattr into the header; rc "
18d1dbf1d401e (Harvey Harrison     2008-04-29 00:59:48 -0700 306) 					       "= [%d]\n", __func__, rc);
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 307) 					ClearPageUptodate(page);
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 308) 					goto out;
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 309) 				}
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 310) 				SetPageUptodate(page);
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 311) 			} else {
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 312) 				rc = ecryptfs_read_lower_page_segment(
09cbfeaf1a5a6 (Kirill A. Shutemov  2016-04-01 15:29:47 +0300 313) 					page, index, 0, PAGE_SIZE,
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 314) 					mapping->host);
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 315) 				if (rc) {
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 316) 					printk(KERN_ERR "%s: Error reading "
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 317) 					       "page; rc = [%d]\n",
18d1dbf1d401e (Harvey Harrison     2008-04-29 00:59:48 -0700 318) 					       __func__, rc);
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 319) 					ClearPageUptodate(page);
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 320) 					goto out;
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 321) 				}
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 322) 				SetPageUptodate(page);
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 323) 			}
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 324) 		} else {
24562486be76c (Frank Swiderski     2010-11-15 10:43:22 -0800 325) 			if (prev_page_end_size
24562486be76c (Frank Swiderski     2010-11-15 10:43:22 -0800 326) 			    >= i_size_read(page->mapping->host)) {
09cbfeaf1a5a6 (Kirill A. Shutemov  2016-04-01 15:29:47 +0300 327) 				zero_user(page, 0, PAGE_SIZE);
e4bc6522d53b7 (Li Wang             2012-10-30 19:52:40 +0800 328) 				SetPageUptodate(page);
09cbfeaf1a5a6 (Kirill A. Shutemov  2016-04-01 15:29:47 +0300 329) 			} else if (len < PAGE_SIZE) {
24562486be76c (Frank Swiderski     2010-11-15 10:43:22 -0800 330) 				rc = ecryptfs_decrypt_page(page);
24562486be76c (Frank Swiderski     2010-11-15 10:43:22 -0800 331) 				if (rc) {
24562486be76c (Frank Swiderski     2010-11-15 10:43:22 -0800 332) 					printk(KERN_ERR "%s: Error decrypting "
24562486be76c (Frank Swiderski     2010-11-15 10:43:22 -0800 333) 					       "page at index [%ld]; "
24562486be76c (Frank Swiderski     2010-11-15 10:43:22 -0800 334) 					       "rc = [%d]\n",
24562486be76c (Frank Swiderski     2010-11-15 10:43:22 -0800 335) 					       __func__, page->index, rc);
24562486be76c (Frank Swiderski     2010-11-15 10:43:22 -0800 336) 					ClearPageUptodate(page);
24562486be76c (Frank Swiderski     2010-11-15 10:43:22 -0800 337) 					goto out;
24562486be76c (Frank Swiderski     2010-11-15 10:43:22 -0800 338) 				}
e4bc6522d53b7 (Li Wang             2012-10-30 19:52:40 +0800 339) 				SetPageUptodate(page);
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 340) 			}
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 341) 		}
16a72c455a67b (Michael Halcrow     2007-10-16 01:28:14 -0700 342) 	}
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 343) 	/* If creating a page or more of holes, zero them out via truncate.
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 344) 	 * Note, this will increase i_size. */
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 345) 	if (index != 0) {
7a3f595cc8298 (Eric Sandeen        2007-12-17 16:20:10 -0800 346) 		if (prev_page_end_size > i_size_read(page->mapping->host)) {
240e2df5c740d (Michael Halcrow     2007-06-27 14:09:44 -0700 347) 			rc = ecryptfs_truncate(file->f_path.dentry,
7a3f595cc8298 (Eric Sandeen        2007-12-17 16:20:10 -0800 348) 					       prev_page_end_size);
240e2df5c740d (Michael Halcrow     2007-06-27 14:09:44 -0700 349) 			if (rc) {
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 350) 				printk(KERN_ERR "%s: Error on attempt to "
240e2df5c740d (Michael Halcrow     2007-06-27 14:09:44 -0700 351) 				       "truncate to (higher) offset [%lld];"
18d1dbf1d401e (Harvey Harrison     2008-04-29 00:59:48 -0700 352) 				       " rc = [%d]\n", __func__,
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 353) 				       prev_page_end_size, rc);
240e2df5c740d (Michael Halcrow     2007-06-27 14:09:44 -0700 354) 				goto out;
240e2df5c740d (Michael Halcrow     2007-06-27 14:09:44 -0700 355) 			}
53a2731f9310a (Michael Halcrow     2007-05-23 13:58:15 -0700 356) 		}
7a3f595cc8298 (Eric Sandeen        2007-12-17 16:20:10 -0800 357) 	}
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 358) 	/* Writing to a new page, and creating a small hole from start
e4465fdaeb3f7 (Michael Halcrow     2008-03-04 14:29:24 -0800 359) 	 * of page?  Zero it out. */
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 360) 	if ((i_size_read(mapping->host) == prev_page_end_size)
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 361) 	    && (pos != 0))
09cbfeaf1a5a6 (Kirill A. Shutemov  2016-04-01 15:29:47 +0300 362) 		zero_user(page, 0, PAGE_SIZE);
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 363) out:
50f198ae16ac6 (Tyler Hicks         2011-03-09 11:49:13 -0600 364) 	if (unlikely(rc)) {
50f198ae16ac6 (Tyler Hicks         2011-03-09 11:49:13 -0600 365) 		unlock_page(page);
09cbfeaf1a5a6 (Kirill A. Shutemov  2016-04-01 15:29:47 +0300 366) 		put_page(page);
50f198ae16ac6 (Tyler Hicks         2011-03-09 11:49:13 -0600 367) 		*pagep = NULL;
50f198ae16ac6 (Tyler Hicks         2011-03-09 11:49:13 -0600 368) 	}
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 369) 	return rc;
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 370) }
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 371) 
688a9f7cd824e (Lee Jones           2021-03-30 17:44:56 +0100 372) /*
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 373)  * ecryptfs_write_inode_size_to_header
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 374)  *
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 375)  * Writes the lower file size to the first 8 bytes of the header.
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 376)  *
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 377)  * Returns zero on success; non-zero on error.
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 378)  */
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700 379) static int ecryptfs_write_inode_size_to_header(struct inode *ecryptfs_inode)
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 380) {
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700 381) 	char *file_size_virt;
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700 382) 	int rc;
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 383) 
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700 384) 	file_size_virt = kmalloc(sizeof(u64), GFP_KERNEL);
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700 385) 	if (!file_size_virt) {
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700 386) 		rc = -ENOMEM;
ae73fc093a8ca (Michael Halcrow     2007-02-28 20:12:16 -0800 387) 		goto out;
ae73fc093a8ca (Michael Halcrow     2007-02-28 20:12:16 -0800 388) 	}
0a688ad713949 (Harvey Harrison     2008-07-23 21:30:07 -0700 389) 	put_unaligned_be64(i_size_read(ecryptfs_inode), file_size_virt);
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700 390) 	rc = ecryptfs_write_lower(ecryptfs_inode, file_size_virt, 0,
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700 391) 				  sizeof(u64));
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700 392) 	kfree(file_size_virt);
96a7b9c2f5df8 (Tyler Hicks         2009-09-16 19:04:20 -0500 393) 	if (rc < 0)
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700 394) 		printk(KERN_ERR "%s: Error writing file size to header; "
18d1dbf1d401e (Harvey Harrison     2008-04-29 00:59:48 -0700 395) 		       "rc = [%d]\n", __func__, rc);
96a7b9c2f5df8 (Tyler Hicks         2009-09-16 19:04:20 -0500 396) 	else
96a7b9c2f5df8 (Tyler Hicks         2009-09-16 19:04:20 -0500 397) 		rc = 0;
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 398) out:
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 399) 	return rc;
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 400) }
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 401) 
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700 402) struct kmem_cache *ecryptfs_xattr_cache;
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700 403) 
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700 404) static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 405) {
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 406) 	ssize_t size;
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 407) 	void *xattr_virt;
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700 408) 	struct dentry *lower_dentry =
b583043e99bc6 (Al Viro             2014-10-31 01:22:04 -0400 409) 		ecryptfs_inode_to_private(ecryptfs_inode)->lower_file->f_path.dentry;
2b0143b5c986b (David Howells       2015-03-17 22:25:59 +0000 410) 	struct inode *lower_inode = d_inode(lower_dentry);
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 411) 	int rc;
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 412) 
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 413) 	if (!(lower_inode->i_opflags & IOP_XATTR)) {
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700 414) 		printk(KERN_WARNING
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700 415) 		       "No support for setting xattr in lower filesystem\n");
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700 416) 		rc = -ENOSYS;
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700 417) 		goto out;
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700 418) 	}
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 419) 	xattr_virt = kmem_cache_alloc(ecryptfs_xattr_cache, GFP_KERNEL);
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 420) 	if (!xattr_virt) {
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 421) 		rc = -ENOMEM;
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 422) 		goto out;
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 423) 	}
5955102c9984f (Al Viro             2016-01-22 15:40:57 -0500 424) 	inode_lock(lower_inode);
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 425) 	size = __vfs_getxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME,
5d6c31910bc07 (Andreas Gruenbacher 2016-09-29 17:48:42 +0200 426) 			      xattr_virt, PAGE_SIZE);
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 427) 	if (size < 0)
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 428) 		size = 8;
0a688ad713949 (Harvey Harrison     2008-07-23 21:30:07 -0700 429) 	put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt);
c7c7a1a18af4c (Tycho Andersen      2021-01-21 14:19:28 +0100 430) 	rc = __vfs_setxattr(&init_user_ns, lower_dentry, lower_inode,
c7c7a1a18af4c (Tycho Andersen      2021-01-21 14:19:28 +0100 431) 			    ECRYPTFS_XATTR_NAME, xattr_virt, size, 0);
5955102c9984f (Al Viro             2016-01-22 15:40:57 -0500 432) 	inode_unlock(lower_inode);
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 433) 	if (rc)
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 434) 		printk(KERN_ERR "Error whilst attempting to write inode size "
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 435) 		       "to lower file xattr; rc = [%d]\n", rc);
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 436) 	kmem_cache_free(ecryptfs_xattr_cache, xattr_virt);
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 437) out:
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 438) 	return rc;
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 439) }
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 440) 
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700 441) int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode)
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 442) {
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 443) 	struct ecryptfs_crypt_stat *crypt_stat;
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 444) 
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700 445) 	crypt_stat = &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
13a791b4e63eb (Tyler Hicks         2009-04-13 15:29:27 -0500 446) 	BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED));
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 447) 	if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700 448) 		return ecryptfs_write_inode_size_to_xattr(ecryptfs_inode);
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 449) 	else
0216f7f792175 (Michael Halcrow     2007-10-16 01:28:08 -0700 450) 		return ecryptfs_write_inode_size_to_header(ecryptfs_inode);
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 451) }
dd2a3b7ad98f8 (Michael Halcrow     2007-02-12 00:53:46 -0800 452) 
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 453) /**
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 454)  * ecryptfs_write_end
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 455)  * @file: The eCryptfs file object
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 456)  * @mapping: The eCryptfs object
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 457)  * @pos: The file position
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 458)  * @len: The length of the data (unused)
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 459)  * @copied: The amount of data copied
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 460)  * @page: The eCryptfs page
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 461)  * @fsdata: The fsdata (unused)
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 462)  */
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 463) static int ecryptfs_write_end(struct file *file,
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 464) 			struct address_space *mapping,
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 465) 			loff_t pos, unsigned len, unsigned copied,
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 466) 			struct page *page, void *fsdata)
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 467) {
09cbfeaf1a5a6 (Kirill A. Shutemov  2016-04-01 15:29:47 +0300 468) 	pgoff_t index = pos >> PAGE_SHIFT;
09cbfeaf1a5a6 (Kirill A. Shutemov  2016-04-01 15:29:47 +0300 469) 	unsigned from = pos & (PAGE_SIZE - 1);
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 470) 	unsigned to = from + copied;
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 471) 	struct inode *ecryptfs_inode = mapping->host;
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 472) 	struct ecryptfs_crypt_stat *crypt_stat =
bef5bc2464517 (Al Viro             2010-05-21 10:56:12 -0400 473) 		&ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 474) 	int rc;
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 475) 
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 476) 	ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page"
888d57bbc91eb (Joe Perches         2010-11-10 15:46:16 -0800 477) 			"(page w/ index = [0x%.16lx], to = [%d])\n", index, to);
13a791b4e63eb (Tyler Hicks         2009-04-13 15:29:27 -0500 478) 	if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
13a791b4e63eb (Tyler Hicks         2009-04-13 15:29:27 -0500 479) 		rc = ecryptfs_write_lower_page_segment(ecryptfs_inode, page, 0,
13a791b4e63eb (Tyler Hicks         2009-04-13 15:29:27 -0500 480) 						       to);
13a791b4e63eb (Tyler Hicks         2009-04-13 15:29:27 -0500 481) 		if (!rc) {
13a791b4e63eb (Tyler Hicks         2009-04-13 15:29:27 -0500 482) 			rc = copied;
13a791b4e63eb (Tyler Hicks         2009-04-13 15:29:27 -0500 483) 			fsstack_copy_inode_size(ecryptfs_inode,
13a791b4e63eb (Tyler Hicks         2009-04-13 15:29:27 -0500 484) 				ecryptfs_inode_to_lower(ecryptfs_inode));
13a791b4e63eb (Tyler Hicks         2009-04-13 15:29:27 -0500 485) 		}
13a791b4e63eb (Tyler Hicks         2009-04-13 15:29:27 -0500 486) 		goto out;
13a791b4e63eb (Tyler Hicks         2009-04-13 15:29:27 -0500 487) 	}
e4bc6522d53b7 (Li Wang             2012-10-30 19:52:40 +0800 488) 	if (!PageUptodate(page)) {
09cbfeaf1a5a6 (Kirill A. Shutemov  2016-04-01 15:29:47 +0300 489) 		if (copied < PAGE_SIZE) {
e4bc6522d53b7 (Li Wang             2012-10-30 19:52:40 +0800 490) 			rc = 0;
e4bc6522d53b7 (Li Wang             2012-10-30 19:52:40 +0800 491) 			goto out;
e4bc6522d53b7 (Li Wang             2012-10-30 19:52:40 +0800 492) 		}
e4bc6522d53b7 (Li Wang             2012-10-30 19:52:40 +0800 493) 		SetPageUptodate(page);
e4bc6522d53b7 (Li Wang             2012-10-30 19:52:40 +0800 494) 	}
bf12be1cc851c (Michael Halcrow     2007-10-16 01:28:11 -0700 495) 	/* Fills in zeros if 'to' goes beyond inode size */
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 496) 	rc = fill_zeros_to_end_of_page(page, to);
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 497) 	if (rc) {
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 498) 		ecryptfs_printk(KERN_WARNING, "Error attempting to fill "
888d57bbc91eb (Joe Perches         2010-11-10 15:46:16 -0800 499) 			"zeros in page with index = [0x%.16lx]\n", index);
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 500) 		goto out;
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 501) 	}
821f7494a7762 (Tyler Hicks         2012-07-03 16:50:57 -0700 502) 	rc = ecryptfs_encrypt_page(page);
821f7494a7762 (Tyler Hicks         2012-07-03 16:50:57 -0700 503) 	if (rc) {
821f7494a7762 (Tyler Hicks         2012-07-03 16:50:57 -0700 504) 		ecryptfs_printk(KERN_WARNING, "Error encrypting page (upper "
821f7494a7762 (Tyler Hicks         2012-07-03 16:50:57 -0700 505) 				"index [0x%.16lx])\n", index);
821f7494a7762 (Tyler Hicks         2012-07-03 16:50:57 -0700 506) 		goto out;
821f7494a7762 (Tyler Hicks         2012-07-03 16:50:57 -0700 507) 	}
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 508) 	if (pos + copied > i_size_read(ecryptfs_inode)) {
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 509) 		i_size_write(ecryptfs_inode, pos + copied);
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 510) 		ecryptfs_printk(KERN_DEBUG, "Expanded file size to "
888d57bbc91eb (Joe Perches         2010-11-10 15:46:16 -0800 511) 			"[0x%.16llx]\n",
888d57bbc91eb (Joe Perches         2010-11-10 15:46:16 -0800 512) 			(unsigned long long)i_size_read(ecryptfs_inode));
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 513) 	}
821f7494a7762 (Tyler Hicks         2012-07-03 16:50:57 -0700 514) 	rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode);
821f7494a7762 (Tyler Hicks         2012-07-03 16:50:57 -0700 515) 	if (rc)
821f7494a7762 (Tyler Hicks         2012-07-03 16:50:57 -0700 516) 		printk(KERN_ERR "Error writing inode size to metadata; "
821f7494a7762 (Tyler Hicks         2012-07-03 16:50:57 -0700 517) 		       "rc = [%d]\n", rc);
821f7494a7762 (Tyler Hicks         2012-07-03 16:50:57 -0700 518) 	else
821f7494a7762 (Tyler Hicks         2012-07-03 16:50:57 -0700 519) 		rc = copied;
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 520) out:
821f7494a7762 (Tyler Hicks         2012-07-03 16:50:57 -0700 521) 	unlock_page(page);
09cbfeaf1a5a6 (Kirill A. Shutemov  2016-04-01 15:29:47 +0300 522) 	put_page(page);
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 523) 	return rc;
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 524) }
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 525) 
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 526) static sector_t ecryptfs_bmap(struct address_space *mapping, sector_t block)
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 527) {
569d2056def7a (Carlos Maiolino     2020-01-09 14:30:43 +0100 528) 	struct inode *lower_inode = ecryptfs_inode_to_lower(mapping->host);
569d2056def7a (Carlos Maiolino     2020-01-09 14:30:43 +0100 529) 	int ret = bmap(lower_inode, &block);
569d2056def7a (Carlos Maiolino     2020-01-09 14:30:43 +0100 530) 
569d2056def7a (Carlos Maiolino     2020-01-09 14:30:43 +0100 531) 	if (ret)
569d2056def7a (Carlos Maiolino     2020-01-09 14:30:43 +0100 532) 		return 0;
569d2056def7a (Carlos Maiolino     2020-01-09 14:30:43 +0100 533) 	return block;
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 534) }
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 535) 
7f09410bbc430 (Alexey Dobriyan     2009-09-21 17:01:10 -0700 536) const struct address_space_operations ecryptfs_aops = {
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 537) 	.writepage = ecryptfs_writepage,
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 538) 	.readpage = ecryptfs_readpage,
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 539) 	.write_begin = ecryptfs_write_begin,
807b7ebe41ab8 (Badari Pulavarty    2008-10-15 22:02:50 -0700 540) 	.write_end = ecryptfs_write_end,
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 541) 	.bmap = ecryptfs_bmap,
237fead619984 (Michael Halcrow     2006-10-04 02:16:22 -0700 542) };