Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3cfd4ba7 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 1b887bf3 cc6f67bc
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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;

+28 −5
Original line number Diff line number Diff line
@@ -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,11 +512,28 @@ static int ovl_remove_and_whiteout(struct dentry *dentry, bool is_dir)
	struct dentry *opaquedir = NULL;
	int err;

	if (is_dir && OVL_TYPE_MERGE_OR_LOWER(ovl_path_type(dentry))) {
	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);
			err = PTR_ERR(opaquedir);
			if (IS_ERR(opaquedir))
				goto out;
		} else {
			LIST_HEAD(list);

			/*
			 * When removing an empty opaque directory, then it
			 * makes no sense to replace it with an exact replica of
			 * itself.  But emptiness still needs to be checked.
			 */
			err = ovl_check_empty_dir(dentry, &list);
			ovl_cache_free(&list);
			if (err)
				goto out;
		}
	}

	err = ovl_lock_rename_workdir(workdir, upperdir);
+5 −5
Original line number Diff line number Diff line
@@ -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 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
	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++)