diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-06-30 10:22:59 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-06-30 10:22:59 -0700 |
commit | 86c3e00afd64a507aef954cd581547f28807e51a (patch) | |
tree | df0ad2fcc7749a282683acc5aac473c398b2bbc5 /fs | |
parent | 4d8a991d460d4fa4829beaffdcba45a217ca0fa7 (diff) | |
parent | fbaf94ee3cd5cfa85fe2d4d04be968820cb00556 (diff) |
Merge branch 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs
Pull overlayfs fixes from Miklos Szeredi:
"Fix two bugs in copy-up code. One introduced in 4.11 and one in
4.12-rc"
* 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs:
ovl: don't set origin on broken lower hardlink
ovl: copy-up: don't unlock between lookup and link
Diffstat (limited to 'fs')
-rw-r--r-- | fs/overlayfs/copy_up.c | 33 |
1 files changed, 19 insertions, 14 deletions
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index 7a44533f4bbf..a2a65120c9d0 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -330,15 +330,9 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, .link = link }; - upper = lookup_one_len(dentry->d_name.name, upperdir, - dentry->d_name.len); - err = PTR_ERR(upper); - if (IS_ERR(upper)) - goto out; - err = security_inode_copy_up(dentry, &new_creds); if (err < 0) - goto out1; + goto out; if (new_creds) old_creds = override_creds(new_creds); @@ -362,7 +356,7 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, } if (err) - goto out2; + goto out; if (S_ISREG(stat->mode)) { struct path upperpath; @@ -398,10 +392,23 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, /* * Store identifier of lower inode in upper inode xattr to * allow lookup of the copy up origin inode. + * + * Don't set origin when we are breaking the association with a lower + * hard link. */ - err = ovl_set_origin(dentry, lowerpath->dentry, temp); - if (err) + if (S_ISDIR(stat->mode) || stat->nlink == 1) { + err = ovl_set_origin(dentry, lowerpath->dentry, temp); + if (err) + goto out_cleanup; + } + + upper = lookup_one_len(dentry->d_name.name, upperdir, + dentry->d_name.len); + if (IS_ERR(upper)) { + err = PTR_ERR(upper); + upper = NULL; goto out_cleanup; + } if (tmpfile) err = ovl_do_link(temp, udir, upper, true); @@ -416,17 +423,15 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, /* Restore timestamps on parent (best effort) */ ovl_set_timestamps(upperdir, pstat); -out2: +out: dput(temp); -out1: dput(upper); -out: return err; out_cleanup: if (!tmpfile) ovl_cleanup(wdir, temp); - goto out2; + goto out; } /* |