ovl: fix missing unlock_rename() in ovl_do_copy_up()
authorAmir Goldstein <amir73il@gmail.com>
Mon, 25 Sep 2017 13:39:55 +0000 (16:39 +0300)
committerMiklos Szeredi <mszeredi@redhat.com>
Thu, 5 Oct 2017 13:53:18 +0000 (15:53 +0200)
Use the ovl_lock_rename_workdir() helper which requires
unlock_rename() only on lock success.

Fixes: ("fd210b7d67ee ovl: move copy up lock out")
Cc: <stable@vger.kernel.org> # v4.13
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
fs/overlayfs/copy_up.c
fs/overlayfs/dir.c
fs/overlayfs/overlayfs.h
fs/overlayfs/util.c

index aad97b30d5e657199f741f02700208c41e5424ae..c441f9387a1ba0f2ddf1f1426a114a5533fb6e30 100644 (file)
@@ -561,10 +561,8 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c)
                c->tmpfile = true;
                err = ovl_copy_up_locked(c);
        } else {
-               err = -EIO;
-               if (lock_rename(c->workdir, c->destdir) != NULL) {
-                       pr_err("overlayfs: failed to lock workdir+upperdir\n");
-               } else {
+               err = ovl_lock_rename_workdir(c->workdir, c->destdir);
+               if (!err) {
                        err = ovl_copy_up_locked(c);
                        unlock_rename(c->workdir, c->destdir);
                }
index 3309b1912241769bba93e2caba483a4e2f57035a..cc961a3bd3bdec34fcace34553f9e8cfb319db25 100644 (file)
@@ -216,26 +216,6 @@ out_unlock:
        return err;
 }
 
-static int ovl_lock_rename_workdir(struct dentry *workdir,
-                                  struct dentry *upperdir)
-{
-       /* Workdir should not be the same as upperdir */
-       if (workdir == upperdir)
-               goto err;
-
-       /* Workdir should not be subdir of upperdir and vice versa */
-       if (lock_rename(workdir, upperdir) != NULL)
-               goto err_unlock;
-
-       return 0;
-
-err_unlock:
-       unlock_rename(workdir, upperdir);
-err:
-       pr_err("overlayfs: failed to lock workdir+upperdir\n");
-       return -EIO;
-}
-
 static struct dentry *ovl_clear_empty(struct dentry *dentry,
                                      struct list_head *list)
 {
index d4e8c1a08fb0f5d7b4c79de7aa88a5211a4996a4..c706a6f999288136b567d75777f5f6742682a9a2 100644 (file)
@@ -235,6 +235,7 @@ bool ovl_inuse_trylock(struct dentry *dentry);
 void ovl_inuse_unlock(struct dentry *dentry);
 int ovl_nlink_start(struct dentry *dentry, bool *locked);
 void ovl_nlink_end(struct dentry *dentry, bool locked);
+int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir);
 
 static inline bool ovl_is_impuredir(struct dentry *dentry)
 {
index 7ae33d225a67c74cdffb44ffb5cf824e8ee5ff05..b9b239fa5cfd28d18b120696d05e817330e44241 100644 (file)
@@ -560,3 +560,22 @@ void ovl_nlink_end(struct dentry *dentry, bool locked)
                mutex_unlock(&OVL_I(d_inode(dentry))->lock);
        }
 }
+
+int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir)
+{
+       /* Workdir should not be the same as upperdir */
+       if (workdir == upperdir)
+               goto err;
+
+       /* Workdir should not be subdir of upperdir and vice versa */
+       if (lock_rename(workdir, upperdir) != NULL)
+               goto err_unlock;
+
+       return 0;
+
+err_unlock:
+       unlock_rename(workdir, upperdir);
+err:
+       pr_err("overlayfs: failed to lock workdir+upperdir\n");
+       return -EIO;
+}