Blame view

fs/ecryptfs/mmap.c 16 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;
0216f7f79   Michael Halcrow   eCryptfs: replace...
62
  	rc = ecryptfs_encrypt_page(page);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
63
64
65
66
67
68
69
70
71
72
73
74
  	if (rc) {
  		ecryptfs_printk(KERN_WARNING, "Error encrypting "
  				"page (upper index [0x%.16x])
  ", page->index);
  		ClearPageUptodate(page);
  		goto out;
  	}
  	SetPageUptodate(page);
  	unlock_page(page);
  out:
  	return rc;
  }
f4e60e6b3   Tyler Hicks   eCryptfs: Strip m...
75
76
77
78
79
80
81
82
83
84
85
86
  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:...
87
  /**
e77a56ddc   Michael Halcrow   [PATCH] eCryptfs:...
88
89
90
91
92
93
94
95
96
97
98
99
100
101
   *   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:...
102
103
  
  /**
bf12be1cc   Michael Halcrow   eCryptfs: convert...
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
   * 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...
123
124
  		loff_t view_extent_num = ((((loff_t)page->index)
  					   * num_extents_per_page)
bf12be1cc   Michael Halcrow   eCryptfs: convert...
125
  					  + extent_num_in_page);
cc11beffd   Michael Halcrow   eCryptfs: track h...
126
  		size_t num_header_extents_at_front =
fa3ef1cb4   Tyler Hicks   eCryptfs: Rename ...
127
  			(crypt_stat->metadata_size / crypt_stat->extent_size);
bf12be1cc   Michael Halcrow   eCryptfs: convert...
128

cc11beffd   Michael Halcrow   eCryptfs: track h...
129
  		if (view_extent_num < num_header_extents_at_front) {
bf12be1cc   Michael Halcrow   eCryptfs: convert...
130
131
132
133
134
135
136
  			/* 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...
137
  				size_t written;
bf12be1cc   Michael Halcrow   eCryptfs: convert...
138
139
  				rc = ecryptfs_read_xattr_region(
  					page_virt, page->mapping->host);
f4e60e6b3   Tyler Hicks   eCryptfs: Strip m...
140
  				strip_xattr_flag(page_virt + 16, crypt_stat);
157f10713   Tyler Hicks   eCryptfs: Fix met...
141
142
143
  				ecryptfs_write_header_metadata(page_virt + 20,
  							       crypt_stat,
  							       &written);
bf12be1cc   Michael Halcrow   eCryptfs: convert...
144
145
146
147
  			}
  			kunmap_atomic(page_virt, KM_USER0);
  			flush_dcache_page(page);
  			if (rc) {
bf12be1cc   Michael Halcrow   eCryptfs: convert...
148
  				printk(KERN_ERR "%s: Error reading xattr "
18d1dbf1d   Harvey Harrison   ecryptfs: replace...
149
150
  				       "region; rc = [%d]
  ", __func__, rc);
bf12be1cc   Michael Halcrow   eCryptfs: convert...
151
152
  				goto out;
  			}
bf12be1cc   Michael Halcrow   eCryptfs: convert...
153
154
155
  		} else {
  			/* This is an encrypted data extent */
  			loff_t lower_offset =
cc11beffd   Michael Halcrow   eCryptfs: track h...
156
  				((view_extent_num * crypt_stat->extent_size)
fa3ef1cb4   Tyler Hicks   eCryptfs: Rename ...
157
  				 - crypt_stat->metadata_size);
bf12be1cc   Michael Halcrow   eCryptfs: convert...
158
159
160
161
162
163
164
165
  
  			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...
166
167
  				       "file; rc = [%d]
  ", __func__,
bf12be1cc   Michael Halcrow   eCryptfs: convert...
168
169
170
171
172
173
174
175
176
177
178
  				       lower_offset, rc);
  				goto out;
  			}
  		}
  		extent_num_in_page++;
  	}
  out:
  	return rc;
  }
  
  /**
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
179
   * ecryptfs_readpage
bf12be1cc   Michael Halcrow   eCryptfs: convert...
180
181
   * @file: An eCryptfs file
   * @page: Page from eCryptfs inode mapping into which to stick the read data
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
182
183
184
185
186
187
188
   *
   * 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...
189
  	struct ecryptfs_crypt_stat *crypt_stat =
bef5bc246   Al Viro   simplify access t...
190
  		&ecryptfs_inode_to_private(page->mapping->host)->crypt_stat;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
191
  	int rc = 0;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
192

237fead61   Michael Halcrow   [PATCH] ecryptfs:...
193
  	if (!crypt_stat
e2bd99ec5   Michael Halcrow   [PATCH] eCryptfs:...
194
195
  	    || !(crypt_stat->flags & ECRYPTFS_ENCRYPTED)
  	    || (crypt_stat->flags & ECRYPTFS_NEW_FILE)) {
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
196
197
198
  		ecryptfs_printk(KERN_DEBUG,
  				"Passing through unencrypted page
  ");
bf12be1cc   Michael Halcrow   eCryptfs: convert...
199
200
201
  		rc = ecryptfs_read_lower_page_segment(page, page->index, 0,
  						      PAGE_CACHE_SIZE,
  						      page->mapping->host);
e77a56ddc   Michael Halcrow   [PATCH] eCryptfs:...
202
203
  	} else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) {
  		if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) {
bf12be1cc   Michael Halcrow   eCryptfs: convert...
204
205
206
207
208
209
210
  			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...
211
212
  				       "[%d]
  ", __func__, rc);
bf12be1cc   Michael Halcrow   eCryptfs: convert...
213
  				goto out;
e77a56ddc   Michael Halcrow   [PATCH] eCryptfs:...
214
  			}
bf12be1cc   Michael Halcrow   eCryptfs: convert...
215

e77a56ddc   Michael Halcrow   [PATCH] eCryptfs:...
216
  		} else {
bf12be1cc   Michael Halcrow   eCryptfs: convert...
217
218
219
  			rc = ecryptfs_read_lower_page_segment(
  				page, page->index, 0, PAGE_CACHE_SIZE,
  				page->mapping->host);
e77a56ddc   Michael Halcrow   [PATCH] eCryptfs:...
220
221
222
223
224
225
226
  			if (rc) {
  				printk(KERN_ERR "Error reading page; rc = "
  				       "[%d]
  ", rc);
  				goto out;
  			}
  		}
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
227
  	} else {
0216f7f79   Michael Halcrow   eCryptfs: replace...
228
  		rc = ecryptfs_decrypt_page(page);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
229
  		if (rc) {
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
230
231
232
233
234
235
  			ecryptfs_printk(KERN_ERR, "Error decrypting page; "
  					"rc = [%d]
  ", rc);
  			goto out;
  		}
  	}
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
236
  out:
16a72c455   Michael Halcrow   ecryptfs: clean u...
237
238
239
240
  	if (rc)
  		ClearPageUptodate(page);
  	else
  		SetPageUptodate(page);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
241
242
243
244
245
246
  	ecryptfs_printk(KERN_DEBUG, "Unlocking page with index = [0x%.16x]
  ",
  			page->index);
  	unlock_page(page);
  	return rc;
  }
dd2a3b7ad   Michael Halcrow   [PATCH] eCryptfs:...
247
248
249
  /**
   * Called with lower inode mutex held.
   */
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
250
251
252
253
  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:...
254

9d8b8ce55   Michael Halcrow   [PATCH] eCryptfs:...
255
256
257
258
259
  	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...
260
  	zero_user_segment(page, end_byte_in_page, PAGE_CACHE_SIZE);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
261
  out:
9d8b8ce55   Michael Halcrow   [PATCH] eCryptfs:...
262
  	return 0;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
263
  }
e4465fdae   Michael Halcrow   eCryptfs: make ec...
264
  /**
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
265
   * ecryptfs_write_begin
e4465fdae   Michael Halcrow   eCryptfs: make ec...
266
   * @file: The eCryptfs file
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
267
268
269
270
271
272
   * @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...
273
274
275
276
277
   *
   * This function must zero any hole we create
   *
   * Returns zero on success; non-zero otherwise
   */
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
278
279
280
281
  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:...
282
  {
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
283
284
  	pgoff_t index = pos >> PAGE_CACHE_SHIFT;
  	struct page *page;
7a3f595cc   Eric Sandeen   ecryptfs: fix fsx...
285
  	loff_t prev_page_end_size;
e4465fdae   Michael Halcrow   eCryptfs: make ec...
286
  	int rc = 0;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
287

54566b2c1   Nick Piggin   fs: symlink write...
288
  	page = grab_cache_page_write_begin(mapping, index, flags);
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
289
290
291
  	if (!page)
  		return -ENOMEM;
  	*pagep = page;
16a72c455   Michael Halcrow   ecryptfs: clean u...
292
  	if (!PageUptodate(page)) {
e4465fdae   Michael Halcrow   eCryptfs: make ec...
293
  		struct ecryptfs_crypt_stat *crypt_stat =
bef5bc246   Al Viro   simplify access t...
294
  			&ecryptfs_inode_to_private(mapping->host)->crypt_stat;
e4465fdae   Michael Halcrow   eCryptfs: make ec...
295
296
297
298
  
  		if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)
  		    || (crypt_stat->flags & ECRYPTFS_NEW_FILE)) {
  			rc = ecryptfs_read_lower_page_segment(
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
299
  				page, index, 0, PAGE_CACHE_SIZE, mapping->host);
e4465fdae   Michael Halcrow   eCryptfs: make ec...
300
301
302
303
  			if (rc) {
  				printk(KERN_ERR "%s: Error attemping to read "
  				       "lower page segment; rc = [%d]
  ",
18d1dbf1d   Harvey Harrison   ecryptfs: replace...
304
  				       __func__, rc);
e4465fdae   Michael Halcrow   eCryptfs: make ec...
305
306
307
308
309
310
311
312
313
314
315
316
317
318
  				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...
319
320
  					       "= [%d]
  ", __func__, rc);
e4465fdae   Michael Halcrow   eCryptfs: make ec...
321
322
323
324
325
326
  					ClearPageUptodate(page);
  					goto out;
  				}
  				SetPageUptodate(page);
  			} else {
  				rc = ecryptfs_read_lower_page_segment(
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
327
328
  					page, index, 0, PAGE_CACHE_SIZE,
  					mapping->host);
e4465fdae   Michael Halcrow   eCryptfs: make ec...
329
330
331
332
  				if (rc) {
  					printk(KERN_ERR "%s: Error reading "
  					       "page; rc = [%d]
  ",
18d1dbf1d   Harvey Harrison   ecryptfs: replace...
333
  					       __func__, rc);
e4465fdae   Michael Halcrow   eCryptfs: make ec...
334
335
336
337
338
339
340
341
342
343
344
  					ClearPageUptodate(page);
  					goto out;
  				}
  				SetPageUptodate(page);
  			}
  		} else {
  			rc = ecryptfs_decrypt_page(page);
  			if (rc) {
  				printk(KERN_ERR "%s: Error decrypting page "
  				       "at index [%ld]; rc = [%d]
  ",
18d1dbf1d   Harvey Harrison   ecryptfs: replace...
345
  				       __func__, page->index, rc);
e4465fdae   Michael Halcrow   eCryptfs: make ec...
346
347
348
  				ClearPageUptodate(page);
  				goto out;
  			}
16a72c455   Michael Halcrow   ecryptfs: clean u...
349
  			SetPageUptodate(page);
e4465fdae   Michael Halcrow   eCryptfs: make ec...
350
  		}
16a72c455   Michael Halcrow   ecryptfs: clean u...
351
  	}
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
352
  	prev_page_end_size = ((loff_t)index << PAGE_CACHE_SHIFT);
e4465fdae   Michael Halcrow   eCryptfs: make ec...
353
354
  	/* If creating a page or more of holes, zero them out via truncate.
  	 * Note, this will increase i_size. */
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
355
  	if (index != 0) {
7a3f595cc   Eric Sandeen   ecryptfs: fix fsx...
356
  		if (prev_page_end_size > i_size_read(page->mapping->host)) {
240e2df5c   Michael Halcrow   eCryptfs: fix wri...
357
  			rc = ecryptfs_truncate(file->f_path.dentry,
7a3f595cc   Eric Sandeen   ecryptfs: fix fsx...
358
  					       prev_page_end_size);
240e2df5c   Michael Halcrow   eCryptfs: fix wri...
359
  			if (rc) {
e4465fdae   Michael Halcrow   eCryptfs: make ec...
360
  				printk(KERN_ERR "%s: Error on attempt to "
240e2df5c   Michael Halcrow   eCryptfs: fix wri...
361
  				       "truncate to (higher) offset [%lld];"
18d1dbf1d   Harvey Harrison   ecryptfs: replace...
362
363
  				       " rc = [%d]
  ", __func__,
e4465fdae   Michael Halcrow   eCryptfs: make ec...
364
  				       prev_page_end_size, rc);
240e2df5c   Michael Halcrow   eCryptfs: fix wri...
365
366
  				goto out;
  			}
53a2731f9   Michael Halcrow   eCryptfs: delay w...
367
  		}
7a3f595cc   Eric Sandeen   ecryptfs: fix fsx...
368
  	}
e4465fdae   Michael Halcrow   eCryptfs: make ec...
369
370
  	/* Writing to a new page, and creating a small hole from start
  	 * of page?  Zero it out. */
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
371
372
  	if ((i_size_read(mapping->host) == prev_page_end_size)
  	    && (pos != 0))
eebd2aa35   Christoph Lameter   Pagecache zeroing...
373
  		zero_user(page, 0, PAGE_CACHE_SIZE);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
374
375
376
  out:
  	return rc;
  }
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
377
378
379
380
381
382
383
  /**
   * 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...
384
  static int ecryptfs_write_inode_size_to_header(struct inode *ecryptfs_inode)
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
385
  {
0216f7f79   Michael Halcrow   eCryptfs: replace...
386
387
  	char *file_size_virt;
  	int rc;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
388

0216f7f79   Michael Halcrow   eCryptfs: replace...
389
390
391
  	file_size_virt = kmalloc(sizeof(u64), GFP_KERNEL);
  	if (!file_size_virt) {
  		rc = -ENOMEM;
ae73fc093   Michael Halcrow   [PATCH] eCryptfs:...
392
393
  		goto out;
  	}
0a688ad71   Harvey Harrison   ecryptfs: inode.c...
394
  	put_unaligned_be64(i_size_read(ecryptfs_inode), file_size_virt);
0216f7f79   Michael Halcrow   eCryptfs: replace...
395
396
397
  	rc = ecryptfs_write_lower(ecryptfs_inode, file_size_virt, 0,
  				  sizeof(u64));
  	kfree(file_size_virt);
96a7b9c2f   Tyler Hicks   eCryptfs: Propaga...
398
  	if (rc < 0)
0216f7f79   Michael Halcrow   eCryptfs: replace...
399
  		printk(KERN_ERR "%s: Error writing file size to header; "
18d1dbf1d   Harvey Harrison   ecryptfs: replace...
400
401
  		       "rc = [%d]
  ", __func__, rc);
96a7b9c2f   Tyler Hicks   eCryptfs: Propaga...
402
403
  	else
  		rc = 0;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
404
405
406
  out:
  	return rc;
  }
0216f7f79   Michael Halcrow   eCryptfs: replace...
407
408
409
  struct kmem_cache *ecryptfs_xattr_cache;
  
  static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
dd2a3b7ad   Michael Halcrow   [PATCH] eCryptfs:...
410
411
412
  {
  	ssize_t size;
  	void *xattr_virt;
0216f7f79   Michael Halcrow   eCryptfs: replace...
413
414
415
  	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:...
416
  	int rc;
0216f7f79   Michael Halcrow   eCryptfs: replace...
417
418
419
420
421
422
423
  	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:...
424
425
426
427
428
429
430
431
  	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...
432
433
434
  	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:...
435
436
  	if (size < 0)
  		size = 8;
0a688ad71   Harvey Harrison   ecryptfs: inode.c...
437
  	put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt);
0216f7f79   Michael Halcrow   eCryptfs: replace...
438
439
440
  	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:...
441
442
443
444
445
446
447
448
  	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...
449
  int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode)
dd2a3b7ad   Michael Halcrow   [PATCH] eCryptfs:...
450
451
  {
  	struct ecryptfs_crypt_stat *crypt_stat;
0216f7f79   Michael Halcrow   eCryptfs: replace...
452
  	crypt_stat = &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
13a791b4e   Tyler Hicks   eCryptfs: Fix dat...
453
  	BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED));
dd2a3b7ad   Michael Halcrow   [PATCH] eCryptfs:...
454
  	if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
0216f7f79   Michael Halcrow   eCryptfs: replace...
455
  		return ecryptfs_write_inode_size_to_xattr(ecryptfs_inode);
dd2a3b7ad   Michael Halcrow   [PATCH] eCryptfs:...
456
  	else
0216f7f79   Michael Halcrow   eCryptfs: replace...
457
  		return ecryptfs_write_inode_size_to_header(ecryptfs_inode);
dd2a3b7ad   Michael Halcrow   [PATCH] eCryptfs:...
458
  }
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
459
  /**
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
460
   * ecryptfs_write_end
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
461
   * @file: The eCryptfs file object
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
462
463
464
465
   * @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:...
466
   * @page: The eCryptfs page
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
467
   * @fsdata: The fsdata (unused)
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
468
469
470
471
472
   *
   * 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...
473
474
475
476
  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:...
477
  {
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
478
479
480
481
  	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...
482
  	struct ecryptfs_crypt_stat *crypt_stat =
bef5bc246   Al Viro   simplify access t...
483
  		&ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
484
  	int rc;
e2bd99ec5   Michael Halcrow   [PATCH] eCryptfs:...
485
  	if (crypt_stat->flags & ECRYPTFS_NEW_FILE) {
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
486
487
488
  		ecryptfs_printk(KERN_DEBUG, "ECRYPTFS_NEW_FILE flag set in "
  			"crypt_stat at memory location [%p]
  ", crypt_stat);
e2bd99ec5   Michael Halcrow   [PATCH] eCryptfs:...
489
  		crypt_stat->flags &= ~(ECRYPTFS_NEW_FILE);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
490
491
492
493
  	} else
  		ecryptfs_printk(KERN_DEBUG, "Not a new file
  ");
  	ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page"
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
494
495
  			"(page w/ index = [0x%.16x], to = [%d])
  ", index, to);
13a791b4e   Tyler Hicks   eCryptfs: Fix dat...
496
497
498
499
500
501
502
503
504
505
  	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...
506
  	/* Fills in zeros if 'to' goes beyond inode size */
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
507
508
509
  	rc = fill_zeros_to_end_of_page(page, to);
  	if (rc) {
  		ecryptfs_printk(KERN_WARNING, "Error attempting to fill "
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
510
511
  			"zeros in page with index = [0x%.16x]
  ", index);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
512
513
  		goto out;
  	}
0216f7f79   Michael Halcrow   eCryptfs: replace...
514
  	rc = ecryptfs_encrypt_page(page);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
515
516
  	if (rc) {
  		ecryptfs_printk(KERN_WARNING, "Error encrypting page (upper "
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
517
518
  				"index [0x%.16x])
  ", index);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
519
520
  		goto out;
  	}
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
521
522
  	if (pos + copied > i_size_read(ecryptfs_inode)) {
  		i_size_write(ecryptfs_inode, pos + copied);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
523
  		ecryptfs_printk(KERN_DEBUG, "Expanded file size to "
bf12be1cc   Michael Halcrow   eCryptfs: convert...
524
525
  				"[0x%.16x]
  ", i_size_read(ecryptfs_inode));
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
526
  	}
bf12be1cc   Michael Halcrow   eCryptfs: convert...
527
  	rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode);
dd2a3b7ad   Michael Halcrow   [PATCH] eCryptfs:...
528
529
530
531
  	if (rc)
  		printk(KERN_ERR "Error writing inode size to metadata; "
  		       "rc = [%d]
  ", rc);
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
532
533
  	else
  		rc = copied;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
534
  out:
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
535
536
  	unlock_page(page);
  	page_cache_release(page);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
537
538
  	return rc;
  }
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
539
540
541
542
543
544
545
546
547
548
549
550
551
  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...
552
  const struct address_space_operations ecryptfs_aops = {
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
553
554
  	.writepage = ecryptfs_writepage,
  	.readpage = ecryptfs_readpage,
807b7ebe4   Badari Pulavarty   ecryptfs: convert...
555
556
  	.write_begin = ecryptfs_write_begin,
  	.write_end = ecryptfs_write_end,
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
557
  	.bmap = ecryptfs_bmap,
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
558
  };