The commit is pushed to "branch-rh7-3.10.0-327.22.2.vz7.16.x-ovz" and will 
appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-327.22.2.vz7.16.3
------>
commit 81c52241a5b43adbf1fa7acbceb5072cffe8a9cf
Author: Maxim Patlasov <mpatla...@virtuozzo.com>
Date:   Tue Aug 9 12:06:21 2016 +0400

    ms/ovl: verify upper dentry in ovl_remove_and_whiteout()
    
    Backport from 
git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs.git:
    
    commit cfc9fde0b07c3b44b570057c5f93dda59dca1c94
    Author: Maxim Patlasov <mpatla...@virtuozzo.com>
    Date:   Thu Jul 21 18:24:26 2016 -0700
    
        ovl: verify upper dentry in ovl_remove_and_whiteout()
    
        The upper dentry may become stale before we call 
ovl_lock_rename_workdir.
        For example, someone could (mistakenly or maliciously) manually 
unlink(2)
        it directly from upperdir.
    
        To ensure it is not stale, let's lookup it after ovl_lock_rename_workdir
        and and check if it matches the upper dentry.
    
        Essentially, it is the same problem and similar solution as in
        commit 11f3710417d0 ("ovl: verify upper dentry before unlink and 
rename").
    
        Signed-off-by: Maxim Patlasov <mpatla...@virtuozzo.com>
        Signed-off-by: Miklos Szeredi <mszer...@redhat.com>
        Cc: <sta...@vger.kernel.org>
    
    https://jira.sw.ru/browse/PSBM-47981
    
    Signed-off-by: Maxim Patlasov <mpatla...@virtuozzo.com>
---
 fs/overlayfs/dir.c | 54 ++++++++++++++++++++++++------------------------------
 1 file changed, 24 insertions(+), 30 deletions(-)

diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index 229b9e4..5402b9b 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -511,6 +511,7 @@ static int ovl_remove_and_whiteout(struct dentry *dentry, 
bool is_dir)
        struct dentry *upper;
        struct dentry *opaquedir = NULL;
        int err;
+       int flags = 0;
 
        if (WARN_ON(!workdir))
                return -EROFS;
@@ -540,46 +541,39 @@ static int ovl_remove_and_whiteout(struct dentry *dentry, 
bool is_dir)
        if (err)
                goto out_dput;
 
-       whiteout = ovl_whiteout(workdir, dentry);
-       err = PTR_ERR(whiteout);
-       if (IS_ERR(whiteout))
+       upper = lookup_one_len(dentry->d_name.name, upperdir,
+                              dentry->d_name.len);
+       err = PTR_ERR(upper);
+       if (IS_ERR(upper))
                goto out_unlock;
 
-       upper = ovl_dentry_upper(dentry);
-       if (!upper) {
-               upper = lookup_one_len(dentry->d_name.name, upperdir,
-                                      dentry->d_name.len);
-               err = PTR_ERR(upper);
-               if (IS_ERR(upper))
-                       goto kill_whiteout;
-
-               err = ovl_do_rename(wdir, whiteout, udir, upper, 0);
-               dput(upper);
-               if (err)
-                       goto kill_whiteout;
-       } else {
-               int flags = 0;
+       err = -ESTALE;
+       if ((opaquedir && upper != opaquedir) ||
+           (!opaquedir && ovl_dentry_upper(dentry) &&
+            upper != ovl_dentry_upper(dentry))) {
+               goto out_dput_upper;
+       }
 
-               if (opaquedir)
-                       upper = opaquedir;
-               err = -ESTALE;
-               if (upper->d_parent != upperdir)
-                       goto kill_whiteout;
+       whiteout = ovl_whiteout(workdir, dentry);
+       err = PTR_ERR(whiteout);
+       if (IS_ERR(whiteout))
+               goto out_dput_upper;
 
-               if (is_dir)
-                       flags |= RENAME_EXCHANGE;
+       if (d_is_dir(upper))
+               flags = RENAME_EXCHANGE;
 
-               err = ovl_do_rename(wdir, whiteout, udir, upper, flags);
-               if (err)
-                       goto kill_whiteout;
+       err = ovl_do_rename(wdir, whiteout, udir, upper, flags);
+       if (err)
+               goto kill_whiteout;
+       if (flags)
+               ovl_cleanup(wdir, upper);
 
-               if (is_dir)
-                       ovl_cleanup(wdir, upper);
-       }
        ovl_dentry_version_inc(dentry->d_parent);
 out_d_drop:
        d_drop(dentry);
        dput(whiteout);
+out_dput_upper:
+       dput(upper);
 out_unlock:
        unlock_rename(workdir, upperdir);
 out_dput:
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to