Re: [PATCH v2] ovl: check for incomapt features in work dir

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Sep 1, 2020 at 12:17 PM Miklos Szeredi <miklos@xxxxxxxxxx> wrote:
>
> On Sun, Aug 30, 2020 at 10:28 PM Amir Goldstein <amir73il@xxxxxxxxx> wrote:
> >
> > An incompatible feature is marked by a non-empty directory nested
> > 2 levels deep under "work" dir, e.g.:
> > workdir/work/incompat/volatile.
> >
> > This commit checks for marked incompat features, warns about them
> > and fails to mount the overlay, for example:
> >   overlayfs: overlay with incompat feature 'volatile' cannot be mounted
> >
> > Very old kernels (i.e. v3.18) will fail to remove a non-empty "work"
> > dir and fail the mount.  Newer kernels will fail to remove a "work"
> > dir with entries nested 3 levels and fall back to read-only mount.
> >
> > User mounting with old kernel will see a warning like these in dmesg:
> >   overlayfs: cleanup of 'incompat/...' failed (-39)
> >   overlayfs: cleanup of 'work/incompat' failed (-39)
> >   overlayfs: cleanup of 'ovl-work/work' failed (-39)
> >   overlayfs: failed to create directory /vdf/ovl-work/work (errno: 17);
> >              mounting read-only
> >
> > These warnings should give the hint to the user that:
> > 1. mount failure is caused by backward incompatible features
> > 2. mount failure can be resolved by manually removing the "work" directory
> >
> > There is nothing preventing users on old kernels from manually removing
> > workdir entirely or mounting overlay with a new workdir, so this is in
> > no way a full proof backward compatibility enforcement, but only a best
> > effort.
> >
> > Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx>
> > ---
> >
> > Vivek,
> >
> > Re-posting with minor cleanups.
> > Also pushed to branch ovl-incompat.
> >
> > Thanks,
> > Amir.
> >
> > Changes since v1:
> > - Move check for "incompat" name to ovl_workdir_cleanup_recurse()
> >
> >
> >  fs/overlayfs/readdir.c | 30 +++++++++++++++++++++++++-----
> >  fs/overlayfs/super.c   | 25 ++++++++++++++++++-------
> >  2 files changed, 43 insertions(+), 12 deletions(-)
> >
> > diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c
> > index 6918b98faeb6..683c6f27ab77 100644
> > --- a/fs/overlayfs/readdir.c
> > +++ b/fs/overlayfs/readdir.c
> > @@ -1051,7 +1051,9 @@ int ovl_check_d_type_supported(struct path *realpath)
> >         return rdd.d_type_supported;
> >  }
> >
> > -static void ovl_workdir_cleanup_recurse(struct path *path, int level)
> > +#define OVL_INCOMPATDIR_NAME "incompat"
> > +
> > +static int ovl_workdir_cleanup_recurse(struct path *path, int level)
> >  {
> >         int err;
> >         struct inode *dir = path->dentry->d_inode;
> > @@ -1065,6 +1067,15 @@ static void ovl_workdir_cleanup_recurse(struct path *path, int level)
> >                 .root = &root,
> >                 .is_lowest = false,
> >         };
> > +       bool incompat = false;
> > +
> > +       /*
> > +        * The "work/incompat" directory is treated specially - if it is not
> > +        * empty, instead of printing a generic error and mounting read-only,
> > +        * we will error about incompat features and fail the mount.
> > +        */
> > +       if (level == 2 && !strcmp(path->dentry->d_name.name, OVL_INCOMPATDIR_NAME))
> > +               incompat = true;
>
> Should the test be specific to "work/incompat"?  AFAICS this will
> trigger under "index" as well...

When called from ovl_indexdir_cleanup(), path->dentry->d_name.name[0] == '#',
because cleanup starts at level 1 and ovl_workdir_cleanup_recurse() is called
with level 2.

>
> >
> >         err = ovl_dir_read(path, &rdd);
> >         if (err)
> > @@ -1079,21 +1090,29 @@ static void ovl_workdir_cleanup_recurse(struct path *path, int level)
> >                                 continue;
> >                         if (p->len == 2 && p->name[1] == '.')
> >                                 continue;
> > +               } else if (incompat) {
> > +                       pr_warn("overlay with incompat feature '%.*s' cannot be mounted\n",
> > +                               p->len, p->name);
> > +                       err = -EEXIST;
>
> EEXIST feels counterintuitive.  I'd rather opt for EINVAL.

I usually prefer to use EINVAL for illegal user input and this is a border line,
so I prefer errors that indicate the state of the object, like EEXIST
or ENOTEMPTY,
but because these errors are not expected on mount, I can live with EINVAL.

Assuming that you agree with my response to ovl_indexdir_cleanup(), let
me know if you need me to post v3 or if you can change the choice of error
and s/pr_warn/pr_err on commit.

Thanks,
Amir.



[Index of Archives]     [Linux Filesystems Devel]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux