aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-05-27 12:47:57 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-05-27 12:47:57 -0400
commit3cfd4ba7d37b52eb965ed05209647072932dfd0a (patch)
tree099660db38046f017104820623e4431dd126b757 /fs
parent1b887bf31dd6e2f8cef80d205d6e9949a7dd98cc (diff)
parentcc6f67bcafcb6bbbb2d1be1603dcd95125a52800 (diff)
Merge branch 'overlayfs-next' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs
Pull two overlayfs fixes from Miklos Szeredi: "Overlayfs rmdir() failed to check for emptiness in one case; this was introduced in 4.0. The other bug was there since day one: failure to mount if upper fs is full, which bit some OpenWRT folks" * 'overlayfs-next' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs: ovl: mount read-only if workdir can't be created ovl: don't remove non-empty opaque directory
Diffstat (limited to 'fs')
-rw-r--r--fs/overlayfs/copy_up.c3
-rw-r--r--fs/overlayfs/dir.c33
-rw-r--r--fs/overlayfs/super.c10
3 files changed, 36 insertions, 10 deletions
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index 24f640441bd9..84d693d37428 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -299,6 +299,9 @@ int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
299 struct cred *override_cred; 299 struct cred *override_cred;
300 char *link = NULL; 300 char *link = NULL;
301 301
302 if (WARN_ON(!workdir))
303 return -EROFS;
304
302 ovl_path_upper(parent, &parentpath); 305 ovl_path_upper(parent, &parentpath);
303 upperdir = parentpath.dentry; 306 upperdir = parentpath.dentry;
304 307
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index d139405d2bfa..692ceda3bc21 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -222,6 +222,9 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry,
222 struct kstat stat; 222 struct kstat stat;
223 int err; 223 int err;
224 224
225 if (WARN_ON(!workdir))
226 return ERR_PTR(-EROFS);
227
225 err = ovl_lock_rename_workdir(workdir, upperdir); 228 err = ovl_lock_rename_workdir(workdir, upperdir);
226 if (err) 229 if (err)
227 goto out; 230 goto out;
@@ -322,6 +325,9 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
322 struct dentry *newdentry; 325 struct dentry *newdentry;
323 int err; 326 int err;
324 327
328 if (WARN_ON(!workdir))
329 return -EROFS;
330
325 err = ovl_lock_rename_workdir(workdir, upperdir); 331 err = ovl_lock_rename_workdir(workdir, upperdir);
326 if (err) 332 if (err)
327 goto out; 333 goto out;
@@ -506,11 +512,28 @@ static int ovl_remove_and_whiteout(struct dentry *dentry, bool is_dir)
506 struct dentry *opaquedir = NULL; 512 struct dentry *opaquedir = NULL;
507 int err; 513 int err;
508 514
509 if (is_dir && OVL_TYPE_MERGE_OR_LOWER(ovl_path_type(dentry))) { 515 if (WARN_ON(!workdir))
510 opaquedir = ovl_check_empty_and_clear(dentry); 516 return -EROFS;
511 err = PTR_ERR(opaquedir); 517
512 if (IS_ERR(opaquedir)) 518 if (is_dir) {
513 goto out; 519 if (OVL_TYPE_MERGE_OR_LOWER(ovl_path_type(dentry))) {
520 opaquedir = ovl_check_empty_and_clear(dentry);
521 err = PTR_ERR(opaquedir);
522 if (IS_ERR(opaquedir))
523 goto out;
524 } else {
525 LIST_HEAD(list);
526
527 /*
528 * When removing an empty opaque directory, then it
529 * makes no sense to replace it with an exact replica of
530 * itself. But emptiness still needs to be checked.
531 */
532 err = ovl_check_empty_dir(dentry, &list);
533 ovl_cache_free(&list);
534 if (err)
535 goto out;
536 }
514 } 537 }
515 538
516 err = ovl_lock_rename_workdir(workdir, upperdir); 539 err = ovl_lock_rename_workdir(workdir, upperdir);
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 5f0d1993e6e3..bf8537c7f455 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -529,7 +529,7 @@ static int ovl_remount(struct super_block *sb, int *flags, char *data)
529{ 529{
530 struct ovl_fs *ufs = sb->s_fs_info; 530 struct ovl_fs *ufs = sb->s_fs_info;
531 531
532 if (!(*flags & MS_RDONLY) && !ufs->upper_mnt) 532 if (!(*flags & MS_RDONLY) && (!ufs->upper_mnt || !ufs->workdir))
533 return -EROFS; 533 return -EROFS;
534 534
535 return 0; 535 return 0;
@@ -925,9 +925,10 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
925 ufs->workdir = ovl_workdir_create(ufs->upper_mnt, workpath.dentry); 925 ufs->workdir = ovl_workdir_create(ufs->upper_mnt, workpath.dentry);
926 err = PTR_ERR(ufs->workdir); 926 err = PTR_ERR(ufs->workdir);
927 if (IS_ERR(ufs->workdir)) { 927 if (IS_ERR(ufs->workdir)) {
928 pr_err("overlayfs: failed to create directory %s/%s\n", 928 pr_warn("overlayfs: failed to create directory %s/%s (errno: %i); mounting read-only\n",
929 ufs->config.workdir, OVL_WORKDIR_NAME); 929 ufs->config.workdir, OVL_WORKDIR_NAME, -err);
930 goto out_put_upper_mnt; 930 sb->s_flags |= MS_RDONLY;
931 ufs->workdir = NULL;
931 } 932 }
932 } 933 }
933 934
@@ -997,7 +998,6 @@ out_put_lower_mnt:
997 kfree(ufs->lower_mnt); 998 kfree(ufs->lower_mnt);
998out_put_workdir: 999out_put_workdir:
999 dput(ufs->workdir); 1000 dput(ufs->workdir);
1000out_put_upper_mnt:
1001 mntput(ufs->upper_mnt); 1001 mntput(ufs->upper_mnt);
1002out_put_lowerpath: 1002out_put_lowerpath:
1003 for (i = 0; i < numlower; i++) 1003 for (i = 0; i < numlower; i++)