Blame view

fs/ecryptfs/file.c 10.4 KB
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
1
2
3
4
5
  /**
   * eCryptfs: Linux filesystem encryption layer
   *
   * Copyright (C) 1997-2004 Erez Zadok
   * Copyright (C) 2001-2004 Stony Brook University
dd2a3b7ad   Michael Halcrow   [PATCH] eCryptfs:...
6
   * Copyright (C) 2004-2007 International Business Machines Corp.
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
   *   Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
   *   		Michael C. Thompson <mcthomps@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/file.h>
  #include <linux/poll.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
28
  #include <linux/slab.h>
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
29
30
31
  #include <linux/mount.h>
  #include <linux/pagemap.h>
  #include <linux/security.h>
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
32
  #include <linux/compat.h>
0cc72dc7f   Josef "Jeff" Sipek   [PATCH] eCryptfs:...
33
  #include <linux/fs_stack.h>
dda6445e2   Jonathan Corbet   ecryptfs: fasync ...
34
  #include <linux/smp_lock.h>
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
35
36
37
  #include "ecryptfs_kernel.h"
  
  /**
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
   * ecryptfs_read_update_atime
   *
   * generic_file_read updates the atime of upper layer inode.  But, it
   * doesn't give us a chance to update the atime of the lower layer
   * inode.  This function is a wrapper to generic_file_read.  It
   * updates the atime of the lower level inode if generic_file_read
   * returns without any errors. This is to be used only for file reads.
   * The function to be used for directory reads is ecryptfs_read.
   */
  static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb,
  				const struct iovec *iov,
  				unsigned long nr_segs, loff_t pos)
  {
  	int rc;
  	struct dentry *lower_dentry;
  	struct vfsmount *lower_vfsmount;
  	struct file *file = iocb->ki_filp;
  
  	rc = generic_file_aio_read(iocb, iov, nr_segs, pos);
  	/*
  	 * Even though this is a async interface, we need to wait
  	 * for IO to finish to update atime
  	 */
  	if (-EIOCBQUEUED == rc)
  		rc = wait_on_sync_kiocb(iocb);
  	if (rc >= 0) {
bd243a4b4   Josef "Jeff" Sipek   [PATCH] ecryptfs:...
64
65
  		lower_dentry = ecryptfs_dentry_to_lower(file->f_path.dentry);
  		lower_vfsmount = ecryptfs_dentry_to_lower_mnt(file->f_path.dentry);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
66
67
68
69
70
71
72
73
74
  		touch_atime(lower_vfsmount, lower_dentry);
  	}
  	return rc;
  }
  
  struct ecryptfs_getdents_callback {
  	void *dirent;
  	struct dentry *dentry;
  	filldir_t filldir;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
75
76
77
  	int filldir_called;
  	int entries_written;
  };
7d6c70455   Michael Halcrow   eCryptfs: remove ...
78
  /* Inspired by generic filldir in fs/readdir.c */
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
79
  static int
addd65ad8   Michael Halcrow   eCryptfs: Filenam...
80
81
  ecryptfs_filldir(void *dirent, const char *lower_name, int lower_namelen,
  		 loff_t offset, u64 ino, unsigned int d_type)
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
82
  {
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
83
84
  	struct ecryptfs_getdents_callback *buf =
  	    (struct ecryptfs_getdents_callback *)dirent;
a8f12864c   Michael Halcrow   eCryptfs: Fix dat...
85
  	size_t name_size;
addd65ad8   Michael Halcrow   eCryptfs: Filenam...
86
  	char *name;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
87
  	int rc;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
88

237fead61   Michael Halcrow   [PATCH] ecryptfs:...
89
  	buf->filldir_called++;
addd65ad8   Michael Halcrow   eCryptfs: Filenam...
90
91
92
93
94
95
96
97
  	rc = ecryptfs_decode_and_decrypt_filename(&name, &name_size,
  						  buf->dentry, lower_name,
  						  lower_namelen);
  	if (rc) {
  		printk(KERN_ERR "%s: Error attempting to decode and decrypt "
  		       "filename [%s]; rc = [%d]
  ", __func__, lower_name,
  		       rc);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
98
99
  		goto out;
  	}
addd65ad8   Michael Halcrow   eCryptfs: Filenam...
100
101
  	rc = buf->filldir(buf->dirent, name, name_size, offset, ino, d_type);
  	kfree(name);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
102
103
104
105
106
107
108
109
  	if (rc >= 0)
  		buf->entries_written++;
  out:
  	return rc;
  }
  
  /**
   * ecryptfs_readdir
addd65ad8   Michael Halcrow   eCryptfs: Filenam...
110
111
   * @file: The eCryptfs directory file
   * @dirent: Directory entry handle
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
112
113
114
115
116
117
118
119
120
121
122
   * @filldir: The filldir callback function
   */
  static int ecryptfs_readdir(struct file *file, void *dirent, filldir_t filldir)
  {
  	int rc;
  	struct file *lower_file;
  	struct inode *inode;
  	struct ecryptfs_getdents_callback buf;
  
  	lower_file = ecryptfs_file_to_lower(file);
  	lower_file->f_pos = file->f_pos;
bd243a4b4   Josef "Jeff" Sipek   [PATCH] ecryptfs:...
123
  	inode = file->f_path.dentry->d_inode;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
124
125
  	memset(&buf, 0, sizeof(buf));
  	buf.dirent = dirent;
bd243a4b4   Josef "Jeff" Sipek   [PATCH] ecryptfs:...
126
  	buf.dentry = file->f_path.dentry;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
127
  	buf.filldir = filldir;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
128
129
  	buf.filldir_called = 0;
  	buf.entries_written = 0;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
130
  	rc = vfs_readdir(lower_file, ecryptfs_filldir, (void *)&buf);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
131
  	file->f_pos = lower_file->f_pos;
7d6c70455   Michael Halcrow   eCryptfs: remove ...
132
133
134
135
  	if (rc < 0)
  		goto out;
  	if (buf.filldir_called && !buf.entries_written)
  		goto out;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
136
  	if (rc >= 0)
7d6c70455   Michael Halcrow   eCryptfs: remove ...
137
138
139
  		fsstack_copy_attr_atime(inode,
  					lower_file->f_path.dentry->d_inode);
  out:
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
  	return rc;
  }
  
  struct kmem_cache *ecryptfs_file_info_cache;
  
  /**
   * ecryptfs_open
   * @inode: inode speciying file to open
   * @file: Structure to return filled in
   *
   * Opens the file specified by inode.
   *
   * Returns zero on success; non-zero otherwise
   */
  static int ecryptfs_open(struct inode *inode, struct file *file)
  {
  	int rc = 0;
  	struct ecryptfs_crypt_stat *crypt_stat = NULL;
  	struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
bd243a4b4   Josef "Jeff" Sipek   [PATCH] ecryptfs:...
159
  	struct dentry *ecryptfs_dentry = file->f_path.dentry;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
160
161
  	/* Private value of ecryptfs_dentry allocated in
  	 * ecryptfs_lookup() */
4aa25bcb7   Julia Lawall   ecryptfs: Elimina...
162
  	struct dentry *lower_dentry;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
163
  	struct ecryptfs_file_info *file_info;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
164

e77a56ddc   Michael Halcrow   [PATCH] eCryptfs:...
165
166
167
168
169
170
171
172
173
174
175
176
  	mount_crypt_stat = &ecryptfs_superblock_to_private(
  		ecryptfs_dentry->d_sb)->mount_crypt_stat;
  	if ((mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED)
  	    && ((file->f_flags & O_WRONLY) || (file->f_flags & O_RDWR)
  		|| (file->f_flags & O_CREAT) || (file->f_flags & O_TRUNC)
  		|| (file->f_flags & O_APPEND))) {
  		printk(KERN_WARNING "Mount has encrypted view enabled; "
  		       "files may only be read
  ");
  		rc = -EPERM;
  		goto out;
  	}
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
177
  	/* Released in ecryptfs_release or end of function if failure */
c37622296   Robert P. J. Day   [PATCH] Transform...
178
  	file_info = kmem_cache_zalloc(ecryptfs_file_info_cache, GFP_KERNEL);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
179
180
181
182
183
184
185
186
  	ecryptfs_set_file_private(file, file_info);
  	if (!file_info) {
  		ecryptfs_printk(KERN_ERR,
  				"Error attempting to allocate memory
  ");
  		rc = -ENOMEM;
  		goto out;
  	}
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
187
188
  	lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
  	crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
189
  	mutex_lock(&crypt_stat->cs_mutex);
e2bd99ec5   Michael Halcrow   [PATCH] eCryptfs:...
190
  	if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)) {
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
191
192
193
  		ecryptfs_printk(KERN_DEBUG, "Setting flags for stat...
  ");
  		/* Policy code enabled in future release */
2ed92554a   Michael Halcrow   eCryptfs: make op...
194
195
  		crypt_stat->flags |= (ECRYPTFS_POLICY_APPLIED
  				      | ECRYPTFS_ENCRYPTED);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
196
197
  	}
  	mutex_unlock(&crypt_stat->cs_mutex);
72b55fffd   Michael Halcrow   eCryptfs: do not ...
198
  	if (!ecryptfs_inode_to_private(inode)->lower_file) {
72b55fffd   Michael Halcrow   eCryptfs: do not ...
199
200
201
202
203
204
205
  		rc = ecryptfs_init_persistent_file(ecryptfs_dentry);
  		if (rc) {
  			printk(KERN_ERR "%s: Error attempting to initialize "
  			       "the persistent file for the dentry with name "
  			       "[%s]; rc = [%d]
  ", __func__,
  			       ecryptfs_dentry->d_name.name, rc);
ceeab9297   Julia Lawall   fs/ecryptfs/file....
206
  			goto out_free;
72b55fffd   Michael Halcrow   eCryptfs: do not ...
207
208
  		}
  	}
e27759d7a   Erez Zadok   ecryptfs: initial...
209
210
211
212
213
214
  	if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_RDONLY)
  	    && !(file->f_flags & O_RDONLY)) {
  		rc = -EPERM;
  		printk(KERN_WARNING "%s: Lower persistent file is RO; eCryptfs "
  		       "file must hence be opened RO
  ", __func__);
ceeab9297   Julia Lawall   fs/ecryptfs/file....
215
  		goto out_free;
e27759d7a   Erez Zadok   ecryptfs: initial...
216
  	}
2ed92554a   Michael Halcrow   eCryptfs: make op...
217
218
  	ecryptfs_set_file_lower(
  		file, ecryptfs_inode_to_private(inode)->lower_file);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
219
220
221
  	if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
  		ecryptfs_printk(KERN_DEBUG, "This is a directory
  ");
2f9b12a31   Michael Halcrow   eCryptfs: protect...
222
  		mutex_lock(&crypt_stat->cs_mutex);
e2bd99ec5   Michael Halcrow   [PATCH] eCryptfs:...
223
  		crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
2f9b12a31   Michael Halcrow   eCryptfs: protect...
224
  		mutex_unlock(&crypt_stat->cs_mutex);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
225
226
227
228
  		rc = 0;
  		goto out;
  	}
  	mutex_lock(&crypt_stat->cs_mutex);
e2bd99ec5   Michael Halcrow   [PATCH] eCryptfs:...
229
230
  	if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)
  	    || !(crypt_stat->flags & ECRYPTFS_KEY_VALID)) {
d7cdc5feb   Michael Halcrow   eCryptfs: update ...
231
  		rc = ecryptfs_read_metadata(ecryptfs_dentry);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
232
233
234
235
236
237
238
  		if (rc) {
  			ecryptfs_printk(KERN_DEBUG,
  					"Valid headers not found
  ");
  			if (!(mount_crypt_stat->flags
  			      & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
  				rc = -EIO;
25bd81740   Michael Halcrow   eCryptfs: Minor f...
239
  				printk(KERN_WARNING "Either the lower file "
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
240
  				       "is not in a valid eCryptfs format, "
25bd81740   Michael Halcrow   eCryptfs: Minor f...
241
242
  				       "or the key could not be retrieved. "
  				       "Plaintext passthrough mode is not "
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
243
244
245
  				       "enabled; returning -EIO
  ");
  				mutex_unlock(&crypt_stat->cs_mutex);
2ed92554a   Michael Halcrow   eCryptfs: make op...
246
  				goto out_free;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
247
  			}
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
248
  			rc = 0;
e2bd99ec5   Michael Halcrow   [PATCH] eCryptfs:...
249
  			crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
250
251
252
253
254
255
256
257
258
  			mutex_unlock(&crypt_stat->cs_mutex);
  			goto out;
  		}
  	}
  	mutex_unlock(&crypt_stat->cs_mutex);
  	ecryptfs_printk(KERN_DEBUG, "inode w/ addr = [0x%p], i_ino = [0x%.16x] "
  			"size: [0x%.16x]
  ", inode, inode->i_ino,
  			i_size_read(inode));
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
259
  	goto out;
2ed92554a   Michael Halcrow   eCryptfs: make op...
260
  out_free:
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
  	kmem_cache_free(ecryptfs_file_info_cache,
  			ecryptfs_file_to_private(file));
  out:
  	return rc;
  }
  
  static int ecryptfs_flush(struct file *file, fl_owner_t td)
  {
  	int rc = 0;
  	struct file *lower_file = NULL;
  
  	lower_file = ecryptfs_file_to_lower(file);
  	if (lower_file->f_op && lower_file->f_op->flush)
  		rc = lower_file->f_op->flush(lower_file, td);
  	return rc;
  }
  
  static int ecryptfs_release(struct inode *inode, struct file *file)
  {
2ed92554a   Michael Halcrow   eCryptfs: make op...
280
281
282
  	kmem_cache_free(ecryptfs_file_info_cache,
  			ecryptfs_file_to_private(file));
  	return 0;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
283
284
285
  }
  
  static int
7ea808591   Christoph Hellwig   drop unused dentr...
286
  ecryptfs_fsync(struct file *file, int datasync)
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
287
  {
8018ab057   Christoph Hellwig   sanitize vfs_fsyn...
288
  	return vfs_fsync(ecryptfs_file_to_lower(file), datasync);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
289
290
291
292
293
294
  }
  
  static int ecryptfs_fasync(int fd, struct file *file, int flag)
  {
  	int rc = 0;
  	struct file *lower_file = NULL;
dda6445e2   Jonathan Corbet   ecryptfs: fasync ...
295
  	lock_kernel();
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
296
297
298
  	lower_file = ecryptfs_file_to_lower(file);
  	if (lower_file->f_op && lower_file->f_op->fasync)
  		rc = lower_file->f_op->fasync(fd, lower_file, flag);
dda6445e2   Jonathan Corbet   ecryptfs: fasync ...
299
  	unlock_kernel();
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
300
301
  	return rc;
  }
c43f7b8fb   Tyler Hicks   eCryptfs: Handle ...
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
  static long
  ecryptfs_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  {
  	struct file *lower_file = NULL;
  	long rc = -ENOTTY;
  
  	if (ecryptfs_file_to_private(file))
  		lower_file = ecryptfs_file_to_lower(file);
  	if (lower_file && lower_file->f_op && lower_file->f_op->unlocked_ioctl)
  		rc = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg);
  	return rc;
  }
  
  #ifdef CONFIG_COMPAT
  static long
  ecryptfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  {
  	struct file *lower_file = NULL;
  	long rc = -ENOIOCTLCMD;
  
  	if (ecryptfs_file_to_private(file))
  		lower_file = ecryptfs_file_to_lower(file);
  	if (lower_file && lower_file->f_op && lower_file->f_op->compat_ioctl)
  		rc = lower_file->f_op->compat_ioctl(lower_file, cmd, arg);
  	return rc;
  }
  #endif
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
329
330
331
  
  const struct file_operations ecryptfs_dir_fops = {
  	.readdir = ecryptfs_readdir,
c43f7b8fb   Tyler Hicks   eCryptfs: Handle ...
332
333
334
335
  	.unlocked_ioctl = ecryptfs_unlocked_ioctl,
  #ifdef CONFIG_COMPAT
  	.compat_ioctl = ecryptfs_compat_ioctl,
  #endif
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
336
337
338
339
340
  	.open = ecryptfs_open,
  	.flush = ecryptfs_flush,
  	.release = ecryptfs_release,
  	.fsync = ecryptfs_fsync,
  	.fasync = ecryptfs_fasync,
e9f6a99cb   Michael Halcrow   eCryptfs: Use gen...
341
  	.splice_read = generic_file_splice_read,
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
342
343
344
  };
  
  const struct file_operations ecryptfs_main_fops = {
53a2731f9   Michael Halcrow   eCryptfs: delay w...
345
  	.llseek = generic_file_llseek,
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
346
347
348
349
350
  	.read = do_sync_read,
  	.aio_read = ecryptfs_read_update_atime,
  	.write = do_sync_write,
  	.aio_write = generic_file_aio_write,
  	.readdir = ecryptfs_readdir,
c43f7b8fb   Tyler Hicks   eCryptfs: Handle ...
351
352
353
354
  	.unlocked_ioctl = ecryptfs_unlocked_ioctl,
  #ifdef CONFIG_COMPAT
  	.compat_ioctl = ecryptfs_compat_ioctl,
  #endif
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
355
356
357
358
359
360
  	.mmap = generic_file_mmap,
  	.open = ecryptfs_open,
  	.flush = ecryptfs_flush,
  	.release = ecryptfs_release,
  	.fsync = ecryptfs_fsync,
  	.fasync = ecryptfs_fasync,
e9f6a99cb   Michael Halcrow   eCryptfs: Use gen...
361
  	.splice_read = generic_file_splice_read,
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
362
  };