Index | Thread | Search

From:
Vitaliy Makkoveev <mvs@openbsd.org>
Subject:
Re: fuse: allow control of the MNT_LOCAL flag
To:
"Kirill A. Korinsky" <kirill@korins.ky>
Cc:
OpenBSD tech <tech@openbsd.org>
Date:
Thu, 2 May 2024 17:58:31 +0300

Download raw body.

Thread
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
>