From: Kirill A. Korinsky Subject: fuse: allow control of the MNT_LOCAL flag To: OpenBSD tech Date: Thu, 02 May 2024 13:47:54 +0200 tech@, May I ask you to review this patch? FUSE is a rather unique FS that can be used to mount local files like a zip archive and remote resources like sshfs. So, such a system should not always be mounted with MNT_LOCAL, which is seen as a local flag by mount. This flag can be used by various filters to avoid running on non-local FS. For example, /usr/libexec/security walks over mounted via FUSE sshfs and other network FS because it has this flag. So the proposed patch allows to control this flag via FUSE mount options, and inside the driver as fuse_opt_insert_arg with -ononlocal. No other FS is affected by this change and MNT_LOCAL is ignored. It also doesn't change current behavior on existing drivers, to remove the MNT_LOCAL flag the fuse driver needs to be patched, or the user should add a commind line argument. This patch has been tested on -curent/amd64 using sshfs. P.S. This is a cleaner solution than ignoring fuse in libexec/security. diff --git lib/libfuse/fuse.c lib/libfuse/fuse.c index 2b8c0ebdfc6..51e560ff6d5 100644 --- lib/libfuse/fuse.c +++ lib/libfuse/fuse.c @@ -106,6 +106,7 @@ static struct fuse_opt fuse_mount_opts[] = { FUSE_OPT_KEY("max_write", KEY_STUB), FUSE_MOUNT_OPT("noatime", noatime), FUSE_MOUNT_OPT("nonempty", nonempty), + FUSE_MOUNT_OPT("nonlocal", nonlocal), FUSE_MOUNT_OPT("-r", rdonly), FUSE_MOUNT_OPT("ro", rdonly), FUSE_OPT_KEY("ro_fallback", KEY_STUB), @@ -302,6 +303,8 @@ fuse_mount(const char *dir, struct fuse_args *args) mnt_flags |= MNT_RDONLY; if (opts.noatime) mnt_flags |= MNT_NOATIME; + if (!opts.nonlocal) + mnt_flags |= MNT_LOCAL; if (opts.max_read > FUSEBUFMAXSIZE) { fprintf(stderr, "fuse: invalid max_read (%d > %d)\n", diff --git lib/libfuse/fuse_private.h lib/libfuse/fuse_private.h index 208c997828a..438100bf0b9 100644 --- lib/libfuse/fuse_private.h +++ lib/libfuse/fuse_private.h @@ -95,6 +95,7 @@ struct fuse_mount_opts { int noatime; int nonempty; int rdonly; + int nonlocal; }; struct fuse { diff --git sys/kern/vfs_syscalls.c sys/kern/vfs_syscalls.c index 40445f251bf..906653947ee 100644 --- sys/kern/vfs_syscalls.c +++ sys/kern/vfs_syscalls.c @@ -243,6 +243,14 @@ update: mp->mnt_flag |= flags & (MNT_NOSUID | MNT_NOEXEC | MNT_WXALLOWED | MNT_NODEV | MNT_SYNCHRONOUS | MNT_ASYNC | MNT_NOATIME | MNT_NOPERM | MNT_FORCE); + +#ifdef FUSE + if (strcmp(vfsp->vfc_name, MOUNT_FUSEFS) == 0) { + mp->mnt_flag &=~ MNT_LOCAL; + mp->mnt_flag |= flags & MNT_LOCAL; + } +#endif + /* * Mount the filesystem. */ diff --git sys/miscfs/fuse/fuse_vfsops.c sys/miscfs/fuse/fuse_vfsops.c index 5b30b1544aa..9e2fc0060fd 100644 --- sys/miscfs/fuse/fuse_vfsops.c +++ sys/miscfs/fuse/fuse_vfsops.c @@ -114,7 +114,6 @@ fusefs_mount(struct mount *mp, const char *path, void *data, fmp->allow_other = args->allow_other; mp->mnt_data = fmp; - mp->mnt_flag |= MNT_LOCAL; vfs_getnewfsid(mp); memset(mp->mnt_stat.f_mntonname, 0, MNAMELEN); -- wbr, Kirill