Blame view

fs/ecryptfs/mmap.c 16.2 KB
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
1
2
3
4
5
6
7
8
  /**
   * eCryptfs: Linux filesystem encryption layer
   * This is where eCryptfs coordinates the symmetric encryption and
   * decryption of the file data as it passes between the lower
   * encrypted file and the upper decrypted file.
   *
   * Copyright (C) 1997-2003 Erez Zadok
   * Copyright (C) 2001-2003 Stony Brook University
dd2a3b7ad   Michael Halcrow   [PATCH] eCryptfs:...
9
   * Copyright (C) 2004-2007 International Business Machines Corp.
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
   *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License as
   * published by the Free Software Foundation; either version 2 of the
   * License, or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   * 02111-1307, USA.
   */
  
  #include <linux/pagemap.h>
  #include <linux/writeback.h>
  #include <linux/page-flags.h>
  #include <linux/mount.h>
  #include <linux/file.h>
  #include <linux/crypto.h>
  #include <linux/scatterlist.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
35
  #include <linux/slab.h>
0a688ad71   Harvey Harrison   ecryptfs: inode.c...
36
  #include <asm/unaligned.h>
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
37
  #include "ecryptfs_kernel.h"
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
38
  /**
16a72c455   Michael Halcrow   ecryptfs: clean u...
39
   * ecryptfs_get_locked_page
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
40
41
42
   *
   * Get one page from cache or lower f/s, return error otherwise.
   *
16a72c455   Michael Halcrow   ecryptfs: clean u...
43
   * Returns locked and up-to-date page (if ok), with increased
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
44
45
   * refcnt.
   */
02bd97997   Al Viro   switch ecryptfs_g...
46
  struct page *ecryptfs_get_locked_page(struct inode *inode, loff_t index)
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
47
  {
02bd97997   Al Viro   switch ecryptfs_g...
48
  	struct page *page = read_mapping_page(inode->i_mapping, index, NULL);
16a72c455   Michael Halcrow   ecryptfs: clean u...
49
50
51
  	if (!IS_ERR(page))
  		lock_page(page);
  	return page;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
52
  }
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
53
  /**
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
54
55
56
57
58
59
60
   * ecryptfs_writepage
   * @page: Page that is locked before this call is made
   *
   * Returns zero on success; non-zero otherwise
   */
  static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc)
  {
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
61
  	int rc;
57db4e8d7   Thieu Le   ecryptfs: modify ...
62
63
64
65
66
67
68
69
70
71
72
  	/*
  	 * Refuse to write the page out if we are called from reclaim context
  	 * since our writepage() path may potentially allocate memory when
  	 * calling into the lower fs vfs_write() which may in turn invoke
  	 * us again.
  	 */
  	if (current->flags & PF_MEMALLOC) {
  		redirty_page_for_writepage(wbc, page);
  		rc = 0;
  		goto out;
  	}
0216f7f79   Michael Halcrow   eCryptfs: replace...
73
  	rc = ecryptfs_encrypt_page(page);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
74
75
  	if (rc) {
  		ecryptfs_printk(KERN_WARNING, "Error encrypting "
888d57bbc   Joe Perches   fs/ecryptfs: Add ...
76
77
  				"page (upper index [0x%.16lx])
  ", page->index);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
78
79
80
81
  		ClearPageUptodate(page);
  		goto out;
  	}
  	SetPageUptodate(page);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
82
  out:
57db4e8d7   Thieu Le   ecryptfs: modify ...
83
  	unlock_page(page);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
84
85
  	return rc;
  }
f4e60e6b3   Tyler Hicks   eCryptfs: Strip m...
86
87
88
89
90
91
92
93
94
95
96
97
  static void strip_xattr_flag(char *page_virt,
  			     struct ecryptfs_crypt_stat *crypt_stat)
  {
  	if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) {
  		size_t written;
  
  		crypt_stat->flags &= ~ECRYPTFS_METADATA_IN_XATTR;
  		ecryptfs_write_crypt_stat_flags(page_virt, crypt_stat,
  						&written);
  		crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;
  	}
  }
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
98
  /**
e77a56ddc   Michael Halcrow   [PATCH] eCryptfs:...
99
100
101
102
103
104
105
106
107
108
109
110
111
112
   *   Header Extent:
   *     Octets 0-7:        Unencrypted file size (big-endian)
   *     Octets 8-15:       eCryptfs special marker
   *     Octets 16-19:      Flags
   *      Octet 16:         File format version number (between 0 and 255)
   *      Octets 17-18:     Reserved
   *      Octet 19:         Bit 1 (lsb): Reserved
   *                        Bit 2: Encrypted?
   *                        Bits 3-8: Reserved
   *     Octets 20-23:      Header extent size (big-endian)
   *     Octets 24-25:      Number of header extents at front of file
   *                        (big-endian)
   *     Octet  26:         Begin RFC 2440 authentication token packet set
   */
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
113
114
  
  /**
bf12be1cc   Michael Halcrow   eCryptfs: convert...
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
   * ecryptfs_copy_up_encrypted_with_header
   * @page: Sort of a ``virtual'' representation of the encrypted lower
   *        file. The actual lower file does not have the metadata in
   *        the header. This is locked.
   * @crypt_stat: The eCryptfs inode's cryptographic context
   *
   * The ``view'' is the version of the file that userspace winds up
   * seeing, with the header information inserted.
   */
  static int
  ecryptfs_copy_up_encrypted_with_header(struct page *page,
  				       struct ecryptfs_crypt_stat *crypt_stat)
  {
  	loff_t extent_num_in_page = 0;
  	loff_t num_extents_per_page = (PAGE_CACHE_SIZE
  				       / crypt_stat->extent_size);
  	int rc = 0;
  
  	while (extent_num_in_page < num_extents_per_page) {
d6a13c171   Michael Halcrow   eCryptfs: fix dat...
134
135
  		loff_t view_extent_num = ((((loff_t)page->index)
  					   * num_extents_per_page)
bf12be1cc   Michael Halcrow   eCryptfs: convert...
136
  					  + extent_num_in_page);
cc11beffd   Michael Halcrow   eCryptfs: track h...
137
  		size_t num_header_extents_at_front =
fa3ef1cb4   Tyler Hicks   eCryptfs: Rename ...
138
  			(crypt_stat->metadata_size / crypt_stat->extent_size);
bf12be1cc   Michael Halcrow   eCryptfs: convert...
139

cc11beffd   Michael Halcrow   eCryptfs: track h...
140
  		if (view_extent_num < num_header_extents_at_front) {
bf12be1cc   Michael Halcrow   eCryptfs: convert...
141
142
143
144
145
146
147
  			/* This is a header extent */
  			char *page_virt;
  
  			page_virt = kmap_atomic(page, KM_USER0);
  			memset(page_virt, 0, PAGE_CACHE_SIZE);
  			/* TODO: Support more than one header extent */
  			if (view_extent_num == 0) {
157f10713   Tyler Hicks   eCryptfs: Fix met...
148
  				size_t written;
bf12be1cc   Michael Halcrow   eCryptfs: convert...
149
150
  				rc = ecryptfs_read_xattr_region(
  					page_virt, page->mapping->host);
f4e60e6b3   Tyler Hicks   eCryptfs: Strip m...
151
  				strip_xattr_flag(page_virt + 16, crypt_stat);
157f10713   Tyler Hicks   eCryptfs: Fix met...
152
153
154
  				ecryptfs_write_header_metadata(page_virt + 20,
  							       crypt_stat,
  							       &written);
bf12be1cc   Michael Halcrow   eCryptfs: convert...
155
156
157
158
  			}
  			kunmap_atomic(page_virt, KM_USER0);
  			flush_dcache_page(page);
  			if (rc) {
bf12be1cc   Michael Halcrow   eCryptfs: convert...
159
  				printk(KERN_ERR "%s: Error reading xattr "
18d1dbf1d   Harvey Harrison   ecryptfs: replace...
160
161
  				       "region; rc = [%d]
  ", __func__, rc);
bf12be1cc   Michael Halcrow   eCryptfs: convert...
162
163
  				goto out;
  			}
bf12be1cc   Michael Halcrow   eCryptfs: convert...
164
165
166
  		} else {
  			/* This is an encrypted data extent */
  			loff_t lower_offset =
cc11beffd   Michael Halcrow   eCryptfs: track h...
167
  				((view_extent_num * crypt_stat->extent_size)
fa3ef1cb4   Tyler Hicks   eCryptfs: Rename ...
168
  				 - crypt_stat->metadata_size);
bf12be1cc   Michael Halcrow   eCryptfs: convert...
169
170
171
172
173
174
175
176
  
  			rc = ecryptfs_read_lower_page_segment(
  				page, (lower_offset >> PAGE_CACHE_SHIFT),
  				(lower_offset & ~PAGE_CACHE_MASK),
  				crypt_stat->extent_size, page->mapping->host);
  			if (rc) {
  				printk(KERN_ERR "%s: Error attempting to read "
  				       "extent at offset [%lld] in the lower "
18d1dbf1d   Harvey Harrison   ecryptfs: replace...
177
178
  				       "file; rc = [%d]
  ", __func__,
bf12be1cc   Michael Halcrow   eCryptfs: convert...
179
180
181
182
183
184
185
186
187
188
189
  				       lower_offset, rc);
  				goto out;
  			}
  		}
  		extent_num_in_page++;
  	}
  out:
  	return rc;
  }
  
  /**
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
190
   * ecryptfs_readpage
bf12be1cc   Michael Halcrow   eCryptfs: convert...
191
192
   * @file: An eCryptfs file
   * @page: Page from eCryptfs inode mapping into which to stick the read data
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
193
194
195
196
197
198
199
   *
   * Read in a page, decrypting if necessary.
   *
   * Returns zero on success; non-zero on error.
   */
  static int ecryptfs_readpage(struct file *file, struct page *page)
  {
bf12be1cc   Michael Halcrow   eCryptfs: convert...
200
  	struct ecryptfs_crypt_stat *crypt_stat =
bef5bc246   Al Viro   simplify access t...
201
  		&ecryptfs_inode_to_private(page->mapping->host)->crypt_stat;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
202
  	int rc = 0;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
203

fed8859b3   Tyler Hicks   eCryptfs: Remove ...
204
  	if (!crypt_stat || !(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
bf12be1cc   Michael Halcrow   eCryptfs: convert...
205
206
207
  		rc = ecryptfs_read_lower_page_segment(page, page->index, 0,
  						      PAGE_CACHE_SIZE,
  						      page->mapping->host);
e77a56ddc   Michael Halcrow   [PATCH] eCryptfs:...
208
209
  	} else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) {
  		if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) {
bf12be1cc   Michael Halcrow   eCryptfs: convert...
210
211
212
213
214
215
216
  			rc = ecryptfs_copy_up_encrypted_with_header(page,
  								    crypt_stat);
  			if (rc) {
  				printk(KERN_ERR "%s: Error attempting to copy "
  				       "the encrypted content from the lower "
  				       "file whilst inserting the metadata "
  				       "from the xattr into the header; rc = "
18d1dbf1d   Harvey Harrison   ecryptfs: replace...
217
218
  				       "[%d]
  ", __func__, rc);
bf12be1cc   Michael Halcrow   eCryptfs: convert...
219
  				goto out;
e77a56ddc   Michael Halcrow   [PATCH] eCryptfs:...
220
  			}
bf12be1cc   Michael Halcrow   eCryptfs: convert...
221

e77a56ddc   Michael Halcrow   [PATCH] eCryptfs:...
222
  		} else {
bf12be1cc   Michael Halcrow   eCryptfs: convert...
223
224
225
  			rc = ecryptfs_read_lower_page_segment(
  				page, page->index, 0, PAGE_CACHE_SIZE,
  				page->mapping->host);
e77a56ddc   Michael Halcrow   [PATCH] eCryptfs:...
226
227
228
229
230
231
232
  			if (rc) {
  				printk(KERN_ERR "Error reading page; rc = "
  				       "[%d]
  ", rc);
  				goto out;
  			}
  		}
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
233
  	} else {
0216f7f79   Michael Halcrow   eCryptfs: replace...
234
  		rc = ecryptfs_decrypt_page(page);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
235
  		if (rc) {
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
236
237
238
239
240
241
  			ecryptfs_printk(KERN_ERR, "Error decrypting page; "
  					"rc = [%d]
  ", rc);
  			goto out;
  		}
  	}
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
242
  out:
16a72c455   Michael Halcrow   ecryptfs: clean u...
243
244
245
246
  	if (rc)
  		ClearPageUptodate(page);
  	else
  		SetPageUptodate(page);
888d57bbc   Joe Perches   fs/ecryptfs: Add ...
247
248
  	ecryptfs_printk(KERN_DEBUG, "Unlocking page with index = [0x%.16lx]
  ",
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
249
250
251
252
  			page->index);
  	unlock_page(page);
  	return rc;
  }
dd2a3b7ad   Michael Halcrow   [PATCH] eCryptfs:...
253
254
255
  /**
   * Called with lower inode mutex held.
   */
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
256
257
258
259
  static int fill_zeros_to_end_of_page(struct page *page, unsigned int to)
  {
  	struct inode *inode = page->mapping->host;
  	int end_byte_in_page;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
260

9d8b8ce55   Michael Halcrow   [PATCH] eCryptfs:...
261
262
263
264
265
  	if ((i_size_read(inode) / PAGE_CACHE_SIZE) != page->index)
  		goto out;
  	end_byte_in_page = i_size_read(inode) % PAGE_CACHE_SIZE;
  	if (to > end_byte_in_page)
  		end_byte_in_page = to;
eebd2aa35   Christoph Lameter   Pagecache zeroing...
266
  	zero_user_segment(page, end_byte_in_page, PAGE_CACHE_SIZE);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
267
  out:
9d8b8ce55   Michael Halcrow   [PATCH] eCryptfs:...
268
  	return 0;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
269
  }
e4465fdae   Michael Halcrow   eCryptfs: make ec...
270
  /**
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
271
   * ecryptfs_write_begin
e4465fdae   Michael Halcrow   eCryptfs: make ec...
272
   * @file: The eCryptfs file
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
273
274
275
276
277
278
   * @mapping: The eCryptfs object
   * @pos: The file offset at which to start writing
   * @len: Length of the write
   * @flags: Various flags
   * @pagep: Pointer to return the page
   * @fsdata: Pointer to return fs data (unused)
e4465fdae   Michael Halcrow   eCryptfs: make ec...
279
280
281
282
283
   *
   * This function must zero any hole we create
   *
   * Returns zero on success; non-zero otherwise
   */
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
284
285
286
287
  static int ecryptfs_write_begin(struct file *file,
  			struct address_space *mapping,
  			loff_t pos, unsigned len, unsigned flags,
  			struct page **pagep, void **fsdata)
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
288
  {
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
289
290
  	pgoff_t index = pos >> PAGE_CACHE_SHIFT;
  	struct page *page;
7a3f595cc   Eric Sandeen   ecryptfs: fix fsx...
291
  	loff_t prev_page_end_size;
e4465fdae   Michael Halcrow   eCryptfs: make ec...
292
  	int rc = 0;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
293

54566b2c1   Nick Piggin   fs: symlink write...
294
  	page = grab_cache_page_write_begin(mapping, index, flags);
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
295
296
297
  	if (!page)
  		return -ENOMEM;
  	*pagep = page;
24562486b   Frank Swiderski   ecryptfs: remove ...
298
  	prev_page_end_size = ((loff_t)index << PAGE_CACHE_SHIFT);
16a72c455   Michael Halcrow   ecryptfs: clean u...
299
  	if (!PageUptodate(page)) {
e4465fdae   Michael Halcrow   eCryptfs: make ec...
300
  		struct ecryptfs_crypt_stat *crypt_stat =
bef5bc246   Al Viro   simplify access t...
301
  			&ecryptfs_inode_to_private(mapping->host)->crypt_stat;
e4465fdae   Michael Halcrow   eCryptfs: make ec...
302

fed8859b3   Tyler Hicks   eCryptfs: Remove ...
303
  		if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
e4465fdae   Michael Halcrow   eCryptfs: make ec...
304
  			rc = ecryptfs_read_lower_page_segment(
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
305
  				page, index, 0, PAGE_CACHE_SIZE, mapping->host);
e4465fdae   Michael Halcrow   eCryptfs: make ec...
306
307
308
309
  			if (rc) {
  				printk(KERN_ERR "%s: Error attemping to read "
  				       "lower page segment; rc = [%d]
  ",
18d1dbf1d   Harvey Harrison   ecryptfs: replace...
310
  				       __func__, rc);
e4465fdae   Michael Halcrow   eCryptfs: make ec...
311
312
313
314
315
316
317
318
319
320
321
322
323
324
  				ClearPageUptodate(page);
  				goto out;
  			} else
  				SetPageUptodate(page);
  		} else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) {
  			if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) {
  				rc = ecryptfs_copy_up_encrypted_with_header(
  					page, crypt_stat);
  				if (rc) {
  					printk(KERN_ERR "%s: Error attempting "
  					       "to copy the encrypted content "
  					       "from the lower file whilst "
  					       "inserting the metadata from "
  					       "the xattr into the header; rc "
18d1dbf1d   Harvey Harrison   ecryptfs: replace...
325
326
  					       "= [%d]
  ", __func__, rc);
e4465fdae   Michael Halcrow   eCryptfs: make ec...
327
328
329
330
331
332
  					ClearPageUptodate(page);
  					goto out;
  				}
  				SetPageUptodate(page);
  			} else {
  				rc = ecryptfs_read_lower_page_segment(
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
333
334
  					page, index, 0, PAGE_CACHE_SIZE,
  					mapping->host);
e4465fdae   Michael Halcrow   eCryptfs: make ec...
335
336
337
338
  				if (rc) {
  					printk(KERN_ERR "%s: Error reading "
  					       "page; rc = [%d]
  ",
18d1dbf1d   Harvey Harrison   ecryptfs: replace...
339
  					       __func__, rc);
e4465fdae   Michael Halcrow   eCryptfs: make ec...
340
341
342
343
344
345
  					ClearPageUptodate(page);
  					goto out;
  				}
  				SetPageUptodate(page);
  			}
  		} else {
24562486b   Frank Swiderski   ecryptfs: remove ...
346
347
348
349
350
351
352
353
354
355
356
357
358
359
  			if (prev_page_end_size
  			    >= i_size_read(page->mapping->host)) {
  				zero_user(page, 0, PAGE_CACHE_SIZE);
  			} else {
  				rc = ecryptfs_decrypt_page(page);
  				if (rc) {
  					printk(KERN_ERR "%s: Error decrypting "
  					       "page at index [%ld]; "
  					       "rc = [%d]
  ",
  					       __func__, page->index, rc);
  					ClearPageUptodate(page);
  					goto out;
  				}
e4465fdae   Michael Halcrow   eCryptfs: make ec...
360
  			}
16a72c455   Michael Halcrow   ecryptfs: clean u...
361
  			SetPageUptodate(page);
e4465fdae   Michael Halcrow   eCryptfs: make ec...
362
  		}
16a72c455   Michael Halcrow   ecryptfs: clean u...
363
  	}
e4465fdae   Michael Halcrow   eCryptfs: make ec...
364
365
  	/* If creating a page or more of holes, zero them out via truncate.
  	 * Note, this will increase i_size. */
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
366
  	if (index != 0) {
7a3f595cc   Eric Sandeen   ecryptfs: fix fsx...
367
  		if (prev_page_end_size > i_size_read(page->mapping->host)) {
240e2df5c   Michael Halcrow   eCryptfs: fix wri...
368
  			rc = ecryptfs_truncate(file->f_path.dentry,
7a3f595cc   Eric Sandeen   ecryptfs: fix fsx...
369
  					       prev_page_end_size);
240e2df5c   Michael Halcrow   eCryptfs: fix wri...
370
  			if (rc) {
e4465fdae   Michael Halcrow   eCryptfs: make ec...
371
  				printk(KERN_ERR "%s: Error on attempt to "
240e2df5c   Michael Halcrow   eCryptfs: fix wri...
372
  				       "truncate to (higher) offset [%lld];"
18d1dbf1d   Harvey Harrison   ecryptfs: replace...
373
374
  				       " rc = [%d]
  ", __func__,
e4465fdae   Michael Halcrow   eCryptfs: make ec...
375
  				       prev_page_end_size, rc);
240e2df5c   Michael Halcrow   eCryptfs: fix wri...
376
377
  				goto out;
  			}
53a2731f9   Michael Halcrow   eCryptfs: delay w...
378
  		}
7a3f595cc   Eric Sandeen   ecryptfs: fix fsx...
379
  	}
e4465fdae   Michael Halcrow   eCryptfs: make ec...
380
381
  	/* Writing to a new page, and creating a small hole from start
  	 * of page?  Zero it out. */
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
382
383
  	if ((i_size_read(mapping->host) == prev_page_end_size)
  	    && (pos != 0))
eebd2aa35   Christoph Lameter   Pagecache zeroing...
384
  		zero_user(page, 0, PAGE_CACHE_SIZE);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
385
  out:
50f198ae1   Tyler Hicks   eCryptfs: Unlock ...
386
387
388
389
390
  	if (unlikely(rc)) {
  		unlock_page(page);
  		page_cache_release(page);
  		*pagep = NULL;
  	}
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
391
392
  	return rc;
  }
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
393
394
395
396
397
398
399
  /**
   * ecryptfs_write_inode_size_to_header
   *
   * Writes the lower file size to the first 8 bytes of the header.
   *
   * Returns zero on success; non-zero on error.
   */
0216f7f79   Michael Halcrow   eCryptfs: replace...
400
  static int ecryptfs_write_inode_size_to_header(struct inode *ecryptfs_inode)
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
401
  {
0216f7f79   Michael Halcrow   eCryptfs: replace...
402
403
  	char *file_size_virt;
  	int rc;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
404

0216f7f79   Michael Halcrow   eCryptfs: replace...
405
406
407
  	file_size_virt = kmalloc(sizeof(u64), GFP_KERNEL);
  	if (!file_size_virt) {
  		rc = -ENOMEM;
ae73fc093   Michael Halcrow   [PATCH] eCryptfs:...
408
409
  		goto out;
  	}
0a688ad71   Harvey Harrison   ecryptfs: inode.c...
410
  	put_unaligned_be64(i_size_read(ecryptfs_inode), file_size_virt);
0216f7f79   Michael Halcrow   eCryptfs: replace...
411
412
413
  	rc = ecryptfs_write_lower(ecryptfs_inode, file_size_virt, 0,
  				  sizeof(u64));
  	kfree(file_size_virt);
96a7b9c2f   Tyler Hicks   eCryptfs: Propaga...
414
  	if (rc < 0)
0216f7f79   Michael Halcrow   eCryptfs: replace...
415
  		printk(KERN_ERR "%s: Error writing file size to header; "
18d1dbf1d   Harvey Harrison   ecryptfs: replace...
416
417
  		       "rc = [%d]
  ", __func__, rc);
96a7b9c2f   Tyler Hicks   eCryptfs: Propaga...
418
419
  	else
  		rc = 0;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
420
421
422
  out:
  	return rc;
  }
0216f7f79   Michael Halcrow   eCryptfs: replace...
423
424
425
  struct kmem_cache *ecryptfs_xattr_cache;
  
  static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
dd2a3b7ad   Michael Halcrow   [PATCH] eCryptfs:...
426
427
428
  {
  	ssize_t size;
  	void *xattr_virt;
0216f7f79   Michael Halcrow   eCryptfs: replace...
429
430
431
  	struct dentry *lower_dentry =
  		ecryptfs_inode_to_private(ecryptfs_inode)->lower_file->f_dentry;
  	struct inode *lower_inode = lower_dentry->d_inode;
dd2a3b7ad   Michael Halcrow   [PATCH] eCryptfs:...
432
  	int rc;
0216f7f79   Michael Halcrow   eCryptfs: replace...
433
434
435
436
437
438
439
  	if (!lower_inode->i_op->getxattr || !lower_inode->i_op->setxattr) {
  		printk(KERN_WARNING
  		       "No support for setting xattr in lower filesystem
  ");
  		rc = -ENOSYS;
  		goto out;
  	}
dd2a3b7ad   Michael Halcrow   [PATCH] eCryptfs:...
440
441
442
443
444
445
446
447
  	xattr_virt = kmem_cache_alloc(ecryptfs_xattr_cache, GFP_KERNEL);
  	if (!xattr_virt) {
  		printk(KERN_ERR "Out of memory whilst attempting to write "
  		       "inode size to xattr
  ");
  		rc = -ENOMEM;
  		goto out;
  	}
0216f7f79   Michael Halcrow   eCryptfs: replace...
448
449
450
  	mutex_lock(&lower_inode->i_mutex);
  	size = lower_inode->i_op->getxattr(lower_dentry, ECRYPTFS_XATTR_NAME,
  					   xattr_virt, PAGE_CACHE_SIZE);
dd2a3b7ad   Michael Halcrow   [PATCH] eCryptfs:...
451
452
  	if (size < 0)
  		size = 8;
0a688ad71   Harvey Harrison   ecryptfs: inode.c...
453
  	put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt);
0216f7f79   Michael Halcrow   eCryptfs: replace...
454
455
456
  	rc = lower_inode->i_op->setxattr(lower_dentry, ECRYPTFS_XATTR_NAME,
  					 xattr_virt, size, 0);
  	mutex_unlock(&lower_inode->i_mutex);
dd2a3b7ad   Michael Halcrow   [PATCH] eCryptfs:...
457
458
459
460
461
462
463
464
  	if (rc)
  		printk(KERN_ERR "Error whilst attempting to write inode size "
  		       "to lower file xattr; rc = [%d]
  ", rc);
  	kmem_cache_free(ecryptfs_xattr_cache, xattr_virt);
  out:
  	return rc;
  }
0216f7f79   Michael Halcrow   eCryptfs: replace...
465
  int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode)
dd2a3b7ad   Michael Halcrow   [PATCH] eCryptfs:...
466
467
  {
  	struct ecryptfs_crypt_stat *crypt_stat;
0216f7f79   Michael Halcrow   eCryptfs: replace...
468
  	crypt_stat = &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
13a791b4e   Tyler Hicks   eCryptfs: Fix dat...
469
  	BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED));
dd2a3b7ad   Michael Halcrow   [PATCH] eCryptfs:...
470
  	if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
0216f7f79   Michael Halcrow   eCryptfs: replace...
471
  		return ecryptfs_write_inode_size_to_xattr(ecryptfs_inode);
dd2a3b7ad   Michael Halcrow   [PATCH] eCryptfs:...
472
  	else
0216f7f79   Michael Halcrow   eCryptfs: replace...
473
  		return ecryptfs_write_inode_size_to_header(ecryptfs_inode);
dd2a3b7ad   Michael Halcrow   [PATCH] eCryptfs:...
474
  }
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
475
  /**
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
476
   * ecryptfs_write_end
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
477
   * @file: The eCryptfs file object
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
478
479
480
481
   * @mapping: The eCryptfs object
   * @pos: The file position
   * @len: The length of the data (unused)
   * @copied: The amount of data copied
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
482
   * @page: The eCryptfs page
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
483
   * @fsdata: The fsdata (unused)
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
484
485
486
487
488
   *
   * This is where we encrypt the data and pass the encrypted data to
   * the lower filesystem.  In OpenPGP-compatible mode, we operate on
   * entire underlying packets.
   */
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
489
490
491
492
  static int ecryptfs_write_end(struct file *file,
  			struct address_space *mapping,
  			loff_t pos, unsigned len, unsigned copied,
  			struct page *page, void *fsdata)
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
493
  {
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
494
495
496
497
  	pgoff_t index = pos >> PAGE_CACHE_SHIFT;
  	unsigned from = pos & (PAGE_CACHE_SIZE - 1);
  	unsigned to = from + copied;
  	struct inode *ecryptfs_inode = mapping->host;
bf12be1cc   Michael Halcrow   eCryptfs: convert...
498
  	struct ecryptfs_crypt_stat *crypt_stat =
bef5bc246   Al Viro   simplify access t...
499
  		&ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
500
  	int rc;
57db4e8d7   Thieu Le   ecryptfs: modify ...
501
  	int need_unlock_page = 1;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
502

237fead61   Michael Halcrow   [PATCH] ecryptfs:...
503
  	ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page"
888d57bbc   Joe Perches   fs/ecryptfs: Add ...
504
505
  			"(page w/ index = [0x%.16lx], to = [%d])
  ", index, to);
13a791b4e   Tyler Hicks   eCryptfs: Fix dat...
506
507
508
509
510
511
512
513
514
515
  	if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
  		rc = ecryptfs_write_lower_page_segment(ecryptfs_inode, page, 0,
  						       to);
  		if (!rc) {
  			rc = copied;
  			fsstack_copy_inode_size(ecryptfs_inode,
  				ecryptfs_inode_to_lower(ecryptfs_inode));
  		}
  		goto out;
  	}
bf12be1cc   Michael Halcrow   eCryptfs: convert...
516
  	/* Fills in zeros if 'to' goes beyond inode size */
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
517
518
519
  	rc = fill_zeros_to_end_of_page(page, to);
  	if (rc) {
  		ecryptfs_printk(KERN_WARNING, "Error attempting to fill "
888d57bbc   Joe Perches   fs/ecryptfs: Add ...
520
521
  			"zeros in page with index = [0x%.16lx]
  ", index);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
522
523
  		goto out;
  	}
57db4e8d7   Thieu Le   ecryptfs: modify ...
524
525
526
  	set_page_dirty(page);
  	unlock_page(page);
  	need_unlock_page = 0;
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
527
528
  	if (pos + copied > i_size_read(ecryptfs_inode)) {
  		i_size_write(ecryptfs_inode, pos + copied);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
529
  		ecryptfs_printk(KERN_DEBUG, "Expanded file size to "
888d57bbc   Joe Perches   fs/ecryptfs: Add ...
530
531
532
  			"[0x%.16llx]
  ",
  			(unsigned long long)i_size_read(ecryptfs_inode));
57db4e8d7   Thieu Le   ecryptfs: modify ...
533
534
535
536
537
538
539
540
  		balance_dirty_pages_ratelimited(mapping);
  		rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode);
  		if (rc) {
  			printk(KERN_ERR "Error writing inode size to metadata; "
  			       "rc = [%d]
  ", rc);
  			goto out;
  		}
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
541
  	}
57db4e8d7   Thieu Le   ecryptfs: modify ...
542
  	rc = copied;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
543
  out:
57db4e8d7   Thieu Le   ecryptfs: modify ...
544
545
  	if (need_unlock_page)
  		unlock_page(page);
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
546
  	page_cache_release(page);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
547
548
  	return rc;
  }
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
549
550
551
552
553
554
555
556
557
558
559
560
561
  static sector_t ecryptfs_bmap(struct address_space *mapping, sector_t block)
  {
  	int rc = 0;
  	struct inode *inode;
  	struct inode *lower_inode;
  
  	inode = (struct inode *)mapping->host;
  	lower_inode = ecryptfs_inode_to_lower(inode);
  	if (lower_inode->i_mapping->a_ops->bmap)
  		rc = lower_inode->i_mapping->a_ops->bmap(lower_inode->i_mapping,
  							 block);
  	return rc;
  }
7f09410bb   Alexey Dobriyan   const: mark remai...
562
  const struct address_space_operations ecryptfs_aops = {
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
563
564
  	.writepage = ecryptfs_writepage,
  	.readpage = ecryptfs_readpage,
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
565
566
  	.write_begin = ecryptfs_write_begin,
  	.write_end = ecryptfs_write_end,
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
567
  	.bmap = ecryptfs_bmap,
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
568
  };