Blame view

fs/ecryptfs/inode.c 32.2 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
28
29
30
31
   *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
   *              Michael C. Thompsion <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/vmalloc.h>
  #include <linux/pagemap.h>
  #include <linux/dcache.h>
  #include <linux/namei.h>
  #include <linux/mount.h>
0cc72dc7f   Josef "Jeff" Sipek   [PATCH] eCryptfs:...
32
  #include <linux/fs_stack.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
33
  #include <linux/slab.h>
48b512e68   Roberto Sassu   ecryptfs: call vf...
34
  #include <linux/xattr.h>
0a688ad71   Harvey Harrison   ecryptfs: inode.c...
35
  #include <asm/unaligned.h>
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
36
37
38
39
40
  #include "ecryptfs_kernel.h"
  
  static struct dentry *lock_parent(struct dentry *dentry)
  {
  	struct dentry *dir;
8dc4e3736   Miklos Szeredi   ecryptfs: clean u...
41
  	dir = dget_parent(dentry);
5955102c9   Al Viro   wrappers for ->i_...
42
  	inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
43
44
  	return dir;
  }
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
45
46
  static void unlock_dir(struct dentry *dir)
  {
5955102c9   Al Viro   wrappers for ->i_...
47
  	inode_unlock(d_inode(dir));
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
48
49
  	dput(dir);
  }
c4f790736   Tyler Hicks   eCryptfs: Consoli...
50
51
  static int ecryptfs_inode_test(struct inode *inode, void *lower_inode)
  {
c4cf3ba4f   Himangi Saraogi   ecryptfs: Drop cast
52
  	return ecryptfs_inode_to_lower(inode) == lower_inode;
c4f790736   Tyler Hicks   eCryptfs: Consoli...
53
  }
5ccf92037   Tyler Hicks   eCryptfs: Cleanup...
54
  static int ecryptfs_inode_set(struct inode *inode, void *opaque)
c4f790736   Tyler Hicks   eCryptfs: Consoli...
55
  {
5ccf92037   Tyler Hicks   eCryptfs: Cleanup...
56
57
58
59
60
61
62
  	struct inode *lower_inode = opaque;
  
  	ecryptfs_set_inode_lower(inode, lower_inode);
  	fsstack_copy_attr_all(inode, lower_inode);
  	/* i_size will be overwritten for encrypted regular files */
  	fsstack_copy_inode_size(inode, lower_inode);
  	inode->i_ino = lower_inode->i_ino;
c4f790736   Tyler Hicks   eCryptfs: Consoli...
63
  	inode->i_version++;
c4f790736   Tyler Hicks   eCryptfs: Consoli...
64
  	inode->i_mapping->a_ops = &ecryptfs_aops;
5ccf92037   Tyler Hicks   eCryptfs: Cleanup...
65
66
67
68
69
70
71
72
73
74
75
76
77
78
  
  	if (S_ISLNK(inode->i_mode))
  		inode->i_op = &ecryptfs_symlink_iops;
  	else if (S_ISDIR(inode->i_mode))
  		inode->i_op = &ecryptfs_dir_iops;
  	else
  		inode->i_op = &ecryptfs_main_iops;
  
  	if (S_ISDIR(inode->i_mode))
  		inode->i_fop = &ecryptfs_dir_fops;
  	else if (special_file(inode->i_mode))
  		init_special_inode(inode, inode->i_mode, inode->i_rdev);
  	else
  		inode->i_fop = &ecryptfs_main_fops;
c4f790736   Tyler Hicks   eCryptfs: Consoli...
79
80
  	return 0;
  }
5ccf92037   Tyler Hicks   eCryptfs: Cleanup...
81
82
  static struct inode *__ecryptfs_get_inode(struct inode *lower_inode,
  					  struct super_block *sb)
c4f790736   Tyler Hicks   eCryptfs: Consoli...
83
84
  {
  	struct inode *inode;
c4f790736   Tyler Hicks   eCryptfs: Consoli...
85

5ccf92037   Tyler Hicks   eCryptfs: Cleanup...
86
87
88
89
  	if (lower_inode->i_sb != ecryptfs_superblock_to_lower(sb))
  		return ERR_PTR(-EXDEV);
  	if (!igrab(lower_inode))
  		return ERR_PTR(-ESTALE);
c4f790736   Tyler Hicks   eCryptfs: Consoli...
90
91
92
93
  	inode = iget5_locked(sb, (unsigned long)lower_inode,
  			     ecryptfs_inode_test, ecryptfs_inode_set,
  			     lower_inode);
  	if (!inode) {
c4f790736   Tyler Hicks   eCryptfs: Consoli...
94
  		iput(lower_inode);
5ccf92037   Tyler Hicks   eCryptfs: Cleanup...
95
  		return ERR_PTR(-EACCES);
c4f790736   Tyler Hicks   eCryptfs: Consoli...
96
  	}
5ccf92037   Tyler Hicks   eCryptfs: Cleanup...
97
  	if (!(inode->i_state & I_NEW))
c4f790736   Tyler Hicks   eCryptfs: Consoli...
98
  		iput(lower_inode);
5ccf92037   Tyler Hicks   eCryptfs: Cleanup...
99
100
101
102
103
104
105
106
107
108
109
  
  	return inode;
  }
  
  struct inode *ecryptfs_get_inode(struct inode *lower_inode,
  				 struct super_block *sb)
  {
  	struct inode *inode = __ecryptfs_get_inode(lower_inode, sb);
  
  	if (!IS_ERR(inode) && (inode->i_state & I_NEW))
  		unlock_new_inode(inode);
c4f790736   Tyler Hicks   eCryptfs: Consoli...
110
  	return inode;
c4f790736   Tyler Hicks   eCryptfs: Consoli...
111
  }
c4f790736   Tyler Hicks   eCryptfs: Consoli...
112
113
114
115
116
  /**
   * ecryptfs_interpose
   * @lower_dentry: Existing dentry in the lower filesystem
   * @dentry: ecryptfs' dentry
   * @sb: ecryptfs's super_block
c4f790736   Tyler Hicks   eCryptfs: Consoli...
117
118
119
120
121
122
   *
   * Interposes upper and lower dentries.
   *
   * Returns zero on success; non-zero otherwise
   */
  static int ecryptfs_interpose(struct dentry *lower_dentry,
5ccf92037   Tyler Hicks   eCryptfs: Cleanup...
123
  			      struct dentry *dentry, struct super_block *sb)
c4f790736   Tyler Hicks   eCryptfs: Consoli...
124
  {
2b0143b5c   David Howells   VFS: normal files...
125
  	struct inode *inode = ecryptfs_get_inode(d_inode(lower_dentry), sb);
5ccf92037   Tyler Hicks   eCryptfs: Cleanup...
126

c4f790736   Tyler Hicks   eCryptfs: Consoli...
127
128
  	if (IS_ERR(inode))
  		return PTR_ERR(inode);
5ccf92037   Tyler Hicks   eCryptfs: Cleanup...
129
  	d_instantiate(dentry, inode);
c4f790736   Tyler Hicks   eCryptfs: Consoli...
130
131
  	return 0;
  }
8bc2d3cf6   Tyler Hicks   eCryptfs: Unlink ...
132
133
134
135
136
137
138
139
140
141
  static int ecryptfs_do_unlink(struct inode *dir, struct dentry *dentry,
  			      struct inode *inode)
  {
  	struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
  	struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir);
  	struct dentry *lower_dir_dentry;
  	int rc;
  
  	dget(lower_dentry);
  	lower_dir_dentry = lock_parent(lower_dentry);
b21996e36   J. Bruce Fields   locks: break dele...
142
  	rc = vfs_unlink(lower_dir_inode, lower_dentry, NULL);
8bc2d3cf6   Tyler Hicks   eCryptfs: Unlink ...
143
144
145
146
147
148
149
150
151
152
153
154
155
156
  	if (rc) {
  		printk(KERN_ERR "Error in vfs_unlink; rc = [%d]
  ", rc);
  		goto out_unlock;
  	}
  	fsstack_copy_attr_times(dir, lower_dir_inode);
  	set_nlink(inode, ecryptfs_inode_to_lower(inode)->i_nlink);
  	inode->i_ctime = dir->i_ctime;
  	d_drop(dentry);
  out_unlock:
  	unlock_dir(lower_dir_dentry);
  	dput(lower_dentry);
  	return rc;
  }
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
157
  /**
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
158
159
160
161
   * ecryptfs_do_create
   * @directory_inode: inode of the new file's dentry's parent in ecryptfs
   * @ecryptfs_dentry: New file's dentry in ecryptfs
   * @mode: The mode of the new file
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
162
163
164
165
166
   *
   * Creates the underlying file and the eCryptfs inode which will link to
   * it. It will also update the eCryptfs directory inode to mimic the
   * stat of the lower directory inode.
   *
b59db43ad   Tyler Hicks   eCryptfs: Prevent...
167
   * Returns the new eCryptfs inode on success; an ERR_PTR on error condition
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
168
   */
b59db43ad   Tyler Hicks   eCryptfs: Prevent...
169
  static struct inode *
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
170
  ecryptfs_do_create(struct inode *directory_inode,
175a4eb7e   Al Viro   fs: propagate umo...
171
  		   struct dentry *ecryptfs_dentry, umode_t mode)
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
172
173
174
175
  {
  	int rc;
  	struct dentry *lower_dentry;
  	struct dentry *lower_dir_dentry;
b59db43ad   Tyler Hicks   eCryptfs: Prevent...
176
  	struct inode *inode;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
177
178
179
  
  	lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
  	lower_dir_dentry = lock_parent(lower_dentry);
2b0143b5c   David Howells   VFS: normal files...
180
  	rc = vfs_create(d_inode(lower_dir_dentry), lower_dentry, mode, true);
4981e081c   Michael Halcrow   eCryptfs: set up ...
181
  	if (rc) {
caeeeecfd   Michael Halcrow   eCryptfs: fix den...
182
  		printk(KERN_ERR "%s: Failure to create dentry in lower fs; "
18d1dbf1d   Harvey Harrison   ecryptfs: replace...
183
184
  		       "rc = [%d]
  ", __func__, rc);
b59db43ad   Tyler Hicks   eCryptfs: Prevent...
185
  		inode = ERR_PTR(rc);
caeeeecfd   Michael Halcrow   eCryptfs: fix den...
186
  		goto out_lock;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
187
  	}
2b0143b5c   David Howells   VFS: normal files...
188
  	inode = __ecryptfs_get_inode(d_inode(lower_dentry),
b59db43ad   Tyler Hicks   eCryptfs: Prevent...
189
  				     directory_inode->i_sb);
8bc2d3cf6   Tyler Hicks   eCryptfs: Unlink ...
190
  	if (IS_ERR(inode)) {
2b0143b5c   David Howells   VFS: normal files...
191
  		vfs_unlink(d_inode(lower_dir_dentry), lower_dentry, NULL);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
192
  		goto out_lock;
8bc2d3cf6   Tyler Hicks   eCryptfs: Unlink ...
193
  	}
2b0143b5c   David Howells   VFS: normal files...
194
195
  	fsstack_copy_attr_times(directory_inode, d_inode(lower_dir_dentry));
  	fsstack_copy_inode_size(directory_inode, d_inode(lower_dir_dentry));
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
196
197
  out_lock:
  	unlock_dir(lower_dir_dentry);
b59db43ad   Tyler Hicks   eCryptfs: Prevent...
198
  	return inode;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
199
200
201
  }
  
  /**
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
202
203
204
205
206
207
208
   * ecryptfs_initialize_file
   *
   * Cause the file to be changed from a basic empty file to an ecryptfs
   * file with a header and first data page.
   *
   * Returns zero on success
   */
e3ccaa976   Tyler Hicks   eCryptfs: Initial...
209
210
  int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry,
  			     struct inode *ecryptfs_inode)
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
211
  {
d7cdc5feb   Michael Halcrow   eCryptfs: update ...
212
  	struct ecryptfs_crypt_stat *crypt_stat =
b59db43ad   Tyler Hicks   eCryptfs: Prevent...
213
  		&ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
214
  	int rc = 0;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
215

b59db43ad   Tyler Hicks   eCryptfs: Prevent...
216
  	if (S_ISDIR(ecryptfs_inode->i_mode)) {
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
217
218
  		ecryptfs_printk(KERN_DEBUG, "This is a directory
  ");
e2bd99ec5   Michael Halcrow   [PATCH] eCryptfs:...
219
  		crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
d7cdc5feb   Michael Halcrow   eCryptfs: update ...
220
  		goto out;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
221
  	}
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
222
223
  	ecryptfs_printk(KERN_DEBUG, "Initializing crypto context
  ");
b59db43ad   Tyler Hicks   eCryptfs: Prevent...
224
  	rc = ecryptfs_new_file_context(ecryptfs_inode);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
225
  	if (rc) {
d7cdc5feb   Michael Halcrow   eCryptfs: update ...
226
227
228
229
  		ecryptfs_printk(KERN_ERR, "Error creating new file "
  				"context; rc = [%d]
  ", rc);
  		goto out;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
230
  	}
b59db43ad   Tyler Hicks   eCryptfs: Prevent...
231
  	rc = ecryptfs_get_lower_file(ecryptfs_dentry, ecryptfs_inode);
27992890b   Roberto Sassu   ecryptfs: test lo...
232
233
  	if (rc) {
  		printk(KERN_ERR "%s: Error attempting to initialize "
332ab16f8   Tyler Hicks   eCryptfs: Add ref...
234
  			"the lower file for the dentry with name "
9e78d14a9   David Howells   Use %pd in eCryptFS
235
236
237
  			"[%pd]; rc = [%d]
  ", __func__,
  			ecryptfs_dentry, rc);
27992890b   Roberto Sassu   ecryptfs: test lo...
238
  		goto out;
391b52f98   Michael Halcrow   eCryptfs: Make al...
239
  	}
b59db43ad   Tyler Hicks   eCryptfs: Prevent...
240
  	rc = ecryptfs_write_metadata(ecryptfs_dentry, ecryptfs_inode);
332ab16f8   Tyler Hicks   eCryptfs: Add ref...
241
  	if (rc)
d7cdc5feb   Michael Halcrow   eCryptfs: update ...
242
243
  		printk(KERN_ERR "Error writing headers; rc = [%d]
  ", rc);
b59db43ad   Tyler Hicks   eCryptfs: Prevent...
244
  	ecryptfs_put_lower_file(ecryptfs_inode);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
245
246
247
248
249
250
251
252
253
  out:
  	return rc;
  }
  
  /**
   * ecryptfs_create
   * @dir: The inode of the directory in which to create the file.
   * @dentry: The eCryptfs dentry
   * @mode: The mode of the new file.
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
254
255
256
257
258
259
260
   *
   * Creates a new file.
   *
   * Returns zero on success; non-zero on error condition
   */
  static int
  ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry,
ebfc3b49a   Al Viro   don't pass nameid...
261
  		umode_t mode, bool excl)
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
262
  {
b59db43ad   Tyler Hicks   eCryptfs: Prevent...
263
  	struct inode *ecryptfs_inode;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
264
  	int rc;
b59db43ad   Tyler Hicks   eCryptfs: Prevent...
265
266
  	ecryptfs_inode = ecryptfs_do_create(directory_inode, ecryptfs_dentry,
  					    mode);
a1c83681d   Viresh Kumar   fs: Drop unlikely...
267
  	if (IS_ERR(ecryptfs_inode)) {
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
268
269
270
  		ecryptfs_printk(KERN_WARNING, "Failed to create file in"
  				"lower filesystem
  ");
b59db43ad   Tyler Hicks   eCryptfs: Prevent...
271
  		rc = PTR_ERR(ecryptfs_inode);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
272
273
274
275
  		goto out;
  	}
  	/* At this point, a file exists on "disk"; we need to make sure
  	 * that this on disk file is prepared to be an ecryptfs file */
b59db43ad   Tyler Hicks   eCryptfs: Prevent...
276
277
  	rc = ecryptfs_initialize_file(ecryptfs_dentry, ecryptfs_inode);
  	if (rc) {
8bc2d3cf6   Tyler Hicks   eCryptfs: Unlink ...
278
279
  		ecryptfs_do_unlink(directory_inode, ecryptfs_dentry,
  				   ecryptfs_inode);
0e81ba231   Al Viro   don't opencode ig...
280
  		iget_failed(ecryptfs_inode);
b59db43ad   Tyler Hicks   eCryptfs: Prevent...
281
282
  		goto out;
  	}
f440ea85d   Al Viro   do d_instantiate/...
283
  	d_instantiate_new(ecryptfs_dentry, ecryptfs_inode);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
284
285
286
  out:
  	return rc;
  }
778aeb42a   Tyler Hicks   eCryptfs: Cleanup...
287
288
289
290
291
292
293
294
295
  static int ecryptfs_i_size_read(struct dentry *dentry, struct inode *inode)
  {
  	struct ecryptfs_crypt_stat *crypt_stat;
  	int rc;
  
  	rc = ecryptfs_get_lower_file(dentry, inode);
  	if (rc) {
  		printk(KERN_ERR "%s: Error attempting to initialize "
  			"the lower file for the dentry with name "
9e78d14a9   David Howells   Use %pd in eCryptFS
296
297
298
  			"[%pd]; rc = [%d]
  ", __func__,
  			dentry, rc);
778aeb42a   Tyler Hicks   eCryptfs: Cleanup...
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
  		return rc;
  	}
  
  	crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
  	/* TODO: lock for crypt_stat comparison */
  	if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED))
  		ecryptfs_set_default_sizes(crypt_stat);
  
  	rc = ecryptfs_read_and_validate_header_region(inode);
  	ecryptfs_put_lower_file(inode);
  	if (rc) {
  		rc = ecryptfs_read_and_validate_xattr_region(dentry, inode);
  		if (!rc)
  			crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;
  	}
  
  	/* Must return 0 to allow non-eCryptfs files to be looked up, too */
  	return 0;
  }
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
318
  /**
5ccf92037   Tyler Hicks   eCryptfs: Cleanup...
319
   * ecryptfs_lookup_interpose - Dentry interposition for a lookup
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
320
   */
b1168a928   Al Viro   ecryptfs: avoid m...
321
322
  static struct dentry *ecryptfs_lookup_interpose(struct dentry *dentry,
  				     struct dentry *lower_dentry)
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
323
  {
2b0143b5c   David Howells   VFS: normal files...
324
  	struct inode *inode, *lower_inode = d_inode(lower_dentry);
778aeb42a   Tyler Hicks   eCryptfs: Cleanup...
325
  	struct ecryptfs_dentry_info *dentry_info;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
326
  	struct vfsmount *lower_mnt;
778aeb42a   Tyler Hicks   eCryptfs: Cleanup...
327
  	int rc = 0;
778aeb42a   Tyler Hicks   eCryptfs: Cleanup...
328
  	dentry_info = kmem_cache_alloc(ecryptfs_dentry_info_cache, GFP_KERNEL);
778aeb42a   Tyler Hicks   eCryptfs: Cleanup...
329
  	if (!dentry_info) {
addd65ad8   Michael Halcrow   eCryptfs: Filenam...
330
331
332
333
  		printk(KERN_ERR "%s: Out of memory whilst attempting "
  		       "to allocate ecryptfs_dentry_info struct
  ",
  			__func__);
778aeb42a   Tyler Hicks   eCryptfs: Cleanup...
334
  		dput(lower_dentry);
b1168a928   Al Viro   ecryptfs: avoid m...
335
  		return ERR_PTR(-ENOMEM);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
336
  	}
0b1d90119   Al Viro   ecryptfs_lookup_i...
337
338
  
  	lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent));
b1168a928   Al Viro   ecryptfs: avoid m...
339
340
  	fsstack_copy_attr_atime(d_inode(dentry->d_parent),
  				d_inode(lower_dentry->d_parent));
84d08fa88   Al Viro   helper for readin...
341
  	BUG_ON(!d_count(lower_dentry));
0b1d90119   Al Viro   ecryptfs_lookup_i...
342
343
  
  	ecryptfs_set_dentry_private(dentry, dentry_info);
92dd12303   Al Viro   ecryptfs: get rid...
344
345
  	dentry_info->lower_path.mnt = lower_mnt;
  	dentry_info->lower_path.dentry = lower_dentry;
778aeb42a   Tyler Hicks   eCryptfs: Cleanup...
346

2b0143b5c   David Howells   VFS: normal files...
347
  	if (d_really_is_negative(lower_dentry)) {
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
348
  		/* We want to add because we couldn't find in lower */
778aeb42a   Tyler Hicks   eCryptfs: Cleanup...
349
  		d_add(dentry, NULL);
b1168a928   Al Viro   ecryptfs: avoid m...
350
  		return NULL;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
351
  	}
b1168a928   Al Viro   ecryptfs: avoid m...
352
  	inode = __ecryptfs_get_inode(lower_inode, dentry->d_sb);
5ccf92037   Tyler Hicks   eCryptfs: Cleanup...
353
  	if (IS_ERR(inode)) {
778aeb42a   Tyler Hicks   eCryptfs: Cleanup...
354
355
356
  		printk(KERN_ERR "%s: Error interposing; rc = [%ld]
  ",
  		       __func__, PTR_ERR(inode));
b1168a928   Al Viro   ecryptfs: avoid m...
357
  		return ERR_CAST(inode);
391b52f98   Michael Halcrow   eCryptfs: Make al...
358
  	}
778aeb42a   Tyler Hicks   eCryptfs: Cleanup...
359
360
  	if (S_ISREG(inode->i_mode)) {
  		rc = ecryptfs_i_size_read(dentry, inode);
dd2a3b7ad   Michael Halcrow   [PATCH] eCryptfs:...
361
  		if (rc) {
778aeb42a   Tyler Hicks   eCryptfs: Cleanup...
362
  			make_bad_inode(inode);
b1168a928   Al Viro   ecryptfs: avoid m...
363
  			return ERR_PTR(rc);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
364
  		}
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
365
  	}
778aeb42a   Tyler Hicks   eCryptfs: Cleanup...
366

3b06b3ebf   Tyler Hicks   eCryptfs: Fix new...
367
368
  	if (inode->i_state & I_NEW)
  		unlock_new_inode(inode);
b1168a928   Al Viro   ecryptfs: avoid m...
369
  	return d_splice_alias(inode, dentry);
addd65ad8   Michael Halcrow   eCryptfs: Filenam...
370
371
372
373
374
375
  }
  
  /**
   * ecryptfs_lookup
   * @ecryptfs_dir_inode: The eCryptfs directory inode
   * @ecryptfs_dentry: The eCryptfs dentry that we are looking up
89076bc31   Al Viro   get rid of assort...
376
   * @flags: lookup flags
addd65ad8   Michael Halcrow   eCryptfs: Filenam...
377
378
379
380
381
382
   *
   * Find a file on disk. If the file does not exist, then we'll add it to the
   * dentry cache and continue on to read it from the disk.
   */
  static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
  				      struct dentry *ecryptfs_dentry,
00cd8dd3b   Al Viro   stop passing name...
383
  				      unsigned int flags)
addd65ad8   Michael Halcrow   eCryptfs: Filenam...
384
385
  {
  	char *encrypted_and_encoded_name = NULL;
88ae4ab98   Al Viro   ecryptfs_lookup()...
386
  	struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
addd65ad8   Michael Halcrow   eCryptfs: Filenam...
387
  	struct dentry *lower_dir_dentry, *lower_dentry;
88ae4ab98   Al Viro   ecryptfs_lookup()...
388
389
  	const char *name = ecryptfs_dentry->d_name.name;
  	size_t len = ecryptfs_dentry->d_name.len;
b1168a928   Al Viro   ecryptfs: avoid m...
390
  	struct dentry *res;
addd65ad8   Michael Halcrow   eCryptfs: Filenam...
391
  	int rc = 0;
addd65ad8   Michael Halcrow   eCryptfs: Filenam...
392
  	lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent);
88ae4ab98   Al Viro   ecryptfs_lookup()...
393

2aac0cf88   Tyler Hicks   eCryptfs: NULL cr...
394
395
  	mount_crypt_stat = &ecryptfs_superblock_to_private(
  				ecryptfs_dentry->d_sb)->mount_crypt_stat;
88ae4ab98   Al Viro   ecryptfs_lookup()...
396
397
398
399
400
401
402
403
404
405
406
407
  	if (mount_crypt_stat
  	    && (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)) {
  		rc = ecryptfs_encrypt_and_encode_filename(
  			&encrypted_and_encoded_name, &len,
  			mount_crypt_stat, name, len);
  		if (rc) {
  			printk(KERN_ERR "%s: Error attempting to encrypt and encode "
  			       "filename; rc = [%d]
  ", __func__, rc);
  			return ERR_PTR(rc);
  		}
  		name = encrypted_and_encoded_name;
addd65ad8   Michael Halcrow   eCryptfs: Filenam...
408
  	}
88ae4ab98   Al Viro   ecryptfs_lookup()...
409
410
  
  	lower_dentry = lookup_one_len_unlocked(name, lower_dir_dentry, len);
addd65ad8   Michael Halcrow   eCryptfs: Filenam...
411
  	if (IS_ERR(lower_dentry)) {
8787c7a3e   Tyler Hicks   eCryptfs: Revert ...
412
  		ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned "
b1168a928   Al Viro   ecryptfs: avoid m...
413
414
415
  				"[%ld] on lower_dentry = [%s]
  ", __func__,
  				PTR_ERR(lower_dentry),
88ae4ab98   Al Viro   ecryptfs_lookup()...
416
  				name);
b1168a928   Al Viro   ecryptfs: avoid m...
417
  		res = ERR_CAST(lower_dentry);
88ae4ab98   Al Viro   ecryptfs_lookup()...
418
419
  	} else {
  		res = ecryptfs_lookup_interpose(ecryptfs_dentry, lower_dentry);
addd65ad8   Michael Halcrow   eCryptfs: Filenam...
420
  	}
addd65ad8   Michael Halcrow   eCryptfs: Filenam...
421
  	kfree(encrypted_and_encoded_name);
b1168a928   Al Viro   ecryptfs: avoid m...
422
  	return res;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
423
424
425
426
427
428
429
430
431
432
  }
  
  static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir,
  			 struct dentry *new_dentry)
  {
  	struct dentry *lower_old_dentry;
  	struct dentry *lower_new_dentry;
  	struct dentry *lower_dir_dentry;
  	u64 file_size_save;
  	int rc;
2b0143b5c   David Howells   VFS: normal files...
433
  	file_size_save = i_size_read(d_inode(old_dentry));
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
434
435
436
437
438
  	lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
  	lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
  	dget(lower_old_dentry);
  	dget(lower_new_dentry);
  	lower_dir_dentry = lock_parent(lower_new_dentry);
2b0143b5c   David Howells   VFS: normal files...
439
  	rc = vfs_link(lower_old_dentry, d_inode(lower_dir_dentry),
146a8595c   J. Bruce Fields   locks: break dele...
440
  		      lower_new_dentry, NULL);
2b0143b5c   David Howells   VFS: normal files...
441
  	if (rc || d_really_is_negative(lower_new_dentry))
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
442
  		goto out_lock;
5ccf92037   Tyler Hicks   eCryptfs: Cleanup...
443
  	rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
444
445
  	if (rc)
  		goto out_lock;
2b0143b5c   David Howells   VFS: normal files...
446
447
448
449
450
  	fsstack_copy_attr_times(dir, d_inode(lower_dir_dentry));
  	fsstack_copy_inode_size(dir, d_inode(lower_dir_dentry));
  	set_nlink(d_inode(old_dentry),
  		  ecryptfs_inode_to_lower(d_inode(old_dentry))->i_nlink);
  	i_size_write(d_inode(new_dentry), file_size_save);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
451
452
453
454
  out_lock:
  	unlock_dir(lower_dir_dentry);
  	dput(lower_new_dentry);
  	dput(lower_old_dentry);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
455
456
457
458
459
  	return rc;
  }
  
  static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry)
  {
2b0143b5c   David Howells   VFS: normal files...
460
  	return ecryptfs_do_unlink(dir, dentry, d_inode(dentry));
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
461
462
463
464
465
466
467
468
  }
  
  static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry,
  			    const char *symname)
  {
  	int rc;
  	struct dentry *lower_dentry;
  	struct dentry *lower_dir_dentry;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
469
  	char *encoded_symname;
addd65ad8   Michael Halcrow   eCryptfs: Filenam...
470
471
  	size_t encoded_symlen;
  	struct ecryptfs_mount_crypt_stat *mount_crypt_stat = NULL;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
472
473
474
475
  
  	lower_dentry = ecryptfs_dentry_to_lower(dentry);
  	dget(lower_dentry);
  	lower_dir_dentry = lock_parent(lower_dentry);
addd65ad8   Michael Halcrow   eCryptfs: Filenam...
476
477
478
479
  	mount_crypt_stat = &ecryptfs_superblock_to_private(
  		dir->i_sb)->mount_crypt_stat;
  	rc = ecryptfs_encrypt_and_encode_filename(&encoded_symname,
  						  &encoded_symlen,
addd65ad8   Michael Halcrow   eCryptfs: Filenam...
480
481
482
  						  mount_crypt_stat, symname,
  						  strlen(symname));
  	if (rc)
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
483
  		goto out_lock;
2b0143b5c   David Howells   VFS: normal files...
484
  	rc = vfs_symlink(d_inode(lower_dir_dentry), lower_dentry,
db2e747b1   Miklos Szeredi   [patch 5/5] vfs: ...
485
  			 encoded_symname);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
486
  	kfree(encoded_symname);
2b0143b5c   David Howells   VFS: normal files...
487
  	if (rc || d_really_is_negative(lower_dentry))
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
488
  		goto out_lock;
5ccf92037   Tyler Hicks   eCryptfs: Cleanup...
489
  	rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
490
491
  	if (rc)
  		goto out_lock;
2b0143b5c   David Howells   VFS: normal files...
492
493
  	fsstack_copy_attr_times(dir, d_inode(lower_dir_dentry));
  	fsstack_copy_inode_size(dir, d_inode(lower_dir_dentry));
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
494
495
496
  out_lock:
  	unlock_dir(lower_dir_dentry);
  	dput(lower_dentry);
2b0143b5c   David Howells   VFS: normal files...
497
  	if (d_really_is_negative(dentry))
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
498
499
500
  		d_drop(dentry);
  	return rc;
  }
18bb1db3e   Al Viro   switch vfs_mkdir(...
501
  static int ecryptfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
502
503
504
505
506
507
508
  {
  	int rc;
  	struct dentry *lower_dentry;
  	struct dentry *lower_dir_dentry;
  
  	lower_dentry = ecryptfs_dentry_to_lower(dentry);
  	lower_dir_dentry = lock_parent(lower_dentry);
2b0143b5c   David Howells   VFS: normal files...
509
510
  	rc = vfs_mkdir(d_inode(lower_dir_dentry), lower_dentry, mode);
  	if (rc || d_really_is_negative(lower_dentry))
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
511
  		goto out;
5ccf92037   Tyler Hicks   eCryptfs: Cleanup...
512
  	rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
513
514
  	if (rc)
  		goto out;
2b0143b5c   David Howells   VFS: normal files...
515
516
517
  	fsstack_copy_attr_times(dir, d_inode(lower_dir_dentry));
  	fsstack_copy_inode_size(dir, d_inode(lower_dir_dentry));
  	set_nlink(dir, d_inode(lower_dir_dentry)->i_nlink);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
518
519
  out:
  	unlock_dir(lower_dir_dentry);
2b0143b5c   David Howells   VFS: normal files...
520
  	if (d_really_is_negative(dentry))
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
521
522
523
524
525
526
  		d_drop(dentry);
  	return rc;
  }
  
  static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
  {
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
527
  	struct dentry *lower_dentry;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
528
  	struct dentry *lower_dir_dentry;
45ec4abab   Michael Halcrow   [PATCH] eCryptfs:...
529
  	int rc;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
530
531
  
  	lower_dentry = ecryptfs_dentry_to_lower(dentry);
45ec4abab   Michael Halcrow   [PATCH] eCryptfs:...
532
  	dget(dentry);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
533
  	lower_dir_dentry = lock_parent(lower_dentry);
45ec4abab   Michael Halcrow   [PATCH] eCryptfs:...
534
  	dget(lower_dentry);
2b0143b5c   David Howells   VFS: normal files...
535
  	rc = vfs_rmdir(d_inode(lower_dir_dentry), lower_dentry);
45ec4abab   Michael Halcrow   [PATCH] eCryptfs:...
536
  	dput(lower_dentry);
2b0143b5c   David Howells   VFS: normal files...
537
538
539
540
  	if (!rc && d_really_is_positive(dentry))
  		clear_nlink(d_inode(dentry));
  	fsstack_copy_attr_times(dir, d_inode(lower_dir_dentry));
  	set_nlink(dir, d_inode(lower_dir_dentry)->i_nlink);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
541
542
543
  	unlock_dir(lower_dir_dentry);
  	if (!rc)
  		d_drop(dentry);
45ec4abab   Michael Halcrow   [PATCH] eCryptfs:...
544
  	dput(dentry);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
545
546
547
548
  	return rc;
  }
  
  static int
1a67aafb5   Al Viro   switch ->mknod() ...
549
  ecryptfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
550
551
552
553
554
555
556
  {
  	int rc;
  	struct dentry *lower_dentry;
  	struct dentry *lower_dir_dentry;
  
  	lower_dentry = ecryptfs_dentry_to_lower(dentry);
  	lower_dir_dentry = lock_parent(lower_dentry);
2b0143b5c   David Howells   VFS: normal files...
557
558
  	rc = vfs_mknod(d_inode(lower_dir_dentry), lower_dentry, mode, dev);
  	if (rc || d_really_is_negative(lower_dentry))
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
559
  		goto out;
5ccf92037   Tyler Hicks   eCryptfs: Cleanup...
560
  	rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
561
562
  	if (rc)
  		goto out;
2b0143b5c   David Howells   VFS: normal files...
563
564
  	fsstack_copy_attr_times(dir, d_inode(lower_dir_dentry));
  	fsstack_copy_inode_size(dir, d_inode(lower_dir_dentry));
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
565
566
  out:
  	unlock_dir(lower_dir_dentry);
2b0143b5c   David Howells   VFS: normal files...
567
  	if (d_really_is_negative(dentry))
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
568
569
570
571
572
573
  		d_drop(dentry);
  	return rc;
  }
  
  static int
  ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
1cd66c93b   Miklos Szeredi   fs: make remainin...
574
575
  		struct inode *new_dir, struct dentry *new_dentry,
  		unsigned int flags)
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
576
577
578
579
580
581
  {
  	int rc;
  	struct dentry *lower_old_dentry;
  	struct dentry *lower_new_dentry;
  	struct dentry *lower_old_dir_dentry;
  	struct dentry *lower_new_dir_dentry;
0d132f736   Erez Zadok   ecryptfs: don't i...
582
  	struct dentry *trap = NULL;
8335eafc2   Tyler Hicks   eCryptfs: Copy up...
583
  	struct inode *target_inode;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
584

1cd66c93b   Miklos Szeredi   fs: make remainin...
585
586
  	if (flags)
  		return -EINVAL;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
587
588
589
590
591
592
  	lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
  	lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
  	dget(lower_old_dentry);
  	dget(lower_new_dentry);
  	lower_old_dir_dentry = dget_parent(lower_old_dentry);
  	lower_new_dir_dentry = dget_parent(lower_new_dentry);
2b0143b5c   David Howells   VFS: normal files...
593
  	target_inode = d_inode(new_dentry);
0d132f736   Erez Zadok   ecryptfs: don't i...
594
595
596
597
598
599
600
601
602
603
604
  	trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
  	/* source should not be ancestor of target */
  	if (trap == lower_old_dentry) {
  		rc = -EINVAL;
  		goto out_lock;
  	}
  	/* target should not be ancestor of source */
  	if (trap == lower_new_dentry) {
  		rc = -ENOTEMPTY;
  		goto out_lock;
  	}
2b0143b5c   David Howells   VFS: normal files...
605
606
  	rc = vfs_rename(d_inode(lower_old_dir_dentry), lower_old_dentry,
  			d_inode(lower_new_dir_dentry), lower_new_dentry,
520c8b165   Miklos Szeredi   vfs: add renameat...
607
  			NULL, 0);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
608
609
  	if (rc)
  		goto out_lock;
8335eafc2   Tyler Hicks   eCryptfs: Copy up...
610
611
612
  	if (target_inode)
  		fsstack_copy_attr_all(target_inode,
  				      ecryptfs_inode_to_lower(target_inode));
2b0143b5c   David Howells   VFS: normal files...
613
  	fsstack_copy_attr_all(new_dir, d_inode(lower_new_dir_dentry));
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
614
  	if (new_dir != old_dir)
2b0143b5c   David Howells   VFS: normal files...
615
  		fsstack_copy_attr_all(old_dir, d_inode(lower_old_dir_dentry));
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
616
617
  out_lock:
  	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
dd55c8985   Tyler Hicks   eCryptfs: dput de...
618
619
  	dput(lower_new_dir_dentry);
  	dput(lower_old_dir_dentry);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
620
621
622
623
  	dput(lower_new_dentry);
  	dput(lower_old_dentry);
  	return rc;
  }
b22e8fedc   Al Viro   ecryptfs: fix fai...
624
  static char *ecryptfs_readlink_lower(struct dentry *dentry, size_t *bufsiz)
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
625
  {
6c988f575   Miklos Szeredi   ecryptfs: use vfs...
626
  	DEFINE_DELAYED_CALL(done);
3a60a1686   Tyler Hicks   eCryptfs: Decrypt...
627
  	struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
6c988f575   Miklos Szeredi   ecryptfs: use vfs...
628
  	const char *link;
b22e8fedc   Al Viro   ecryptfs: fix fai...
629
  	char *buf;
addd65ad8   Michael Halcrow   eCryptfs: Filenam...
630
  	int rc;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
631

6c988f575   Miklos Szeredi   ecryptfs: use vfs...
632
633
634
  	link = vfs_get_link(lower_dentry, &done);
  	if (IS_ERR(link))
  		return ERR_CAST(link);
b22e8fedc   Al Viro   ecryptfs: fix fai...
635
  	rc = ecryptfs_decode_and_decrypt_filename(&buf, bufsiz, dentry->d_sb,
6c988f575   Miklos Szeredi   ecryptfs: use vfs...
636
637
638
639
640
641
  						  link, strlen(link));
  	do_delayed_call(&done);
  	if (rc)
  		return ERR_PTR(rc);
  
  	return buf;
3a60a1686   Tyler Hicks   eCryptfs: Decrypt...
642
  }
6b2553918   Al Viro   replace ->follow_...
643
  static const char *ecryptfs_get_link(struct dentry *dentry,
fceef393a   Al Viro   switch ->get_link...
644
645
  				     struct inode *inode,
  				     struct delayed_call *done)
3a60a1686   Tyler Hicks   eCryptfs: Decrypt...
646
  {
b22e8fedc   Al Viro   ecryptfs: fix fai...
647
  	size_t len;
6b2553918   Al Viro   replace ->follow_...
648
649
650
651
652
653
  	char *buf;
  
  	if (!dentry)
  		return ERR_PTR(-ECHILD);
  
  	buf = ecryptfs_readlink_lower(dentry, &len);
b22e8fedc   Al Viro   ecryptfs: fix fai...
654
  	if (IS_ERR(buf))
680baacbc   Al Viro   new ->follow_link...
655
  		return buf;
2b0143b5c   David Howells   VFS: normal files...
656
657
  	fsstack_copy_attr_atime(d_inode(dentry),
  				d_inode(ecryptfs_dentry_to_lower(dentry)));
408bd629b   Al Viro   get rid of pointl...
658
  	buf[len] = '\0';
fceef393a   Al Viro   switch ->get_link...
659
660
  	set_delayed_call(done, kfree_link, buf);
  	return buf;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
661
  }
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
662
663
664
665
666
  /**
   * upper_size_to_lower_size
   * @crypt_stat: Crypt_stat associated with file
   * @upper_size: Size of the upper file
   *
cc11beffd   Michael Halcrow   eCryptfs: track h...
667
   * Calculate the required size of the lower file based on the
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
668
669
670
671
672
673
674
675
676
677
   * specified size of the upper file. This calculation is based on the
   * number of headers in the underlying file and the extent size.
   *
   * Returns Calculated size of the lower file.
   */
  static loff_t
  upper_size_to_lower_size(struct ecryptfs_crypt_stat *crypt_stat,
  			 loff_t upper_size)
  {
  	loff_t lower_size;
157f10713   Tyler Hicks   eCryptfs: Fix met...
678
  	lower_size = ecryptfs_lower_header_size(crypt_stat);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
679
680
681
682
683
684
685
686
687
688
689
690
  	if (upper_size != 0) {
  		loff_t num_extents;
  
  		num_extents = upper_size >> crypt_stat->extent_shift;
  		if (upper_size & ~crypt_stat->extent_mask)
  			num_extents++;
  		lower_size += (num_extents * crypt_stat->extent_size);
  	}
  	return lower_size;
  }
  
  /**
5f3ef64f4   Tyler Hicks   eCryptfs: Use not...
691
   * truncate_upper
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
692
   * @dentry: The ecryptfs layer dentry
5f3ef64f4   Tyler Hicks   eCryptfs: Use not...
693
694
   * @ia: Address of the ecryptfs inode's attributes
   * @lower_ia: Address of the lower inode's attributes
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
695
696
697
   *
   * Function to handle truncations modifying the size of the file. Note
   * that the file sizes are interpolated. When expanding, we are simply
5f3ef64f4   Tyler Hicks   eCryptfs: Use not...
698
699
700
701
702
   * writing strings of 0's out. When truncating, we truncate the upper
   * inode and update the lower_ia according to the page index
   * interpolations. If ATTR_SIZE is set in lower_ia->ia_valid upon return,
   * the caller must use lower_ia in a call to notify_change() to perform
   * the truncation of the lower inode.
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
703
704
705
   *
   * Returns zero on success; non-zero otherwise
   */
5f3ef64f4   Tyler Hicks   eCryptfs: Use not...
706
707
  static int truncate_upper(struct dentry *dentry, struct iattr *ia,
  			  struct iattr *lower_ia)
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
708
709
  {
  	int rc = 0;
2b0143b5c   David Howells   VFS: normal files...
710
  	struct inode *inode = d_inode(dentry);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
711
712
713
714
  	struct ecryptfs_crypt_stat *crypt_stat;
  	loff_t i_size = i_size_read(inode);
  	loff_t lower_size_before_truncate;
  	loff_t lower_size_after_truncate;
5f3ef64f4   Tyler Hicks   eCryptfs: Use not...
715
716
  	if (unlikely((ia->ia_size == i_size))) {
  		lower_ia->ia_valid &= ~ATTR_SIZE;
332ab16f8   Tyler Hicks   eCryptfs: Add ref...
717
  		return 0;
5f3ef64f4   Tyler Hicks   eCryptfs: Use not...
718
  	}
3b06b3ebf   Tyler Hicks   eCryptfs: Fix new...
719
  	rc = ecryptfs_get_lower_file(dentry, inode);
332ab16f8   Tyler Hicks   eCryptfs: Add ref...
720
721
  	if (rc)
  		return rc;
2b0143b5c   David Howells   VFS: normal files...
722
  	crypt_stat = &ecryptfs_inode_to_private(d_inode(dentry))->crypt_stat;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
723
  	/* Switch on growing or shrinking file */
5f3ef64f4   Tyler Hicks   eCryptfs: Use not...
724
  	if (ia->ia_size > i_size) {
2ed92554a   Michael Halcrow   eCryptfs: make op...
725
  		char zero[] = { 0x00 };
5f3ef64f4   Tyler Hicks   eCryptfs: Use not...
726
  		lower_ia->ia_valid &= ~ATTR_SIZE;
2ed92554a   Michael Halcrow   eCryptfs: make op...
727
728
729
730
  		/* Write a single 0 at the last position of the file;
  		 * this triggers code that will fill in 0's throughout
  		 * the intermediate portion of the previous end of the
  		 * file and the new and of the file */
48c1e44ac   Al Viro   switch ecryptfs_w...
731
  		rc = ecryptfs_write(inode, zero,
5f3ef64f4   Tyler Hicks   eCryptfs: Use not...
732
733
734
735
  				    (ia->ia_size - 1), 1);
  	} else { /* ia->ia_size < i_size_read(inode) */
  		/* We're chopping off all the pages down to the page
  		 * in which ia->ia_size is located. Fill in the end of
ea1754a08   Kirill A. Shutemov   mm, fs: remove re...
736
737
  		 * that page from (ia->ia_size & ~PAGE_MASK) to
  		 * PAGE_SIZE with zeros. */
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
738
739
  		size_t num_zeros = (PAGE_SIZE
  				    - (ia->ia_size & ~PAGE_MASK));
2ed92554a   Michael Halcrow   eCryptfs: make op...
740

13a791b4e   Tyler Hicks   eCryptfs: Fix dat...
741
  		if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
2c27c65ed   Christoph Hellwig   check ATTR_SIZE c...
742
  			truncate_setsize(inode, ia->ia_size);
5f3ef64f4   Tyler Hicks   eCryptfs: Use not...
743
744
  			lower_ia->ia_size = ia->ia_size;
  			lower_ia->ia_valid |= ATTR_SIZE;
48c1e44ac   Al Viro   switch ecryptfs_w...
745
  			goto out;
13a791b4e   Tyler Hicks   eCryptfs: Fix dat...
746
  		}
2ed92554a   Michael Halcrow   eCryptfs: make op...
747
748
749
750
751
752
  		if (num_zeros) {
  			char *zeros_virt;
  
  			zeros_virt = kzalloc(num_zeros, GFP_KERNEL);
  			if (!zeros_virt) {
  				rc = -ENOMEM;
48c1e44ac   Al Viro   switch ecryptfs_w...
753
  				goto out;
2ed92554a   Michael Halcrow   eCryptfs: make op...
754
  			}
48c1e44ac   Al Viro   switch ecryptfs_w...
755
  			rc = ecryptfs_write(inode, zeros_virt,
5f3ef64f4   Tyler Hicks   eCryptfs: Use not...
756
  					    ia->ia_size, num_zeros);
2ed92554a   Michael Halcrow   eCryptfs: make op...
757
  			kfree(zeros_virt);
5dda6992a   Michael Halcrow   eCryptfs: remove ...
758
  			if (rc) {
240e2df5c   Michael Halcrow   eCryptfs: fix wri...
759
760
761
762
  				printk(KERN_ERR "Error attempting to zero out "
  				       "the remainder of the end page on "
  				       "reducing truncate; rc = [%d]
  ", rc);
48c1e44ac   Al Viro   switch ecryptfs_w...
763
  				goto out;
240e2df5c   Michael Halcrow   eCryptfs: fix wri...
764
765
  			}
  		}
2c27c65ed   Christoph Hellwig   check ATTR_SIZE c...
766
  		truncate_setsize(inode, ia->ia_size);
0216f7f79   Michael Halcrow   eCryptfs: replace...
767
  		rc = ecryptfs_write_inode_size_to_metadata(inode);
dd2a3b7ad   Michael Halcrow   [PATCH] eCryptfs:...
768
769
770
771
772
  		if (rc) {
  			printk(KERN_ERR	"Problem with "
  			       "ecryptfs_write_inode_size_to_metadata; "
  			       "rc = [%d]
  ", rc);
48c1e44ac   Al Viro   switch ecryptfs_w...
773
  			goto out;
dd2a3b7ad   Michael Halcrow   [PATCH] eCryptfs:...
774
  		}
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
775
776
777
778
779
  		/* We are reducing the size of the ecryptfs file, and need to
  		 * know if we need to reduce the size of the lower file. */
  		lower_size_before_truncate =
  		    upper_size_to_lower_size(crypt_stat, i_size);
  		lower_size_after_truncate =
5f3ef64f4   Tyler Hicks   eCryptfs: Use not...
780
781
782
783
784
785
  		    upper_size_to_lower_size(crypt_stat, ia->ia_size);
  		if (lower_size_after_truncate < lower_size_before_truncate) {
  			lower_ia->ia_size = lower_size_after_truncate;
  			lower_ia->ia_valid |= ATTR_SIZE;
  		} else
  			lower_ia->ia_valid &= ~ATTR_SIZE;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
786
  	}
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
787
  out:
332ab16f8   Tyler Hicks   eCryptfs: Add ref...
788
  	ecryptfs_put_lower_file(inode);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
789
790
  	return rc;
  }
a261a0390   Tyler Hicks   eCryptfs: Check i...
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
  static int ecryptfs_inode_newsize_ok(struct inode *inode, loff_t offset)
  {
  	struct ecryptfs_crypt_stat *crypt_stat;
  	loff_t lower_oldsize, lower_newsize;
  
  	crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
  	lower_oldsize = upper_size_to_lower_size(crypt_stat,
  						 i_size_read(inode));
  	lower_newsize = upper_size_to_lower_size(crypt_stat, offset);
  	if (lower_newsize > lower_oldsize) {
  		/*
  		 * The eCryptfs inode and the new *lower* size are mixed here
  		 * because we may not have the lower i_mutex held and/or it may
  		 * not be appropriate to call inode_newsize_ok() with inodes
  		 * from other filesystems.
  		 */
  		return inode_newsize_ok(inode, lower_newsize);
  	}
  
  	return 0;
  }
5f3ef64f4   Tyler Hicks   eCryptfs: Use not...
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
  /**
   * ecryptfs_truncate
   * @dentry: The ecryptfs layer dentry
   * @new_length: The length to expand the file to
   *
   * Simple function that handles the truncation of an eCryptfs inode and
   * its corresponding lower inode.
   *
   * Returns zero on success; non-zero otherwise
   */
  int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
  {
  	struct iattr ia = { .ia_valid = ATTR_SIZE, .ia_size = new_length };
  	struct iattr lower_ia = { .ia_valid = 0 };
  	int rc;
2b0143b5c   David Howells   VFS: normal files...
827
  	rc = ecryptfs_inode_newsize_ok(d_inode(dentry), new_length);
a261a0390   Tyler Hicks   eCryptfs: Check i...
828
829
  	if (rc)
  		return rc;
5f3ef64f4   Tyler Hicks   eCryptfs: Use not...
830
831
832
  	rc = truncate_upper(dentry, &ia, &lower_ia);
  	if (!rc && lower_ia.ia_valid & ATTR_SIZE) {
  		struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
5955102c9   Al Viro   wrappers for ->i_...
833
  		inode_lock(d_inode(lower_dentry));
27ac0ffea   J. Bruce Fields   locks: break dele...
834
  		rc = notify_change(lower_dentry, &lower_ia, NULL);
5955102c9   Al Viro   wrappers for ->i_...
835
  		inode_unlock(d_inode(lower_dentry));
5f3ef64f4   Tyler Hicks   eCryptfs: Use not...
836
837
838
  	}
  	return rc;
  }
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
839
  static int
10556cb21   Al Viro   ->permission() sa...
840
  ecryptfs_permission(struct inode *inode, int mask)
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
841
  {
f419a2e3b   Al Viro   [PATCH] kill name...
842
  	return inode_permission(ecryptfs_inode_to_lower(inode), mask);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
  }
  
  /**
   * ecryptfs_setattr
   * @dentry: dentry handle to the inode to modify
   * @ia: Structure with flags of what to change and values
   *
   * Updates the metadata of an inode. If the update is to the size
   * i.e. truncation, then ecryptfs_truncate will handle the size modification
   * of both the ecryptfs inode and the lower inode.
   *
   * All other metadata changes will be passed right to the lower filesystem,
   * and we will just update our inode to look like the lower.
   */
  static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
  {
  	int rc = 0;
  	struct dentry *lower_dentry;
5f3ef64f4   Tyler Hicks   eCryptfs: Use not...
861
  	struct iattr lower_ia;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
862
863
864
  	struct inode *inode;
  	struct inode *lower_inode;
  	struct ecryptfs_crypt_stat *crypt_stat;
2b0143b5c   David Howells   VFS: normal files...
865
  	crypt_stat = &ecryptfs_inode_to_private(d_inode(dentry))->crypt_stat;
e81f3340b   Herbert Xu   eCryptfs: Do not ...
866
867
868
869
870
  	if (!(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED)) {
  		rc = ecryptfs_init_crypt_stat(crypt_stat);
  		if (rc)
  			return rc;
  	}
2b0143b5c   David Howells   VFS: normal files...
871
  	inode = d_inode(dentry);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
872
  	lower_inode = ecryptfs_inode_to_lower(inode);
e10f281bc   Michael Halcrow   eCryptfs: initial...
873
874
  	lower_dentry = ecryptfs_dentry_to_lower(dentry);
  	mutex_lock(&crypt_stat->cs_mutex);
e36cb0b89   David Howells   VFS: (Scripted) C...
875
  	if (d_is_dir(dentry))
e10f281bc   Michael Halcrow   eCryptfs: initial...
876
  		crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
e36cb0b89   David Howells   VFS: (Scripted) C...
877
  	else if (d_is_reg(dentry)
64ee4808a   Michael Halcrow   eCryptfs: ecryptf...
878
879
  		 && (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)
  		     || !(crypt_stat->flags & ECRYPTFS_KEY_VALID))) {
e10f281bc   Michael Halcrow   eCryptfs: initial...
880
  		struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
e10f281bc   Michael Halcrow   eCryptfs: initial...
881

e10f281bc   Michael Halcrow   eCryptfs: initial...
882
883
  		mount_crypt_stat = &ecryptfs_superblock_to_private(
  			dentry->d_sb)->mount_crypt_stat;
3b06b3ebf   Tyler Hicks   eCryptfs: Fix new...
884
  		rc = ecryptfs_get_lower_file(dentry, inode);
332ab16f8   Tyler Hicks   eCryptfs: Add ref...
885
886
887
888
  		if (rc) {
  			mutex_unlock(&crypt_stat->cs_mutex);
  			goto out;
  		}
d7cdc5feb   Michael Halcrow   eCryptfs: update ...
889
  		rc = ecryptfs_read_metadata(dentry);
332ab16f8   Tyler Hicks   eCryptfs: Add ref...
890
  		ecryptfs_put_lower_file(inode);
5dda6992a   Michael Halcrow   eCryptfs: remove ...
891
  		if (rc) {
e10f281bc   Michael Halcrow   eCryptfs: initial...
892
893
894
  			if (!(mount_crypt_stat->flags
  			      & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
  				rc = -EIO;
25bd81740   Michael Halcrow   eCryptfs: Minor f...
895
  				printk(KERN_WARNING "Either the lower file "
e10f281bc   Michael Halcrow   eCryptfs: initial...
896
  				       "is not in a valid eCryptfs format, "
25bd81740   Michael Halcrow   eCryptfs: Minor f...
897
898
  				       "or the key could not be retrieved. "
  				       "Plaintext passthrough mode is not "
e10f281bc   Michael Halcrow   eCryptfs: initial...
899
900
  				       "enabled; returning -EIO
  ");
e10f281bc   Michael Halcrow   eCryptfs: initial...
901
  				mutex_unlock(&crypt_stat->cs_mutex);
e10f281bc   Michael Halcrow   eCryptfs: initial...
902
903
904
  				goto out;
  			}
  			rc = 0;
3aeb86ea4   Tyler Hicks   eCryptfs: Handle ...
905
906
  			crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED
  					       | ECRYPTFS_ENCRYPTED);
e10f281bc   Michael Halcrow   eCryptfs: initial...
907
  		}
e10f281bc   Michael Halcrow   eCryptfs: initial...
908
909
  	}
  	mutex_unlock(&crypt_stat->cs_mutex);
a261a0390   Tyler Hicks   eCryptfs: Check i...
910

31051c85b   Jan Kara   fs: Give dentry t...
911
  	rc = setattr_prepare(dentry, ia);
a261a0390   Tyler Hicks   eCryptfs: Check i...
912
913
914
915
916
917
918
  	if (rc)
  		goto out;
  	if (ia->ia_valid & ATTR_SIZE) {
  		rc = ecryptfs_inode_newsize_ok(inode, ia->ia_size);
  		if (rc)
  			goto out;
  	}
5f3ef64f4   Tyler Hicks   eCryptfs: Use not...
919
920
921
  	memcpy(&lower_ia, ia, sizeof(lower_ia));
  	if (ia->ia_valid & ATTR_FILE)
  		lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
922
  	if (ia->ia_valid & ATTR_SIZE) {
5f3ef64f4   Tyler Hicks   eCryptfs: Use not...
923
  		rc = truncate_upper(dentry, ia, &lower_ia);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
924
925
926
  		if (rc < 0)
  			goto out;
  	}
1ac564eca   Jeff Layton   ecryptfs: allow l...
927
928
929
930
931
  
  	/*
  	 * mode change is for clearing setuid/setgid bits. Allow lower fs
  	 * to interpret this in its own way.
  	 */
5f3ef64f4   Tyler Hicks   eCryptfs: Use not...
932
933
  	if (lower_ia.ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
  		lower_ia.ia_valid &= ~ATTR_MODE;
1ac564eca   Jeff Layton   ecryptfs: allow l...
934

5955102c9   Al Viro   wrappers for ->i_...
935
  	inode_lock(d_inode(lower_dentry));
27ac0ffea   J. Bruce Fields   locks: break dele...
936
  	rc = notify_change(lower_dentry, &lower_ia, NULL);
5955102c9   Al Viro   wrappers for ->i_...
937
  	inode_unlock(d_inode(lower_dentry));
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
938
  out:
9afa2fb6c   Erez Zadok   fsstack/ecryptfs:...
939
  	fsstack_copy_attr_all(inode, lower_inode);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
940
941
  	return rc;
  }
a528d35e8   David Howells   statx: Add a syst...
942
943
  static int ecryptfs_getattr_link(const struct path *path, struct kstat *stat,
  				 u32 request_mask, unsigned int flags)
3a60a1686   Tyler Hicks   eCryptfs: Decrypt...
944
  {
a528d35e8   David Howells   statx: Add a syst...
945
  	struct dentry *dentry = path->dentry;
3a60a1686   Tyler Hicks   eCryptfs: Decrypt...
946
947
948
949
950
  	struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
  	int rc = 0;
  
  	mount_crypt_stat = &ecryptfs_superblock_to_private(
  						dentry->d_sb)->mount_crypt_stat;
2b0143b5c   David Howells   VFS: normal files...
951
  	generic_fillattr(d_inode(dentry), stat);
3a60a1686   Tyler Hicks   eCryptfs: Decrypt...
952
953
954
  	if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) {
  		char *target;
  		size_t targetsiz;
b22e8fedc   Al Viro   ecryptfs: fix fai...
955
956
  		target = ecryptfs_readlink_lower(dentry, &targetsiz);
  		if (!IS_ERR(target)) {
3a60a1686   Tyler Hicks   eCryptfs: Decrypt...
957
958
  			kfree(target);
  			stat->size = targetsiz;
b22e8fedc   Al Viro   ecryptfs: fix fai...
959
960
  		} else {
  			rc = PTR_ERR(target);
3a60a1686   Tyler Hicks   eCryptfs: Decrypt...
961
962
963
964
  		}
  	}
  	return rc;
  }
a528d35e8   David Howells   statx: Add a syst...
965
966
  static int ecryptfs_getattr(const struct path *path, struct kstat *stat,
  			    u32 request_mask, unsigned int flags)
f8f484d1b   Tyler Hicks   eCryptfs: Add get...
967
  {
a528d35e8   David Howells   statx: Add a syst...
968
  	struct dentry *dentry = path->dentry;
f8f484d1b   Tyler Hicks   eCryptfs: Add get...
969
970
  	struct kstat lower_stat;
  	int rc;
a528d35e8   David Howells   statx: Add a syst...
971
972
  	rc = vfs_getattr(ecryptfs_dentry_to_lower_path(dentry), &lower_stat,
  			 request_mask, flags);
f8f484d1b   Tyler Hicks   eCryptfs: Add get...
973
  	if (!rc) {
2b0143b5c   David Howells   VFS: normal files...
974
975
976
  		fsstack_copy_attr_all(d_inode(dentry),
  				      ecryptfs_inode_to_lower(d_inode(dentry)));
  		generic_fillattr(d_inode(dentry), stat);
f8f484d1b   Tyler Hicks   eCryptfs: Add get...
977
978
979
980
  		stat->blocks = lower_stat.blocks;
  	}
  	return rc;
  }
dd2a3b7ad   Michael Halcrow   [PATCH] eCryptfs:...
981
  int
3767e255b   Al Viro   switch ->setxattr...
982
983
  ecryptfs_setxattr(struct dentry *dentry, struct inode *inode,
  		  const char *name, const void *value,
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
984
985
  		  size_t size, int flags)
  {
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
986
  	int rc;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
987
988
989
  	struct dentry *lower_dentry;
  
  	lower_dentry = ecryptfs_dentry_to_lower(dentry);
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
990
  	if (!(d_inode(lower_dentry)->i_opflags & IOP_XATTR)) {
cfce08c6b   Christian Pulvermacher   ecryptfs: fix err...
991
  		rc = -EOPNOTSUPP;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
992
993
  		goto out;
  	}
48b512e68   Roberto Sassu   ecryptfs: call vf...
994
  	rc = vfs_setxattr(lower_dentry, name, value, size, flags);
3767e255b   Al Viro   switch ->setxattr...
995
996
  	if (!rc && inode)
  		fsstack_copy_attr_all(inode, d_inode(lower_dentry));
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
997
998
999
  out:
  	return rc;
  }
dd2a3b7ad   Michael Halcrow   [PATCH] eCryptfs:...
1000
  ssize_t
ce23e6401   Al Viro   ->getxattr(): pas...
1001
1002
  ecryptfs_getxattr_lower(struct dentry *lower_dentry, struct inode *lower_inode,
  			const char *name, void *value, size_t size)
d7cdc5feb   Michael Halcrow   eCryptfs: update ...
1003
  {
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
1004
  	int rc;
d7cdc5feb   Michael Halcrow   eCryptfs: update ...
1005

5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
1006
  	if (!(lower_inode->i_opflags & IOP_XATTR)) {
cfce08c6b   Christian Pulvermacher   ecryptfs: fix err...
1007
  		rc = -EOPNOTSUPP;
d7cdc5feb   Michael Halcrow   eCryptfs: update ...
1008
1009
  		goto out;
  	}
ce23e6401   Al Viro   ->getxattr(): pas...
1010
  	inode_lock(lower_inode);
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
1011
  	rc = __vfs_getxattr(lower_dentry, lower_inode, name, value, size);
ce23e6401   Al Viro   ->getxattr(): pas...
1012
  	inode_unlock(lower_inode);
d7cdc5feb   Michael Halcrow   eCryptfs: update ...
1013
1014
1015
  out:
  	return rc;
  }
7896b6318   Adrian Bunk   fs/ecryptfs/: pos...
1016
  static ssize_t
ce23e6401   Al Viro   ->getxattr(): pas...
1017
1018
  ecryptfs_getxattr(struct dentry *dentry, struct inode *inode,
  		  const char *name, void *value, size_t size)
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
1019
  {
ce23e6401   Al Viro   ->getxattr(): pas...
1020
1021
1022
  	return ecryptfs_getxattr_lower(ecryptfs_dentry_to_lower(dentry),
  				       ecryptfs_inode_to_lower(inode),
  				       name, value, size);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
1023
1024
1025
1026
1027
1028
1029
1030
1031
  }
  
  static ssize_t
  ecryptfs_listxattr(struct dentry *dentry, char *list, size_t size)
  {
  	int rc = 0;
  	struct dentry *lower_dentry;
  
  	lower_dentry = ecryptfs_dentry_to_lower(dentry);
2b0143b5c   David Howells   VFS: normal files...
1032
  	if (!d_inode(lower_dentry)->i_op->listxattr) {
cfce08c6b   Christian Pulvermacher   ecryptfs: fix err...
1033
  		rc = -EOPNOTSUPP;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
1034
1035
  		goto out;
  	}
5955102c9   Al Viro   wrappers for ->i_...
1036
  	inode_lock(d_inode(lower_dentry));
2b0143b5c   David Howells   VFS: normal files...
1037
  	rc = d_inode(lower_dentry)->i_op->listxattr(lower_dentry, list, size);
5955102c9   Al Viro   wrappers for ->i_...
1038
  	inode_unlock(d_inode(lower_dentry));
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
1039
1040
1041
  out:
  	return rc;
  }
4b899da50   Andreas Gruenbacher   ecryptfs: Switch ...
1042
1043
  static int ecryptfs_removexattr(struct dentry *dentry, struct inode *inode,
  				const char *name)
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
1044
  {
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
1045
  	int rc;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
1046
  	struct dentry *lower_dentry;
4b899da50   Andreas Gruenbacher   ecryptfs: Switch ...
1047
  	struct inode *lower_inode;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
1048
1049
  
  	lower_dentry = ecryptfs_dentry_to_lower(dentry);
4b899da50   Andreas Gruenbacher   ecryptfs: Switch ...
1050
  	lower_inode = ecryptfs_inode_to_lower(inode);
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
1051
  	if (!(lower_inode->i_opflags & IOP_XATTR)) {
cfce08c6b   Christian Pulvermacher   ecryptfs: fix err...
1052
  		rc = -EOPNOTSUPP;
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
1053
1054
  		goto out;
  	}
4b899da50   Andreas Gruenbacher   ecryptfs: Switch ...
1055
  	inode_lock(lower_inode);
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
1056
  	rc = __vfs_removexattr(lower_dentry, name);
4b899da50   Andreas Gruenbacher   ecryptfs: Switch ...
1057
  	inode_unlock(lower_inode);
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
1058
1059
1060
  out:
  	return rc;
  }
754661f14   Arjan van de Ven   [PATCH] mark stru...
1061
  const struct inode_operations ecryptfs_symlink_iops = {
6b2553918   Al Viro   replace ->follow_...
1062
  	.get_link = ecryptfs_get_link,
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
1063
1064
  	.permission = ecryptfs_permission,
  	.setattr = ecryptfs_setattr,
3a60a1686   Tyler Hicks   eCryptfs: Decrypt...
1065
  	.getattr = ecryptfs_getattr_link,
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
1066
  	.listxattr = ecryptfs_listxattr,
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
1067
  };
754661f14   Arjan van de Ven   [PATCH] mark stru...
1068
  const struct inode_operations ecryptfs_dir_iops = {
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
  	.create = ecryptfs_create,
  	.lookup = ecryptfs_lookup,
  	.link = ecryptfs_link,
  	.unlink = ecryptfs_unlink,
  	.symlink = ecryptfs_symlink,
  	.mkdir = ecryptfs_mkdir,
  	.rmdir = ecryptfs_rmdir,
  	.mknod = ecryptfs_mknod,
  	.rename = ecryptfs_rename,
  	.permission = ecryptfs_permission,
  	.setattr = ecryptfs_setattr,
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
1080
  	.listxattr = ecryptfs_listxattr,
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
1081
  };
754661f14   Arjan van de Ven   [PATCH] mark stru...
1082
  const struct inode_operations ecryptfs_main_iops = {
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
1083
1084
  	.permission = ecryptfs_permission,
  	.setattr = ecryptfs_setattr,
f8f484d1b   Tyler Hicks   eCryptfs: Add get...
1085
  	.getattr = ecryptfs_getattr,
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
1086
  	.listxattr = ecryptfs_listxattr,
4b899da50   Andreas Gruenbacher   ecryptfs: Switch ...
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
  };
  
  static int ecryptfs_xattr_get(const struct xattr_handler *handler,
  			      struct dentry *dentry, struct inode *inode,
  			      const char *name, void *buffer, size_t size)
  {
  	return ecryptfs_getxattr(dentry, inode, name, buffer, size);
  }
  
  static int ecryptfs_xattr_set(const struct xattr_handler *handler,
  			      struct dentry *dentry, struct inode *inode,
  			      const char *name, const void *value, size_t size,
  			      int flags)
  {
  	if (value)
  		return ecryptfs_setxattr(dentry, inode, name, value, size, flags);
  	else {
  		BUG_ON(flags != XATTR_REPLACE);
  		return ecryptfs_removexattr(dentry, inode, name);
  	}
  }
  
  const struct xattr_handler ecryptfs_xattr_handler = {
  	.prefix = "",  /* match anything */
  	.get = ecryptfs_xattr_get,
  	.set = ecryptfs_xattr_set,
  };
  
  const struct xattr_handler *ecryptfs_xattr_handlers[] = {
  	&ecryptfs_xattr_handler,
  	NULL
237fead61   Michael Halcrow   [PATCH] ecryptfs:...
1118
  };