]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
vfs: add FS_USERNS_DELEGATABLE flag and set it for NFS
authorJeff Layton <jlayton@kernel.org>
Thu, 29 Jan 2026 21:47:43 +0000 (16:47 -0500)
committerChristian Brauner <brauner@kernel.org>
Tue, 9 Jun 2026 15:17:29 +0000 (17:17 +0200)
Commit e1c5ae59c0f2 ("fs: don't allow non-init s_user_ns for filesystems
without FS_USERNS_MOUNT") prevents the mount of any filesystem inside a
container that doesn't have FS_USERNS_MOUNT set.

This broke NFS mounts in our containerized environment. We have a daemon
somewhat like systemd-mountfsd running in the init_ns. A process does a
fsopen() inside the container and passes it to the daemon via unix
socket.

The daemon then vets that the request is for an allowed NFS server and
performs the mount. This now fails because the fc->user_ns is set to the
value in the container and NFS doesn't set FS_USERNS_MOUNT.  We don't
want to add FS_USERNS_MOUNT to NFS since that would allow the container
to mount any NFS server (even malicious ones).

Add a new FS_USERNS_DELEGATABLE flag, and enable it on NFS.

Fixes: e1c5ae59c0f2 ("fs: don't allow non-init s_user_ns for filesystems without FS_USERNS_MOUNT")
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Link: https://patch.msgid.link/20260129-twmount-v1-1-4874ed2a15c4@kernel.org
Acked-by: Anna Schumaker <anna.schumaker@oracle.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
fs/nfs/fs_context.c
fs/super.c
include/linux/fs.h

index c105882edd16e7f45b3964339aca1052e51efa85..1967de7d1dff979f2ee63ae7d25024777accddf7 100644 (file)
@@ -1769,7 +1769,9 @@ struct file_system_type nfs_fs_type = {
        .init_fs_context        = nfs_init_fs_context,
        .parameters             = nfs_fs_parameters,
        .kill_sb                = nfs_kill_super,
-       .fs_flags               = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
+       .fs_flags               = FS_RENAME_DOES_D_MOVE |
+                                 FS_BINARY_MOUNTDATA   |
+                                 FS_USERNS_DELEGATABLE,
 };
 MODULE_ALIAS_FS("nfs");
 EXPORT_SYMBOL_GPL(nfs_fs_type);
@@ -1781,7 +1783,9 @@ struct file_system_type nfs4_fs_type = {
        .init_fs_context        = nfs_init_fs_context,
        .parameters             = nfs_fs_parameters,
        .kill_sb                = nfs_kill_super,
-       .fs_flags               = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
+       .fs_flags               = FS_RENAME_DOES_D_MOVE |
+                                 FS_BINARY_MOUNTDATA   |
+                                 FS_USERNS_DELEGATABLE,
 };
 MODULE_ALIAS_FS("nfs4");
 MODULE_ALIAS("nfs4");
index 5d46a0d5b6169c185d2587bb070544de89cd4894..d254105e29b2cb09dca47a76a9011b7d3b30ab1e 100644 (file)
@@ -741,12 +741,13 @@ struct super_block *sget_fc(struct fs_context *fc,
        int err;
 
        /*
-        * Never allow s_user_ns != &init_user_ns when FS_USERNS_MOUNT is
-        * not set, as the filesystem is likely unprepared to handle it.
-        * This can happen when fsconfig() is called from init_user_ns with
-        * an fs_fd opened in another user namespace.
+        * Never allow s_user_ns != &init_user_ns when FS_USERNS_MOUNT or
+        * FS_USERNS_DELEGATABLE is not set, as the filesystem is likely
+        * unprepared to handle it. This can happen when fsconfig() is called
+        * from init_user_ns with an fs_fd opened in another user namespace.
         */
-       if (user_ns != &init_user_ns && !(fc->fs_type->fs_flags & FS_USERNS_MOUNT)) {
+       if (user_ns != &init_user_ns &&
+           !(fc->fs_type->fs_flags & (FS_USERNS_MOUNT | FS_USERNS_DELEGATABLE))) {
                errorfc(fc, "VFS: Mounting from non-initial user namespace is not allowed");
                return ERR_PTR(-EPERM);
        }
index 11559c513dfbb2f9bf15a8c7516f031aab3e094f..10d35a68f59756c26fb17b24a0e482e2575281a7 100644 (file)
@@ -2281,6 +2281,7 @@ struct file_system_type {
 #define FS_MGTIME              64      /* FS uses multigrain timestamps */
 #define FS_LBS                 128     /* FS supports LBS */
 #define FS_POWER_FREEZE                256     /* Always freeze on suspend/hibernate */
+#define FS_USERNS_DELEGATABLE  1024    /* Can be mounted inside userns from outside */
 #define FS_RENAME_DOES_D_MOVE  32768   /* FS will handle d_move() during rename() internally. */
        int (*init_fs_context)(struct fs_context *);
        const struct fs_parameter_spec *parameters;