diff options
| author | Amir Goldstein <amir73il@gmail.com> | 2017-09-25 09:39:55 -0400 |
|---|---|---|
| committer | Miklos Szeredi <mszeredi@redhat.com> | 2017-10-05 09:53:18 -0400 |
| commit | 5820dc0888d302ac05f8b91ffdf7e4e53b4fbf53 (patch) | |
| tree | e22ae933b338fe9a51f34cef6658d82484aaff91 | |
| parent | dc7ab6773e8171e07f16fd0df0c5eea28c899503 (diff) | |
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: ("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>
| -rw-r--r-- | fs/overlayfs/copy_up.c | 6 | ||||
| -rw-r--r-- | fs/overlayfs/dir.c | 20 | ||||
| -rw-r--r-- | fs/overlayfs/overlayfs.h | 1 | ||||
| -rw-r--r-- | fs/overlayfs/util.c | 19 |
4 files changed, 22 insertions, 24 deletions
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index aad97b30d5e6..c441f9387a1b 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c | |||
| @@ -561,10 +561,8 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c) | |||
| 561 | c->tmpfile = true; | 561 | c->tmpfile = true; |
| 562 | err = ovl_copy_up_locked(c); | 562 | err = ovl_copy_up_locked(c); |
| 563 | } else { | 563 | } else { |
| 564 | err = -EIO; | 564 | err = ovl_lock_rename_workdir(c->workdir, c->destdir); |
| 565 | if (lock_rename(c->workdir, c->destdir) != NULL) { | 565 | if (!err) { |
| 566 | pr_err("overlayfs: failed to lock workdir+upperdir\n"); | ||
| 567 | } else { | ||
| 568 | err = ovl_copy_up_locked(c); | 566 | err = ovl_copy_up_locked(c); |
| 569 | unlock_rename(c->workdir, c->destdir); | 567 | unlock_rename(c->workdir, c->destdir); |
| 570 | } | 568 | } |
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index 3309b1912241..cc961a3bd3bd 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c | |||
| @@ -216,26 +216,6 @@ out_unlock: | |||
| 216 | return err; | 216 | return err; |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | static int ovl_lock_rename_workdir(struct dentry *workdir, | ||
| 220 | struct dentry *upperdir) | ||
| 221 | { | ||
| 222 | /* Workdir should not be the same as upperdir */ | ||
| 223 | if (workdir == upperdir) | ||
| 224 | goto err; | ||
| 225 | |||
| 226 | /* Workdir should not be subdir of upperdir and vice versa */ | ||
| 227 | if (lock_rename(workdir, upperdir) != NULL) | ||
| 228 | goto err_unlock; | ||
| 229 | |||
| 230 | return 0; | ||
| 231 | |||
| 232 | err_unlock: | ||
| 233 | unlock_rename(workdir, upperdir); | ||
| 234 | err: | ||
| 235 | pr_err("overlayfs: failed to lock workdir+upperdir\n"); | ||
| 236 | return -EIO; | ||
| 237 | } | ||
| 238 | |||
| 239 | static struct dentry *ovl_clear_empty(struct dentry *dentry, | 219 | static struct dentry *ovl_clear_empty(struct dentry *dentry, |
| 240 | struct list_head *list) | 220 | struct list_head *list) |
| 241 | { | 221 | { |
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index d4e8c1a08fb0..c706a6f99928 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h | |||
| @@ -235,6 +235,7 @@ bool ovl_inuse_trylock(struct dentry *dentry); | |||
| 235 | void ovl_inuse_unlock(struct dentry *dentry); | 235 | void ovl_inuse_unlock(struct dentry *dentry); |
| 236 | int ovl_nlink_start(struct dentry *dentry, bool *locked); | 236 | int ovl_nlink_start(struct dentry *dentry, bool *locked); |
| 237 | void ovl_nlink_end(struct dentry *dentry, bool locked); | 237 | void ovl_nlink_end(struct dentry *dentry, bool locked); |
| 238 | int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir); | ||
| 238 | 239 | ||
| 239 | static inline bool ovl_is_impuredir(struct dentry *dentry) | 240 | static inline bool ovl_is_impuredir(struct dentry *dentry) |
| 240 | { | 241 | { |
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index 7ae33d225a67..b9b239fa5cfd 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c | |||
| @@ -560,3 +560,22 @@ void ovl_nlink_end(struct dentry *dentry, bool locked) | |||
| 560 | mutex_unlock(&OVL_I(d_inode(dentry))->lock); | 560 | mutex_unlock(&OVL_I(d_inode(dentry))->lock); |
| 561 | } | 561 | } |
| 562 | } | 562 | } |
| 563 | |||
| 564 | int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir) | ||
| 565 | { | ||
| 566 | /* Workdir should not be the same as upperdir */ | ||
| 567 | if (workdir == upperdir) | ||
| 568 | goto err; | ||
| 569 | |||
| 570 | /* Workdir should not be subdir of upperdir and vice versa */ | ||
| 571 | if (lock_rename(workdir, upperdir) != NULL) | ||
| 572 | goto err_unlock; | ||
| 573 | |||
| 574 | return 0; | ||
| 575 | |||
| 576 | err_unlock: | ||
| 577 | unlock_rename(workdir, upperdir); | ||
| 578 | err: | ||
| 579 | pr_err("overlayfs: failed to lock workdir+upperdir\n"); | ||
| 580 | return -EIO; | ||
| 581 | } | ||
