[OpenWrt-Devel] [PATCH] [kernel] upstream fix: mount overlayfs r/o if workdir cannot be created

Bastian Bittorf bittorf at bluebottle.com
Tue May 19 10:17:42 EDT 2015


runtime tested on ar71xx with kernel 3.18.11
this paritially fixes #19564

Signed-off-by: Bastian Bittorf <bittorf at bluebottle.com>
---
 ...unt-read-only-if-workdir-can-t-be-created.patch |  114 ++++++++++++++++++++
 1 file changed, 114 insertions(+)
 create mode 100644 target/linux/ar71xx/patches-3.18/910-overlayfs-mount-read-only-if-workdir-can-t-be-created.patch

diff --git a/target/linux/ar71xx/patches-3.18/910-overlayfs-mount-read-only-if-workdir-can-t-be-created.patch b/target/linux/ar71xx/patches-3.18/910-overlayfs-mount-read-only-if-workdir-can-t-be-created.patch
new file mode 100644
index 0000000..e563398
--- /dev/null
+++ b/target/linux/ar71xx/patches-3.18/910-overlayfs-mount-read-only-if-workdir-can-t-be-created.patch
@@ -0,0 +1,114 @@
+From cc6f67bcafcb6bbbb2d1be1603dcd95125a52800 Mon Sep 17 00:00:00 2001
+From: Miklos Szeredi <mszeredi at suse.cz>
+Date: Tue, 19 May 2015 14:30:12 +0200
+Subject: [PATCH] ovl: mount read-only if workdir can't be created
+
+OpenWRT folks reported that overlayfs fails to mount if upper fs is full,
+because workdir can't be created.  Wordir creation can fail for various
+other reasons too.
+
+There's no reason that the mount itself should fail, overlayfs can work
+fine without a workdir, as long as the overlay isn't modified.
+
+So mount it read-only and don't allow remounting read-write.
+
+Add a couple of WARN_ON()s for the impossible case of workdir being used
+despite being read-only.
+
+Reported-by: Bastian Bittorf <bittorf at bluebottle.com>
+Signed-off-by: Miklos Szeredi <mszeredi at suse.cz>
+Cc: <stable at vger.kernel.org> # v3.18+
+Signed-off-by: Bastian Bittorf <bittorf at bluebottle.com>
+
+---
+ fs/overlayfs/copy_up.c |    3 +++
+ fs/overlayfs/dir.c     |    9 +++++++++
+ fs/overlayfs/super.c   |   10 +++++-----
+ 3 files changed, 17 insertions(+), 5 deletions(-)
+
+diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
+index 24f6404..84d693d 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,
+ 	struct cred *override_cred;
+ 	char *link = NULL;
+ 
++	if (WARN_ON(!workdir))
++		return -EROFS;
++
+ 	ovl_path_upper(parent, &parentpath);
+ 	upperdir = parentpath.dentry;
+ 
+diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
+index 2578a0c..692ceda 100644
+--- a/fs/overlayfs/dir.c
++++ b/fs/overlayfs/dir.c
+@@ -222,6 +222,9 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry,
+ 	struct kstat stat;
+ 	int err;
+ 
++	if (WARN_ON(!workdir))
++		return ERR_PTR(-EROFS);
++
+ 	err = ovl_lock_rename_workdir(workdir, upperdir);
+ 	if (err)
+ 		goto out;
+@@ -322,6 +325,9 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
+ 	struct dentry *newdentry;
+ 	int err;
+ 
++	if (WARN_ON(!workdir))
++		return -EROFS;
++
+ 	err = ovl_lock_rename_workdir(workdir, upperdir);
+ 	if (err)
+ 		goto out;
+@@ -506,6 +512,9 @@ static int ovl_remove_and_whiteout(struct dentry *dentry, bool is_dir)
+ 	struct dentry *opaquedir = NULL;
+ 	int err;
+ 
++	if (WARN_ON(!workdir))
++		return -EROFS;
++
+ 	if (is_dir) {
+ 		if (OVL_TYPE_MERGE_OR_LOWER(ovl_path_type(dentry))) {
+ 			opaquedir = ovl_check_empty_and_clear(dentry);
+diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
+index 5f0d199..bf8537c 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)
+ {
+ 	struct ovl_fs *ufs = sb->s_fs_info;
+ 
+-	if (!(*flags & MS_RDONLY) && !ufs->upper_mnt)
++	if (!(*flags & MS_RDONLY) && (!ufs->upper_mnt || !ufs->workdir))
+ 		return -EROFS;
+ 
+ 	return 0;
+@@ -925,9 +925,10 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
+ 		ufs->workdir = ovl_workdir_create(ufs->upper_mnt, workpath.dentry);
+ 		err = PTR_ERR(ufs->workdir);
+ 		if (IS_ERR(ufs->workdir)) {
+-			pr_err("overlayfs: failed to create directory %s/%s\n",
+-			       ufs->config.workdir, OVL_WORKDIR_NAME);
+-			goto out_put_upper_mnt;
++			pr_warn("overlayfs: failed to create directory %s/%s (errno: %i); mounting read-only\n",
++				ufs->config.workdir, OVL_WORKDIR_NAME, -err);
++			sb->s_flags |= MS_RDONLY;
++			ufs->workdir = NULL;
+ 		}
+ 	}
+ 
+@@ -997,7 +998,6 @@ out_put_lower_mnt:
+ 	kfree(ufs->lower_mnt);
+ out_put_workdir:
+ 	dput(ufs->workdir);
+-out_put_upper_mnt:
+ 	mntput(ufs->upper_mnt);
+ out_put_lowerpath:
+ 	for (i = 0; i < numlower; i++)
+-- 
+1.7.10.4
+
-- 
1.7.10.4
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list