On Tue, Apr 8, 2025 at 5:40 PM Miklos Szeredi <mszeredi@xxxxxxxxxx> wrote: > > Allow the special case of a redirect from a lower layer to a data layer > without having to turn on metacopy. This makes the feature work with > userxattr, which in turn allows data layers to be usable in user > namespaces. > > Minimize the risk by only enabling redirect from a single lower layer to a > data layer iff a data layer is specified. The only way to access a data > layer is to enable this, so there's really no reason not to enable this. > > This can be used safely if the lower layer is read-only and the > user.overlay.redirect xattr cannot be modified. > > Signed-off-by: Miklos Szeredi <mszeredi@xxxxxxxxxx> Reviewed-by: Amir Goldstein <amir73il@xxxxxxxxx> > --- > Documentation/filesystems/overlayfs.rst | 7 +++++++ > fs/overlayfs/namei.c | 14 ++++++++------ > fs/overlayfs/params.c | 5 ----- > 3 files changed, 15 insertions(+), 11 deletions(-) > > diff --git a/Documentation/filesystems/overlayfs.rst b/Documentation/filesystems/overlayfs.rst > index 2db379b4b31e..4133a336486d 100644 > --- a/Documentation/filesystems/overlayfs.rst > +++ b/Documentation/filesystems/overlayfs.rst > @@ -443,6 +443,13 @@ Only the data of the files in the "data-only" lower layers may be visible > when a "metacopy" file in one of the lower layers above it, has a "redirect" > to the absolute path of the "lower data" file in the "data-only" lower layer. > > +Instead of explicitly enabling "metacopy=on" it is sufficient to specify at > +least one data-only layer to enable redirection of data to a data-only layer. > +In this case other forms of metacopy are rejected. Note: this way data-only > +layers may be used toghether with "userxattr", in which case careful attention > +must be given to privileges needed to change the "user.overlay.redirect" xattr > +to prevent misuse. > + > Since kernel version v6.8, "data-only" lower layers can also be added using > the "datadir+" mount options and the fsconfig syscall from new mount api. > For example:: > diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c > index 5cebdd05ab3a..3d99e5fe5cfc 100644 > --- a/fs/overlayfs/namei.c > +++ b/fs/overlayfs/namei.c > @@ -1068,6 +1068,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, > struct inode *inode = NULL; > bool upperopaque = false; > char *upperredirect = NULL; > + bool check_redirect = (ovl_redirect_follow(ofs) || ofs->numdatalayer); > struct dentry *this; > unsigned int i; > int err; > @@ -1080,7 +1081,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, > .is_dir = false, > .opaque = false, > .stop = false, > - .last = ovl_redirect_follow(ofs) ? false : !ovl_numlower(poe), > + .last = check_redirect ? false : !ovl_numlower(poe), > .redirect = NULL, > .metacopy = 0, > .nextredirect = false, > @@ -1152,7 +1153,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, > goto out_put; > } > > - if (!ovl_redirect_follow(ofs)) > + if (!check_redirect) > d.last = i == ovl_numlower(poe) - 1; > else if (d.is_dir || !ofs->numdatalayer) > d.last = lower.layer->idx == ovl_numlower(roe); > @@ -1233,13 +1234,14 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, > } > } > > - /* Defer lookup of lowerdata in data-only layers to first access */ > + /* > + * Defer lookup of lowerdata in data-only layers to first access. > + * Don't require redirect=follow and metacopy=on in this case. > + */ > if (d.metacopy && ctr && ofs->numdatalayer && d.absolute_redirect) { > d.metacopy = 0; > ctr++; > - } > - > - if (!ovl_check_nextredirect(&d)) { > + } else if (!ovl_check_nextredirect(&d)) { > err = -EPERM; > goto out_put; > } > diff --git a/fs/overlayfs/params.c b/fs/overlayfs/params.c > index 6759f7d040c8..2468b436bb13 100644 > --- a/fs/overlayfs/params.c > +++ b/fs/overlayfs/params.c > @@ -1025,11 +1025,6 @@ int ovl_fs_params_verify(const struct ovl_fs_context *ctx, > */ > } > > - if (ctx->nr_data > 0 && !config->metacopy) { > - pr_err("lower data-only dirs require metacopy support.\n"); > - return -EINVAL; > - } > - > return 0; > } > > -- > 2.49.0 >