aboutsummaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2011-06-08 16:53:50 +0200
committerJohn Rigby <john.rigby@linaro.org>2011-11-16 14:25:00 -0700
commitcd8f884e2b67d14d2d5c5ba07b99ac102098b603 (patch)
tree7b7a4aece9234c8fa62056dec647f3f3f7873517 /fs
parent2e3df442f6fb9b94632956041adcbbc79caa00d2 (diff)
downloadlinux-linaro-precise-cd8f884e2b67d14d2d5c5ba07b99ac102098b603.tar.gz
UBUNTU: ubuntu: overlayfs -- ovl: fix overlayfs over overlayfs
Overlayfs expects ->permission() to not check for readonliness (which is normally checked by the VFS) and so not return with -EROFS. This is not true of some filesystems, notably overlayfs itself. The following patch should fix this by making sure that if the upper layer is read-only (such as squashfs) then it will mark overlayfs read-only too and by making ovl_permission() only return EROFS in the excpetional case where the upper filesystem became r/o after the overlay was constructed. Reported-by: Jordi Pujol <jordipujolp@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Signed-off-by: Andy Whitcroft <apw@canonical.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/overlayfs/inode.c11
-rw-r--r--fs/overlayfs/super.c4
2 files changed, 14 insertions, 1 deletions
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 289006e8d49..ce39fab84ec 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -90,9 +90,18 @@ int ovl_permission(struct inode *inode, int mask, unsigned int flags)
/*
* Writes will always be redirected to upper layer, so
* ignore lower layer being read-only.
+ *
+ * If the overlay itself is read-only then proceed
+ * with the permission check, don't return EROFS.
+ * This will only happen if this is the lower layer of
+ * another overlayfs.
+ *
+ * If upper fs becomes read-only after the overlay was
+ * constructed return EROFS to prevent modification of
+ * upper layer.
*/
err = -EROFS;
- if (is_upper && IS_RDONLY(realinode) &&
+ if (is_upper && !IS_RDONLY(inode) && IS_RDONLY(realinode) &&
(S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
goto out_dput;
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 7109b45a171..c741b17835a 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -548,6 +548,10 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
goto out_put_upper_mnt;
}
+ /* If the upper fs is r/o, we mark overlayfs r/o too */
+ if (ufs->upper_mnt->mnt_sb->s_flags & MS_RDONLY)
+ sb->s_flags |= MS_RDONLY;
+
if (!(sb->s_flags & MS_RDONLY)) {
err = mnt_want_write(ufs->upper_mnt);
if (err)