Skip to content

Commit

Permalink
ovl: mount read-only if workdir can't be created
Browse files Browse the repository at this point in the history
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 <[email protected]> 
Signed-off-by: Miklos Szeredi <[email protected]>
Cc: <[email protected]> # v3.18+
  • Loading branch information
Miklos Szeredi committed May 19, 2015
1 parent d377c5e commit cc6f67b
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 5 deletions.
3 changes: 3 additions & 0 deletions fs/overlayfs/copy_up.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
9 changes: 9 additions & 0 deletions fs/overlayfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
10 changes: 5 additions & 5 deletions fs/overlayfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}

Expand Down Expand Up @@ -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++)
Expand Down

0 comments on commit cc6f67b

Please sign in to comment.