Commit 5820dc08 authored by Amir Goldstein's avatar Amir Goldstein Committed by Miklos Szeredi

ovl: fix missing unlock_rename() in ovl_do_copy_up()

Use the ovl_lock_rename_workdir() helper which requires
unlock_rename() only on lock success.

Fixes: ("fd210b7d ovl: move copy up lock out")
Cc: <stable@vger.kernel.org> # v4.13
Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent dc7ab677
...@@ -561,10 +561,8 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c) ...@@ -561,10 +561,8 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c)
c->tmpfile = true; c->tmpfile = true;
err = ovl_copy_up_locked(c); err = ovl_copy_up_locked(c);
} else { } else {
err = -EIO; err = ovl_lock_rename_workdir(c->workdir, c->destdir);
if (lock_rename(c->workdir, c->destdir) != NULL) { if (!err) {
pr_err("overlayfs: failed to lock workdir+upperdir\n");
} else {
err = ovl_copy_up_locked(c); err = ovl_copy_up_locked(c);
unlock_rename(c->workdir, c->destdir); unlock_rename(c->workdir, c->destdir);
} }
......
...@@ -216,26 +216,6 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode, ...@@ -216,26 +216,6 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode,
return err; 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, static struct dentry *ovl_clear_empty(struct dentry *dentry,
struct list_head *list) struct list_head *list)
{ {
......
...@@ -235,6 +235,7 @@ bool ovl_inuse_trylock(struct dentry *dentry); ...@@ -235,6 +235,7 @@ bool ovl_inuse_trylock(struct dentry *dentry);
void ovl_inuse_unlock(struct dentry *dentry); void ovl_inuse_unlock(struct dentry *dentry);
int ovl_nlink_start(struct dentry *dentry, bool *locked); int ovl_nlink_start(struct dentry *dentry, bool *locked);
void ovl_nlink_end(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) static inline bool ovl_is_impuredir(struct dentry *dentry)
{ {
......
...@@ -560,3 +560,22 @@ void ovl_nlink_end(struct dentry *dentry, bool locked) ...@@ -560,3 +560,22 @@ void ovl_nlink_end(struct dentry *dentry, bool locked)
mutex_unlock(&OVL_I(d_inode(dentry))->lock); 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;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment