Re: [PATCH] nfsd: do not allow exporting of special kernel filesystems

Amir Goldstein
2026-01-21T10:25:03Z

On Wed, Jan 21, 2026 at 10:50 AM NeilBrown <neilb@ownmail.net> wrote:
>
> On Wed, 21 Jan 2026, Amir Goldstein wrote:
> > pidfs and nsfs recently gained support for encode/decode of file handles
> > via name_to_handle_at(2)/opan_by_handle_at(2).
> >
> > These special kernel filesystems have custom ->open() and ->permission()
> > export methods, which nfsd does not respect and it was never meant to be
> > used for exporting those filesystems by nfsd.
> >
> > Therefore, do not allow nfsd to export filesystems with custom ->open()
> > or ->permission() methods.
> >
> > Fixes: b3caba8f7a34a ("pidfs: implement file handle support")
> > Fixes: 5222470b2fbb3 ("nsfs: support file handles")
> > Signed-off-by: Amir Goldstein <amir73il@gmail.com>
> > ---
> > fs/nfsd/export.c | 21 +++++++++++++--------
> > 1 file changed, 13 insertions(+), 8 deletions(-)
> >
> > Christian,
> >
> > I had enough of the stable file handles discussion [1].
> >
> > This patch which I already suggested [2] on week ago, states a justified
> > technical reason why pidfs and nsfs should not be exported by nfsd,
> > so let's use this technical reasoning and stop the philosophic discussions
> > about what is a stable file handle is please.
> >
> > Regarding cgroupfs, we can either deal with it later or not - it is not
> > a clear but as pidfs and nsfs which absolutely should be fixed
> > retroactively in stable kernels.
> >
> > If you think that cgroupfs could benefit from "exhaustive" file handles [3]
> > then we can implement open_by_handle_at(FD_CGROUPFS_ROOT, ... and that
> > would classify cgroupfs the same as pidfs and nsfs.
> >
> > Thanks,
> > Amir.
> >
> > [1] https://lore.kernel.org/linux-fsdevel/20250912-work-namespace-v2-0-1a247645cef5@kernel.org/
> > [2] https://lore.kernel.org/linux-fsdevel/CAOQ4uxhkaGFtQRzTj2xaf2GJucoAY5CGiyUjB=8YA2zTbOtFvw@mail.gmail.com/
> > [3] https://lore.kernel.org/linux-fsdevel/20250912-work-namespace-v2-29-1a247645cef5@kernel.org/
> >
> > diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
> > index 2a1499f2ad196..232dacac611e9 100644
> > --- a/fs/nfsd/export.c
> > +++ b/fs/nfsd/export.c
> > @@ -405,6 +405,7 @@ static struct svc_export *svc_export_lookup(struct svc_export *);
> > static int check_export(const struct path *path, int *flags, unsigned char *uuid)
> > {
> > struct inode *inode = d_inode(path->dentry);
> > + const struct export_operations *nop = inode->i_sb->s_export_op;
> >
> > /*
> > * We currently export only dirs, regular files, and (for v4
> > @@ -422,13 +423,12 @@ static int check_export(const struct path *path, int *flags, unsigned char *uuid
> > if (*flags & NFSEXP_V4ROOT)
> > *flags |= NFSEXP_READONLY;
> >
> > - /* There are two requirements on a filesystem to be exportable.
> > - * 1: We must be able to identify the filesystem from a number.
> > - * either a device number (so FS_REQUIRES_DEV needed)
> > - * or an FSID number (so NFSEXP_FSID or ->uuid is needed).
> > - * 2: We must be able to find an inode from a filehandle.
> > - * This means that s_export_op must be set.
> > - * 3: We must not currently be on an idmapped mount.
> > + /*
> > + * The requirements for a filesystem to be exportable:
> > + * 1. The filehandle must identify a filesystem by number
> > + * 2. The filehandle must uniquely identify an inode
> > + * 3. The filesystem must not have custom filehandle open/perm methods
> > + * 4. The requested file must not reside on an idmapped mount
> > */
> > if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) &&
> > !(*flags & NFSEXP_FSID) &&
> > @@ -437,11 +437,16 @@ static int check_export(const struct path *path, int *flags, unsigned char *uuid
> > return -EINVAL;
> > }
> >
> > - if (!exportfs_can_decode_fh(inode->i_sb->s_export_op)) {
> > + if (!exportfs_can_decode_fh(nop)) {
> > dprintk("exp_export: export of invalid fs type.\n");
> > return -EINVAL;
> > }
> >
> > + if (nop->open || nop->permission) {
> > + dprintk("exp_export: export of non-standard fs type.\n");
> > + return -EINVAL;
> > + }
> > +
>
> It is not immediately obvious that this is safe when nop is NULL, but it
> is because exportfs_can_decode_fh() checks for that case. As that is a
> static inline a static analyser can easily confirm this. So it is
> probably OK.

Heh, in the RFC patch [1], I had those conditions wrapped in a helper
just below exportfs_can_decode_fh(), so this was more clear, but now
I tried to avoid adding a helper named exportfs_may_nfs_export()... ;)

>
> "non-standard" is not totally clear. "special" might be better, or it
> might not. It is only a dprintk so it probably doesn't matter much.
>

In said RFC patch it was using the same dprinkt() ("invalid fs type")
I am not sure that the distinction to two different classes is important.
printing the fstype->name, either with dprintk() or trace point would
be much more valuable IMO.

But Jeff has a patch to convert dprink() to trace point, so I will gladly
leave those decisions for him.

Thanks,
Amir.

[1] https://lore.kernel.org/linux-fsdevel/CAOQ4uxhkaGFtQRzTj2xaf2GJucoAY5CGiyUjB=8YA2zTbOtFvw@mail.gmail.com/