mountfsd: add new systemd-mountfsd component

This commit is contained in:
Lennart Poettering
2023-03-09 12:27:29 +01:00
parent 54452c7b2a
commit 702a52f4b5
19 changed files with 1407 additions and 1 deletions

View File

@@ -676,3 +676,21 @@ Tools using the Varlink protocol (such as `varlinkctl`) or sd-bus (such as
service. Takes a file system path: if specified the tool will listen on an
`AF_UNIX` stream socket on the specified path in addition to whatever else it
would listen on.
`systemd-mountfsd`:
* `$SYSTEMD_MOUNTFSD_TRUSTED_DIRECTORIES` takes a boolean argument. If true
disk images from the usual disk image directories (`/var/lib/machines/`,
`/var/lib/confexts/`, …) will be considered "trusted", i.e. are validated
with a more relaxed image policy (typically not requiring Verity signature
checking) than those from other directories (where Verity signature checks
are mandatory). If false all images are treated the same, regardless if
placed in the usual disk image directories or elsewhere. If not set defaults
to a compile time setting.
* `$SYSTEMD_MOUNTFSD_IMAGE_POLICY_TRUSTED`,
`$SYSTEMD_MOUNTFSD_IMAGE_POLICY_UNTRUSTED` the default image policy to
apply to trusted and untrusted disk images. An image is considered trusted if
placed in a trusted disk image directory (see above), or if suitable polkit
authentication was acquired. See `systemd.image-policy(7)` for the valid
syntax for image policy strings.

View File

@@ -999,6 +999,7 @@ manpages = [
['systemd-measure', '1', [], 'HAVE_TPM2 HAVE_BLKID HAVE_OPENSSL'],
['systemd-modules-load.service', '8', ['systemd-modules-load'], 'HAVE_KMOD'],
['systemd-mount', '1', ['systemd-umount'], ''],
['systemd-mountfsd.service', '8', ['systemd-mountfsd'], 'ENABLE_MOUNTFSD'],
['systemd-network-generator.service', '8', ['systemd-network-generator'], ''],
['systemd-networkd-wait-online.service',
'8',

View File

@@ -0,0 +1,70 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
<refentry id="systemd-mountfsd.service" conditional='ENABLE_MOUNTFSD'>
<refentryinfo>
<title>systemd-mountfsd.service</title>
<productname>systemd</productname>
</refentryinfo>
<refmeta>
<refentrytitle>systemd-mountfsd.service</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
<refname>systemd-mountfsd.service</refname>
<refname>systemd-mountfsd</refname>
<refpurpose>Disk Image File System Mount Service</refpurpose>
</refnamediv>
<refsynopsisdiv>
<para><filename>systemd-mountfsd.service</filename></para>
<para><filename>/usr/lib/systemd/systemd-mountfsd</filename></para>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><command>systemd-mountfsd</command> is a system service that dissects disk images, and returns mount
file descriptors for the file systems contained therein to clients, via a Varlink IPC API.</para>
<para>The disk images provided must contain a raw file system image or must follow the <ulink
url="https://uapi-group.org/specifications/specs/discoverable_partitions_specification/">Discoverable
Partitions Specification</ulink>. Before mounting any file systems authenticity of the disk image is
established in one or a combination of the following ways:</para>
<orderedlist>
<listitem><para>If the disk image is located in a regular file in one of the directories
<filename>/var/lib/machines/</filename>, <filename>/var/lib/portables/</filename>,
<filename>/var/lib/extensions/</filename>, <filename>/var/lib/confexts/</filename> or their
counterparts in the <filename>/etc/</filename>, <filename>/run/</filename>,
<filename>/usr/lib/</filename> it is assumed to be trusted.</para></listitem>
<listitem><para>If the disk image contains a Verity enabled disk image, along with a signature
partition with a key in the kernel keyring or in <filename>/etc/verity.d/</filename> (and related
directories) the disk image is considered trusted.</para></listitem>
</orderedlist>
<para>This service provides one <ulink url="https://varlink.org/">Varlink</ulink> service:
<constant>io.systemd.MountFileSystem</constant> which accepts a file descriptor to a regular file or
block device, and returns a number of file descriptors referring to an <function>fsmount()</function>
file descriptor the client may then attach to a path of their choice.</para>
<para>The returned mounts are automatically allowlisted in the per-user-namespace allowlist maintained by
<citerefentry><refentrytitle>systemd-nsresourced.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
<para>The file systems are automatically fsck'ed before mounting.</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-nsresourced.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@@ -272,6 +272,7 @@ conf.set_quoted('SYSTEMD_TEST_DATA', testdata_dir)
conf.set_quoted('SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH', bindir / 'systemd-tty-ask-password-agent')
conf.set_quoted('SYSTEMD_UPDATE_HELPER_PATH', libexecdir / 'systemd-update-helper')
conf.set_quoted('SYSTEMD_USERWORK_PATH', libexecdir / 'systemd-userwork')
conf.set_quoted('SYSTEMD_MOUNTWORK_PATH', libexecdir / 'systemd-mountwork')
conf.set_quoted('SYSTEMD_NSRESOURCEWORK_PATH', libexecdir / 'systemd-nsresourcework')
conf.set_quoted('SYSTEMD_VERITYSETUP_PATH', libexecdir / 'systemd-veritysetup')
conf.set_quoted('SYSTEM_CONFIG_UNIT_DIR', pkgsysconfdir / 'system')
@@ -1598,6 +1599,8 @@ conf.set10('ENABLE_REMOTE', have)
feature = get_option('vmspawn').disable_auto_if(conf.get('BUILD_MODE_DEVELOPER') == 0)
conf.set10('ENABLE_VMSPAWN', feature.allowed())
conf.set10('DEFAULT_MOUNTFSD_TRUSTED_DIRECTORIES', get_option('default-mountfsd-trusted-directories'))
foreach term : ['analyze',
'backlight',
'binfmt',
@@ -1618,6 +1621,7 @@ foreach term : ['analyze',
'localed',
'logind',
'machined',
'mountfsd',
'networkd',
'nscd',
'nsresourced',
@@ -2276,6 +2280,7 @@ subdir('src/locale')
subdir('src/login')
subdir('src/machine')
subdir('src/machine-id-setup')
subdir('src/mountfsd')
subdir('src/modules-load')
subdir('src/mount')
subdir('src/network')

View File

@@ -124,6 +124,8 @@ option('portabled', type : 'boolean',
description : 'install the systemd-portabled stack')
option('sysext', type : 'boolean',
description : 'install the systemd-sysext stack')
option('mountfsd', type : 'boolean',
description : 'install the systemd-mountfsd stack')
option('userdb', type : 'boolean',
description : 'install the systemd-userdbd stack')
option('homed', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' },
@@ -528,3 +530,6 @@ option('vmlinux-h', type : 'combo', choices : ['auto', 'provided', 'generated',
description : 'which vmlinux.h to use')
option('vmlinux-h-path', type : 'string', value : '',
description : 'path to vmlinux.h to use')
option('default-mountfsd-trusted-directories', type : 'boolean', value: false,
description : 'controls whether mountfsd should apply a relaxed policy on DDIs in system DDI directories')

View File

@@ -23,9 +23,10 @@ enable systemd-homed.service
enable systemd-homed-activate.service
enable systemd-homed-firstboot.service
enable systemd-journald-audit.socket
enable systemd-mountfsd.socket
enable systemd-network-generator.service
enable systemd-networkd-wait-online.service
enable systemd-networkd.service
enable systemd-networkd-wait-online.service
enable systemd-nsresourced.socket
enable systemd-pstore.service
enable systemd-resolved.service

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?> <!--*-nxml-*-->
<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
"https://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1-or-later
This file is part of systemd.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
-->
<policyconfig>
<vendor>The systemd Project</vendor>
<vendor_url>https://systemd.io</vendor_url>
<!-- Allow mounting DDIs into the host user namespace -->
<action id="io.systemd.mount-file-system.mount-image">
<!-- This action is generally checked first: we'll first try to mount the image with
signature checks on. If that fails, we'll retry with the untrusted action below. -->
<description gettext-domain="systemd">Allow mounting of file system image</description>
<message gettext-domain="systemd">Authentication is required for an application to mount a file system image.</message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
<action id="io.systemd.mount-file-system.mount-untrusted-image">
<!-- If the image cannot be mounted via the regular action because it is not signed by a
recognized key, we'll try this action. -->
<description gettext-domain="systemd">Allow mounting of untrusted file system image</description>
<message gettext-domain="systemd">Authentication is required for an application to mount a cryptographically unsigned file system image or an image whose cryptographic signature is not recognized.</message>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.imply">io.systemd.mount-file-system.mount-image</annotate>
</action>
<!-- Allow mounting DDIs into a private user namespace -->
<action id="io.systemd.mount-file-system.mount-image-privately">
<description gettext-domain="systemd">Allow private mounting of trusted file system image</description>
<message gettext-domain="systemd">Authentication is required for an application to privately mount a file system image or an image whose cryptographic signature is recognized.</message>
<defaults>
<allow_any>yes</allow_any>
<allow_inactive>yes</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
<action id="io.systemd.mount-file-system.mount-untrusted-image-privately">
<description gettext-domain="systemd">Allow private mounting of untrusted file system image</description>
<message gettext-domain="systemd">Authentication is required for an application to privately mount a cryptographically unsigned file system image or an image whose cryptographic signature is not recognized.</message>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.imply">io.systemd.mount-file-system.mount-image-privately</annotate>
</action>
</policyconfig>

28
src/mountfsd/meson.build Normal file
View File

@@ -0,0 +1,28 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
systemd_mountwork_sources = files(
'mountwork.c',
)
systemd_mountfsd_sources = files(
'mountfsd.c',
'mountfsd-manager.c',
)
executables += [
libexec_template + {
'name' : 'systemd-mountfsd',
'conditions' : ['ENABLE_MOUNTFSD'],
'sources' : systemd_mountfsd_sources,
},
libexec_template + {
'name' : 'systemd-mountwork',
'conditions' : ['ENABLE_MOUNTFSD'],
'sources' : systemd_mountwork_sources,
'link_with' : common_libs,
'dependencies' : common_deps,
},
]
install_data('io.systemd.mount-file-system.policy',
install_dir : polkitpolicydir)

View File

@@ -0,0 +1,277 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <sys/wait.h>
#include "sd-daemon.h"
#include "build-path.h"
#include "common-signal.h"
#include "env-util.h"
#include "fd-util.h"
#include "fs-util.h"
#include "mkdir.h"
#include "mountfsd-manager.h"
#include "process-util.h"
#include "set.h"
#include "signal-util.h"
#include "socket-util.h"
#include "stdio-util.h"
#include "umask-util.h"
#define LISTEN_TIMEOUT_USEC (25 * USEC_PER_SEC)
static int start_workers(Manager *m, bool explicit_request);
static size_t manager_current_workers(Manager *m) {
assert(m);
return set_size(m->workers_fixed) + set_size(m->workers_dynamic);
}
static int on_worker_exit(sd_event_source *s, const siginfo_t *si, void *userdata) {
Manager *m = ASSERT_PTR(userdata);
assert(s);
assert_se(!set_remove(m->workers_dynamic, s) != !set_remove(m->workers_fixed, s));
sd_event_source_disable_unref(s);
if (si->si_code == CLD_EXITED) {
if (si->si_status == EXIT_SUCCESS)
log_debug("Worker " PID_FMT " exited successfully.", si->si_pid);
else
log_warning("Worker " PID_FMT " died with a failure exit status %i, ignoring.", si->si_pid, si->si_status);
} else if (si->si_code == CLD_KILLED)
log_warning("Worker " PID_FMT " was killed by signal %s, ignoring.", si->si_pid, signal_to_string(si->si_status));
else if (si->si_code == CLD_DUMPED)
log_warning("Worker " PID_FMT " dumped core by signal %s, ignoring.", si->si_pid, signal_to_string(si->si_status));
else
log_warning("Got unexpected exit code via SIGCHLD, ignoring.");
(void) start_workers(m, /* explicit_request= */ false); /* Fill up workers again if we fell below the low watermark */
return 0;
}
static int on_sigusr2(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
Manager *m = ASSERT_PTR(userdata);
(void) start_workers(m, /* explicit_request= */ true); /* Workers told us there's more work, let's add one more worker as long as we are below the high watermark */
return 0;
}
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
event_source_hash_ops,
sd_event_source,
(void (*)(const sd_event_source*, struct siphash*)) trivial_hash_func,
(int (*)(const sd_event_source*, const sd_event_source*)) trivial_compare_func,
sd_event_source_disable_unref);
int manager_new(Manager **ret) {
_cleanup_(manager_freep) Manager *m = NULL;
int r;
m = new(Manager, 1);
if (!m)
return -ENOMEM;
*m = (Manager) {
.listen_fd = -EBADF,
.worker_ratelimit = {
.interval = 5 * USEC_PER_SEC,
.burst = 50,
},
};
r = sd_event_new(&m->event);
if (r < 0)
return r;
r = sd_event_set_signal_exit(m->event, true);
if (r < 0)
return r;
r = sd_event_add_signal(m->event, NULL, (SIGRTMIN+18)|SD_EVENT_SIGNAL_PROCMASK, sigrtmin18_handler, NULL);
if (r < 0)
return r;
r = sd_event_add_memory_pressure(m->event, NULL, NULL, NULL);
if (r < 0)
log_debug_errno(r, "Failed allocate memory pressure event source, ignoring: %m");
r = sd_event_set_watchdog(m->event, true);
if (r < 0)
log_debug_errno(r, "Failed to enable watchdog handling, ignoring: %m");
r = sd_event_add_signal(m->event, NULL, SIGUSR2|SD_EVENT_SIGNAL_PROCMASK, on_sigusr2, m);
if (r < 0)
return r;
*ret = TAKE_PTR(m);
return 0;
}
Manager* manager_free(Manager *m) {
if (!m)
return NULL;
set_free(m->workers_fixed);
set_free(m->workers_dynamic);
/* Note: we rely on PR_DEATHSIG to kill the workers for us */
sd_event_unref(m->event);
return mfree(m);
}
static int start_one_worker(Manager *m) {
_cleanup_(sd_event_source_disable_unrefp) sd_event_source *source = NULL;
bool fixed;
pid_t pid;
int r;
assert(m);
fixed = set_size(m->workers_fixed) < MOUNTFS_WORKERS_MIN;
r = safe_fork_full(
"(sd-worker)",
/* stdio_fds= */ NULL,
&m->listen_fd, 1,
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_CLOSE_ALL_FDS,
&pid);
if (r < 0)
return log_error_errno(r, "Failed to fork new worker child: %m");
if (r == 0) {
char pids[DECIMAL_STR_MAX(pid_t)];
/* Child */
if (m->listen_fd == 3) {
r = fd_cloexec(3, false);
if (r < 0) {
log_error_errno(r, "Failed to turn off O_CLOEXEC for fd 3: %m");
_exit(EXIT_FAILURE);
}
} else {
if (dup2(m->listen_fd, 3) < 0) { /* dup2() creates with O_CLOEXEC off */
log_error_errno(errno, "Failed to move listen fd to 3: %m");
_exit(EXIT_FAILURE);
}
safe_close(m->listen_fd);
}
xsprintf(pids, PID_FMT, pid);
if (setenv("LISTEN_PID", pids, 1) < 0) {
log_error_errno(errno, "Failed to set $LISTEN_PID: %m");
_exit(EXIT_FAILURE);
}
if (setenv("LISTEN_FDS", "1", 1) < 0) {
log_error_errno(errno, "Failed to set $LISTEN_FDS: %m");
_exit(EXIT_FAILURE);
}
if (setenv("MOUNTFS_FIXED_WORKER", one_zero(fixed), 1) < 0) {
log_error_errno(errno, "Failed to set $MOUNTFS_FIXED_WORKER: %m");
_exit(EXIT_FAILURE);
}
r = setenv_systemd_log_level();
if (r < 0) {
log_error_errno(r, "Failed to set $SYSTEMD_LOG_LEVEL: %m");
_exit(EXIT_FAILURE);
}
r = invoke_callout_binary(SYSTEMD_MOUNTWORK_PATH, STRV_MAKE("systemd-mountwork", "xxxxxxxxxxxxxxxx")); /* With some extra space rename_process() can make use of */
log_error_errno(r, "Failed start worker process: %m");
_exit(EXIT_FAILURE);
}
r = sd_event_add_child(m->event, &source, pid, WEXITED, on_worker_exit, m);
if (r < 0)
return log_error_errno(r, "Failed to watch child " PID_FMT ": %m", pid);
r = set_ensure_put(
fixed ? &m->workers_fixed : &m->workers_dynamic,
&event_source_hash_ops,
source);
if (r < 0)
return log_error_errno(r, "Failed to add child process to set: %m");
TAKE_PTR(source);
return 0;
}
static int start_workers(Manager *m, bool explicit_request) {
int r;
assert(m);
for (;;) {
size_t n;
n = manager_current_workers(m);
log_debug("%zu workers running.", n);
if (n >= MOUNTFS_WORKERS_MIN && (!explicit_request || n >= MOUNTFS_WORKERS_MAX))
break;
if (!ratelimit_below(&m->worker_ratelimit)) {
/* If we keep starting workers too often, let's fail the whole daemon, something is wrong */
sd_event_exit(m->event, EXIT_FAILURE);
return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN), "Worker threads requested too frequently, something is wrong.");
}
r = start_one_worker(m);
if (r < 0)
return r;
explicit_request = false;
}
return 0;
}
int manager_startup(Manager *m) {
int n;
assert(m);
assert(m->listen_fd < 0);
n = sd_listen_fds(false);
if (n < 0)
return log_error_errno(n, "Failed to determine number of passed file descriptors: %m");
if (n > 1)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Expected one listening fd, got %i.", n);
if (n == 1)
m->listen_fd = SD_LISTEN_FDS_START;
else {
static const union sockaddr_union sockaddr = {
.un.sun_family = AF_UNIX,
.un.sun_path = "/run/systemd/io.systemd.MountFileSystem",
};
m->listen_fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
if (m->listen_fd < 0)
return log_error_errno(errno, "Failed to bind on socket: %m");
(void) sockaddr_un_unlink(&sockaddr.un);
WITH_UMASK(0000)
if (bind(m->listen_fd, &sockaddr.sa, SOCKADDR_UN_LEN(sockaddr.un)) < 0)
return log_error_errno(errno, "Failed to bind socket: %m");
if (listen(m->listen_fd, SOMAXCONN) < 0)
return log_error_errno(errno, "Failed to listen on socket: %m");
}
/* Let's make sure every accept() call on this socket times out after 25s. This allows workers to be
* GC'ed on idle */
if (setsockopt(m->listen_fd, SOL_SOCKET, SO_RCVTIMEO, TIMEVAL_STORE(LISTEN_TIMEOUT_USEC), sizeof(struct timeval)) < 0)
return log_error_errno(errno, "Failed to se SO_RCVTIMEO: %m");
return start_workers(m, /* explicit_request= */ false);
}

View File

@@ -0,0 +1,30 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "sd-bus.h"
#include "sd-event.h"
typedef struct Manager Manager;
#include "hashmap.h"
#include "ratelimit.h"
#define MOUNTFS_WORKERS_MIN 3
#define MOUNTFS_WORKERS_MAX 4096
struct Manager {
sd_event *event;
Set *workers_fixed; /* Workers 0…MOUNTFS_WORKERS_MIN */
Set *workers_dynamic; /* Workers MOUNTFS_WORKERS_MIN+1…MOUNTFS_WORKERS_MAX */
int listen_fd;
RateLimit worker_ratelimit;
};
int manager_new(Manager **ret);
Manager* manager_free(Manager *m);
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
int manager_startup(Manager *m);

43
src/mountfsd/mountfsd.c Normal file
View File

@@ -0,0 +1,43 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <sys/stat.h>
#include <sys/types.h>
#include "daemon-util.h"
#include "log.h"
#include "main-func.h"
#include "mountfsd-manager.h"
#include "signal-util.h"
static int run(int argc, char *argv[]) {
_unused_ _cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
_cleanup_(manager_freep) Manager *m = NULL;
int r;
log_setup();
umask(0022);
if (argc != 1)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments.");
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
r = manager_new(&m);
if (r < 0)
return log_error_errno(r, "Could not create manager: %m");
r = manager_startup(m);
if (r < 0)
return log_error_errno(r, "Failed to start up daemon: %m");
notify_stop = notify_start(NOTIFY_READY, NOTIFY_STOPPING);
r = sd_event_loop(m->event);
if (r < 0)
return log_error_errno(r, "Event loop failed: %m");
return 0;
}
DEFINE_MAIN_FUNCTION(run);

703
src/mountfsd/mountwork.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -181,6 +181,7 @@ shared_sources = files(
'varlink-io.systemd.Hostname.c',
'varlink-io.systemd.Journal.c',
'varlink-io.systemd.ManagedOOM.c',
'varlink-io.systemd.MountFileSystem.c',
'varlink-io.systemd.NamespaceResource.c',
'varlink-io.systemd.Network.c',
'varlink-io.systemd.PCRExtend.c',

View File

@@ -0,0 +1,69 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "varlink-io.systemd.MountFileSystem.h"
static VARLINK_DEFINE_ENUM_TYPE(
PartitionDesignator,
VARLINK_DEFINE_ENUM_VALUE(root),
VARLINK_DEFINE_ENUM_VALUE(usr),
VARLINK_DEFINE_ENUM_VALUE(home),
VARLINK_DEFINE_ENUM_VALUE(srv),
VARLINK_DEFINE_ENUM_VALUE(esp),
VARLINK_DEFINE_ENUM_VALUE(xbootldr),
VARLINK_DEFINE_ENUM_VALUE(swap),
VARLINK_DEFINE_ENUM_VALUE(root_verity),
VARLINK_DEFINE_ENUM_VALUE(usr_verity),
VARLINK_DEFINE_ENUM_VALUE(root_verity_sig),
VARLINK_DEFINE_ENUM_VALUE(usr_verity_sig),
VARLINK_DEFINE_ENUM_VALUE(tmp),
VARLINK_DEFINE_ENUM_VALUE(var));
static VARLINK_DEFINE_STRUCT_TYPE(
PartitionInfo,
VARLINK_DEFINE_FIELD(designator, VARLINK_STRING, 0),
VARLINK_DEFINE_FIELD(writable, VARLINK_BOOL, 0),
VARLINK_DEFINE_FIELD(growFileSystem, VARLINK_BOOL, 0),
VARLINK_DEFINE_FIELD(partitionNumber, VARLINK_INT, VARLINK_NULLABLE),
VARLINK_DEFINE_FIELD(architecture, VARLINK_STRING, VARLINK_NULLABLE),
VARLINK_DEFINE_FIELD(partitionUuid, VARLINK_STRING, VARLINK_NULLABLE),
VARLINK_DEFINE_FIELD(fileSystemType, VARLINK_STRING, 0),
VARLINK_DEFINE_FIELD(partitionLabel, VARLINK_STRING, VARLINK_NULLABLE),
VARLINK_DEFINE_FIELD(size, VARLINK_INT, 0),
VARLINK_DEFINE_FIELD(offset, VARLINK_INT, 0),
VARLINK_DEFINE_FIELD(mountFileDescriptor, VARLINK_INT, 0));
static VARLINK_DEFINE_METHOD(
MountImage,
VARLINK_DEFINE_INPUT(imageFileDescriptor, VARLINK_INT, 0),
VARLINK_DEFINE_INPUT(userNamespaceFileDescriptor, VARLINK_INT, VARLINK_NULLABLE),
VARLINK_DEFINE_INPUT(readOnly, VARLINK_BOOL, VARLINK_NULLABLE),
VARLINK_DEFINE_INPUT(growFileSystems, VARLINK_BOOL, VARLINK_NULLABLE),
VARLINK_DEFINE_INPUT(password, VARLINK_STRING, VARLINK_NULLABLE),
VARLINK_DEFINE_INPUT(imagePolicy, VARLINK_STRING, VARLINK_NULLABLE),
VARLINK_DEFINE_INPUT(allowInteractiveAuthentication, VARLINK_BOOL, VARLINK_NULLABLE),
VARLINK_DEFINE_OUTPUT_BY_TYPE(partitions, PartitionInfo, VARLINK_ARRAY),
VARLINK_DEFINE_OUTPUT(imagePolicy, VARLINK_STRING, 0),
VARLINK_DEFINE_OUTPUT(imageSize, VARLINK_INT, 0),
VARLINK_DEFINE_OUTPUT(sectorSize, VARLINK_INT, 0),
VARLINK_DEFINE_OUTPUT(imageName, VARLINK_STRING, VARLINK_NULLABLE),
VARLINK_DEFINE_OUTPUT(imageUuid, VARLINK_STRING, VARLINK_NULLABLE));
static VARLINK_DEFINE_ERROR(IncompatibleImage);
static VARLINK_DEFINE_ERROR(MultipleRootPartitionsFound);
static VARLINK_DEFINE_ERROR(RootPartitionNotFound);
static VARLINK_DEFINE_ERROR(DeniedByImagePolicy);
static VARLINK_DEFINE_ERROR(KeyNotFound);
static VARLINK_DEFINE_ERROR(VerityFailure);
VARLINK_DEFINE_INTERFACE(
io_systemd_MountFileSystem,
"io.systemd.MountFileSystem",
&vl_type_PartitionDesignator,
&vl_type_PartitionInfo,
&vl_method_MountImage,
&vl_error_IncompatibleImage,
&vl_error_MultipleRootPartitionsFound,
&vl_error_RootPartitionNotFound,
&vl_error_DeniedByImagePolicy,
&vl_error_KeyNotFound,
&vl_error_VerityFailure);

View File

@@ -0,0 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "varlink-idl.h"
extern const VarlinkInterface vl_interface_io_systemd_MountFileSystem;

View File

@@ -12,6 +12,7 @@
#include "varlink-io.systemd.Credentials.h"
#include "varlink-io.systemd.Journal.h"
#include "varlink-io.systemd.ManagedOOM.h"
#include "varlink-io.systemd.MountFileSystem.h"
#include "varlink-io.systemd.NamespaceResource.h"
#include "varlink-io.systemd.Network.h"
#include "varlink-io.systemd.PCRExtend.h"
@@ -140,6 +141,8 @@ TEST(parse_format) {
print_separator();
test_parse_format_one(&vl_interface_io_systemd_ManagedOOM);
print_separator();
test_parse_format_one(&vl_interface_io_systemd_MountFileSystem);
print_separator();
test_parse_format_one(&vl_interface_io_systemd_Network);
print_separator();
test_parse_format_one(&vl_interface_io_systemd_oom);

View File

@@ -732,6 +732,14 @@ units = [
'file' : 'systemd-userdbd.socket',
'conditions' : ['ENABLE_USERDB'],
},
{
'file' : 'systemd-mountfsd.service.in',
'conditions' : ['ENABLE_MOUNTFSD'],
},
{
'file' : 'systemd-mountfsd.socket',
'conditions' : ['ENABLE_MOUNTFSD'],
},
{
'file' : 'systemd-nsresourced.service.in',
'conditions' : ['ENABLE_NSRESOURCED'],

View File

@@ -0,0 +1,46 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=DDI File System Mounter
Documentation=man:systemd-mountfsd.service(8)
Requires=systemd-mountfsd.socket
After=systemd-mountfsd.socket
Conflicts=shutdown.target
Before=sysinit.target shutdown.target
DefaultDependencies=no
[Service]
#CapabilityBoundingSet=CAP_DAC_READ_SEARCH CAP_SYS_RESOURCE CAP_BPF CAP_PERFMON CAP_SETGID CAP_SETUID
ExecStart={{LIBEXECDIR}}/systemd-mountfsd
IPAddressDeny=any
LimitNOFILE={{HIGH_RLIMIT_NOFILE}}
LockPersonality=yes
MemoryDenyWriteExecute=yes
NoNewPrivileges=yes
ProtectProc=invisible
ProtectControlGroups=yes
ProtectHome=yes
ProtectHostname=yes
ProtectKernelLogs=yes
ProtectKernelModules=yes
ProtectSystem=strict
RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
RestrictRealtime=yes
RestrictSUIDSGID=yes
SystemCallArchitectures=native
SystemCallErrorNumber=EPERM
SystemCallFilter=@system-service @mount
Type=notify
NotifyAccess=all
FileDescriptorStoreMax=4096
{{SERVICE_WATCHDOG}}
[Install]
Also=systemd-mountfsd.socket

View File

@@ -0,0 +1,22 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=DDI File System Mounter Socket
Documentation=man:systemd-mountfsd.service(8)
DefaultDependencies=no
Conflicts=shutdown.target
Before=sockets.target shutdown.target
[Socket]
ListenStream=/run/systemd/io.systemd.MountFileSystem
SocketMode=0666
[Install]
WantedBy=sockets.target