From: Vitaliy Makkoveev Subject: Re: fuse: allow control of the MNT_LOCAL flag To: "Kirill A. Korinsky" Cc: OpenBSD tech Date: Thu, 2 May 2024 17:58:31 +0300 On Thu, May 02, 2024 at 01:47:54PM +0200, Kirill A. Korinsky wrote: > 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. > I see FreeBSD just clears [1] MNT_LOCAL flag and this looks reasonable to me. 1. https://lists.freebsd.org/pipermail/svn-src-projects/2019-May/013565.html > 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 >