From: "Darrick J. Wong" <djwong@kernel.org>
To: linux-fsdevel <linux-fsdevel@vger.kernel.org>,
linux-ext4 <linux-ext4@vger.kernel.org>,
fuse-devel <fuse-devel@lists.linux.dev>
Cc: Miklos Szeredi <miklos@szeredi.hu>,
Bernd Schubert <bernd@bsbernd.com>,
Joanne Koong <joannelkoong@gmail.com>,
Theodore Ts'o <tytso@mit.edu>, Neal Gompa <neal@gompa.dev>,
Amir Goldstein <amir73il@gmail.com>,
Christian Brauner <brauner@kernel.org>,
demiobenour@gmail.com
Subject: [RFC PATCH 4/4] httpdirfs: enable fuse systemd service mode
Date: Wed, 22 Apr 2026 16:32:55 -0700 [thread overview]
Message-ID: <20260422233255.GJ7739@frogsfrogsfrogs> (raw)
In-Reply-To: <20260422231518.GA7717@frogsfrogsfrogs>
From: Darrick J. Wong <djwong@kernel.org>
Enable use of httpdirfs as a contained systemd service.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
src/fuse_local.h | 2 +
meson.build | 26 ++++++++++++
src/fuse_local.c | 62 ++++++++++++++++++++++++++++
src/httpdirfs.socket.in | 16 +++++++
src/httpdirfs@.service.in | 99 +++++++++++++++++++++++++++++++++++++++++++++
src/main.c | 7 +++
6 files changed, 210 insertions(+), 2 deletions(-)
create mode 100644 src/httpdirfs.socket.in
create mode 100644 src/httpdirfs@.service.in
diff --git a/src/fuse_local.h b/src/fuse_local.h
index 9f459c1e1a8151..69157cd3fa7883 100644
--- a/src/fuse_local.h
+++ b/src/fuse_local.h
@@ -9,4 +9,6 @@
/* Initialise fuse */
int fuse_local_init(int argc, char **argv);
+int fuse_local_main(int argc, char *argv[], int (*main)(int argc, char **argv));
+
#endif
diff --git a/meson.build b/meson.build
index 431a1547b20bfc..5d7c4721bb756c 100644
--- a/meson.build
+++ b/meson.build
@@ -41,6 +41,32 @@ expat_dep = dependency('expat')
openssl_dep = dependency('openssl')
execinfo_dep = cc.find_library('execinfo', required: false)
+# Check for systemd support
+systemd_dep = dependency('systemd', required: false)
+if systemd_dep.found()
+ systemd_system_unit_dir = systemd_dep.get_variable(pkgconfig: 'systemd_system_unit_dir', default_value: '')
+ libfuse_service_socket_dir = fuse_dep.get_variable(pkgconfig: 'service_socket_dir', default_value: '')
+ libfuse_service_socket_perms = fuse_dep.get_variable(pkgconfig: 'service_socket_perms', default_value: '')
+endif
+
+private_cfg = configuration_data()
+if systemd_system_unit_dir == '' or libfuse_service_socket_dir == ''
+ warning('systemd service support will not be built')
+else
+ private_cfg.set('SYSTEMD_SYSTEM_UNIT_DIR', systemd_system_unit_dir)
+ private_cfg.set('LIBFUSE_SERVICE_SOCKET_DIR', libfuse_service_socket_dir)
+ private_cfg.set('LIBFUSE_SERVICE_SOCKET_PERMS', libfuse_service_socket_perms)
+ private_cfg.set('BINDIR', get_option('bindir'))
+ c_args += [ '-DHAVE_HTTPDIR_FUSE_SERVICE' ]
+
+ configure_file(input: 'src/httpdirfs@.service.in',
+ output: 'httpdirfs@.service',
+ configuration: private_cfg)
+ configure_file(input: 'src/httpdirfs.socket.in',
+ output: 'httpdirfs.socket',
+ configuration: private_cfg)
+endif
+
httpdirfs = executable('httpdirfs',
srcs,
dependencies : [gumbo_dep, libcurl_dep, fuse_dep, uuid_dep, expat_dep, openssl_dep, execinfo_dep],
diff --git a/src/fuse_local.c b/src/fuse_local.c
index ae9778f84e6ef3..c373bd67214335 100644
--- a/src/fuse_local.c
+++ b/src/fuse_local.c
@@ -6,13 +6,58 @@
/*
* must be included before including <fuse.h>
*/
-#define FUSE_USE_VERSION 30
+#define FUSE_USE_VERSION 319
#include <fuse.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
+#ifdef HAVE_HTTPDIR_FUSE_SERVICE
+# include <sys/mount.h>
+# include <fuse_service.h>
+
+static struct fuse_service *service;
+
+static inline bool fs_is_service(void)
+{
+ return fuse_service_accepted(service);
+}
+
+static int fs_service_connect(struct fuse_args *args)
+{
+ int ret;
+
+ ret = fuse_service_accept(&service);
+ if (ret)
+ return ret;
+
+ if (fuse_service_accepted(service))
+ return fuse_service_append_args(service, args);
+
+ return 0;
+}
+
+static int fs_service_run(int argc, char **argv,
+ const struct fuse_operations *fs_oper)
+{
+ struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+ int exitcode;
+
+ fuse_service_expect_mount_format(service, S_IFDIR);
+ exitcode = fuse_service_main(service, &args, fs_oper, NULL);
+
+ fuse_service_send_goodbye(service, exitcode);
+ fuse_service_destroy(&service);
+
+ return fuse_service_exit(exitcode);
+}
+#else
+# define fs_is_service(...) (false)
+# define fs_service_connect(...) (0)
+# define fs_service_run(...) (1)
+#endif /* HAVE_HTTPDIR_FUSE_SERVICE */
+
static void *fs_init(struct fuse_conn_info *conn, struct fuse_config *cfg)
{
(void) conn;
@@ -183,5 +228,20 @@ static struct fuse_operations fs_oper = {
int fuse_local_init(int argc, char **argv)
{
+ if (fs_is_service())
+ return fs_service_run(argc, argv, &fs_oper);
+
return fuse_main(argc, argv, &fs_oper, NULL);
}
+
+int fuse_local_main(int argc, char *argv[], int (*main)(int argc, char **argv))
+{
+ struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+ int ret;
+
+ ret = fs_service_connect(&args);
+ if (ret)
+ return ret;
+
+ return main(args.argc, args.argv);
+}
diff --git a/src/httpdirfs.socket.in b/src/httpdirfs.socket.in
new file mode 100644
index 00000000000000..ae587646ad707e
--- /dev/null
+++ b/src/httpdirfs.socket.in
@@ -0,0 +1,16 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2026 Oracle. All Rights Reserved.
+# Author: Darrick J. Wong <djwong@kernel.org>
+[Unit]
+Description=Socket for httpdirfs Service
+
+[Socket]
+ListenSequentialPacket=@LIBFUSE_SERVICE_SOCKET_DIR@/http
+ListenSequentialPacket=@LIBFUSE_SERVICE_SOCKET_DIR@/https
+Accept=yes
+SocketMode=@LIBFUSE_SERVICE_SOCKET_PERMS@
+RemoveOnStop=yes
+
+[Install]
+WantedBy=sockets.target
diff --git a/src/httpdirfs@.service.in b/src/httpdirfs@.service.in
new file mode 100644
index 00000000000000..d808feca3238d7
--- /dev/null
+++ b/src/httpdirfs@.service.in
@@ -0,0 +1,99 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2026 Oracle. All Rights Reserved.
+# Author: Darrick J. Wong <djwong@kernel.org>
+[Unit]
+Description=httpdirfs Service
+
+# Don't leave failed units behind, systemd does not clean them up!
+CollectMode=inactive-or-failed
+
+[Service]
+Type=exec
+ExecStart=/@BINDIR@/httpdirfs
+
+# Try to capture core dumps
+LimitCORE=infinity
+
+SyslogIdentifier=%N
+
+# No realtime CPU scheduling
+RestrictRealtime=true
+
+# Don't let us see anything in the regular system, and don't run as root
+DynamicUser=true
+ProtectSystem=strict
+ProtectHome=true
+PrivateTmp=true
+PrivateDevices=true
+PrivateUsers=true
+
+# Some network access
+ProtectHostname=true
+
+# Don't let the program mess with the kernel configuration at all
+ProtectKernelLogs=true
+ProtectKernelModules=true
+ProtectKernelTunables=true
+ProtectControlGroups=true
+ProtectProc=invisible
+RestrictNamespaces=true
+RestrictFileSystems=
+
+# Hide everything in /proc, even /proc/mounts
+ProcSubset=pid
+
+# Only allow the default personality Linux
+LockPersonality=true
+
+# No writable memory pages
+MemoryDenyWriteExecute=true
+
+# Don't let our mounts leak out to the host
+PrivateMounts=true
+
+# Restrict system calls to the native arch and only enough to get things going
+SystemCallArchitectures=native
+SystemCallFilter=@system-service
+#SystemCallFilter=~@privileged # not sure why this breaks http??
+SystemCallFilter=~@resources
+
+SystemCallFilter=~@clock
+SystemCallFilter=~@cpu-emulation
+SystemCallFilter=~@debug
+SystemCallFilter=~@module
+SystemCallFilter=~@reboot
+SystemCallFilter=~@swap
+
+SystemCallFilter=~@mount
+
+# libfuse io_uring wants to pin cores and memory
+SystemCallFilter=mbind
+SystemCallFilter=sched_setaffinity
+
+# Leave a breadcrumb if we get whacked by the system call filter
+SystemCallErrorNumber=EL3RST
+
+# Log to the kernel dmesg, just like an in-kernel ext4 driver
+StandardOutput=append:/dev/ttyprintk
+StandardError=append:/dev/ttyprintk
+
+# Run with no capabilities at all
+CapabilityBoundingSet=
+AmbientCapabilities=
+NoNewPrivileges=true
+
+# fuse4fs doesn't create files
+UMask=7777
+
+# No access to hardware /dev files at all
+ProtectClock=true
+DevicePolicy=closed
+
+# Don't mess with set[ug]id anything.
+RestrictSUIDSGID=true
+
+# Don't let OOM kills of processes in this containment group kill the whole
+# service, because we don't want filesystem drivers to go down.
+OOMPolicy=continue
+OOMScoreAdjust=-1000
diff --git a/src/main.c b/src/main.c
index c93162a9bf4129..4c23d4e5d4419f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -16,7 +16,7 @@ void parse_config_file(char ***argv, int *argc);
static char *config_path = NULL;
-int main(int argc, char **argv)
+static int __main(int argc, char **argv)
{
/*
* Automatically print help if not enough arguments are supplied
@@ -114,6 +114,11 @@ activate Sonic mode.\n");
return 0;
}
+int main(int argc, char *argv[])
+{
+ return fuse_local_main(argc, argv, __main);
+}
+
static char *get_XDG_CONFIG_HOME(void)
{
const char *default_config_subdir = "/.config";
prev parent reply other threads:[~2026-04-22 23:32 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-22 23:15 [PATCHBOMB v5] fuse/libfuse/e2fsprogs/etc: containerize ext4 for safer operation Darrick J. Wong
2026-04-22 23:18 ` [PATCHSET v5] libfuse: run fuse servers as a contained service Darrick J. Wong
2026-04-22 23:19 ` [PATCH 01/13] Refactor mount code / move common functions to mount_util.c Darrick J. Wong
2026-04-22 23:19 ` [PATCH 02/13] mount_service: add systemd socket service mounting helper Darrick J. Wong
2026-04-22 23:20 ` [PATCH 03/13] mount_service: create high level fuse helpers Darrick J. Wong
2026-04-22 23:20 ` [PATCH 04/13] mount_service: use the new mount api for the mount service Darrick J. Wong
2026-04-22 23:20 ` [PATCH 05/13] mount_service: update mtab after a successful mount Darrick J. Wong
2026-04-22 23:20 ` [PATCH 06/13] util: hoist the fuse.conf parsing and setuid mode enforcement code Darrick J. Wong
2026-04-22 23:21 ` [PATCH 07/13] util: fix checkpatch complaints in fuser_conf.[ch] Darrick J. Wong
2026-04-22 23:21 ` [PATCH 08/13] mount_service: enable unprivileged users in a similar manner as fusermount Darrick J. Wong
2026-04-22 23:21 ` [PATCH 09/13] mount.fuse3: integrate systemd service startup Darrick J. Wong
2026-04-22 23:21 ` [PATCH 10/13] mount_service: allow installation as a setuid program Darrick J. Wong
2026-04-22 23:22 ` [PATCH 11/13] example/service_ll: create a sample systemd service fuse server Darrick J. Wong
2026-04-22 23:22 ` [PATCH 12/13] example/service: create a sample systemd service for a high-level " Darrick J. Wong
2026-04-22 23:22 ` [PATCH 13/13] nullfs: support fuse systemd service mode Darrick J. Wong
2026-04-22 23:19 ` [PATCHSET v5 2/2] fuse4fs: run servers as a contained service Darrick J. Wong
2026-04-22 23:23 ` [PATCH 01/10] libext2fs: make it possible to extract the fd from an IO manager Darrick J. Wong
2026-04-22 23:24 ` [PATCH 02/10] libext2fs: fix checking for valid fds in mmp.c Darrick J. Wong
2026-04-22 23:24 ` [PATCH 03/10] unix_io: allow passing /dev/fd/XXX paths to the unixfd IO manager Darrick J. Wong
2026-04-22 23:24 ` [PATCH 04/10] libext2fs: fix MMP code to work with " Darrick J. Wong
2026-04-22 23:24 ` [PATCH 05/10] libext2fs: bump libfuse API version to 3.19 Darrick J. Wong
2026-04-22 23:25 ` [PATCH 06/10] fuse4fs: hoist some code out of fuse4fs_main Darrick J. Wong
2026-04-22 23:25 ` [PATCH 07/10] fuse4fs: enable safe service mode Darrick J. Wong
2026-04-22 23:25 ` [PATCH 08/10] fuse4fs: set proc title when in fuse " Darrick J. Wong
2026-04-22 23:25 ` [PATCH 09/10] fuse4fs: make MMP work correctly in safe " Darrick J. Wong
2026-04-22 23:26 ` [PATCH 10/10] debian: update packaging for fuse4fs service Darrick J. Wong
2026-04-22 23:29 ` [RFC PATCH 1/4] fusefatfs: enable fuse systemd service mode Darrick J. Wong
2026-04-22 23:30 ` [RFC PATCH 2/4] exfat: " Darrick J. Wong
2026-04-22 23:32 ` [RFC PATCH 3/4] fuseiso: enable " Darrick J. Wong
2026-04-22 23:32 ` Darrick J. Wong [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=20260422233255.GJ7739@frogsfrogsfrogs \
--to=djwong@kernel.org \
--cc=amir73il@gmail.com \
--cc=bernd@bsbernd.com \
--cc=brauner@kernel.org \
--cc=demiobenour@gmail.com \
--cc=fuse-devel@lists.linux.dev \
--cc=joannelkoong@gmail.com \
--cc=linux-ext4@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=miklos@szeredi.hu \
--cc=neal@gompa.dev \
--cc=tytso@mit.edu \
/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