Compare commits

...

8 Commits

Author SHA1 Message Date
Luca Boccassi edf9cf0a22
Merge 9c2dd1b787 into bbec1c87d3 2024-11-26 11:56:12 -08:00
gerblesh bbec1c87d3 sysext: set SELinux context for hierarchies and workdir 2024-11-26 17:47:32 +00:00
Yu Watanabe f29a07f3fc man: several more assorted fixes
Continuation of 4ebbb5bfe8.
Closes #35307.
2024-11-26 17:28:14 +01:00
Luca Boccassi 0566bd9643
machine: increase timeouts in attempt to fix #35115 (#35117)
An attempt to fix https://github.com/systemd/systemd/issues/35115
2024-11-26 16:12:56 +00:00
Lennart Poettering 7b4b3a8f7b sd-varlink: fix bug when enqueuing messages with fds asynchronously
When determining the poll events to wait for we need to take the queue
of pending messages that carry fds into account. Otherwise we might end
up not waking up if such an fd-carrying message is enqueued
asynchronously (i.e. not from a dispatch callback).
2024-11-26 16:06:53 +00:00
Luca Boccassi 9c2dd1b787 test: split VM-only subtests from TEST-74-AUX-UTILS to new VM-only test
TEST-74-AUX-UTILS covers many subtests, as it's a catch-all job, and a few
need a VM to run. The job is thus marked VM-only. But that means in settings
where we can't run VM tests (no KVM available), the entire thing is skipped,
losing tons of coverage that doesn't need skipping.

Move the VM-only subtests to TEST-87-AUX-UTILS-VM that is configured to only
run in VMs under both runners. This way we keep the existing tests as-is, and
we can add new VM-only tests without worrying. This is how the rest of the
tests are organized.

Follow-up for f4faac2073
2024-11-25 16:09:22 +00:00
Ivan Kruglov 3aa3f130c1 machine: add debug for systemd-nspawn@.service 2024-11-19 19:12:32 +01:00
Ivan Kruglov df18408ac6 machine: increase timeouts in attempt to fix #35115 2024-11-19 18:04:27 +01:00
25 changed files with 370 additions and 200 deletions

View File

@ -128,7 +128,8 @@
<para>If <option>-keep-download=yes</option> is specified the image will be downloaded and stored in
a read-only subvolume/directory in the image directory that is named after the specified URL and its
HTTP etag. A writable snapshot is then taken from this subvolume, and named after the specified local
HTTP etag (see <ulink url="https://en.wikipedia.org/wiki/HTTP_ETag">HTTP ETag</ulink> for more
information). A writable snapshot is then taken from this subvolume, and named after the specified local
name. This behavior ensures that creating multiple instances of the same URL is efficient, as
multiple downloads are not necessary. In order to create only the read-only image, and avoid creating
its writable snapshot, specify <literal>-</literal> as local name.</para>

View File

@ -28,7 +28,9 @@
<title>Description</title>
<para><command>pam_systemd_loadkey</command> reads a NUL-separated password list from the kernel keyring,
and sets the last password in the list as the PAM authtok.</para>
and sets the last password in the list as the PAM authtok, which can be used by e.g.
<citerefentry project='man-pages'><refentrytitle>pam_get_authtok</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
</para>
<para>The password list is supposed to be stored in the "user" keyring of the root user,
by an earlier call to

View File

@ -61,7 +61,10 @@
<literal>systemd-run0</literal> PAM stack.</para>
<para>Note that <command>run0</command> is implemented as an alternative multi-call invocation of
<citerefentry><refentrytitle>systemd-run</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para>
<citerefentry><refentrytitle>systemd-run</refentrytitle><manvolnum>1</manvolnum></citerefentry>. That is,
<command>run0</command> is a symbolic link to <command>systemd-run</command> executable file, and it
behaves as <command>run0</command> if it is invoked through the symbolic link, otherwise behaves as
<command>systemd-run</command>.</para>
</refsect1>
<refsect1>

View File

@ -41,8 +41,10 @@
<refsect1>
<title>Kernel Command Line</title>
<para><filename>systemd-rfkill</filename> understands the
following kernel command line parameter:</para>
<para>
<command>systemd-rfkill</command> understands the following kernel command line parameter. See also
<citerefentry><refentrytitle>kernel-command-line</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
</para>
<variablelist class='kernel-commandline-options'>
<varlistentry>

View File

@ -394,9 +394,9 @@
<listitem><para>SBAT metadata associated with the UKI or addon. SBAT policies are useful to revoke
whole groups of UKIs or addons with a single, static policy update that does not take space in
DBX/MOKX. If not specified manually, a default metadata entry consisting of
<literal>uki,1,UKI,uki,1,https://uapi-group.org/specifications/specs/unified_kernel_image/</literal>
<programlisting>uki,1,UKI,uki,1,https://uapi-group.org/specifications/specs/unified_kernel_image/</programlisting>
for UKIs and
<literal>uki-addon,1,UKI Addon,addon,1,https://www.freedesktop.org/software/systemd/man/latest/systemd-stub.html</literal>
<programlisting>uki-addon,1,UKI Addon,addon,1,https://www.freedesktop.org/software/systemd/man/latest/systemd-stub.html</programlisting>
for addons will be used, to ensure it is always possible to revoke them. For more information on
SBAT see <ulink url="https://github.com/rhboot/shim/blob/main/SBAT.md">Shim documentation</ulink>.
</para>

View File

@ -289,7 +289,8 @@ int write_string_file_full(
const char *fn,
const char *line,
WriteStringFileFlags flags,
const struct timespec *ts) {
const struct timespec *ts,
const char *label_fn) {
bool call_label_ops_post = false, made_file = false;
_cleanup_fclose_ FILE *f = NULL;
@ -321,7 +322,8 @@ int write_string_file_full(
mode_t mode = write_string_file_flags_to_mode(flags);
if (FLAGS_SET(flags, WRITE_STRING_FILE_LABEL|WRITE_STRING_FILE_CREATE)) {
r = label_ops_pre(dir_fd, fn, mode);
const char *lookup = label_fn ? label_fn : fn;
r = label_ops_pre(dir_fd, lookup, mode);
if (r < 0)
goto fail;

View File

@ -51,12 +51,13 @@ int write_string_stream_full(FILE *f, const char *line, WriteStringFileFlags fla
static inline int write_string_stream(FILE *f, const char *line, WriteStringFileFlags flags) {
return write_string_stream_full(f, line, flags, /* ts= */ NULL);
}
int write_string_file_full(int dir_fd, const char *fn, const char *line, WriteStringFileFlags flags, const struct timespec *ts);
int write_string_file_full(int dir_fd, const char *fn, const char *line, WriteStringFileFlags flags, const struct timespec *ts, const char *label_fn);
static inline int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags) {
return write_string_file_full(AT_FDCWD, fn, line, flags, /* ts= */ NULL);
return write_string_file_full(AT_FDCWD, fn, line, flags, /* ts= */ NULL, /*label_fn=*/ NULL);
}
static inline int write_string_file_at(int dir_fd, const char *fn, const char *line, WriteStringFileFlags flags) {
return write_string_file_full(dir_fd, fn, line, flags, /* ts= */ NULL);
return write_string_file_full(dir_fd, fn, line, flags, /* ts= */ NULL, /*label_fn=*/ NULL);
}
int write_string_filef(const char *fn, WriteStringFileFlags flags, const char *format, ...) _printf_(3, 4);

View File

@ -1698,7 +1698,8 @@ _public_ int sd_varlink_get_events(sd_varlink *v) {
ret |= EPOLLIN;
if (!v->write_disconnected &&
v->output_buffer_size > 0)
(v->output_queue ||
v->output_buffer_size > 0))
ret |= EPOLLOUT;
return ret;

View File

@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <linux/loop.h>
@ -45,6 +46,7 @@
#include "process-util.h"
#include "rm-rf.h"
#include "sort-util.h"
#include "selinux-util.h"
#include "string-table.h"
#include "string-util.h"
#include "terminal-util.h"
@ -899,6 +901,7 @@ static int resolve_mutable_directory(
_cleanup_free_ char *path = NULL, *resolved_path = NULL, *dir_name = NULL;
const char *root = arg_root, *base = MUTABLE_EXTENSIONS_BASE_DIR;
int r;
_cleanup_close_ int atfd = -EBADF;
assert(hierarchy);
assert(ret_resolved_mutable_directory);
@ -943,6 +946,14 @@ static int resolve_mutable_directory(
r = mkdir_p(path_in_root, 0700);
if (r < 0)
return log_error_errno(r, "Failed to create a directory '%s': %m", path_in_root);
atfd = open(path_in_root, O_DIRECTORY|O_CLOEXEC);
if (atfd < 0)
return log_error_errno(errno, "Failed to open directory '%s': %m", path_in_root);
r = mac_selinux_fix_full(atfd, NULL, hierarchy, 0);
if (r < 0)
return log_error_errno(r, "Failed to fix SELinux label for '%s': %m", path_in_root);
}
r = chase(path, root, CHASE_PREFIX_ROOT, &resolved_path, NULL);
@ -1289,6 +1300,7 @@ static int mount_overlayfs_with_op(
int r;
const char *top_layer = NULL;
_cleanup_close_ int atfd = -EBADF;
assert(op);
assert(overlay_path);
@ -1301,10 +1313,28 @@ static int mount_overlayfs_with_op(
if (r < 0)
return log_error_errno(r, "Failed to make directory '%s': %m", meta_path);
atfd = open(meta_path, O_DIRECTORY|O_CLOEXEC);
if (atfd < 0)
return log_error_errno(errno, "Failed to open directory '%s': %m", meta_path);
r = mac_selinux_fix_full(atfd, NULL, op->hierarchy, 0);
if (r < 0)
return log_error_errno(r, "Failed to fix SELinux label for '%s': %m", meta_path);
if (op->upper_dir && op->work_dir) {
r = mkdir_p(op->work_dir, 0700);
if (r < 0)
return log_error_errno(r, "Failed to make directory '%s': %m", op->work_dir);
_cleanup_close_ int dfd = -EBADF;
dfd = open(op->work_dir, O_DIRECTORY|O_CLOEXEC);
if (dfd < 0)
return log_error_errno(errno, "Failed to open directory '%s': %m", op->work_dir);
r = mac_selinux_fix_full(dfd, NULL, op->hierarchy, 0);
if (r < 0)
return log_error_errno(r, "Failed to fix SELinux label for '%s': %m", op->work_dir);
top_layer = op->upper_dir;
} else {
assert(!strv_isempty(op->lower_dirs));
@ -1325,7 +1355,7 @@ static int mount_overlayfs_with_op(
return 0;
}
static int write_extensions_file(ImageClass image_class, char **extensions, const char *meta_path) {
static int write_extensions_file(ImageClass image_class, char **extensions, const char *meta_path, const char *hierarchy) {
_cleanup_free_ char *f = NULL, *buf = NULL;
int r;
@ -1343,14 +1373,15 @@ static int write_extensions_file(ImageClass image_class, char **extensions, cons
if (!buf)
return log_oom();
r = write_string_file(f, buf, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_MKDIR_0755);
const char *hierarchy_path = path_join(hierarchy, image_class_info[image_class].dot_directory_name, image_class_info[image_class].short_identifier_plural);
r = write_string_file_full(AT_FDCWD,f, buf, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_MKDIR_0755|WRITE_STRING_FILE_LABEL, NULL, hierarchy_path);
if (r < 0)
return log_error_errno(r, "Failed to write extension meta file '%s': %m", f);
return 0;
}
static int write_dev_file(ImageClass image_class, const char *meta_path, const char *overlay_path) {
static int write_dev_file(ImageClass image_class, const char *meta_path, const char *overlay_path, const char *hierarchy) {
_cleanup_free_ char *f = NULL;
struct stat st;
int r;
@ -1372,14 +1403,15 @@ static int write_dev_file(ImageClass image_class, const char *meta_path, const c
/* Modifying the underlying layers while the overlayfs is mounted is technically undefined, but at
* least it won't crash or deadlock, as per the kernel docs about overlayfs:
* https://www.kernel.org/doc/html/latest/filesystems/overlayfs.html#changes-to-underlying-filesystems */
r = write_string_file(f, FORMAT_DEVNUM(st.st_dev), WRITE_STRING_FILE_CREATE);
const char *hierarchy_path = path_join(hierarchy, image_class_info[image_class].dot_directory_name, image_class_info[image_class].short_identifier_plural);
r = write_string_file_full(AT_FDCWD, f, FORMAT_DEVNUM(st.st_dev), WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_LABEL, NULL, hierarchy_path);
if (r < 0)
return log_error_errno(r, "Failed to write '%s': %m", f);
return 0;
}
static int write_work_dir_file(ImageClass image_class, const char *meta_path, const char *work_dir) {
static int write_work_dir_file(ImageClass image_class, const char *meta_path, const char *work_dir, const char* hierarchy) {
_cleanup_free_ char *escaped_work_dir_in_root = NULL, *f = NULL;
char *work_dir_in_root = NULL;
int r;
@ -1406,7 +1438,8 @@ static int write_work_dir_file(ImageClass image_class, const char *meta_path, co
escaped_work_dir_in_root = cescape(work_dir_in_root);
if (!escaped_work_dir_in_root)
return log_oom();
r = write_string_file(f, escaped_work_dir_in_root, WRITE_STRING_FILE_CREATE);
const char *hierarchy_path = path_join(hierarchy, image_class_info[image_class].dot_directory_name, "work_dir");
r = write_string_file_full(AT_FDCWD, f, escaped_work_dir_in_root, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_LABEL, NULL, hierarchy_path);
if (r < 0)
return log_error_errno(r, "Failed to write '%s': %m", f);
@ -1418,8 +1451,10 @@ static int store_info_in_meta(
char **extensions,
const char *meta_path,
const char *overlay_path,
const char *work_dir) {
const char *work_dir,
const char *hierarchy) {
_cleanup_free_ char *f = NULL;
_cleanup_close_ int atfd = -EBADF;
int r;
assert(extensions);
@ -1427,15 +1462,32 @@ static int store_info_in_meta(
assert(overlay_path);
/* work_dir may be NULL */
r = write_extensions_file(image_class, extensions, meta_path);
f = path_join(meta_path, image_class_info[image_class].dot_directory_name);
if (!f)
return log_oom();
r = mkdir_p(f, 0755);
if (r < 0)
return r;
r = write_dev_file(image_class, meta_path, overlay_path);
atfd = open(f, O_DIRECTORY|O_CLOEXEC);
if (atfd < 0)
return log_error_errno(errno, "Failed to open directory '%s': %m", f);
r = mac_selinux_fix_full(atfd, NULL, hierarchy, 0);
if (r < 0)
return log_error_errno(r, "Failed to fix SELinux label for '%s': %m", hierarchy);
r = write_extensions_file(image_class, extensions, meta_path, hierarchy);
if (r < 0)
return r;
r = write_work_dir_file(image_class, meta_path, work_dir);
r = write_dev_file(image_class, meta_path, overlay_path, hierarchy);
if (r < 0)
return r;
r = write_work_dir_file(image_class, meta_path, work_dir, hierarchy);
if (r < 0)
return r;
@ -1501,6 +1553,8 @@ static int merge_hierarchy(
assert(overlay_path);
assert(workspace_path);
mac_selinux_init();
r = determine_used_extensions(hierarchy, paths, &used_paths, &extensions_used);
if (r < 0)
return r;
@ -1528,7 +1582,7 @@ static int merge_hierarchy(
if (r < 0)
return r;
r = store_info_in_meta(image_class, extensions, meta_path, overlay_path, op->work_dir);
r = store_info_in_meta(image_class, extensions, meta_path, overlay_path, op->work_dir, op->hierarchy);
if (r < 0)
return r;

View File

@ -29,7 +29,7 @@ static int apply_timestamp(const char *path, struct timespec *ts) {
timespec_load_nsec(ts)) < 0)
return log_oom();
r = write_string_file_full(AT_FDCWD, path, message, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_LABEL, ts);
r = write_string_file_full(AT_FDCWD, path, message, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_LABEL, ts, NULL);
if (r == -EROFS)
log_debug_errno(r, "Cannot create \"%s\", file system is read-only.", path);
else if (r < 0)

View File

@ -1,10 +1,10 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# Container-specific auxiliary tests. VM-based ones go in TEST-87-AUX-UTILS-VM.
integration_tests += [
integration_test_template + {
'name' : fs.name(meson.current_source_dir()),
'storage': 'persistent',
'vm' : true,
'coredump-exclude-regex' : '/(test-usr-dump|test-dump|bash)$',
},
]

View File

@ -0,0 +1 @@
../TEST-01-BASIC/Makefile

View File

@ -0,0 +1,11 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# VM-specific auxiliary tests. Container-based ones go in TEST-74-AUX-UTILS.
integration_tests += [
integration_test_template + {
'name' : fs.name(meson.current_source_dir()),
'storage': 'persistent',
'coredump-exclude-regex' : '/(test-usr-dump|test-dump|bash)$',
'vm' : true,
},
]

View File

@ -0,0 +1,44 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -e
TEST_DESCRIPTION="Tests for auxiliary utilities (VM)"
TEST_NO_NSPAWN=1
# shellcheck source=test/test-functions
. "${TEST_BASE_DIR:?}/test-functions"
# Make sure vsock is available in the VM
CID=$((RANDOM + 3))
QEMU_OPTIONS+=" -device vhost-vsock-pci,guest-cid=$CID"
test_append_files() {
local workspace="${1:?}"
if ! get_bool "${TEST_PREFER_NSPAWN:-}" && ! get_bool "${TEST_NO_QEMU:-}"; then
# Check if we can correctly boot with an invalid machine ID only if we run
# the QEMU test, as nspawn refuses the invalid machine ID with -EUCLEAN
printf "556f48e837bc4424a710fa2e2c9d3e3c\ne3d\n" >"$workspace/etc/machine-id"
fi
if host_has_btrfs && host_has_mdadm; then
install_btrfs
install_mdadm
generate_module_dependencies
fi
inst_binary socat
inst_binary ssh
inst_binary sshd
inst_binary ssh-keygen
image_install -o /usr/lib/ssh/sshd-session /usr/libexec/openssh/sshd-session
inst_binary usermod
instmods vmw_vsock_virtio_transport
instmods vsock_loopback
instmods vmw_vsock_vmci_transport
inst_binary gcc
generate_module_dependencies
inst_binary openssl
}
do_test "$@"

View File

@ -380,6 +380,7 @@ foreach dirname : [
'TEST-84-STORAGETM',
'TEST-85-NETWORK',
'TEST-86-MULTI-PROFILE-UKI',
'TEST-87-AUX-UTILS-VM',
]
subdir(dirname)
endforeach

View File

@ -22,6 +22,11 @@ trap at_exit EXIT
systemctl service-log-level systemd-machined debug
systemctl service-log-level systemd-importd debug
# per request in https://github.com/systemd/systemd/pull/35117
systemctl edit --runtime --stdin 'systemd-nspawn@.service' --drop-in=debug.conf <<EOF
[Service]
Environment=SYSTEMD_LOG_LEVEL=debug
EOF
# Mount temporary directory over /var/lib/machines to not pollute the image
mkdir -p /var/lib/machines
@ -278,13 +283,13 @@ varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List
# sending TRAP signal
rm -f /var/lib/machines/long-running/trap
varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.Kill '{"name":"long-running", "whom": "leader", "signal": 5}'
timeout 30 bash -c "until test -e /var/lib/machines/long-running/trap; do sleep .5; done"
timeout 120 bash -c "until test -e /var/lib/machines/long-running/trap; do sleep .5; done"
# test io.systemd.Machine.Terminate
long_running_machine_start
rm -f /var/lib/machines/long-running/terminate
varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.Terminate '{"name":"long-running"}'
timeout 10 bash -c "until test -e /var/lib/machines/long-running/terminate; do sleep .5; done"
timeout 30 bash -c "until test -e /var/lib/machines/long-running/terminate; do sleep .5; done"
timeout 30 bash -c "while varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List '{\"name\":\"long-running\"}'; do sleep 0.5; done"
# test io.systemd.Machine.Register
@ -356,7 +361,7 @@ journalctl --sync
machinectl terminate container-without-os-release
machinectl terminate long-running
# wait for the container being stopped, otherwise acquiring image metadata by io.systemd.MachineImage.List may fail in the below.
timeout 10 bash -c "while machinectl status long-running &>/dev/null; do sleep .5; done"
timeout 30 bash -c "while machinectl status long-running &>/dev/null; do sleep .5; done"
systemctl kill --signal=KILL systemd-nspawn@long-running.service || :
(ip addr show lo | grep -q 192.168.1.100) || ip address add 192.168.1.100/24 dev lo

View File

@ -5,7 +5,3 @@ set -o pipefail
SYSTEMD_IN_CHROOT=1 systemd-detect-virt --chroot
(! SYSTEMD_IN_CHROOT=0 systemd-detect-virt --chroot)
if ! systemd-detect-virt -c; then
unshare --mount-proc --fork --user --pid systemd-detect-virt --container
fi

View File

@ -39,149 +39,3 @@ systemd-mount --type=overlay --options="lowerdir=/etc,upperdir=$WORK_DIR/upper,w
touch "$WORK_DIR/overlay/foo"
test -e "$WORK_DIR/upper/foo"
systemd-umount "$WORK_DIR/overlay"
# We're going to play around with block/loop devices, so bail out early
# if we're running in nspawn
if systemd-detect-virt --container >/dev/null; then
echo "Container detected, skipping the test"
exit 0
fi
# Set up a simple block device for further tests
dd if=/dev/zero of="$WORK_DIR/simple.img" bs=1M count=16
mkfs.ext4 -L sd-mount-test "$WORK_DIR/simple.img"
LOOP="$(losetup --show --find "$WORK_DIR/simple.img")"
udevadm wait --timeout 60 --settle "$LOOP"
# Also wait for the .device unit for the loop device is active. Otherwise, the .device unit activation
# that is triggered by the .mount unit introduced by systemd-mount below may time out.
timeout 60 bash -c "until systemctl is-active $LOOP; do sleep 1; done"
mount "$LOOP" "$WORK_DIR/mnt"
touch "$WORK_DIR/mnt/foo.bar"
umount "$LOOP"
(! mountpoint "$WORK_DIR/mnt")
# Wait for the mount unit to be unloaded. Otherwise, creation of the transient unit below may fail.
MOUNT_UNIT=$(systemd-escape --path --suffix=mount "$WORK_DIR/mnt")
timeout 60 bash -c "while [[ -n \$(systemctl list-units --all --no-legend $MOUNT_UNIT) ]]; do sleep 1; done"
# Mount with both source and destination set
systemd-mount "$LOOP" "$WORK_DIR/mnt"
systemctl status "$WORK_DIR/mnt"
systemd-mount --list --full
test -e "$WORK_DIR/mnt/foo.bar"
systemd-umount "$WORK_DIR/mnt"
# Same thing, but with explicitly specified filesystem and disabled filesystem check
systemd-mount --type=ext4 --fsck=no --collect "$LOOP" "$WORK_DIR/mnt"
systemctl status "$(systemd-escape --path "$WORK_DIR/mnt").mount"
test -e "$WORK_DIR/mnt/foo.bar"
systemd-mount --umount "$LOOP"
# Discover additional metadata (unit description should now contain filesystem label)
systemd-mount --no-ask-password --discover "$LOOP" "$WORK_DIR/mnt"
test -e "$WORK_DIR/mnt/foo.bar"
systemctl show -P Description "$WORK_DIR/mnt" | grep -q sd-mount-test
systemd-umount "$WORK_DIR/mnt"
# Set a unit description
systemd-mount --description="Very Important Unit" "$LOOP" "$WORK_DIR/mnt"
test -e "$WORK_DIR/mnt/foo.bar"
systemctl show -P Description "$WORK_DIR/mnt" | grep -q "Very Important Unit"
systemd-umount "$WORK_DIR/mnt"
# Set a property
systemd-mount --property="Description=Foo Bar" "$LOOP" "$WORK_DIR/mnt"
test -e "$WORK_DIR/mnt/foo.bar"
systemctl show -P Description "$WORK_DIR/mnt" | grep -q "Foo Bar"
systemd-umount "$WORK_DIR/mnt"
# Set mount options
systemd-mount --options=ro,x-foo-bar "$LOOP" "$WORK_DIR/mnt"
test -e "$WORK_DIR/mnt/foo.bar"
systemctl show -P Options "$WORK_DIR/mnt" | grep -Eq "(^ro|,ro)"
systemctl show -P Options "$WORK_DIR/mnt" | grep -q "x-foo-bar"
systemd-umount "$WORK_DIR/mnt"
# Mount with only source set
systemd-mount "$LOOP"
systemctl status /run/media/system/sd-mount-test
systemd-mount --list --full
test -e /run/media/system/sd-mount-test/foo.bar
systemd-umount LABEL=sd-mount-test
# Automount
systemd-mount --automount=yes "$LOOP" "$WORK_DIR/mnt"
systemd-mount --list --full
systemctl status "$(systemd-escape --path "$WORK_DIR/mnt").automount"
[[ "$(systemctl show -P ActiveState "$WORK_DIR/mnt")" == inactive ]]
test -e "$WORK_DIR/mnt/foo.bar"
systemctl status "$WORK_DIR/mnt"
systemd-umount "$WORK_DIR/mnt"
# Automount + automount-specific property
systemd-mount -A --automount-property="Description=Bar Baz" "$LOOP" "$WORK_DIR/mnt"
systemctl show -P Description "$(systemd-escape --path "$WORK_DIR/mnt").automount" | grep -q "Bar Baz"
test -e "$WORK_DIR/mnt/foo.bar"
# Call --umount via --machine=, first with a relative path (bad) and then with
# an absolute one (good)
(! systemd-umount --machine=.host "$(realpath --relative-to=. "$WORK_DIR/mnt")")
systemd-umount --machine=.host "$WORK_DIR/mnt"
# ext4 doesn't support uid=/gid=
(! systemd-mount -t ext4 --owner=testuser "$LOOP" "$WORK_DIR/mnt")
# Automount + --bind-device
systemd-mount --automount=yes --bind-device --timeout-idle-sec=1 "$LOOP" "$WORK_DIR/mnt"
systemctl status "$(systemd-escape --path "$WORK_DIR/mnt").automount"
# Trigger the automount
test -e "$WORK_DIR/mnt/foo.bar"
# Wait until it's idle again
sleep 1.5
# Safety net for slower/overloaded systems
timeout 10s bash -c "while systemctl is-active -q $WORK_DIR/mnt; do sleep .2; done"
systemctl status "$(systemd-escape --path "$WORK_DIR/mnt").automount"
# Disassemble the underlying block device
losetup -d "$LOOP"
unset LOOP
# The automount unit should disappear once the underlying blockdev is gone
timeout 10s bash -c "while systemctl status '$(systemd-escape --path "$WORK_DIR/mnt".automount)'; do sleep .2; done"
# Mount a disk image
systemd-mount --discover "$WORK_DIR/simple.img"
# We can access files in the image even if the loopback block device is not initialized by udevd.
test -e /run/media/system/simple.img/foo.bar
# systemd-mount --list and systemd-umount require the loopback block device is initialized by udevd.
udevadm settle --timeout 30
assert_in "/dev/loop.* ext4 +sd-mount-test" "$(systemd-mount --list --full)"
LOOP_AUTO=$(systemd-mount --list --full --no-legend | awk '$7 == "sd-mount-test" { print $1 }')
LOOP_AUTO_DEVPATH=$(udevadm info --query property --property DEVPATH --value "$LOOP_AUTO")
systemd-umount "$WORK_DIR/simple.img"
# Wait for 'change' uevent for the device with DISK_MEDIA_CHANGE=1.
# After the event, the backing_file attribute should be removed.
timeout 60 bash -c "while [[ -e /sys/$LOOP_AUTO_DEVPATH/loop/backing_file ]]; do sleep 1; done"
# --owner + vfat
#
# Create a vfat image, as ext4 doesn't support uid=/gid= fixating for all
# files/directories
dd if=/dev/zero of="$WORK_DIR/owner-vfat.img" bs=1M count=16
mkfs.vfat -n owner-vfat "$WORK_DIR/owner-vfat.img"
LOOP="$(losetup --show --find "$WORK_DIR/owner-vfat.img")"
# If the synthesized uevent triggered by inotify event has been processed earlier than the kernel finishes to
# attach the backing file, then SYSTEMD_READY=0 is set for the device. As a workaround, monitor sysattr
# and re-trigger uevent after that.
LOOP_DEVPATH=$(udevadm info --query property --property DEVPATH --value "$LOOP")
timeout 60 bash -c "until [[ -e /sys/$LOOP_DEVPATH/loop/backing_file ]]; do sleep 1; done"
udevadm trigger --settle "$LOOP"
# Also wait for the .device unit for the loop device is active. Otherwise, the .device unit activation
# that is triggered by the .mount unit introduced by systemd-mount below may time out.
if ! timeout 60 bash -c "until systemctl is-active $LOOP; do sleep 1; done"; then
# For debugging issue like
# https://github.com/systemd/systemd/issues/32680#issuecomment-2120959238
# https://github.com/systemd/systemd/issues/32680#issuecomment-2122074805
udevadm info "$LOOP"
udevadm info --attribute-walk "$LOOP"
cat /sys/"$(udevadm info --query property --property DEVPATH --value "$LOOP")"/loop/backing_file || :
false
fi
# Mount it and check the UID/GID
[[ "$(stat -c "%U:%G" "$WORK_DIR/mnt")" == "root:root" ]]
systemd-mount --owner=testuser "$LOOP" "$WORK_DIR/mnt"
systemctl status "$WORK_DIR/mnt"
[[ "$(stat -c "%U:%G" "$WORK_DIR/mnt")" == "testuser:testuser" ]]
touch "$WORK_DIR/mnt/hello"
[[ "$(stat -c "%U:%G" "$WORK_DIR/mnt/hello")" == "testuser:testuser" ]]
systemd-umount LABEL=owner-vfat

View File

@ -3,11 +3,6 @@
set -eux
set -o pipefail
if systemd-detect-virt --quiet --container; then
echo "running on container, skipping."
exit 0
fi
if ! command -v bootctl >/dev/null; then
echo "bootctl not found, skipping."
exit 0
@ -24,6 +19,8 @@ fi
# shellcheck source=test/units/test-control.sh
. "$(dirname "$0")"/test-control.sh
(! systemd-detect-virt -cq)
basic_tests() {
bootctl "$@" --help
bootctl "$@" --version

View File

@ -19,12 +19,9 @@ at_exit() {
rm -fv -- "$CORE_TEST_BIN" "$CORE_TEST_UNPRIV_BIN" "$MAKE_DUMP_SCRIPT" "$MAKE_STACKTRACE_DUMP"
}
trap at_exit EXIT
(! systemd-detect-virt -cq)
if systemd-detect-virt -cq; then
echo "Running in a container, skipping the systemd-coredump test..."
exit 0
fi
trap at_exit EXIT
# To make all coredump entries stored in system.journal.
journalctl --rotate
@ -81,7 +78,7 @@ timeout 30 bash -c "while [[ \$(coredumpctl list -q --no-legend $CORE_TEST_BIN |
if cgroupfs_supports_user_xattrs; then
# Make sure we can forward crashes back to containers
CONTAINER="TEST-74-AUX-UTILS-container"
CONTAINER="TEST-87-AUX-UTILS-VM-container"
mkdir -p "/var/lib/machines/$CONTAINER"
mkdir -p "/run/systemd/system/systemd-nspawn@$CONTAINER.service.d"

View File

@ -0,0 +1,11 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -eux
set -o pipefail
(! systemd-detect-virt -cq)
SYSTEMD_IN_CHROOT=1 systemd-detect-virt --chroot
(! SYSTEMD_IN_CHROOT=0 systemd-detect-virt --chroot)
unshare --mount-proc --fork --user --pid systemd-detect-virt --container

View File

@ -10,12 +10,9 @@ at_exit() {
rm -rfv "${CONFIG_FILE:?}"
}
trap at_exit EXIT
(! systemd-detect-virt -cq)
if systemd-detect-virt -cq; then
echo "Running in a container, skipping the systemd-modules-load test..."
exit 0
fi
trap at_exit EXIT
ORIG_MODULES_LOAD_CONFIG="$(systemd-analyze cat-config modules-load.d)"

View File

@ -0,0 +1,182 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -eux
set -o pipefail
# shellcheck source=test/units/util.sh
. "$(dirname "$0")"/util.sh
at_exit() {
set +e
[[ -n "${LOOP:-}" ]] && losetup -d "$LOOP"
[[ -n "${WORK_DIR:-}" ]] && rm -fr "$WORK_DIR"
}
(! systemd-detect-virt -cq)
trap at_exit EXIT
WORK_DIR="$(mktemp -d)"
mkdir -p "$WORK_DIR/mnt"
systemd-mount --list
systemd-mount --list --full
systemd-mount --list --no-legend
systemd-mount --list --no-pager
systemd-mount --list --quiet
systemd-mount --list --json=pretty
# tmpfs
mkdir -p "$WORK_DIR/mnt/foo/bar"
systemd-mount --tmpfs "$WORK_DIR/mnt/foo"
test ! -d "$WORK_DIR/mnt/foo/bar"
touch "$WORK_DIR/mnt/foo/baz"
systemd-umount "$WORK_DIR/mnt/foo"
test -d "$WORK_DIR/mnt/foo/bar"
test ! -e "$WORK_DIR/mnt/foo/baz"
# overlay
systemd-mount --type=overlay --options="lowerdir=/etc,upperdir=$WORK_DIR/upper,workdir=$WORK_DIR/work" /etc "$WORK_DIR/overlay"
touch "$WORK_DIR/overlay/foo"
test -e "$WORK_DIR/upper/foo"
systemd-umount "$WORK_DIR/overlay"
# Set up a simple block device for further tests
dd if=/dev/zero of="$WORK_DIR/simple.img" bs=1M count=16
mkfs.ext4 -L sd-mount-test "$WORK_DIR/simple.img"
LOOP="$(losetup --show --find "$WORK_DIR/simple.img")"
udevadm wait --timeout 60 --settle "$LOOP"
# Also wait for the .device unit for the loop device is active. Otherwise, the .device unit activation
# that is triggered by the .mount unit introduced by systemd-mount below may time out.
timeout 60 bash -c "until systemctl is-active $LOOP; do sleep 1; done"
mount "$LOOP" "$WORK_DIR/mnt"
touch "$WORK_DIR/mnt/foo.bar"
umount "$LOOP"
(! mountpoint "$WORK_DIR/mnt")
# Wait for the mount unit to be unloaded. Otherwise, creation of the transient unit below may fail.
MOUNT_UNIT=$(systemd-escape --path --suffix=mount "$WORK_DIR/mnt")
timeout 60 bash -c "while [[ -n \$(systemctl list-units --all --no-legend $MOUNT_UNIT) ]]; do sleep 1; done"
# Mount with both source and destination set
systemd-mount "$LOOP" "$WORK_DIR/mnt"
systemctl status "$WORK_DIR/mnt"
systemd-mount --list --full
test -e "$WORK_DIR/mnt/foo.bar"
systemd-umount "$WORK_DIR/mnt"
# Same thing, but with explicitly specified filesystem and disabled filesystem check
systemd-mount --type=ext4 --fsck=no --collect "$LOOP" "$WORK_DIR/mnt"
systemctl status "$(systemd-escape --path "$WORK_DIR/mnt").mount"
test -e "$WORK_DIR/mnt/foo.bar"
systemd-mount --umount "$LOOP"
# Discover additional metadata (unit description should now contain filesystem label)
systemd-mount --no-ask-password --discover "$LOOP" "$WORK_DIR/mnt"
test -e "$WORK_DIR/mnt/foo.bar"
systemctl show -P Description "$WORK_DIR/mnt" | grep -q sd-mount-test
systemd-umount "$WORK_DIR/mnt"
# Set a unit description
systemd-mount --description="Very Important Unit" "$LOOP" "$WORK_DIR/mnt"
test -e "$WORK_DIR/mnt/foo.bar"
systemctl show -P Description "$WORK_DIR/mnt" | grep -q "Very Important Unit"
systemd-umount "$WORK_DIR/mnt"
# Set a property
systemd-mount --property="Description=Foo Bar" "$LOOP" "$WORK_DIR/mnt"
test -e "$WORK_DIR/mnt/foo.bar"
systemctl show -P Description "$WORK_DIR/mnt" | grep -q "Foo Bar"
systemd-umount "$WORK_DIR/mnt"
# Set mount options
systemd-mount --options=ro,x-foo-bar "$LOOP" "$WORK_DIR/mnt"
test -e "$WORK_DIR/mnt/foo.bar"
systemctl show -P Options "$WORK_DIR/mnt" | grep -Eq "(^ro|,ro)"
systemctl show -P Options "$WORK_DIR/mnt" | grep -q "x-foo-bar"
systemd-umount "$WORK_DIR/mnt"
# Mount with only source set
systemd-mount "$LOOP"
systemctl status /run/media/system/sd-mount-test
systemd-mount --list --full
test -e /run/media/system/sd-mount-test/foo.bar
systemd-umount LABEL=sd-mount-test
# Automount
systemd-mount --automount=yes "$LOOP" "$WORK_DIR/mnt"
systemd-mount --list --full
systemctl status "$(systemd-escape --path "$WORK_DIR/mnt").automount"
[[ "$(systemctl show -P ActiveState "$WORK_DIR/mnt")" == inactive ]]
test -e "$WORK_DIR/mnt/foo.bar"
systemctl status "$WORK_DIR/mnt"
systemd-umount "$WORK_DIR/mnt"
# Automount + automount-specific property
systemd-mount -A --automount-property="Description=Bar Baz" "$LOOP" "$WORK_DIR/mnt"
systemctl show -P Description "$(systemd-escape --path "$WORK_DIR/mnt").automount" | grep -q "Bar Baz"
test -e "$WORK_DIR/mnt/foo.bar"
# Call --umount via --machine=, first with a relative path (bad) and then with
# an absolute one (good)
(! systemd-umount --machine=.host "$(realpath --relative-to=. "$WORK_DIR/mnt")")
systemd-umount --machine=.host "$WORK_DIR/mnt"
# ext4 doesn't support uid=/gid=
(! systemd-mount -t ext4 --owner=testuser "$LOOP" "$WORK_DIR/mnt")
# Automount + --bind-device
systemd-mount --automount=yes --bind-device --timeout-idle-sec=1 "$LOOP" "$WORK_DIR/mnt"
systemctl status "$(systemd-escape --path "$WORK_DIR/mnt").automount"
# Trigger the automount
test -e "$WORK_DIR/mnt/foo.bar"
# Wait until it's idle again
sleep 1.5
# Safety net for slower/overloaded systems
timeout 10s bash -c "while systemctl is-active -q $WORK_DIR/mnt; do sleep .2; done"
systemctl status "$(systemd-escape --path "$WORK_DIR/mnt").automount"
# Disassemble the underlying block device
losetup -d "$LOOP"
unset LOOP
# The automount unit should disappear once the underlying blockdev is gone
timeout 10s bash -c "while systemctl status '$(systemd-escape --path "$WORK_DIR/mnt".automount)'; do sleep .2; done"
# Mount a disk image
systemd-mount --discover "$WORK_DIR/simple.img"
# We can access files in the image even if the loopback block device is not initialized by udevd.
test -e /run/media/system/simple.img/foo.bar
# systemd-mount --list and systemd-umount require the loopback block device is initialized by udevd.
udevadm settle --timeout 30
assert_in "/dev/loop.* ext4 +sd-mount-test" "$(systemd-mount --list --full)"
LOOP_AUTO=$(systemd-mount --list --full --no-legend | awk '$7 == "sd-mount-test" { print $1 }')
LOOP_AUTO_DEVPATH=$(udevadm info --query property --property DEVPATH --value "$LOOP_AUTO")
systemd-umount "$WORK_DIR/simple.img"
# Wait for 'change' uevent for the device with DISK_MEDIA_CHANGE=1.
# After the event, the backing_file attribute should be removed.
timeout 60 bash -c "while [[ -e /sys/$LOOP_AUTO_DEVPATH/loop/backing_file ]]; do sleep 1; done"
# --owner + vfat
#
# Create a vfat image, as ext4 doesn't support uid=/gid= fixating for all
# files/directories
dd if=/dev/zero of="$WORK_DIR/owner-vfat.img" bs=1M count=16
mkfs.vfat -n owner-vfat "$WORK_DIR/owner-vfat.img"
LOOP="$(losetup --show --find "$WORK_DIR/owner-vfat.img")"
# If the synthesized uevent triggered by inotify event has been processed earlier than the kernel finishes to
# attach the backing file, then SYSTEMD_READY=0 is set for the device. As a workaround, monitor sysattr
# and re-trigger uevent after that.
LOOP_DEVPATH=$(udevadm info --query property --property DEVPATH --value "$LOOP")
timeout 60 bash -c "until [[ -e /sys/$LOOP_DEVPATH/loop/backing_file ]]; do sleep 1; done"
udevadm trigger --settle "$LOOP"
# Also wait for the .device unit for the loop device is active. Otherwise, the .device unit activation
# that is triggered by the .mount unit introduced by systemd-mount below may time out.
if ! timeout 60 bash -c "until systemctl is-active $LOOP; do sleep 1; done"; then
# For debugging issue like
# https://github.com/systemd/systemd/issues/32680#issuecomment-2120959238
# https://github.com/systemd/systemd/issues/32680#issuecomment-2122074805
udevadm info "$LOOP"
udevadm info --attribute-walk "$LOOP"
cat /sys/"$(udevadm info --query property --property DEVPATH --value "$LOOP")"/loop/backing_file || :
false
fi
# Mount it and check the UID/GID
[[ "$(stat -c "%U:%G" "$WORK_DIR/mnt")" == "root:root" ]]
systemd-mount --owner=testuser "$LOOP" "$WORK_DIR/mnt"
systemctl status "$WORK_DIR/mnt"
[[ "$(stat -c "%U:%G" "$WORK_DIR/mnt")" == "testuser:testuser" ]]
touch "$WORK_DIR/mnt/hello"
[[ "$(stat -c "%U:%G" "$WORK_DIR/mnt/hello")" == "testuser:testuser" ]]
systemd-umount LABEL=owner-vfat

View File

@ -5,10 +5,7 @@ set -o pipefail
systemctl log-level info
if systemd-detect-virt -cq; then
echo "Running in a container, skipping the systemd-pstore test..."
exit 0
fi
(! systemd-detect-virt -cq)
DUMMY_DMESG_0="$(mktemp)"
cat >"$DUMMY_DMESG_0" <<\EOF

View File

@ -0,0 +1,11 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -eux
set -o pipefail
# shellcheck source=test/units/test-control.sh
. "$(dirname "$0")"/test-control.sh
run_subtests
touch /testok