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

NeilBrown
2026-01-21T09:50:49Z

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.

"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.

Reviewed-by: NeilBrown <neil@brown.name>

Thanks for posting this. I think this is a good check to have whether
or not we decide to add a flag.

Thanks,
NeilBrown

> if (is_idmapped_mnt(path->mnt)) {
> dprintk("exp_export: export of idmapped mounts not yet supported.\n");
> return -EINVAL;
> --
> 2.52.0
>
>
>