Blame view

fs/overlayfs/dir.c 28 KB
d2912cb15   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
e9be9d5e7   Miklos Szeredi   overlay filesystem
2
3
4
  /*
   *
   * Copyright (C) 2011 Novell Inc.
e9be9d5e7   Miklos Szeredi   overlay filesystem
5
6
7
8
9
10
11
   */
  
  #include <linux/fs.h>
  #include <linux/namei.h>
  #include <linux/xattr.h>
  #include <linux/security.h>
  #include <linux/cred.h>
3ea22a71b   Miklos Szeredi   ovl: allow settin...
12
  #include <linux/module.h>
38b256973   Miklos Szeredi   ovl: handle umask...
13
14
  #include <linux/posix_acl.h>
  #include <linux/posix_acl_xattr.h>
6a45b3628   Richard Weinberger   ovl: Fix info lea...
15
  #include <linux/atomic.h>
a6c606551   Miklos Szeredi   ovl: redirect on ...
16
  #include <linux/ratelimit.h>
e9be9d5e7   Miklos Szeredi   overlay filesystem
17
  #include "overlayfs.h"
3ea22a71b   Miklos Szeredi   ovl: allow settin...
18
19
  static unsigned short ovl_redirect_max = 256;
  module_param_named(redirect_max, ovl_redirect_max, ushort, 0644);
253e74833   Nicolas Schier   ovl: fix typo in ...
20
  MODULE_PARM_DESC(redirect_max,
3ea22a71b   Miklos Szeredi   ovl: allow settin...
21
  		 "Maximum length of absolute redirect xattr value");
4120fe64d   Vivek Goyal   ovl: Set redirect...
22
  static int ovl_set_redirect(struct dentry *dentry, bool samedir);
415543d5c   Amir Goldstein   ovl: cleanup bad ...
23
  int ovl_cleanup(struct inode *wdir, struct dentry *wdentry)
e9be9d5e7   Miklos Szeredi   overlay filesystem
24
25
26
27
  {
  	int err;
  
  	dget(wdentry);
e36cb0b89   David Howells   VFS: (Scripted) C...
28
  	if (d_is_dir(wdentry))
e9be9d5e7   Miklos Szeredi   overlay filesystem
29
30
31
32
33
34
35
36
37
38
  		err = ovl_do_rmdir(wdir, wdentry);
  	else
  		err = ovl_do_unlink(wdir, wdentry);
  	dput(wdentry);
  
  	if (err) {
  		pr_err("overlayfs: cleanup of '%pd2' failed (%i)
  ",
  		       wdentry, err);
  	}
415543d5c   Amir Goldstein   ovl: cleanup bad ...
39
40
  
  	return err;
e9be9d5e7   Miklos Szeredi   overlay filesystem
41
  }
137ec526a   Amir Goldstein   ovl: create helpe...
42
  static struct dentry *ovl_lookup_temp(struct dentry *workdir)
e9be9d5e7   Miklos Szeredi   overlay filesystem
43
44
45
  {
  	struct dentry *temp;
  	char name[20];
6a45b3628   Richard Weinberger   ovl: Fix info lea...
46
  	static atomic_t temp_id = ATOMIC_INIT(0);
e9be9d5e7   Miklos Szeredi   overlay filesystem
47

6a45b3628   Richard Weinberger   ovl: Fix info lea...
48
49
  	/* counter is allowed to wrap, since temp dentries are ephemeral */
  	snprintf(name, sizeof(name), "#%x", atomic_inc_return(&temp_id));
e9be9d5e7   Miklos Szeredi   overlay filesystem
50
51
52
53
54
55
56
57
58
59
60
61
62
  
  	temp = lookup_one_len(name, workdir, strlen(name));
  	if (!IS_ERR(temp) && temp->d_inode) {
  		pr_err("overlayfs: workdir/%s already exists
  ", name);
  		dput(temp);
  		temp = ERR_PTR(-EIO);
  	}
  
  	return temp;
  }
  
  /* caller holds i_mutex on workdir */
e7dd0e713   Amir Goldstein   ovl: whiteout ind...
63
  static struct dentry *ovl_whiteout(struct dentry *workdir)
e9be9d5e7   Miklos Szeredi   overlay filesystem
64
65
66
67
  {
  	int err;
  	struct dentry *whiteout;
  	struct inode *wdir = workdir->d_inode;
3d27573ce   Miklos Szeredi   ovl: remove unuse...
68
  	whiteout = ovl_lookup_temp(workdir);
e9be9d5e7   Miklos Szeredi   overlay filesystem
69
70
71
72
73
74
75
76
77
78
79
  	if (IS_ERR(whiteout))
  		return whiteout;
  
  	err = ovl_do_whiteout(wdir, whiteout);
  	if (err) {
  		dput(whiteout);
  		whiteout = ERR_PTR(err);
  	}
  
  	return whiteout;
  }
e7dd0e713   Amir Goldstein   ovl: whiteout ind...
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
  /* Caller must hold i_mutex on both workdir and dir */
  int ovl_cleanup_and_whiteout(struct dentry *workdir, struct inode *dir,
  			     struct dentry *dentry)
  {
  	struct inode *wdir = workdir->d_inode;
  	struct dentry *whiteout;
  	int err;
  	int flags = 0;
  
  	whiteout = ovl_whiteout(workdir);
  	err = PTR_ERR(whiteout);
  	if (IS_ERR(whiteout))
  		return err;
  
  	if (d_is_dir(dentry))
  		flags = RENAME_EXCHANGE;
  
  	err = ovl_do_rename(wdir, whiteout, dir, dentry, flags);
  	if (err)
  		goto kill_whiteout;
  	if (flags)
  		ovl_cleanup(wdir, dentry);
  
  out:
  	dput(whiteout);
  	return err;
  
  kill_whiteout:
  	ovl_cleanup(wdir, whiteout);
  	goto out;
  }
f73cc77c3   Al Viro   ovl: make ovl_cre...
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
  static int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry,
  			  umode_t mode)
  {
  	int err;
  	struct dentry *d, *dentry = *newdentry;
  
  	err = ovl_do_mkdir(dir, dentry, mode);
  	if (err)
  		return err;
  
  	if (likely(!d_unhashed(dentry)))
  		return 0;
  
  	/*
  	 * vfs_mkdir() may succeed and leave the dentry passed
  	 * to it unhashed and negative. If that happens, try to
  	 * lookup a new hashed and positive dentry.
  	 */
  	d = lookup_one_len(dentry->d_name.name, dentry->d_parent,
  			   dentry->d_name.len);
  	if (IS_ERR(d)) {
  		pr_warn("overlayfs: failed lookup after mkdir (%pd2, err=%i).
  ",
  			dentry, err);
  		return PTR_ERR(d);
  	}
  	dput(dentry);
  	*newdentry = d;
  
  	return 0;
  }
95a1c8153   Miklos Szeredi   ovl: return dentr...
142
143
  struct dentry *ovl_create_real(struct inode *dir, struct dentry *newdentry,
  			       struct ovl_cattr *attr)
e9be9d5e7   Miklos Szeredi   overlay filesystem
144
145
  {
  	int err;
95a1c8153   Miklos Szeredi   ovl: return dentr...
146
147
148
149
  	if (IS_ERR(newdentry))
  		return newdentry;
  
  	err = -ESTALE;
e9be9d5e7   Miklos Szeredi   overlay filesystem
150
  	if (newdentry->d_inode)
95a1c8153   Miklos Szeredi   ovl: return dentr...
151
  		goto out;
e9be9d5e7   Miklos Szeredi   overlay filesystem
152

471ec5dcf   Amir Goldstein   ovl: struct cattr...
153
154
  	if (attr->hardlink) {
  		err = ovl_do_link(attr->hardlink, dir, newdentry);
e9be9d5e7   Miklos Szeredi   overlay filesystem
155
  	} else {
32a3d848e   Al Viro   ovl: clean up kst...
156
  		switch (attr->mode & S_IFMT) {
e9be9d5e7   Miklos Szeredi   overlay filesystem
157
  		case S_IFREG:
6cf00764b   Amir Goldstein   ovl: strip debug ...
158
  			err = ovl_do_create(dir, newdentry, attr->mode);
e9be9d5e7   Miklos Szeredi   overlay filesystem
159
160
161
  			break;
  
  		case S_IFDIR:
f73cc77c3   Al Viro   ovl: make ovl_cre...
162
163
  			/* mkdir is special... */
  			err =  ovl_mkdir_real(dir, &newdentry, attr->mode);
e9be9d5e7   Miklos Szeredi   overlay filesystem
164
165
166
167
168
169
  			break;
  
  		case S_IFCHR:
  		case S_IFBLK:
  		case S_IFIFO:
  		case S_IFSOCK:
6cf00764b   Amir Goldstein   ovl: strip debug ...
170
171
  			err = ovl_do_mknod(dir, newdentry, attr->mode,
  					   attr->rdev);
e9be9d5e7   Miklos Szeredi   overlay filesystem
172
173
174
  			break;
  
  		case S_IFLNK:
6cf00764b   Amir Goldstein   ovl: strip debug ...
175
  			err = ovl_do_symlink(dir, newdentry, attr->link);
e9be9d5e7   Miklos Szeredi   overlay filesystem
176
177
178
179
180
181
182
183
184
185
186
  			break;
  
  		default:
  			err = -EPERM;
  		}
  	}
  	if (!err && WARN_ON(!newdentry->d_inode)) {
  		/*
  		 * Not quite sure if non-instantiated dentry is legal or not.
  		 * VFS doesn't seem to care so check and warn here.
  		 */
dd8ac699e   Miklos Szeredi   ovl: return EIO o...
187
  		err = -EIO;
e9be9d5e7   Miklos Szeredi   overlay filesystem
188
  	}
95a1c8153   Miklos Szeredi   ovl: return dentr...
189
190
191
192
193
194
  out:
  	if (err) {
  		dput(newdentry);
  		return ERR_PTR(err);
  	}
  	return newdentry;
e9be9d5e7   Miklos Szeredi   overlay filesystem
195
  }
137ec526a   Amir Goldstein   ovl: create helpe...
196
197
198
199
200
  struct dentry *ovl_create_temp(struct dentry *workdir, struct ovl_cattr *attr)
  {
  	return ovl_create_real(d_inode(workdir), ovl_lookup_temp(workdir),
  			       attr);
  }
21a228781   Amir Goldstein   ovl: handle renam...
201
202
  static int ovl_set_opaque_xerr(struct dentry *dentry, struct dentry *upper,
  			       int xerr)
e9be9d5e7   Miklos Szeredi   overlay filesystem
203
  {
5cf5b477f   Miklos Szeredi   ovl: opaque cleanup
204
  	int err;
21a228781   Amir Goldstein   ovl: handle renam...
205
  	err = ovl_check_setxattr(dentry, upper, OVL_XATTR_OPAQUE, "y", 1, xerr);
5cf5b477f   Miklos Szeredi   ovl: opaque cleanup
206
207
208
209
  	if (!err)
  		ovl_dentry_set_opaque(dentry);
  
  	return err;
e9be9d5e7   Miklos Szeredi   overlay filesystem
210
  }
21a228781   Amir Goldstein   ovl: handle renam...
211
212
213
214
215
216
217
218
219
  static int ovl_set_opaque(struct dentry *dentry, struct dentry *upperdentry)
  {
  	/*
  	 * Fail with -EIO when trying to create opaque dir and upper doesn't
  	 * support xattrs. ovl_rename() calls ovl_set_opaque_xerr(-EXDEV) to
  	 * return a specific error for noxattr case.
  	 */
  	return ovl_set_opaque_xerr(dentry, upperdentry, -EIO);
  }
01b39dcc9   Amir Goldstein   ovl: use inode_in...
220
221
222
223
224
225
226
  /*
   * Common operations required to be done after creation of file on upper.
   * If @hardlink is false, then @inode is a pre-allocated inode, we may or
   * may not use to instantiate the new dentry.
   */
  static int ovl_instantiate(struct dentry *dentry, struct inode *inode,
  			   struct dentry *newdentry, bool hardlink)
72e484818   Vivek Goyal   ovl: move some co...
227
  {
01b39dcc9   Amir Goldstein   ovl: use inode_in...
228
229
230
231
  	struct ovl_inode_params oip = {
  		.upperdentry = newdentry,
  		.newinode = inode,
  	};
d9854c87f   Miklos Szeredi   ovl: copy up times
232
  	ovl_dir_modified(dentry->d_parent, false);
55acc6618   Miklos Szeredi   ovl: add flag for...
233
  	ovl_dentry_set_upper_alias(dentry);
51f7e52dc   Miklos Szeredi   ovl: share inode ...
234
  	if (!hardlink) {
01b39dcc9   Amir Goldstein   ovl: use inode_in...
235
236
237
238
239
240
241
242
243
244
245
246
247
  		/*
  		 * ovl_obtain_alias() can be called after ovl_create_real()
  		 * and before we get here, so we may get an inode from cache
  		 * with the same real upperdentry that is not the inode we
  		 * pre-allocated.  In this case we will use the cached inode
  		 * to instantiate the new dentry.
  		 *
  		 * XXX: if we ever use ovl_obtain_alias() to decode directory
  		 * file handles, need to use ovl_get_inode_locked() and
  		 * d_instantiate_new() here to prevent from creating two
  		 * hashed directory inode aliases.
  		 */
  		inode = ovl_get_inode(dentry->d_sb, &oip);
acf3062a7   Amir Goldstein   ovl: relax WARN_O...
248
  		if (IS_ERR(inode))
01b39dcc9   Amir Goldstein   ovl: use inode_in...
249
  			return PTR_ERR(inode);
51f7e52dc   Miklos Szeredi   ovl: share inode ...
250
  	} else {
09d8b5867   Miklos Szeredi   ovl: move __upper...
251
252
  		WARN_ON(ovl_inode_real(inode) != d_inode(newdentry));
  		dput(newdentry);
51f7e52dc   Miklos Szeredi   ovl: share inode ...
253
254
  		inc_nlink(inode);
  	}
01b39dcc9   Amir Goldstein   ovl: use inode_in...
255

72e484818   Vivek Goyal   ovl: move some co...
256
  	d_instantiate(dentry, inode);
01b39dcc9   Amir Goldstein   ovl: use inode_in...
257
258
259
260
261
  	if (inode != oip.newinode) {
  		pr_warn_ratelimited("overlayfs: newly created inode found in cache (%pd2)
  ",
  				    dentry);
  	}
5b6c9053f   Amir Goldstein   ovl: persistent i...
262
263
264
  	/* Force lookup of new upper hardlink to find its lower */
  	if (hardlink)
  		d_drop(dentry);
01b39dcc9   Amir Goldstein   ovl: use inode_in...
265
266
  
  	return 0;
72e484818   Vivek Goyal   ovl: move some co...
267
  }
97c684cc9   Amir Goldstein   ovl: create direc...
268
269
270
271
  static bool ovl_type_merge(struct dentry *dentry)
  {
  	return OVL_TYPE_MERGE(ovl_path_type(dentry));
  }
ee1d6d37b   Amir Goldstein   ovl: mark upper d...
272
273
274
275
  static bool ovl_type_origin(struct dentry *dentry)
  {
  	return OVL_TYPE_ORIGIN(ovl_path_type(dentry));
  }
e9be9d5e7   Miklos Szeredi   overlay filesystem
276
  static int ovl_create_upper(struct dentry *dentry, struct inode *inode,
471ec5dcf   Amir Goldstein   ovl: struct cattr...
277
  			    struct ovl_cattr *attr)
e9be9d5e7   Miklos Szeredi   overlay filesystem
278
279
280
281
282
  {
  	struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent);
  	struct inode *udir = upperdir->d_inode;
  	struct dentry *newdentry;
  	int err;
471ec5dcf   Amir Goldstein   ovl: struct cattr...
283
  	if (!attr->hardlink && !IS_POSIXACL(udir))
32a3d848e   Al Viro   ovl: clean up kst...
284
  		attr->mode &= ~current_umask();
38b256973   Miklos Szeredi   ovl: handle umask...
285

5955102c9   Al Viro   wrappers for ->i_...
286
  	inode_lock_nested(udir, I_MUTEX_PARENT);
95a1c8153   Miklos Szeredi   ovl: return dentr...
287
288
289
290
291
  	newdentry = ovl_create_real(udir,
  				    lookup_one_len(dentry->d_name.name,
  						   upperdir,
  						   dentry->d_name.len),
  				    attr);
e9be9d5e7   Miklos Szeredi   overlay filesystem
292
293
294
  	err = PTR_ERR(newdentry);
  	if (IS_ERR(newdentry))
  		goto out_unlock;
e9be9d5e7   Miklos Szeredi   overlay filesystem
295

4a99f3c83   Amir Goldstein   ovl: do not set o...
296
  	if (ovl_type_merge(dentry->d_parent) && d_is_dir(newdentry)) {
97c684cc9   Amir Goldstein   ovl: create direc...
297
298
299
  		/* Setting opaque here is just an optimization, allow to fail */
  		ovl_set_opaque(dentry, newdentry);
  	}
01b39dcc9   Amir Goldstein   ovl: use inode_in...
300
301
302
  	err = ovl_instantiate(dentry, inode, newdentry, !!attr->hardlink);
  	if (err)
  		goto out_cleanup;
e9be9d5e7   Miklos Szeredi   overlay filesystem
303
  out_unlock:
5955102c9   Al Viro   wrappers for ->i_...
304
  	inode_unlock(udir);
e9be9d5e7   Miklos Szeredi   overlay filesystem
305
  	return err;
01b39dcc9   Amir Goldstein   ovl: use inode_in...
306
307
308
309
310
  
  out_cleanup:
  	ovl_cleanup(udir, newdentry);
  	dput(newdentry);
  	goto out_unlock;
e9be9d5e7   Miklos Szeredi   overlay filesystem
311
  }
e9be9d5e7   Miklos Szeredi   overlay filesystem
312
313
314
315
316
317
318
319
320
321
322
323
  static struct dentry *ovl_clear_empty(struct dentry *dentry,
  				      struct list_head *list)
  {
  	struct dentry *workdir = ovl_workdir(dentry);
  	struct inode *wdir = workdir->d_inode;
  	struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent);
  	struct inode *udir = upperdir->d_inode;
  	struct path upperpath;
  	struct dentry *upper;
  	struct dentry *opaquedir;
  	struct kstat stat;
  	int err;
cc6f67bca   Miklos Szeredi   ovl: mount read-o...
324
325
  	if (WARN_ON(!workdir))
  		return ERR_PTR(-EROFS);
e9be9d5e7   Miklos Szeredi   overlay filesystem
326
327
328
329
330
  	err = ovl_lock_rename_workdir(workdir, upperdir);
  	if (err)
  		goto out;
  
  	ovl_path_upper(dentry, &upperpath);
a528d35e8   David Howells   statx: Add a syst...
331
332
  	err = vfs_getattr(&upperpath, &stat,
  			  STATX_BASIC_STATS, AT_STATX_SYNC_AS_STAT);
e9be9d5e7   Miklos Szeredi   overlay filesystem
333
334
335
336
337
338
339
340
341
  	if (err)
  		goto out_unlock;
  
  	err = -ESTALE;
  	if (!S_ISDIR(stat.mode))
  		goto out_unlock;
  	upper = upperpath.dentry;
  	if (upper->d_parent->d_inode != udir)
  		goto out_unlock;
137ec526a   Amir Goldstein   ovl: create helpe...
342
  	opaquedir = ovl_create_temp(workdir, OVL_CATTR(stat.mode));
e9be9d5e7   Miklos Szeredi   overlay filesystem
343
344
345
  	err = PTR_ERR(opaquedir);
  	if (IS_ERR(opaquedir))
  		goto out_unlock;
e9be9d5e7   Miklos Szeredi   overlay filesystem
346
347
348
  	err = ovl_copy_xattr(upper, opaquedir);
  	if (err)
  		goto out_cleanup;
5cf5b477f   Miklos Szeredi   ovl: opaque cleanup
349
  	err = ovl_set_opaque(dentry, opaquedir);
e9be9d5e7   Miklos Szeredi   overlay filesystem
350
351
  	if (err)
  		goto out_cleanup;
5955102c9   Al Viro   wrappers for ->i_...
352
  	inode_lock(opaquedir->d_inode);
e9be9d5e7   Miklos Szeredi   overlay filesystem
353
  	err = ovl_set_attr(opaquedir, &stat);
5955102c9   Al Viro   wrappers for ->i_...
354
  	inode_unlock(opaquedir->d_inode);
e9be9d5e7   Miklos Szeredi   overlay filesystem
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
  	if (err)
  		goto out_cleanup;
  
  	err = ovl_do_rename(wdir, opaquedir, udir, upper, RENAME_EXCHANGE);
  	if (err)
  		goto out_cleanup;
  
  	ovl_cleanup_whiteouts(upper, list);
  	ovl_cleanup(wdir, upper);
  	unlock_rename(workdir, upperdir);
  
  	/* dentry's upper doesn't match now, get rid of it */
  	d_drop(dentry);
  
  	return opaquedir;
  
  out_cleanup:
  	ovl_cleanup(wdir, opaquedir);
e9be9d5e7   Miklos Szeredi   overlay filesystem
373
374
375
376
377
378
  	dput(opaquedir);
  out_unlock:
  	unlock_rename(workdir, upperdir);
  out:
  	return ERR_PTR(err);
  }
38b256973   Miklos Szeredi   ovl: handle umask...
379
380
381
382
383
384
385
386
387
  static int ovl_set_upper_acl(struct dentry *upperdentry, const char *name,
  			     const struct posix_acl *acl)
  {
  	void *buffer;
  	size_t size;
  	int err;
  
  	if (!IS_ENABLED(CONFIG_FS_POSIX_ACL) || !acl)
  		return 0;
14fa08564   Chengguang Xu   ovl: using posix_...
388
  	size = posix_acl_xattr_size(acl->a_count);
38b256973   Miklos Szeredi   ovl: handle umask...
389
390
391
  	buffer = kmalloc(size, GFP_KERNEL);
  	if (!buffer)
  		return -ENOMEM;
14fa08564   Chengguang Xu   ovl: using posix_...
392
  	err = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
38b256973   Miklos Szeredi   ovl: handle umask...
393
394
395
396
397
398
399
400
  	if (err < 0)
  		goto out_free;
  
  	err = vfs_setxattr(upperdentry, name, buffer, size, XATTR_CREATE);
  out_free:
  	kfree(buffer);
  	return err;
  }
e9be9d5e7   Miklos Szeredi   overlay filesystem
401
  static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
471ec5dcf   Amir Goldstein   ovl: struct cattr...
402
  				    struct ovl_cattr *cattr)
e9be9d5e7   Miklos Szeredi   overlay filesystem
403
404
405
406
407
408
409
410
  {
  	struct dentry *workdir = ovl_workdir(dentry);
  	struct inode *wdir = workdir->d_inode;
  	struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent);
  	struct inode *udir = upperdir->d_inode;
  	struct dentry *upper;
  	struct dentry *newdentry;
  	int err;
38b256973   Miklos Szeredi   ovl: handle umask...
411
  	struct posix_acl *acl, *default_acl;
471ec5dcf   Amir Goldstein   ovl: struct cattr...
412
  	bool hardlink = !!cattr->hardlink;
e9be9d5e7   Miklos Szeredi   overlay filesystem
413

cc6f67bca   Miklos Szeredi   ovl: mount read-o...
414
415
  	if (WARN_ON(!workdir))
  		return -EROFS;
38b256973   Miklos Szeredi   ovl: handle umask...
416
417
  	if (!hardlink) {
  		err = posix_acl_create(dentry->d_parent->d_inode,
32a3d848e   Al Viro   ovl: clean up kst...
418
  				       &cattr->mode, &default_acl, &acl);
38b256973   Miklos Szeredi   ovl: handle umask...
419
420
421
  		if (err)
  			return err;
  	}
e9be9d5e7   Miklos Szeredi   overlay filesystem
422
423
424
  	err = ovl_lock_rename_workdir(workdir, upperdir);
  	if (err)
  		goto out;
e9be9d5e7   Miklos Szeredi   overlay filesystem
425
426
427
428
  	upper = lookup_one_len(dentry->d_name.name, upperdir,
  			       dentry->d_name.len);
  	err = PTR_ERR(upper);
  	if (IS_ERR(upper))
95a1c8153   Miklos Szeredi   ovl: return dentr...
429
  		goto out_unlock;
e9be9d5e7   Miklos Szeredi   overlay filesystem
430

5e1275808   Miklos Szeredi   ovl: check whiteo...
431
432
433
  	err = -ESTALE;
  	if (d_is_negative(upper) || !IS_WHITEOUT(d_inode(upper)))
  		goto out_dput;
137ec526a   Amir Goldstein   ovl: create helpe...
434
  	newdentry = ovl_create_temp(workdir, cattr);
95a1c8153   Miklos Szeredi   ovl: return dentr...
435
436
437
  	err = PTR_ERR(newdentry);
  	if (IS_ERR(newdentry))
  		goto out_dput;
e9be9d5e7   Miklos Szeredi   overlay filesystem
438

bb0d2b8ad   Miklos Szeredi   ovl: fix sgid on ...
439
440
441
  	/*
  	 * mode could have been mutilated due to umask (e.g. sgid directory)
  	 */
51f7e52dc   Miklos Szeredi   ovl: share inode ...
442
  	if (!hardlink &&
32a3d848e   Al Viro   ovl: clean up kst...
443
444
  	    !S_ISLNK(cattr->mode) &&
  	    newdentry->d_inode->i_mode != cattr->mode) {
bb0d2b8ad   Miklos Szeredi   ovl: fix sgid on ...
445
446
  		struct iattr attr = {
  			.ia_valid = ATTR_MODE,
32a3d848e   Al Viro   ovl: clean up kst...
447
  			.ia_mode = cattr->mode,
bb0d2b8ad   Miklos Szeredi   ovl: fix sgid on ...
448
449
450
451
452
453
454
  		};
  		inode_lock(newdentry->d_inode);
  		err = notify_change(newdentry, &attr, NULL);
  		inode_unlock(newdentry->d_inode);
  		if (err)
  			goto out_cleanup;
  	}
38b256973   Miklos Szeredi   ovl: handle umask...
455
456
457
458
459
460
461
462
463
464
465
  	if (!hardlink) {
  		err = ovl_set_upper_acl(newdentry, XATTR_NAME_POSIX_ACL_ACCESS,
  					acl);
  		if (err)
  			goto out_cleanup;
  
  		err = ovl_set_upper_acl(newdentry, XATTR_NAME_POSIX_ACL_DEFAULT,
  					default_acl);
  		if (err)
  			goto out_cleanup;
  	}
bb0d2b8ad   Miklos Szeredi   ovl: fix sgid on ...
466

32a3d848e   Al Viro   ovl: clean up kst...
467
  	if (!hardlink && S_ISDIR(cattr->mode)) {
5cf5b477f   Miklos Szeredi   ovl: opaque cleanup
468
  		err = ovl_set_opaque(dentry, newdentry);
e9be9d5e7   Miklos Szeredi   overlay filesystem
469
470
471
472
473
474
475
476
477
478
479
480
481
482
  		if (err)
  			goto out_cleanup;
  
  		err = ovl_do_rename(wdir, newdentry, udir, upper,
  				    RENAME_EXCHANGE);
  		if (err)
  			goto out_cleanup;
  
  		ovl_cleanup(wdir, upper);
  	} else {
  		err = ovl_do_rename(wdir, newdentry, udir, upper, 0);
  		if (err)
  			goto out_cleanup;
  	}
01b39dcc9   Amir Goldstein   ovl: use inode_in...
483
484
485
  	err = ovl_instantiate(dentry, inode, newdentry, hardlink);
  	if (err)
  		goto out_cleanup;
e9be9d5e7   Miklos Szeredi   overlay filesystem
486
  out_dput:
95a1c8153   Miklos Szeredi   ovl: return dentr...
487
  	dput(upper);
e9be9d5e7   Miklos Szeredi   overlay filesystem
488
489
490
  out_unlock:
  	unlock_rename(workdir, upperdir);
  out:
38b256973   Miklos Szeredi   ovl: handle umask...
491
492
493
494
  	if (!hardlink) {
  		posix_acl_release(acl);
  		posix_acl_release(default_acl);
  	}
e9be9d5e7   Miklos Szeredi   overlay filesystem
495
496
497
498
  	return err;
  
  out_cleanup:
  	ovl_cleanup(wdir, newdentry);
95a1c8153   Miklos Szeredi   ovl: return dentr...
499
500
  	dput(newdentry);
  	goto out_dput;
e9be9d5e7   Miklos Szeredi   overlay filesystem
501
  }
51f7e52dc   Miklos Szeredi   ovl: share inode ...
502
  static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
471ec5dcf   Amir Goldstein   ovl: struct cattr...
503
  			      struct ovl_cattr *attr, bool origin)
e9be9d5e7   Miklos Szeredi   overlay filesystem
504
505
  {
  	int err;
1175b6b8d   Vivek Goyal   ovl: do operation...
506
507
  	const struct cred *old_cred;
  	struct cred *override_cred;
ea3dad18d   Amir Goldstein   ovl: mark parent ...
508
  	struct dentry *parent = dentry->d_parent;
e9be9d5e7   Miklos Szeredi   overlay filesystem
509

ea3dad18d   Amir Goldstein   ovl: mark parent ...
510
  	err = ovl_copy_up(parent);
e9be9d5e7   Miklos Szeredi   overlay filesystem
511
  	if (err)
51f7e52dc   Miklos Szeredi   ovl: share inode ...
512
  		return err;
bb0d2b8ad   Miklos Szeredi   ovl: fix sgid on ...
513

1175b6b8d   Vivek Goyal   ovl: do operation...
514
  	old_cred = ovl_override_creds(dentry->d_sb);
ea3dad18d   Amir Goldstein   ovl: mark parent ...
515
516
517
518
519
520
521
522
523
524
  
  	/*
  	 * When linking a file with copy up origin into a new parent, mark the
  	 * new parent dir "impure".
  	 */
  	if (origin) {
  		err = ovl_set_impure(parent, ovl_dentry_upper(parent));
  		if (err)
  			goto out_revert_creds;
  	}
1175b6b8d   Vivek Goyal   ovl: do operation...
525
526
527
  	err = -ENOMEM;
  	override_cred = prepare_creds();
  	if (override_cred) {
bb0d2b8ad   Miklos Szeredi   ovl: fix sgid on ...
528
529
  		override_cred->fsuid = inode->i_uid;
  		override_cred->fsgid = inode->i_gid;
471ec5dcf   Amir Goldstein   ovl: struct cattr...
530
  		if (!attr->hardlink) {
2602625b7   Vivek Goyal   security, overlay...
531
  			err = security_dentry_create_files_as(dentry,
32a3d848e   Al Viro   ovl: clean up kst...
532
  					attr->mode, &dentry->d_name, old_cred,
2602625b7   Vivek Goyal   security, overlay...
533
534
535
536
537
538
  					override_cred);
  			if (err) {
  				put_cred(override_cred);
  				goto out_revert_creds;
  			}
  		}
1175b6b8d   Vivek Goyal   ovl: do operation...
539
540
  		put_cred(override_creds(override_cred));
  		put_cred(override_cred);
c412ce498   Miklos Szeredi   ovl: add ovl_dent...
541
  		if (!ovl_dentry_is_whiteout(dentry))
471ec5dcf   Amir Goldstein   ovl: struct cattr...
542
  			err = ovl_create_upper(dentry, inode, attr);
1175b6b8d   Vivek Goyal   ovl: do operation...
543
  		else
471ec5dcf   Amir Goldstein   ovl: struct cattr...
544
  			err = ovl_create_over_whiteout(dentry, inode, attr);
e9be9d5e7   Miklos Szeredi   overlay filesystem
545
  	}
2602625b7   Vivek Goyal   security, overlay...
546
  out_revert_creds:
1175b6b8d   Vivek Goyal   ovl: do operation...
547
  	revert_creds(old_cred);
e9be9d5e7   Miklos Szeredi   overlay filesystem
548
549
550
551
552
553
554
  	return err;
  }
  
  static int ovl_create_object(struct dentry *dentry, int mode, dev_t rdev,
  			     const char *link)
  {
  	int err;
51f7e52dc   Miklos Szeredi   ovl: share inode ...
555
  	struct inode *inode;
471ec5dcf   Amir Goldstein   ovl: struct cattr...
556
  	struct ovl_cattr attr = {
51f7e52dc   Miklos Szeredi   ovl: share inode ...
557
  		.rdev = rdev,
32a3d848e   Al Viro   ovl: clean up kst...
558
  		.link = link,
51f7e52dc   Miklos Szeredi   ovl: share inode ...
559
  	};
e9be9d5e7   Miklos Szeredi   overlay filesystem
560
561
  
  	err = ovl_want_write(dentry);
51f7e52dc   Miklos Szeredi   ovl: share inode ...
562
563
  	if (err)
  		goto out;
01b39dcc9   Amir Goldstein   ovl: use inode_in...
564
  	/* Preallocate inode to be used by ovl_get_inode() */
51f7e52dc   Miklos Szeredi   ovl: share inode ...
565
  	err = -ENOMEM;
ca4c8a3a8   Miklos Szeredi   ovl: treat specia...
566
  	inode = ovl_new_inode(dentry->d_sb, mode, rdev);
51f7e52dc   Miklos Szeredi   ovl: share inode ...
567
568
  	if (!inode)
  		goto out_drop_write;
6faf05c2b   Miklos Szeredi   ovl: set I_CREATI...
569
570
571
  	spin_lock(&inode->i_lock);
  	inode->i_state |= I_CREATING;
  	spin_unlock(&inode->i_lock);
51f7e52dc   Miklos Szeredi   ovl: share inode ...
572
  	inode_init_owner(inode, dentry->d_parent->d_inode, mode);
32a3d848e   Al Viro   ovl: clean up kst...
573
  	attr.mode = inode->i_mode;
51f7e52dc   Miklos Szeredi   ovl: share inode ...
574

471ec5dcf   Amir Goldstein   ovl: struct cattr...
575
  	err = ovl_create_or_link(dentry, inode, &attr, false);
01b39dcc9   Amir Goldstein   ovl: use inode_in...
576
577
  	/* Did we end up using the preallocated inode? */
  	if (inode != d_inode(dentry))
51f7e52dc   Miklos Szeredi   ovl: share inode ...
578
  		iput(inode);
e9be9d5e7   Miklos Szeredi   overlay filesystem
579

51f7e52dc   Miklos Szeredi   ovl: share inode ...
580
581
582
  out_drop_write:
  	ovl_drop_write(dentry);
  out:
e9be9d5e7   Miklos Szeredi   overlay filesystem
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
  	return err;
  }
  
  static int ovl_create(struct inode *dir, struct dentry *dentry, umode_t mode,
  		      bool excl)
  {
  	return ovl_create_object(dentry, (mode & 07777) | S_IFREG, 0, NULL);
  }
  
  static int ovl_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
  {
  	return ovl_create_object(dentry, (mode & 07777) | S_IFDIR, 0, NULL);
  }
  
  static int ovl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
  		     dev_t rdev)
  {
  	/* Don't allow creation of "whiteout" on overlay */
  	if (S_ISCHR(mode) && rdev == WHITEOUT_DEV)
  		return -EPERM;
  
  	return ovl_create_object(dentry, mode, rdev, NULL);
  }
  
  static int ovl_symlink(struct inode *dir, struct dentry *dentry,
  		       const char *link)
  {
  	return ovl_create_object(dentry, S_IFLNK, 0, link);
  }
91ff20f34   Amir Goldstein   ovl: fix missing ...
612
613
614
615
616
617
618
619
620
621
622
  static int ovl_set_link_redirect(struct dentry *dentry)
  {
  	const struct cred *old_cred;
  	int err;
  
  	old_cred = ovl_override_creds(dentry->d_sb);
  	err = ovl_set_redirect(dentry, false);
  	revert_creds(old_cred);
  
  	return err;
  }
e9be9d5e7   Miklos Szeredi   overlay filesystem
623
624
625
626
  static int ovl_link(struct dentry *old, struct inode *newdir,
  		    struct dentry *new)
  {
  	int err;
51f7e52dc   Miklos Szeredi   ovl: share inode ...
627
  	struct inode *inode;
e9be9d5e7   Miklos Szeredi   overlay filesystem
628
629
630
631
632
633
634
635
  
  	err = ovl_want_write(old);
  	if (err)
  		goto out;
  
  	err = ovl_copy_up(old);
  	if (err)
  		goto out_drop_write;
6cd078702   Amir Goldstein   ovl: fix recursiv...
636
637
638
  	err = ovl_copy_up(new->d_parent);
  	if (err)
  		goto out_drop_write;
4120fe64d   Vivek Goyal   ovl: Set redirect...
639
  	if (ovl_is_metacopy_dentry(old)) {
91ff20f34   Amir Goldstein   ovl: fix missing ...
640
  		err = ovl_set_link_redirect(old);
4120fe64d   Vivek Goyal   ovl: Set redirect...
641
642
643
  		if (err)
  			goto out_drop_write;
  	}
0e32992f7   Amir Goldstein   ovl: remove the '...
644
  	err = ovl_nlink_start(old);
5f8415d6b   Amir Goldstein   ovl: persistent o...
645
646
  	if (err)
  		goto out_drop_write;
51f7e52dc   Miklos Szeredi   ovl: share inode ...
647
648
  	inode = d_inode(old);
  	ihold(inode);
471ec5dcf   Amir Goldstein   ovl: struct cattr...
649
650
651
  	err = ovl_create_or_link(new, inode,
  			&(struct ovl_cattr) {.hardlink = ovl_dentry_upper(old)},
  			ovl_type_origin(old));
51f7e52dc   Miklos Szeredi   ovl: share inode ...
652
653
  	if (err)
  		iput(inode);
e9be9d5e7   Miklos Szeredi   overlay filesystem
654

0e32992f7   Amir Goldstein   ovl: remove the '...
655
  	ovl_nlink_end(old);
e9be9d5e7   Miklos Szeredi   overlay filesystem
656
657
658
659
660
  out_drop_write:
  	ovl_drop_write(old);
  out:
  	return err;
  }
9020df372   Miklos Szeredi   ovl: compare inodes
661
662
663
664
  static bool ovl_matches_upper(struct dentry *dentry, struct dentry *upper)
  {
  	return d_inode(ovl_dentry_upper(dentry)) == d_inode(upper);
  }
6d0a8a90a   Amir Goldstein   ovl: take lower d...
665
666
  static int ovl_remove_and_whiteout(struct dentry *dentry,
  				   struct list_head *list)
e9be9d5e7   Miklos Szeredi   overlay filesystem
667
668
  {
  	struct dentry *workdir = ovl_workdir(dentry);
e9be9d5e7   Miklos Szeredi   overlay filesystem
669
  	struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent);
e9be9d5e7   Miklos Szeredi   overlay filesystem
670
671
672
  	struct dentry *upper;
  	struct dentry *opaquedir = NULL;
  	int err;
cc6f67bca   Miklos Szeredi   ovl: mount read-o...
673
674
  	if (WARN_ON(!workdir))
  		return -EROFS;
6d0a8a90a   Amir Goldstein   ovl: take lower d...
675
676
  	if (!list_empty(list)) {
  		opaquedir = ovl_clear_empty(dentry, list);
30c17ebfb   Miklos Szeredi   ovl: simplify emp...
677
678
679
  		err = PTR_ERR(opaquedir);
  		if (IS_ERR(opaquedir))
  			goto out;
e9be9d5e7   Miklos Szeredi   overlay filesystem
680
681
682
683
684
  	}
  
  	err = ovl_lock_rename_workdir(workdir, upperdir);
  	if (err)
  		goto out_dput;
cfc9fde0b   Maxim Patlasov   ovl: verify upper...
685
686
687
688
  	upper = lookup_one_len(dentry->d_name.name, upperdir,
  			       dentry->d_name.len);
  	err = PTR_ERR(upper);
  	if (IS_ERR(upper))
e9be9d5e7   Miklos Szeredi   overlay filesystem
689
  		goto out_unlock;
cfc9fde0b   Maxim Patlasov   ovl: verify upper...
690
691
692
  	err = -ESTALE;
  	if ((opaquedir && upper != opaquedir) ||
  	    (!opaquedir && ovl_dentry_upper(dentry) &&
9020df372   Miklos Szeredi   ovl: compare inodes
693
  	     !ovl_matches_upper(dentry, upper))) {
cfc9fde0b   Maxim Patlasov   ovl: verify upper...
694
695
  		goto out_dput_upper;
  	}
e9be9d5e7   Miklos Szeredi   overlay filesystem
696

e7dd0e713   Amir Goldstein   ovl: whiteout ind...
697
  	err = ovl_cleanup_and_whiteout(workdir, d_inode(upperdir), upper);
cfc9fde0b   Maxim Patlasov   ovl: verify upper...
698
  	if (err)
e7dd0e713   Amir Goldstein   ovl: whiteout ind...
699
  		goto out_d_drop;
e9be9d5e7   Miklos Szeredi   overlay filesystem
700

d9854c87f   Miklos Szeredi   ovl: copy up times
701
  	ovl_dir_modified(dentry->d_parent, true);
e9be9d5e7   Miklos Szeredi   overlay filesystem
702
703
  out_d_drop:
  	d_drop(dentry);
cfc9fde0b   Maxim Patlasov   ovl: verify upper...
704
705
  out_dput_upper:
  	dput(upper);
e9be9d5e7   Miklos Szeredi   overlay filesystem
706
707
708
709
710
711
  out_unlock:
  	unlock_rename(workdir, upperdir);
  out_dput:
  	dput(opaquedir);
  out:
  	return err;
e9be9d5e7   Miklos Szeredi   overlay filesystem
712
  }
6d0a8a90a   Amir Goldstein   ovl: take lower d...
713
714
  static int ovl_remove_upper(struct dentry *dentry, bool is_dir,
  			    struct list_head *list)
e9be9d5e7   Miklos Szeredi   overlay filesystem
715
716
717
  {
  	struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent);
  	struct inode *dir = upperdir->d_inode;
11f371041   Miklos Szeredi   ovl: verify upper...
718
  	struct dentry *upper;
d15951198   Amir Goldstein   ovl: check for em...
719
  	struct dentry *opaquedir = NULL;
e9be9d5e7   Miklos Szeredi   overlay filesystem
720
  	int err;
6d0a8a90a   Amir Goldstein   ovl: take lower d...
721
722
  	if (!list_empty(list)) {
  		opaquedir = ovl_clear_empty(dentry, list);
d15951198   Amir Goldstein   ovl: check for em...
723
724
725
726
  		err = PTR_ERR(opaquedir);
  		if (IS_ERR(opaquedir))
  			goto out;
  	}
5955102c9   Al Viro   wrappers for ->i_...
727
  	inode_lock_nested(dir, I_MUTEX_PARENT);
11f371041   Miklos Szeredi   ovl: verify upper...
728
729
730
731
732
  	upper = lookup_one_len(dentry->d_name.name, upperdir,
  			       dentry->d_name.len);
  	err = PTR_ERR(upper);
  	if (IS_ERR(upper))
  		goto out_unlock;
e9be9d5e7   Miklos Szeredi   overlay filesystem
733
  	err = -ESTALE;
d15951198   Amir Goldstein   ovl: check for em...
734
  	if ((opaquedir && upper != opaquedir) ||
9020df372   Miklos Szeredi   ovl: compare inodes
735
  	    (!opaquedir && !ovl_matches_upper(dentry, upper)))
d15951198   Amir Goldstein   ovl: check for em...
736
737
738
739
740
741
  		goto out_dput_upper;
  
  	if (is_dir)
  		err = vfs_rmdir(dir, upper);
  	else
  		err = vfs_unlink(dir, upper, NULL);
d9854c87f   Miklos Szeredi   ovl: copy up times
742
  	ovl_dir_modified(dentry->d_parent, ovl_type_origin(dentry));
e9be9d5e7   Miklos Szeredi   overlay filesystem
743
744
745
746
747
748
749
  
  	/*
  	 * Keeping this dentry hashed would mean having to release
  	 * upperpath/lowerpath, which could only be done if we are the
  	 * sole user of this dentry.  Too tricky...  Just unhash for
  	 * now.
  	 */
ce9113bbc   Rui Wang   ovl: fix getcwd()...
750
751
  	if (!err)
  		d_drop(dentry);
d15951198   Amir Goldstein   ovl: check for em...
752
753
  out_dput_upper:
  	dput(upper);
11f371041   Miklos Szeredi   ovl: verify upper...
754
  out_unlock:
5955102c9   Al Viro   wrappers for ->i_...
755
  	inode_unlock(dir);
d15951198   Amir Goldstein   ovl: check for em...
756
757
  	dput(opaquedir);
  out:
e9be9d5e7   Miklos Szeredi   overlay filesystem
758
759
  	return err;
  }
6d0a8a90a   Amir Goldstein   ovl: take lower d...
760
761
762
763
764
  static bool ovl_pure_upper(struct dentry *dentry)
  {
  	return !ovl_dentry_lower(dentry) &&
  	       !ovl_test_flag(OVL_WHITEOUTS, d_inode(dentry));
  }
e9be9d5e7   Miklos Szeredi   overlay filesystem
765
766
  static int ovl_do_remove(struct dentry *dentry, bool is_dir)
  {
e9be9d5e7   Miklos Szeredi   overlay filesystem
767
  	int err;
1175b6b8d   Vivek Goyal   ovl: do operation...
768
  	const struct cred *old_cred;
d9854c87f   Miklos Szeredi   ovl: copy up times
769
  	struct dentry *upperdentry;
6d0a8a90a   Amir Goldstein   ovl: take lower d...
770
771
772
773
774
775
776
777
778
  	bool lower_positive = ovl_lower_positive(dentry);
  	LIST_HEAD(list);
  
  	/* No need to clean pure upper removed by vfs_rmdir() */
  	if (is_dir && (lower_positive || !ovl_pure_upper(dentry))) {
  		err = ovl_check_empty_dir(dentry, &list);
  		if (err)
  			goto out;
  	}
1175b6b8d   Vivek Goyal   ovl: do operation...
779

e9be9d5e7   Miklos Szeredi   overlay filesystem
780
781
782
783
784
785
786
  	err = ovl_want_write(dentry);
  	if (err)
  		goto out;
  
  	err = ovl_copy_up(dentry->d_parent);
  	if (err)
  		goto out_drop_write;
0e32992f7   Amir Goldstein   ovl: remove the '...
787
  	err = ovl_nlink_start(dentry);
5f8415d6b   Amir Goldstein   ovl: persistent o...
788
789
  	if (err)
  		goto out_drop_write;
e9be9d5e7   Miklos Szeredi   overlay filesystem
790

1175b6b8d   Vivek Goyal   ovl: do operation...
791
  	old_cred = ovl_override_creds(dentry->d_sb);
6d0a8a90a   Amir Goldstein   ovl: take lower d...
792
793
  	if (!lower_positive)
  		err = ovl_remove_upper(dentry, is_dir, &list);
1175b6b8d   Vivek Goyal   ovl: do operation...
794
  	else
6d0a8a90a   Amir Goldstein   ovl: take lower d...
795
  		err = ovl_remove_and_whiteout(dentry, &list);
1175b6b8d   Vivek Goyal   ovl: do operation...
796
  	revert_creds(old_cred);
dbc816d05   Miklos Szeredi   ovl: clear nlink ...
797
798
799
800
801
802
  	if (!err) {
  		if (is_dir)
  			clear_nlink(dentry->d_inode);
  		else
  			drop_nlink(dentry->d_inode);
  	}
0e32992f7   Amir Goldstein   ovl: remove the '...
803
  	ovl_nlink_end(dentry);
d9854c87f   Miklos Szeredi   ovl: copy up times
804
805
806
807
808
809
810
811
812
813
  
  	/*
  	 * Copy ctime
  	 *
  	 * Note: we fail to update ctime if there was no copy-up, only a
  	 * whiteout
  	 */
  	upperdentry = ovl_dentry_upper(dentry);
  	if (upperdentry)
  		ovl_copyattr(d_inode(upperdentry), d_inode(dentry));
e9be9d5e7   Miklos Szeredi   overlay filesystem
814
815
816
  out_drop_write:
  	ovl_drop_write(dentry);
  out:
6d0a8a90a   Amir Goldstein   ovl: take lower d...
817
  	ovl_cache_free(&list);
e9be9d5e7   Miklos Szeredi   overlay filesystem
818
819
820
821
822
823
824
825
826
827
828
829
  	return err;
  }
  
  static int ovl_unlink(struct inode *dir, struct dentry *dentry)
  {
  	return ovl_do_remove(dentry, false);
  }
  
  static int ovl_rmdir(struct inode *dir, struct dentry *dentry)
  {
  	return ovl_do_remove(dentry, true);
  }
370e55ace   Miklos Szeredi   ovl: rename: simp...
830
831
832
833
834
835
  static bool ovl_type_merge_or_lower(struct dentry *dentry)
  {
  	enum ovl_path_type type = ovl_path_type(dentry);
  
  	return OVL_TYPE_MERGE(type) || !OVL_TYPE_UPPER(type);
  }
a6c606551   Miklos Szeredi   ovl: redirect on ...
836
837
838
839
840
  static bool ovl_can_move(struct dentry *dentry)
  {
  	return ovl_redirect_dir(dentry->d_sb) ||
  		!d_is_dir(dentry) || !ovl_type_merge_or_lower(dentry);
  }
7bb083837   Vivek Goyal   ovl: Set redirect...
841
  static char *ovl_get_redirect(struct dentry *dentry, bool abs_redirect)
a6c606551   Miklos Szeredi   ovl: redirect on ...
842
843
844
  {
  	char *buf, *ret;
  	struct dentry *d, *tmp;
3ea22a71b   Miklos Szeredi   ovl: allow settin...
845
  	int buflen = ovl_redirect_max + 1;
a6c606551   Miklos Szeredi   ovl: redirect on ...
846

7bb083837   Vivek Goyal   ovl: Set redirect...
847
  	if (!abs_redirect) {
a6c606551   Miklos Szeredi   ovl: redirect on ...
848
849
850
851
  		ret = kstrndup(dentry->d_name.name, dentry->d_name.len,
  			       GFP_KERNEL);
  		goto out;
  	}
0ee931c4e   Michal Hocko   mm: treewide: rem...
852
  	buf = ret = kmalloc(buflen, GFP_KERNEL);
a6c606551   Miklos Szeredi   ovl: redirect on ...
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
  	if (!buf)
  		goto out;
  
  	buflen--;
  	buf[buflen] = '\0';
  	for (d = dget(dentry); !IS_ROOT(d);) {
  		const char *name;
  		int thislen;
  
  		spin_lock(&d->d_lock);
  		name = ovl_dentry_get_redirect(d);
  		if (name) {
  			thislen = strlen(name);
  		} else {
  			name = d->d_name.name;
  			thislen = d->d_name.len;
  		}
  
  		/* If path is too long, fall back to userspace move */
  		if (thislen + (name[0] != '/') > buflen) {
  			ret = ERR_PTR(-EXDEV);
  			spin_unlock(&d->d_lock);
  			goto out_put;
  		}
  
  		buflen -= thislen;
  		memcpy(&buf[buflen], name, thislen);
  		tmp = dget_dlock(d->d_parent);
  		spin_unlock(&d->d_lock);
  
  		dput(d);
  		d = tmp;
  
  		/* Absolute redirect: finished */
  		if (buf[buflen] == '/')
  			break;
  		buflen--;
  		buf[buflen] = '/';
  	}
  	ret = kstrdup(&buf[buflen], GFP_KERNEL);
  out_put:
  	dput(d);
  	kfree(buf);
  out:
  	return ret ? ret : ERR_PTR(-ENOMEM);
  }
7bb083837   Vivek Goyal   ovl: Set redirect...
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
  static bool ovl_need_absolute_redirect(struct dentry *dentry, bool samedir)
  {
  	struct dentry *lowerdentry;
  
  	if (!samedir)
  		return true;
  
  	if (d_is_dir(dentry))
  		return false;
  
  	/*
  	 * For non-dir hardlinked files, we need absolute redirects
  	 * in general as two upper hardlinks could be in different
  	 * dirs. We could put a relative redirect now and convert
  	 * it to absolute redirect later. But when nlink > 1 and
  	 * indexing is on, that means relative redirect needs to be
  	 * converted to absolute during copy up of another lower
  	 * hardllink as well.
  	 *
  	 * So without optimizing too much, just check if lower is
  	 * a hard link or not. If lower is hard link, put absolute
  	 * redirect.
  	 */
  	lowerdentry = ovl_dentry_lower(dentry);
  	return (d_inode(lowerdentry)->i_nlink > 1);
  }
a6c606551   Miklos Szeredi   ovl: redirect on ...
925
926
927
928
  static int ovl_set_redirect(struct dentry *dentry, bool samedir)
  {
  	int err;
  	const char *redirect = ovl_dentry_get_redirect(dentry);
7bb083837   Vivek Goyal   ovl: Set redirect...
929
  	bool absolute_redirect = ovl_need_absolute_redirect(dentry, samedir);
a6c606551   Miklos Szeredi   ovl: redirect on ...
930

7bb083837   Vivek Goyal   ovl: Set redirect...
931
  	if (redirect && (!absolute_redirect || redirect[0] == '/'))
a6c606551   Miklos Szeredi   ovl: redirect on ...
932
  		return 0;
7bb083837   Vivek Goyal   ovl: Set redirect...
933
  	redirect = ovl_get_redirect(dentry, absolute_redirect);
a6c606551   Miklos Szeredi   ovl: redirect on ...
934
935
  	if (IS_ERR(redirect))
  		return PTR_ERR(redirect);
21a228781   Amir Goldstein   ovl: handle renam...
936
937
938
  	err = ovl_check_setxattr(dentry, ovl_dentry_upper(dentry),
  				 OVL_XATTR_REDIRECT,
  				 redirect, strlen(redirect), -EXDEV);
a6c606551   Miklos Szeredi   ovl: redirect on ...
939
940
941
942
943
944
  	if (!err) {
  		spin_lock(&dentry->d_lock);
  		ovl_dentry_set_redirect(dentry, redirect);
  		spin_unlock(&dentry->d_lock);
  	} else {
  		kfree(redirect);
da2e6b7ee   Amir Goldstein   ovl: fix overlay:...
945
946
947
  		pr_warn_ratelimited("overlayfs: failed to set redirect (%i)
  ",
  				    err);
a6c606551   Miklos Szeredi   ovl: redirect on ...
948
949
950
951
952
  		/* Fall back to userspace copy-up */
  		err = -EXDEV;
  	}
  	return err;
  }
6c02cb59e   Miklos Szeredi   ovl: rename ovl_r...
953
954
955
  static int ovl_rename(struct inode *olddir, struct dentry *old,
  		      struct inode *newdir, struct dentry *new,
  		      unsigned int flags)
e9be9d5e7   Miklos Szeredi   overlay filesystem
956
957
  {
  	int err;
e9be9d5e7   Miklos Szeredi   overlay filesystem
958
959
960
961
962
963
964
  	struct dentry *old_upperdir;
  	struct dentry *new_upperdir;
  	struct dentry *olddentry;
  	struct dentry *newdentry;
  	struct dentry *trap;
  	bool old_opaque;
  	bool new_opaque;
e9be9d5e7   Miklos Szeredi   overlay filesystem
965
  	bool cleanup_whiteout = false;
0e32992f7   Amir Goldstein   ovl: remove the '...
966
  	bool update_nlink = false;
e9be9d5e7   Miklos Szeredi   overlay filesystem
967
  	bool overwrite = !(flags & RENAME_EXCHANGE);
e36cb0b89   David Howells   VFS: (Scripted) C...
968
  	bool is_dir = d_is_dir(old);
370e55ace   Miklos Szeredi   ovl: rename: simp...
969
  	bool new_is_dir = d_is_dir(new);
a6c606551   Miklos Szeredi   ovl: redirect on ...
970
  	bool samedir = olddir == newdir;
e9be9d5e7   Miklos Szeredi   overlay filesystem
971
972
  	struct dentry *opaquedir = NULL;
  	const struct cred *old_cred = NULL;
6d0a8a90a   Amir Goldstein   ovl: take lower d...
973
  	LIST_HEAD(list);
e9be9d5e7   Miklos Szeredi   overlay filesystem
974
975
976
977
978
979
  
  	err = -EINVAL;
  	if (flags & ~(RENAME_EXCHANGE | RENAME_NOREPLACE))
  		goto out;
  
  	flags &= ~RENAME_NOREPLACE;
e9be9d5e7   Miklos Szeredi   overlay filesystem
980
  	/* Don't copy up directory trees */
e9be9d5e7   Miklos Szeredi   overlay filesystem
981
  	err = -EXDEV;
a6c606551   Miklos Szeredi   ovl: redirect on ...
982
  	if (!ovl_can_move(old))
370e55ace   Miklos Szeredi   ovl: rename: simp...
983
  		goto out;
a6c606551   Miklos Szeredi   ovl: redirect on ...
984
  	if (!overwrite && !ovl_can_move(new))
e9be9d5e7   Miklos Szeredi   overlay filesystem
985
  		goto out;
e9be9d5e7   Miklos Szeredi   overlay filesystem
986

6d0a8a90a   Amir Goldstein   ovl: take lower d...
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
  	if (overwrite && new_is_dir && !ovl_pure_upper(new)) {
  		err = ovl_check_empty_dir(new, &list);
  		if (err)
  			goto out;
  	}
  
  	if (overwrite) {
  		if (ovl_lower_positive(old)) {
  			if (!ovl_dentry_is_whiteout(new)) {
  				/* Whiteout source */
  				flags |= RENAME_WHITEOUT;
  			} else {
  				/* Switch whiteouts */
  				flags |= RENAME_EXCHANGE;
  			}
  		} else if (is_dir && ovl_dentry_is_whiteout(new)) {
  			flags |= RENAME_EXCHANGE;
  			cleanup_whiteout = true;
  		}
  	}
e9be9d5e7   Miklos Szeredi   overlay filesystem
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
  	err = ovl_want_write(old);
  	if (err)
  		goto out;
  
  	err = ovl_copy_up(old);
  	if (err)
  		goto out_drop_write;
  
  	err = ovl_copy_up(new->d_parent);
  	if (err)
  		goto out_drop_write;
  	if (!overwrite) {
  		err = ovl_copy_up(new);
  		if (err)
  			goto out_drop_write;
0e32992f7   Amir Goldstein   ovl: remove the '...
1022
1023
  	} else if (d_inode(new)) {
  		err = ovl_nlink_start(new);
5f8415d6b   Amir Goldstein   ovl: persistent o...
1024
1025
  		if (err)
  			goto out_drop_write;
0e32992f7   Amir Goldstein   ovl: remove the '...
1026
1027
  
  		update_nlink = true;
e9be9d5e7   Miklos Szeredi   overlay filesystem
1028
  	}
1175b6b8d   Vivek Goyal   ovl: do operation...
1029
  	old_cred = ovl_override_creds(old->d_sb);
e9be9d5e7   Miklos Szeredi   overlay filesystem
1030

6d0a8a90a   Amir Goldstein   ovl: take lower d...
1031
1032
  	if (!list_empty(&list)) {
  		opaquedir = ovl_clear_empty(new, &list);
e9be9d5e7   Miklos Szeredi   overlay filesystem
1033
1034
1035
1036
1037
1038
  		err = PTR_ERR(opaquedir);
  		if (IS_ERR(opaquedir)) {
  			opaquedir = NULL;
  			goto out_revert_creds;
  		}
  	}
e9be9d5e7   Miklos Szeredi   overlay filesystem
1039
1040
  	old_upperdir = ovl_dentry_upper(old->d_parent);
  	new_upperdir = ovl_dentry_upper(new->d_parent);
ee1d6d37b   Amir Goldstein   ovl: mark upper d...
1041
1042
1043
  	if (!samedir) {
  		/*
  		 * When moving a merge dir or non-dir with copy up origin into
f3a156858   Amir Goldstein   ovl: mark upper m...
1044
1045
1046
  		 * a new parent, we are marking the new parent dir "impure".
  		 * When ovl_iterate() iterates an "impure" upper dir, it will
  		 * lookup the origin inodes of the entries to fill d_ino.
ee1d6d37b   Amir Goldstein   ovl: mark upper d...
1047
  		 */
f3a156858   Amir Goldstein   ovl: mark upper m...
1048
  		if (ovl_type_origin(old)) {
ee1d6d37b   Amir Goldstein   ovl: mark upper d...
1049
1050
1051
1052
  			err = ovl_set_impure(new->d_parent, new_upperdir);
  			if (err)
  				goto out_revert_creds;
  		}
f3a156858   Amir Goldstein   ovl: mark upper m...
1053
  		if (!overwrite && ovl_type_origin(new)) {
ee1d6d37b   Amir Goldstein   ovl: mark upper d...
1054
1055
1056
1057
1058
  			err = ovl_set_impure(old->d_parent, old_upperdir);
  			if (err)
  				goto out_revert_creds;
  		}
  	}
e9be9d5e7   Miklos Szeredi   overlay filesystem
1059
  	trap = lock_rename(new_upperdir, old_upperdir);
11f371041   Miklos Szeredi   ovl: verify upper...
1060
1061
1062
1063
1064
1065
1066
  	olddentry = lookup_one_len(old->d_name.name, old_upperdir,
  				   old->d_name.len);
  	err = PTR_ERR(olddentry);
  	if (IS_ERR(olddentry))
  		goto out_unlock;
  
  	err = -ESTALE;
9020df372   Miklos Szeredi   ovl: compare inodes
1067
  	if (!ovl_matches_upper(old, olddentry))
11f371041   Miklos Szeredi   ovl: verify upper...
1068
1069
1070
1071
1072
1073
1074
  		goto out_dput_old;
  
  	newdentry = lookup_one_len(new->d_name.name, new_upperdir,
  				   new->d_name.len);
  	err = PTR_ERR(newdentry);
  	if (IS_ERR(newdentry))
  		goto out_dput_old;
3ee23ff10   Miklos Szeredi   ovl: check lower ...
1075
1076
  	old_opaque = ovl_dentry_is_opaque(old);
  	new_opaque = ovl_dentry_is_opaque(new);
11f371041   Miklos Szeredi   ovl: verify upper...
1077
  	err = -ESTALE;
09d8b5867   Miklos Szeredi   ovl: move __upper...
1078
  	if (d_inode(new) && ovl_dentry_upper(new)) {
e9be9d5e7   Miklos Szeredi   overlay filesystem
1079
  		if (opaquedir) {
11f371041   Miklos Szeredi   ovl: verify upper...
1080
1081
  			if (newdentry != opaquedir)
  				goto out_dput;
e9be9d5e7   Miklos Szeredi   overlay filesystem
1082
  		} else {
9020df372   Miklos Szeredi   ovl: compare inodes
1083
  			if (!ovl_matches_upper(new, newdentry))
11f371041   Miklos Szeredi   ovl: verify upper...
1084
  				goto out_dput;
e9be9d5e7   Miklos Szeredi   overlay filesystem
1085
1086
  		}
  	} else {
11f371041   Miklos Szeredi   ovl: verify upper...
1087
1088
1089
  		if (!d_is_negative(newdentry) &&
  		    (!new_opaque || !ovl_is_whiteout(newdentry)))
  			goto out_dput;
e9be9d5e7   Miklos Szeredi   overlay filesystem
1090
  	}
e9be9d5e7   Miklos Szeredi   overlay filesystem
1091
1092
1093
1094
  	if (olddentry == trap)
  		goto out_dput;
  	if (newdentry == trap)
  		goto out_dput;
82a0e2573   Amir Goldstein   ovl: relax WARN_O...
1095
  	if (olddentry->d_inode == newdentry->d_inode)
804032fab   Miklos Szeredi   ovl: don't check ...
1096
  		goto out_dput;
5cf5b477f   Miklos Szeredi   ovl: opaque cleanup
1097
  	err = 0;
7bb083837   Vivek Goyal   ovl: Set redirect...
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
  	if (ovl_type_merge_or_lower(old))
  		err = ovl_set_redirect(old, samedir);
  	else if (is_dir && !old_opaque && ovl_type_merge(new->d_parent))
  		err = ovl_set_opaque_xerr(old, olddentry, -EXDEV);
  	if (err)
  		goto out_dput;
  
  	if (!overwrite && ovl_type_merge_or_lower(new))
  		err = ovl_set_redirect(new, samedir);
  	else if (!overwrite && new_is_dir && !new_opaque &&
  		 ovl_type_merge(old->d_parent))
  		err = ovl_set_opaque_xerr(new, newdentry, -EXDEV);
  	if (err)
  		goto out_dput;
e9be9d5e7   Miklos Szeredi   overlay filesystem
1112

3ee23ff10   Miklos Szeredi   ovl: check lower ...
1113
1114
1115
  	err = ovl_do_rename(old_upperdir->d_inode, olddentry,
  			    new_upperdir->d_inode, newdentry, flags);
  	if (err)
e9be9d5e7   Miklos Szeredi   overlay filesystem
1116
  		goto out_dput;
e9be9d5e7   Miklos Szeredi   overlay filesystem
1117
1118
1119
  
  	if (cleanup_whiteout)
  		ovl_cleanup(old_upperdir->d_inode, newdentry);
f681eb1d5   Amir Goldstein   ovl: fix nlink le...
1120
1121
1122
1123
1124
1125
  	if (overwrite && d_inode(new)) {
  		if (new_is_dir)
  			clear_nlink(d_inode(new));
  		else
  			drop_nlink(d_inode(new));
  	}
d9854c87f   Miklos Szeredi   ovl: copy up times
1126
1127
1128
1129
1130
1131
1132
1133
1134
  	ovl_dir_modified(old->d_parent, ovl_type_origin(old) ||
  			 (!overwrite && ovl_type_origin(new)));
  	ovl_dir_modified(new->d_parent, ovl_type_origin(old) ||
  			 (d_inode(new) && ovl_type_origin(new)));
  
  	/* copy ctime: */
  	ovl_copyattr(d_inode(olddentry), d_inode(old));
  	if (d_inode(new) && ovl_dentry_upper(new))
  		ovl_copyattr(d_inode(newdentry), d_inode(new));
e9be9d5e7   Miklos Szeredi   overlay filesystem
1135
1136
1137
  
  out_dput:
  	dput(newdentry);
11f371041   Miklos Szeredi   ovl: verify upper...
1138
1139
  out_dput_old:
  	dput(olddentry);
e9be9d5e7   Miklos Szeredi   overlay filesystem
1140
1141
1142
  out_unlock:
  	unlock_rename(new_upperdir, old_upperdir);
  out_revert_creds:
1175b6b8d   Vivek Goyal   ovl: do operation...
1143
  	revert_creds(old_cred);
0e32992f7   Amir Goldstein   ovl: remove the '...
1144
1145
  	if (update_nlink)
  		ovl_nlink_end(new);
e9be9d5e7   Miklos Szeredi   overlay filesystem
1146
1147
1148
1149
  out_drop_write:
  	ovl_drop_write(old);
  out:
  	dput(opaquedir);
6d0a8a90a   Amir Goldstein   ovl: take lower d...
1150
  	ovl_cache_free(&list);
e9be9d5e7   Miklos Szeredi   overlay filesystem
1151
1152
1153
1154
1155
1156
1157
1158
1159
  	return err;
  }
  
  const struct inode_operations ovl_dir_inode_operations = {
  	.lookup		= ovl_lookup,
  	.mkdir		= ovl_mkdir,
  	.symlink	= ovl_symlink,
  	.unlink		= ovl_unlink,
  	.rmdir		= ovl_rmdir,
6c02cb59e   Miklos Szeredi   ovl: rename ovl_r...
1160
  	.rename		= ovl_rename,
e9be9d5e7   Miklos Szeredi   overlay filesystem
1161
1162
1163
1164
1165
  	.link		= ovl_link,
  	.setattr	= ovl_setattr,
  	.create		= ovl_create,
  	.mknod		= ovl_mknod,
  	.permission	= ovl_permission,
5b712091a   Miklos Szeredi   ovl: merge getatt...
1166
  	.getattr	= ovl_getattr,
e9be9d5e7   Miklos Szeredi   overlay filesystem
1167
  	.listxattr	= ovl_listxattr,
39a25b2b3   Vivek Goyal   ovl: define ->get...
1168
  	.get_acl	= ovl_get_acl,
d719e8f26   Miklos Szeredi   ovl: update atime...
1169
  	.update_time	= ovl_update_time,
e9be9d5e7   Miklos Szeredi   overlay filesystem
1170
  };