public inbox for linux-fsdevel@vger.kernel.org
 help / color / mirror / Atom feed
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";

      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