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) };