aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-05-31 11:29:02 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-05-31 11:29:02 -0400
commitd602fb6844940b23afb64d4bf70bb963c15571ee (patch)
tree16f19ec73e55f2c53cb56c81a658655f49c6dc1d
parentf511c0b17b081562dca8ac5061dfa86db4c66cc2 (diff)
parenta082c6f680da298cf075886ff032f32ccb7c5e1a (diff)
Merge branch 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs
Pull overlayfs fixes from Miklos Szeredi: "Fix regressions: - missing CONFIG_EXPORTFS dependency - failure if upper fs doesn't support xattr - bad error cleanup This also adds the concept of "impure" directories complementing the "origin" marking introduced in -rc1. Together they enable getting consistent st_ino and d_ino for directory listings. And there's a bug fix and a cleanup as well" * 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs: ovl: filter trusted xattr for non-admin ovl: mark upper merge dir with type origin entries "impure" ovl: mark upper dir with type origin entries "impure" ovl: remove unused arg from ovl_lookup_temp() ovl: handle rename when upper doesn't support xattr ovl: don't fail copy-up if upper doesn't support xattr ovl: check on mount time if upper fs supports setting xattr ovl: fix creds leak in copy up error path ovl: select EXPORTFS
-rw-r--r--fs/overlayfs/Kconfig1
-rw-r--r--fs/overlayfs/copy_up.c24
-rw-r--r--fs/overlayfs/dir.c61
-rw-r--r--fs/overlayfs/inode.c12
-rw-r--r--fs/overlayfs/namei.c16
-rw-r--r--fs/overlayfs/overlayfs.h16
-rw-r--r--fs/overlayfs/ovl_entry.h2
-rw-r--r--fs/overlayfs/super.c18
-rw-r--r--fs/overlayfs/util.c72
9 files changed, 178 insertions, 44 deletions
diff --git a/fs/overlayfs/Kconfig b/fs/overlayfs/Kconfig
index 0daac5112f7a..c0c9683934b7 100644
--- a/fs/overlayfs/Kconfig
+++ b/fs/overlayfs/Kconfig
@@ -1,5 +1,6 @@
1config OVERLAY_FS 1config OVERLAY_FS
2 tristate "Overlay filesystem support" 2 tristate "Overlay filesystem support"
3 select EXPORTFS
3 help 4 help
4 An overlay filesystem combines two filesystems - an 'upper' filesystem 5 An overlay filesystem combines two filesystems - an 'upper' filesystem
5 and a 'lower' filesystem. When a name exists in both filesystems, the 6 and a 'lower' filesystem. When a name exists in both filesystems, the
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index 9008ab9fbd2e..7a44533f4bbf 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -300,7 +300,11 @@ static int ovl_set_origin(struct dentry *dentry, struct dentry *lower,
300 return PTR_ERR(fh); 300 return PTR_ERR(fh);
301 } 301 }
302 302
303 err = ovl_do_setxattr(upper, OVL_XATTR_ORIGIN, fh, fh ? fh->len : 0, 0); 303 /*
304 * Do not fail when upper doesn't support xattrs.
305 */
306 err = ovl_check_setxattr(dentry, upper, OVL_XATTR_ORIGIN, fh,
307 fh ? fh->len : 0, 0);
304 kfree(fh); 308 kfree(fh);
305 309
306 return err; 310 return err;
@@ -342,13 +346,14 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir,
342 if (tmpfile) 346 if (tmpfile)
343 temp = ovl_do_tmpfile(upperdir, stat->mode); 347 temp = ovl_do_tmpfile(upperdir, stat->mode);
344 else 348 else
345 temp = ovl_lookup_temp(workdir, dentry); 349 temp = ovl_lookup_temp(workdir);
346 err = PTR_ERR(temp);
347 if (IS_ERR(temp))
348 goto out1;
349
350 err = 0; 350 err = 0;
351 if (!tmpfile) 351 if (IS_ERR(temp)) {
352 err = PTR_ERR(temp);
353 temp = NULL;
354 }
355
356 if (!err && !tmpfile)
352 err = ovl_create_real(wdir, temp, &cattr, NULL, true); 357 err = ovl_create_real(wdir, temp, &cattr, NULL, true);
353 358
354 if (new_creds) { 359 if (new_creds) {
@@ -454,6 +459,11 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
454 ovl_path_upper(parent, &parentpath); 459 ovl_path_upper(parent, &parentpath);
455 upperdir = parentpath.dentry; 460 upperdir = parentpath.dentry;
456 461
462 /* Mark parent "impure" because it may now contain non-pure upper */
463 err = ovl_set_impure(parent, upperdir);
464 if (err)
465 return err;
466
457 err = vfs_getattr(&parentpath, &pstat, 467 err = vfs_getattr(&parentpath, &pstat,
458 STATX_ATIME | STATX_MTIME, AT_STATX_SYNC_AS_STAT); 468 STATX_ATIME | STATX_MTIME, AT_STATX_SYNC_AS_STAT);
459 if (err) 469 if (err)
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index 723b98b90698..a63a71656e9b 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -41,7 +41,7 @@ void ovl_cleanup(struct inode *wdir, struct dentry *wdentry)
41 } 41 }
42} 42}
43 43
44struct dentry *ovl_lookup_temp(struct dentry *workdir, struct dentry *dentry) 44struct dentry *ovl_lookup_temp(struct dentry *workdir)
45{ 45{
46 struct dentry *temp; 46 struct dentry *temp;
47 char name[20]; 47 char name[20];
@@ -68,7 +68,7 @@ static struct dentry *ovl_whiteout(struct dentry *workdir,
68 struct dentry *whiteout; 68 struct dentry *whiteout;
69 struct inode *wdir = workdir->d_inode; 69 struct inode *wdir = workdir->d_inode;
70 70
71 whiteout = ovl_lookup_temp(workdir, dentry); 71 whiteout = ovl_lookup_temp(workdir);
72 if (IS_ERR(whiteout)) 72 if (IS_ERR(whiteout))
73 return whiteout; 73 return whiteout;
74 74
@@ -127,17 +127,28 @@ int ovl_create_real(struct inode *dir, struct dentry *newdentry,
127 return err; 127 return err;
128} 128}
129 129
130static int ovl_set_opaque(struct dentry *dentry, struct dentry *upperdentry) 130static int ovl_set_opaque_xerr(struct dentry *dentry, struct dentry *upper,
131 int xerr)
131{ 132{
132 int err; 133 int err;
133 134
134 err = ovl_do_setxattr(upperdentry, OVL_XATTR_OPAQUE, "y", 1, 0); 135 err = ovl_check_setxattr(dentry, upper, OVL_XATTR_OPAQUE, "y", 1, xerr);
135 if (!err) 136 if (!err)
136 ovl_dentry_set_opaque(dentry); 137 ovl_dentry_set_opaque(dentry);
137 138
138 return err; 139 return err;
139} 140}
140 141
142static int ovl_set_opaque(struct dentry *dentry, struct dentry *upperdentry)
143{
144 /*
145 * Fail with -EIO when trying to create opaque dir and upper doesn't
146 * support xattrs. ovl_rename() calls ovl_set_opaque_xerr(-EXDEV) to
147 * return a specific error for noxattr case.
148 */
149 return ovl_set_opaque_xerr(dentry, upperdentry, -EIO);
150}
151
141/* Common operations required to be done after creation of file on upper */ 152/* Common operations required to be done after creation of file on upper */
142static void ovl_instantiate(struct dentry *dentry, struct inode *inode, 153static void ovl_instantiate(struct dentry *dentry, struct inode *inode,
143 struct dentry *newdentry, bool hardlink) 154 struct dentry *newdentry, bool hardlink)
@@ -162,6 +173,11 @@ static bool ovl_type_merge(struct dentry *dentry)
162 return OVL_TYPE_MERGE(ovl_path_type(dentry)); 173 return OVL_TYPE_MERGE(ovl_path_type(dentry));
163} 174}
164 175
176static bool ovl_type_origin(struct dentry *dentry)
177{
178 return OVL_TYPE_ORIGIN(ovl_path_type(dentry));
179}
180
165static int ovl_create_upper(struct dentry *dentry, struct inode *inode, 181static int ovl_create_upper(struct dentry *dentry, struct inode *inode,
166 struct cattr *attr, struct dentry *hardlink) 182 struct cattr *attr, struct dentry *hardlink)
167{ 183{
@@ -250,7 +266,7 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry,
250 if (upper->d_parent->d_inode != udir) 266 if (upper->d_parent->d_inode != udir)
251 goto out_unlock; 267 goto out_unlock;
252 268
253 opaquedir = ovl_lookup_temp(workdir, dentry); 269 opaquedir = ovl_lookup_temp(workdir);
254 err = PTR_ERR(opaquedir); 270 err = PTR_ERR(opaquedir);
255 if (IS_ERR(opaquedir)) 271 if (IS_ERR(opaquedir))
256 goto out_unlock; 272 goto out_unlock;
@@ -382,7 +398,7 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
382 if (err) 398 if (err)
383 goto out; 399 goto out;
384 400
385 newdentry = ovl_lookup_temp(workdir, dentry); 401 newdentry = ovl_lookup_temp(workdir);
386 err = PTR_ERR(newdentry); 402 err = PTR_ERR(newdentry);
387 if (IS_ERR(newdentry)) 403 if (IS_ERR(newdentry))
388 goto out_unlock; 404 goto out_unlock;
@@ -846,18 +862,16 @@ static int ovl_set_redirect(struct dentry *dentry, bool samedir)
846 if (IS_ERR(redirect)) 862 if (IS_ERR(redirect))
847 return PTR_ERR(redirect); 863 return PTR_ERR(redirect);
848 864
849 err = ovl_do_setxattr(ovl_dentry_upper(dentry), OVL_XATTR_REDIRECT, 865 err = ovl_check_setxattr(dentry, ovl_dentry_upper(dentry),
850 redirect, strlen(redirect), 0); 866 OVL_XATTR_REDIRECT,
867 redirect, strlen(redirect), -EXDEV);
851 if (!err) { 868 if (!err) {
852 spin_lock(&dentry->d_lock); 869 spin_lock(&dentry->d_lock);
853 ovl_dentry_set_redirect(dentry, redirect); 870 ovl_dentry_set_redirect(dentry, redirect);
854 spin_unlock(&dentry->d_lock); 871 spin_unlock(&dentry->d_lock);
855 } else { 872 } else {
856 kfree(redirect); 873 kfree(redirect);
857 if (err == -EOPNOTSUPP) 874 pr_warn_ratelimited("overlay: failed to set redirect (%i)\n", err);
858 ovl_clear_redirect_dir(dentry->d_sb);
859 else
860 pr_warn_ratelimited("overlay: failed to set redirect (%i)\n", err);
861 /* Fall back to userspace copy-up */ 875 /* Fall back to userspace copy-up */
862 err = -EXDEV; 876 err = -EXDEV;
863 } 877 }
@@ -943,6 +957,25 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
943 old_upperdir = ovl_dentry_upper(old->d_parent); 957 old_upperdir = ovl_dentry_upper(old->d_parent);
944 new_upperdir = ovl_dentry_upper(new->d_parent); 958 new_upperdir = ovl_dentry_upper(new->d_parent);