Commit Graph
5068 Commits
Author SHA1 Message Date
Vitaly Kuznetsov 771085291d dissect-image: introduce 'encryptedwithintegrity' policy
LUKS2 supports built-in integrity checking which may come very handy to
mitigate partial rollback attacks on the storage when only some specific
parts are restored to some old encrypted state. Specific use-cases like
Confidential VMs may want to mandate the usage of feature e.g. on the root
volume. Introduce "encryptedwithintegrity" image policy to support that.

Note, due to the current libcryptsetup limitations, checking whether the
feature is enabled or not for the 'file' case (e.g. DDI image as a raw file)
requires setting up a loop device. To avoid that and keep dissect fully
functional when working unpriviliged, implement a minimal custom LUKS header
parser.
2025-12-18 09:12:54 +01:00
Mike Yuan 4abf7ee02e Revert "acl-util: drop now unused fd_acl_make_writable()"
This reverts commit 4175cd4f40.

It turned out that we still need this. Preparation for later commits.
2025-12-16 20:16:57 +01:00
Mike Yuan fd99348353 bus-unit-util: ReloadSignal is a Service property
Follow-up for c133545430
2025-12-16 10:37:09 +01:00
Yu Watanabe 4c98063d6e test: introduce our own sleep command for testing 2025-12-15 18:09:21 +09:00
Yu Watanabe 93378148d4 tree-wide: normalize comment style 2025-12-15 08:50:13 +09:00
Daan De Meyer 273c6bc045 mount-util: Add mount_fd_clone() helper
The kernel prevents you from open_tree()'ing an open_tree() fd unless it
was created from the caller's mount namespace. For various use cases, we
want to be able to open_tree() arbitrary mount file descriptors. Turns
out there's a way go get around it by mounting the mount file descriptor
in a throw-away mount namespace and then open_tree()'ing the mount file
descriptor. Let's implement this as a new helper mount_fd_clone() and
add a test for it.

Because move_mount()'ing the original fd makes it pretty useless as it
can't be move_mount()'ed again, we optionally make a second clone which
can replace the original fd so it can be cloned again later.
2025-12-14 11:31:59 +01:00
Luca Boccassi 7c0afcdde2 core: gracefully skip unknown policy designators in RootImagePolicy et al (#40060)
Usually we gracefully ignore unknown configuration parameters, so that
service files can be written by upstreams and used across a variegated
range of distributions with various versions of systemd, to avoid
forcing users to the minimum common denominator and only adding settings
that are supported by the oldest distro supported.

Image policies do not behave like this, and any unknown partition or
policy designator causes the whole unit to fail to parse and a hard
error.

Change it so that parsing RootImagePolicy and friends via unit file or
D-Bus logs but otherwise ignores unknown specifiers, like other options
do.

This allows us to add new specifiers in the future, and users to adopt
them immediately.

Follow-up for d452335aa4
2025-12-11 14:38:26 +09:00
Yu Watanabe f117629f28 test: skip several test cases when built with musl 2025-12-07 09:09:03 +09:00
Yu Watanabe 355bcc243c test: support coreutils built with --enable-single-binary=symlinks
Alpine/postmarketOS build coreutils with --enable-single-binary=symlinks.
In that case, all commands provided by coreutils are symlink to
/usr/bin/coreutils, and it calls prctl(PR_SET_NAME, argv[0]), hence the comm
will be the path to the symlink.

This also makes not kill sleep command with SIGKILL in TEST-17-UDEV, that is
totally unnecessary.
2025-12-07 09:09:03 +09:00
Yu Watanabe 3672e24e75 test-seccomp: do not fail when already MemoryDenyWriteExecute= is enabled 2025-12-07 09:09:03 +09:00
Zbigniew Jędrzejewski-Szmek 9454927c76 sd-netlink: read error message for NFNL_MSG_BATCH_BEGIN (#39967)
Before:
```
$ unshare --user --map-users=0:$(id -u):1 --map-groups=0:$(id -g):1 build/test-firewall-util
/* test_v6 */
src/test/test-firewall-util.c:34: Assertion failed: "r = fw_nftables_add_masquerade(nfnl, true, AF_INET6, &u1, 128)" failed with unexpected error: -110/ETIMEDOUT
Aborted (core dumped)
```

After:
```
$ unshare --user --map-users=0:$(id -u):1 --map-groups=0:$(id -g):1 /var/build/test-firewall-util
/* test_v6 */
test-firewall-util: Failed to add IPv6 masquerade, skipping tests: Operation not permitted
/* test_v4 */
test-firewall-util: Failed to add IPv4 masquerade, skipping tests: Operation not permitted
```
2025-12-05 12:12:03 +01:00
Yu Watanabe 53f5aa3fd2 musl: introduce wrappers for getopt() and getopt_long()
musl's getopt_long() behaves something different in handling optional arguments:
```
$ journalctl _PID=1 _COMM=systemd --since 19:19:01 -n all --follow
Failed to add match 'all': Invalid argument
```
This introduces getopt_long_fix() that reorders the passed arguments to make
getopt_long() provided by musl works as what we expect.

Also, musl's getopt() always behaves POSIXLY_CORRECT mode, and stops parsing
arguments when a non-option string found. Let's always use getopt_long().
2025-12-05 11:01:09 +01:00
Yu Watanabe 84990e08e5 test-firewall-util: allow to run test-firewall-util
Now fw_nftables_add_masquerade() should return EOPNOTSUPP or so if
unprivileged. It is not necessary to skip whole tests earlier.
2025-12-04 08:24:28 +09:00
Daan De Meyer 9a6a8f35eb tree-wide: Small fixes for various clang-tidy warnings 2025-11-26 16:22:00 +09:00
Daan De Meyer 5df44d0f6a core: Make libmount optional
Instead of skipping libcore entirely when libmount is not available,
let's only compile out the pieces that need libmount. This makes the
meson logic much less complex and allows systemd-analyze to be built
when libmount is not available.
2025-11-24 16:23:10 +01:00
Daan De Meyer 9c2cd09420 test: Skip protect_kernel_logs test if libmount is missing
libmount is required for setup_namespace() so skip the test if it
is not available.
2025-11-24 16:10:31 +01:00
Lennart Poettering c746488537 block dlopen() once we transition into some foreign namespace (#39824)
Let's make sure we never accidentally end up loading code from a foreign
namespace.
2025-11-24 14:14:16 +01:00
Daan De Meyer d60206c49a meson: Still build libshared even if libmount is disabled (#39871)
Currently, if the libmount feature is disabled, we don't build libshared
and as a result skip building every other executable as well. Among
other things, this makes our nodeps CI builds kind of pointless since
hardly any code will be compiled.

Let's improve on the situation by making libmount properly optional in
libshared. Then, we only skip building the executables that actually
need libmount.
2025-11-24 14:05:29 +01:00
Yu Watanabe 0cc96fc213 test: use log_tests_skipped_errno() at one more place
Follow-up for 12d2abe082.
2025-11-24 21:16:39 +09:00
Daan De Meyer 7336f2c748 meson: Still build libshared even if libmount is disabled
Currently, if the libmount feature is disabled, we don't build
libshared and as a result skip building every other executable as
well. Among other things, this makes our nodeps CI builds kind of
pointless since hardly any code will be compiled.

Let's improve on the situation by making libmount properly optional
in libshared. Then, we only skip building the executables that
actually need libmount.
2025-11-24 13:09:41 +01:00
Daan De Meyer e910f9bc63 test-reread-partition-table: Don't keep open fds around
Avoids EBUSY from BLKRRPART when built without libblkid support.
2025-11-24 13:09:41 +01:00
Daan De Meyer dee7dfea1d test-reread-partition-table: Only check for CAP_SYS_ADMIN
We might have CAP_SYS_ADMIN even without being root.
2025-11-24 13:09:41 +01:00
Daan De Meyer 43687c22ab tests: Assume we're running in a chroot if check fails
running_in_chroot() will fail when a test is executed as a non-root
user without CAP_DAC_READ_SEARCH as it won't be able to access
/proc/1/root.

Let's make things more robust by skipping tests if we can't detect
if we're in a chroot or not, since if we can't even detect if we're
in a chroot or not, chances are we're missing the required privileges
to execute the test anyway.
2025-11-24 13:09:41 +01:00
Lennart Poettering a08f2ea02d process-util: also disable dlopen() in safe_fork() 2025-11-24 11:56:47 +01:00
Lennart Poettering 2c7bdaf9f1 dlfcn-util: let's make our dlopen() code fail if we enter a container namespace
Now that we dlopen() so many deps, it might happen by accident that we
end up dlopen()ening stuff when we entered a container, which we should
really avoid, to not mix host and container libraries.

Let's add a global variable we can set when we want to block dlopen() to
ever succeed. This is then checked primarily in
dlopen_many_sym_or_warn(), where we'll generate EPERM plus a log
message.

There are a couple of other places we invoke dlopen(), without going
through dlopen_many_sym_or_warn(). This adds the same check there.
2025-11-24 09:19:33 +01:00
Daan De Meyer 87fbd33372 clang-tidy: Fix all remaining misc-include-cleaner violations
- Remove unused includes
- Add common false positive headers to misc-include-cleaner.IgnoreHeaders
- Add IWYU pragma keep for uncommon false positive headers
2025-11-22 10:19:41 +01:00
Nick Rosbrook 7d23e27e4c test: skip test-reread-partition-table if missing privileges
Right now, this test runs inside unprivileged chroots, despite the
running_in_chroot() check. This is because running_in_chroot() fails
with -EACCES, which is ignored.

Hence, check for privileges before calling running_in_chroot(),
otherwise call is inconclusive. Note, the test will fail later on if
running without privileges anyways.
2025-11-21 19:28:05 +00:00
Luca Boccassi 12d2abe082 test: check for all errors in test-reread-partition-table
Otherwise if opening the loop dev fails, the test segfaults
dereferencing a NULL variable later

Follow-up for 757887d01d
2025-11-21 19:13:39 +01:00
Luca Boccassi dff4fb7c35 test: skip test-loop-block udev part in chroot too
Same reason as containers, need full udev/uevent machinery for this
2025-11-21 09:16:57 +01:00
Zbigniew Jędrzejewski-Szmek bfb8e9c575 basic/terminal-util: add code to read window size using CSI 18
In my tests, the sequence works on Ptyxis 49.0, gnome-terminal-3.56.3,
xterm-401, rxvt-unicode-9.31, under tmux-3.5a, over ssh and serial console
connected to ptyxis. It did not work on a text console in a VM (TERM=linux) or
under kmscon-9.1.0 (TERM=vt102).
2025-11-20 17:32:50 +01:00
Zbigniew Jędrzejewski-Szmek 0f7d3e34e1 Avoid multiple evaluations in STRERROR_XYZ() macros (#39794) 2025-11-20 08:29:32 +01:00
Yu Watanabe 70fa7d4ccc core: SMACK label to Unix socket path and FD (#39772)
Currently, when a socket unit specifies SmackLabel=,
the label is not applied to the underlying Unix socket file or its file
descriptor.

This change ensures that the SMACK label is applied both to the
Unix socket path on the filesystem and to all associated socket FDs
when the socket is created.

Testing:

- Tested on Fedora 43 with kernel 6.17.7 with SMACK enabled.
- Created a systemd socket unit:

    [Unit]
    Description=UNIX socket

    [Socket]
    ListenStream=/run/test.sock
    SmackLabel=label

    [Install]
    WantedBy=sockets.target

- Created a corresponding service:

    [Unit]
    Description=UNIX socket service
    Requires=test.socket

    [Service]
    ExecStart=/usr/bin/socat -v - -
    StandardInput=socket

    [Install]
    WantedBy=multi-user.target

- Verified SMACK labels using getfattr:

  - Without SmackLabel:
    ```
    # file: run/test.sock
    security.SMACK64="_"
    # file: proc/<pid>/fd/*
    security.SMACK64="*"
    ```
  - With SmackLabel=label:
    ```
    # file: run/test.sock
    security.SMACK64="label"
    # file: proc/<pid>/fd/*
    security.SMACK64="label"
    ```
2025-11-20 13:23:51 +09:00
Yu Watanabe 5de39570c8 Simplify source lists in meson config (#39811) 2025-11-20 13:20:41 +09:00
Zbigniew Jędrzejewski-Szmek 5220bb8c3f meson: automatically add 'extract' to 'sources'
In all cases, everything that we list in 'extract', we also list in
'sources'. We can simplify things by automatically appending the first
list to the second.

In the listings, move 'extract' key right below 'sources', since now
they are both "sources", just with slightly different meanings.
2025-11-20 10:03:48 +09:00
Yu Watanabe cb4b36928a socket-label: move prototype of socket_address_listen() and string table for SocketAddressBindIPv6Only
The function socket_address_listen() is declared at shared/socket-label.c,
however its prototype was in basic/socket-util.h. This moves the
prototype to shared/socket-label.h.

Also, enum SocketAddressBindIPv6Only is not used anymore in basic/*.[ch].
Let's move the definition and its string table to shared/socket-label.[ch].

Follow-up for b25a930f0e.
2025-11-20 09:58:53 +09:00
Yu Watanabe 18f280a478 test: fix tested function name
The test tests STRERROR_OR_EOF(), but logged as STRERROR_OR_ELSE.
2025-11-20 08:58:37 +09:00
Yu Watanabe 3f91ffe0fe core: Verify inherited FDs are writable for stdout/stderr (#39674)
When inheriting file descriptors for stdout/stderr (either from stdin or
when making stderr inherit from stdout), we previously just assumed they
would be writable and dup'd them. This could lead to broken setups if
the inherited FD was actually opened read-only.

Before dup'ing any inherited FDs to stdout/stderr, verify they are
actually writable using the new fd_is_writable() helper. If not, fall
back to /dev/null (or reopen the terminal in the TTY case) with a
warning, rather than silently creating a broken setup where output
operations would fail.
2025-11-20 08:19:46 +09:00
Chris Down e21a431ec4 tests: ASSERT_SIGNAL: Do not allow parent to hallucinate it is the child
assert_signal_internal() returns 0 in two distinct cases:

1. In the child process (immediately after fork returns 0).
2. In the parent process, if the child exited normally (no signal).

ASSERT_SIGNAL fails to distinguish these cases. When a child exited
normally (case 2), the parent process receives 0, incorrectly interprets
it as meaning it is the child, and re-executes the test expression
inside the parent process. Goodness gracious!

This causes two severe test integrity issues:

1. False positives. The parent can run the expression, succeed, and call
   _exit(EXIT_SUCCESS), causing the test to pass even though no signal
   was raised.
2. Silent truncation. The _exit() call in the parent terminates the test
   runner prematurely, preventing subsequent tests in the same file from
   running.

Example of the bug in action, from #39674:

    ASSERT_SIGNAL(fd_is_writable(closed_fd), SIGABRT)

This test should fail (fd_is_writable does not SIGABRT here), but with
the bug, the parent hallucinated being the child, re-ran the expression
successfully, and exited with success.

Fix this by refactoring assert_signal_internal() to be much more strict
about separating control flow from data.

The signal status is now returned via a strictly typed output parameter,
guaranteeing that determining whether we are the child is never
conflated with whether the child exited cleanly.
2025-11-20 02:40:07 +08:00
Chris Down 39adecfcd8 tests: ASSERT_SIGNAL: Stop exit codes from masquerading as signals
When a child process exits normally (si_code == CLD_EXITED),
siginfo.si_status contains the exit code. When it is killed by a signal
(si_code == CLD_KILLED or CLD_DUMPED), si_status contains the signal
number.  However, assert_signal_internal() returns si_status blindly.
This causes exit codes to be misinterpreted as signal numbers.

This allows failing tests to silently pass if their exit code
numerically coincides with the expected signal. For example, a test
expecting SIGABRT (6) would incorrectly pass if the child simply exited
with status 6 instead of being killed by a signal.

Fix this by checking si_code. Only return si_status as a signal number
if the child was actually killed by a signal (CLD_KILLED or CLD_DUMPED).
If the child exited normally (CLD_EXITED), return 0 to indicate that no
signal occurred.
2025-11-20 02:40:07 +08:00
Chris Down 592c57e586 fd-util: Add fd_is_writable() to check if FD is opened for writing
This checks whether a file descriptor is valid and opened in a mode that
allows writing (O_WRONLY or O_RDWR). This is useful when we want to
verify that inherited FDs can actually be used for output operations
before dup'ing them.

The helper explicitly handles O_PATH file descriptors, which cannot be
used for I/O operations and thus are never writable.
2025-11-20 02:02:21 +08:00
Zbigniew Jędrzejewski-Szmek 6fc487564a meson: drop unnessary variable 2025-11-19 17:31:25 +01:00
Yu Watanabe 0ecff59065 Revert "musl: meson: add libutmps support"
This reverts commit bf9bc5beb0.

libutmps does not support utmpxname(), the function always fails
with ENOSYS, and always uses their own file.
However, our code relies on the funtion needs to succeed.

Let's revert the change now, and revisit later when musl users
request to support libutmps.
2025-11-18 02:54:20 +09:00
Yu Watanabe 07910c73b0 test: modernize test-log and add test cases for log_format_iovec() (#39750) 2025-11-18 01:31:02 +09:00
Yu Watanabe f10444319e test-log: add test cases for log_format_iovec() 2025-11-17 23:07:05 +09:00
Yu Watanabe c1792c2005 test-log: migrate to use ASSERT_OK() and friends 2025-11-17 23:07:05 +09:00
Yu Watanabe b9e612e070 cgroup-util: do not check validity of controller in cg_split_spec()
Now the controller part is always ignored, hence let's skip check for
the controller part of the spec. This also make it acceppt unnormalized
path. Previously paths were checked by path_is_normalized(), but now
checked by path_is_safe(). Also, now this mapps an empty path to NULL.
2025-11-17 21:31:51 +09:00
Yu Watanabe a8156588fa cgroup-util: drop 'controller' argument from cg_get_path()
The argument is not used anymore. Let's drop it.
2025-11-17 21:31:50 +09:00
Yu Watanabe 5d397dc7f4 cgroup-util: drop 'controller' argument from cg_get_keyed_attribute() and cg_is_empty()
The argument is completely unused. Let's drop it.
2025-11-17 21:31:50 +09:00
Yu Watanabe 3454b160e4 cgroup-util: drop unused cg_unified() and friends 2025-11-17 21:31:50 +09:00
Yu Watanabe b525a72f7b cgroup-util: drop cgroup v1 support from cg_pid_get_path()
We have dropped cgroup v1 support in v258. Let's drop legacy code.
Then, we can drop 'controller' argument from cg_pid_get_path() and
cg_pidref_get_path().
2025-11-17 21:30:29 +09:00