FILESYSTEM IN USERSPACE (FUSE) development
 help / color / mirror / Atom feed
From: Bernd Schubert <bernd@bsbernd.com>
To: "Darrick J. Wong" <djwong@kernel.org>
Cc: fuse-devel@lists.linux.dev, neal@gompa.dev
Subject: Re: [PATCH v2 14/14] Improve documentation for fuse service mount
Date: Wed, 30 Sep 2026 15:09:20 +0200	[thread overview]
Message-ID: <723b3f96-58bd-4620-9dfa-5e7779cafa87@bsbernd.com> (raw)
In-Reply-To: <20260929024303.GG6253@frogsfrogsfrogs>



On 9/29/26 04:43, Darrick J. Wong wrote:
> On Mon, Sep 28, 2026 at 01:02:16PM +0200, Bernd Schubert via B4 Relay wrote:
>> From: Bernd Schubert <bernd@bsbernd.com>
>>
>> Signed-off-by: Bernd Schubert <bernd@bsbernd.com>
>> ---
>>  doc/README.service-mount      | 312 +++++++++++++++++++++++++++++
>>  doc/README.service-mount-dev  | 456 ++++++++++++++++++++++++++++++++++++++++++
>>  doc/README.service-mount-flow | 201 +++++++++++++++++++
>>  doc/fuservicemount3.8         | 150 +++++++++++++-
>>  doc/mainpage.dox              |  13 ++
>>  doc/mount.fuse3.8             |  18 ++
>>  6 files changed, 1144 insertions(+), 6 deletions(-)
>>
>> diff --git a/doc/README.service-mount b/doc/README.service-mount
>> new file mode 100644
>> index 000000000000..859db863f3da
>> --- /dev/null
>> +++ b/doc/README.service-mount
>> @@ -0,0 +1,312 @@
>> +Mounting FUSE filesystems that run as a socket service
>> +======================================================
>> +
>> +This document is for administrators and end users who want to mount a FUSE
>> +filesystem whose server runs as a sandboxed systemd socket service, rather
>> +than as a process in the mount caller's own context.
>> +
>> +Developers who want to make their FUSE server runnable this way should read
>> +README.service-mount-dev instead.
>> +
>> +
>> +What a service mount is
>> +-----------------------
>> +
>> +A traditional FUSE filesystem runs as a child of whoever mounts it: it
>> +inherits that environment, needs mount permission, and can see the caller's
>> +files. A *service mount* instead keeps the FUSE server running as an
>> +independent systemd service. When someone mounts the filesystem, a small
>> +privileged helper (fuservicemount3) connects to the service over a UNIX
>> +socket, hands it the /dev/fuse device and any backing files it needs, and
>> +performs the mount on its behalf.
>> +
>> +The benefit is isolation. The server can run:
>> +
>> +  - as a separate, unprivileged uid/gid (systemd DynamicUser),
>> +  - with no capabilities at all,
>> +  - in private mount, network, and pid namespaces,
>> +  - with a restricted system-call filter,
>> +
>> +while still being mountable by an ordinary user. The server never gains mount
>> +permission and never runs in the caller's environment; the privileged work is
>> +confined to the fuservicemount3 helper. See example/service_ll@.service for a
>> +fully locked-down unit.
>> +
>> +
>> +Do I need this?
>> +---------------
>> +
>> +This feature exists for one specific goal: running a FUSE server with strong
>> +privilege separation, where the server itself is fully unprivileged and
>> +sandboxed while a separate setuid helper performs the mount. Getting that
>> +requires the server to be written to the fuse_service_* API (see
>> +README.service-mount-dev). An existing FUSE program that simply calls
>> +fuse_main() cannot be mounted this way unmodified: it opens /dev/fuse and
>> +performs the mount itself, which the sandbox does not allow.
>> +
>> +If all you want is to manage an ordinary FUSE filesystem with systemd --
>> +start/stop, journald logging, cgroup resource limits --
>> +you do NOT need this feature. Run the filesystem under a plain systemd service
>> +unit instead, launching it in the foreground so systemd can track it:
>> +
>> +    # myfs.service
>> +    [Service]
>> +    ExecStart=/usr/bin/myfs ... -f <mountpoint>
>> +
>> +systemd-run(1) starts the same thing as a transient unit, without a unit
>> +file. It passes the command line on as typed, so the filesystem can get any
>> +number of arguments. A unit file fixes them in its ExecStart= line, and a
>> +template unit (myfs@.service) takes only one parameter, the instance name.
>> +Set unit directives with -p:
>> +
>> +    sudo systemd-run -p MemoryMax=1G myfs <args> -f <mountpoint>
>> +
>> +This also works in the user's own service manager, as long as fusermount3 is
>> +installed setuid root:
>> +
>> +    systemd-run --user -p MemoryMax=1G myfs <args> -f <mountpoint>
>> +
>> +That filesystem still mounts the traditional way (through fusermount3) and
>> +runs in the service's own context; it is not isolated from the mount the way a
>> +service mount is.
>> +
>> +Use a service mount when you specifically want:
>> +
>> +  - the filesystem server to run as a separate, unprivileged uid with no
>> +    mount permission of its own,
>> +  - it confined to private mount/network/pid namespaces with no capabilities,
>> +  - the privileged mount work isolated in the fuservicemount3 helper,
>> +  - on-demand, socket-activated startup.
>> +
>> +In short: a plain systemd unit gives you lifecycle management; a service mount
>> +gives you lifecycle management AND isolation, at the cost of the fuse server
>> +author adapting the server to the service API.
> 
> "...the fuse server author needing to adapt..."
> 
> Everything below here looked ok to me, though I admit that there's a lot
> of documentation so I may have missed some fine details.


Sorry about about the verbose documentation, just painful to remember
all the details a few years later without it. And I also wanted to
explain to users why it is helpful.
Thanks again for looking it!


Cheers,
Bernd

      reply	other threads:[~2026-09-30 13:09 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-28 11:02 [PATCH v2 00/14] libfuse: Add mount service safety checks and tests Bernd Schubert via B4 Relay
2026-09-28 11:02 ` [PATCH v2 01/14] mount_service: move the command line check into arg_in_cmdline() Bernd Schubert via B4 Relay
2026-09-28 11:02 ` [PATCH v2 02/14] mount_service: warn about paths not named on the command line Bernd Schubert via B4 Relay
2026-09-29  2:10   ` Darrick J. Wong
2026-09-30 11:06     ` Bernd Schubert
2026-09-28 11:02 ` [PATCH v2 03/14] mount_service: refuse paths the user did not name Bernd Schubert via B4 Relay
2026-09-29  2:26   ` Darrick J. Wong
2026-09-30 11:46     ` Bernd Schubert
2026-09-28 11:02 ` [PATCH v2 04/14] mount_service: use openat to OPEN paths Bernd Schubert via B4 Relay
2026-09-29  2:27   ` Darrick J. Wong
2026-09-28 11:02 ` [PATCH v2 05/14] util: give fuservicemount3 an absolute build-tree runpath Bernd Schubert via B4 Relay
2026-09-28 11:02 ` [PATCH v2 06/14] mount.fuse: free the options on the service mount return path Bernd Schubert via B4 Relay
2026-09-28 11:02 ` [PATCH v2 07/14] example/single_file: take no sector size from a regular backing file Bernd Schubert via B4 Relay
2026-09-28 11:02 ` [PATCH v2 08/14] test: check which files fuservicemount3 opens for the server Bernd Schubert via B4 Relay
2026-09-29  3:52   ` Darrick J. Wong
2026-09-28 11:02 ` [PATCH v2 09/14] test: check what fuservicemount3 refuses Bernd Schubert via B4 Relay
2026-09-29  3:55   ` Darrick J. Wong
2026-09-28 11:02 ` [PATCH v2 10/14] test: mount the service examples through fuservicemount3 Bernd Schubert via B4 Relay
2026-09-28 11:02 ` [PATCH v2 11/14] test: run mkfs.ext4 through the service examples Bernd Schubert via B4 Relay
2026-09-28 11:02 ` [PATCH v2 12/14] fuse_service: bound argc and arg len read from the args memfd Bernd Schubert via B4 Relay
2026-09-29  2:33   ` Darrick J. Wong
2026-09-28 11:02 ` [PATCH v2 13/14] build: move the default service socket directory to /run/fuse Bernd Schubert via B4 Relay
2026-09-29  2:34   ` Darrick J. Wong
2026-09-28 11:02 ` [PATCH v2 14/14] Improve documentation for fuse service mount Bernd Schubert via B4 Relay
2026-09-29  2:43   ` Darrick J. Wong
2026-09-30 13:09     ` Bernd Schubert [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=723b3f96-58bd-4620-9dfa-5e7779cafa87@bsbernd.com \
    --to=bernd@bsbernd.com \
    --cc=djwong@kernel.org \
    --cc=fuse-devel@lists.linux.dev \
    --cc=neal@gompa.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox