[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1064993: marked as done (bookworm-pu: package systemd/252.23-1~deb12u1)



Your message dated Sat, 29 Jun 2024 10:46:16 +0000
with message-id <E1sNVay-002bZd-9O@coccia.debian.org>
and subject line Released with 12.6
has caused the Debian Bug report #1064993,
regarding bookworm-pu: package systemd/252.23-1~deb12u1
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
1064993: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1064993
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
Tags: bookworm
User: release.debian.org@packages.debian.org
Usertags: pu
X-Debbugs-Cc: pkg-systemd-maintainers@lists.alioth.debian.org

Dear Release Team,

We would like to upload the latest stable point release of systemd 252
to bookworm-p-u. Stable release branches are maintained upstream with
the intention of providing bug fixes only and no compatibility
breakages, and with automated non-trivial CI jobs that also cover
Debian and Ubuntu. I have already uploaded to p-u.

Packaging changes are limited to refreshing patches. Debdiff attached.
The list of commits included can be seen at:

https://github.com/systemd/systemd-stable/compare/v252.22...v252.23

This also fixes CVE-2023-50387 and CVE-2023-50868.

-- 
Kind regards,
Luca Boccassi
diff -Nru systemd-252.22/debian/changelog systemd-252.23/debian/changelog
--- systemd-252.22/debian/changelog	2024-01-26 21:48:36.000000000 +0000
+++ systemd-252.23/debian/changelog	2024-02-28 17:00:53.000000000 +0000
@@ -1,3 +1,10 @@
+systemd (252.23-1~deb12u1) bookworm; urgency=medium
+
+  * New upstream version 252.23 (CVE-2023-50387, CVE-2023-50868)
+  * Refresh patches
+
+ -- Luca Boccassi <bluca@debian.org>  Wed, 28 Feb 2024 17:00:53 +0000
+
 systemd (252.22-1~deb12u1) bookworm; urgency=medium
 
   * d/t/control: add dependency on stress for upstream suite. Needed by
diff -Nru systemd-252.22/debian/patches/debian/Downgrade-a-couple-of-warnings-to-debug.patch systemd-252.23/debian/patches/debian/Downgrade-a-couple-of-warnings-to-debug.patch
--- systemd-252.22/debian/patches/debian/Downgrade-a-couple-of-warnings-to-debug.patch	2024-01-26 21:48:26.000000000 +0000
+++ systemd-252.23/debian/patches/debian/Downgrade-a-couple-of-warnings-to-debug.patch	2024-02-28 17:00:53.000000000 +0000
@@ -16,7 +16,7 @@
  3 files changed, 7 insertions(+), 3 deletions(-)
 
 diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
-index 1001faa..555492e 100644
+index 5f4d4b0..cf5e55f 100644
 --- a/src/core/load-fragment.c
 +++ b/src/core/load-fragment.c
 @@ -543,6 +543,7 @@ static int patch_var_run(
@@ -51,7 +51,7 @@
                                      "Please update package to include a native systemd unit file, in order to make it more safe and robust.", fpath);
  
 diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
-index 9c3d994..15180a5 100644
+index 281284c..8952a26 100644
 --- a/src/tmpfiles/tmpfiles.c
 +++ b/src/tmpfiles/tmpfiles.c
 @@ -2991,6 +2991,7 @@ static int specifier_expansion_from_arg(const Specifier *specifier_table, Item *
diff -Nru systemd-252.22/debian/patches/debian/fsckd-daemon-for-inter-fsckd-communication.patch systemd-252.23/debian/patches/debian/fsckd-daemon-for-inter-fsckd-communication.patch
--- systemd-252.22/debian/patches/debian/fsckd-daemon-for-inter-fsckd-communication.patch	2024-01-26 21:48:26.000000000 +0000
+++ systemd-252.23/debian/patches/debian/fsckd-daemon-for-inter-fsckd-communication.patch	2024-02-28 17:00:53.000000000 +0000
@@ -239,7 +239,7 @@
 +
 +</refentry>
 diff --git a/meson.build b/meson.build
-index 27d95e7..9ace3e6 100644
+index e707742..6330645 100644
 --- a/meson.build
 +++ b/meson.build
 @@ -3368,6 +3368,15 @@ executable(
diff -Nru systemd-252.22/debian/patches/p11kit-switch-to-dlopen.patch systemd-252.23/debian/patches/p11kit-switch-to-dlopen.patch
--- systemd-252.22/debian/patches/p11kit-switch-to-dlopen.patch	2024-01-26 21:48:26.000000000 +0000
+++ systemd-252.23/debian/patches/p11kit-switch-to-dlopen.patch	2024-02-28 17:00:53.000000000 +0000
@@ -13,7 +13,7 @@
  7 files changed, 202 insertions(+), 60 deletions(-)
 
 diff --git a/meson.build b/meson.build
-index 9de2309..27d95e7 100644
+index afcb4a7..e707742 100644
 --- a/meson.build
 +++ b/meson.build
 @@ -1462,8 +1462,10 @@ if want_p11kit != 'false' and not skip_deps
@@ -718,10 +718,10 @@
  }
  
 diff --git a/test/test-functions b/test/test-functions
-index 73fbef8..0ba7ce2 100644
+index da17bff..58257d4 100644
 --- a/test/test-functions
 +++ b/test/test-functions
-@@ -1386,7 +1386,7 @@ install_missing_libraries() {
+@@ -1391,7 +1391,7 @@ install_missing_libraries() {
      local lib path
      # A number of dependencies is now optional via dlopen, so the install
      # script will not pick them up, since it looks at linkage.
@@ -730,7 +730,7 @@
          ddebug "Searching for $lib via pkg-config"
          if pkg-config --exists "$lib"; then
                  path="$(pkg-config --variable=libdir "$lib")"
-@@ -1398,6 +1398,10 @@ install_missing_libraries() {
+@@ -1403,6 +1403,10 @@ install_missing_libraries() {
                  if ! [[ ${lib} =~ ^lib ]]; then
                          lib="lib${lib}"
                  fi
diff -Nru systemd-252.22/docs/UIDS-GIDS.md systemd-252.23/docs/UIDS-GIDS.md
--- systemd-252.22/docs/UIDS-GIDS.md	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/docs/UIDS-GIDS.md	2024-02-28 16:57:11.000000000 +0000
@@ -21,7 +21,7 @@
 In theory, the range of the C type `uid_t` is 32bit wide on Linux,
 i.e. 0…4294967295. However, four UIDs are special on Linux:
 
-1. 0 → The `root` super-user
+1. 0 → The `root` super-user.
 
 2. 65534 → The `nobody` UID, also called the "overflow" UID or similar. It's
    where various subsystems map unmappable users to, for example file systems
@@ -57,20 +57,20 @@
 
 2. 1000…65533 and 65536…4294967294 → Everything else, i.e. regular (human) users.
 
-Note that most distributions allow changing the boundary between system and
-regular users, even during runtime as user configuration. Moreover, some older
-systems placed the boundary at 499/500, or even 99/100. In `systemd`, the
-boundary is configurable only during compilation time, as this should be a
-decision for distribution builders, not for users. Moreover, we strongly
-discourage downstreams to change the boundary from the upstream default of
-999/1000.
+Some older systems placed the boundary at 499/500, or even 99/100,
+and some distributions allow the boundary between system and regular users to be changed
+via local configuration.
+In `systemd`, the boundary is configurable during compilation time
+and is also queried from `/etc/login.defs` at runtime,
+if the `-Dcompat-mutable-uid-boundaries=true` compile-time setting is used.
+We strongly discourage downstreams from changing the boundary from the upstream default of 999/1000.
 
 Also note that programs such as `adduser` tend to allocate from a subset of the
-available regular user range only, usually 1000..60000. And it's also usually
-user-configurable, too.
+available regular user range only, usually 1000..60000.
+This range can also be configured using `/etc/login.defs`.
 
 Note that systemd requires that system users and groups are resolvable without
-networking available — a requirement that is not made for regular users. This
+network — a requirement that is not made for regular users. This
 means regular users may be stored in remote LDAP or NIS databases, but system
 users may not (except when there's a consistent local cache kept, that is
 available during earliest boot, including in the initrd).
@@ -155,15 +155,15 @@
 `pkg-config`:
 
 ```
-$ pkg-config --variable=systemuidmax systemd
+$ pkg-config --variable=system_uid_max systemd
 999
-$ pkg-config --variable=dynamicuidmin systemd
+$ pkg-config --variable=dynamic_uid_min systemd
 61184
-$ pkg-config --variable=dynamicuidmax systemd
+$ pkg-config --variable=dynamic_uid_max systemd
 65519
-$ pkg-config --variable=containeruidbasemin systemd
+$ pkg-config --variable=container_uid_base_min systemd
 524288
-$ pkg-config --variable=containeruidbasemax systemd
+$ pkg-config --variable=container_uid_base_max systemd
 1878982656
 ```
 
diff -Nru systemd-252.22/.github/workflows/unit_tests.sh systemd-252.23/.github/workflows/unit_tests.sh
--- systemd-252.22/.github/workflows/unit_tests.sh	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/.github/workflows/unit_tests.sh	2024-02-28 16:57:11.000000000 +0000
@@ -76,7 +76,8 @@
             MESON_ARGS+=(--fatal-meson-warnings)
             run_meson -Dnobody-group=nogroup --werror -Dtests=unsafe -Dslow-tests=true -Dfuzz-tests=true "${MESON_ARGS[@]}" build
             ninja -C build -v
-            meson test -C build --print-errorlogs
+            # Ensure setting a timezone (like the reproducible build tests do) does not break time/date unit tests
+            TZ=GMT+12 meson test -C build --print-errorlogs
             ;;
         RUN_ASAN_UBSAN|RUN_GCC_ASAN_UBSAN|RUN_CLANG_ASAN_UBSAN|RUN_CLANG_ASAN_UBSAN_NO_DEPS)
             MESON_ARGS=(--optimization=1)
diff -Nru systemd-252.22/man/machine-id.xml systemd-252.23/man/machine-id.xml
--- systemd-252.22/man/machine-id.xml	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/man/machine-id.xml	2024-02-28 16:57:11.000000000 +0000
@@ -101,7 +101,8 @@
     to use the D-Bus machine ID from <filename>/var/lib/dbus/machine-id</filename>, the
     value of the kernel command line option <varname>container_uuid</varname>, the KVM DMI
     <filename>product_uuid</filename> or the devicetree <filename>vm,uuid</filename>
-    (on KVM systems), and finally a randomly generated UUID.</para>
+    (on KVM systems), the Xen hypervisor <filename>uuid</filename>, and finally a randomly
+    generated UUID.</para>
 
     <para>After the machine ID is established,
     <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
diff -Nru systemd-252.22/man/org.freedesktop.portable1.xml systemd-252.23/man/org.freedesktop.portable1.xml
--- systemd-252.22/man/org.freedesktop.portable1.xml	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/man/org.freedesktop.portable1.xml	2024-02-28 16:57:11.000000000 +0000
@@ -249,7 +249,8 @@
         <listitem><para>mkdir</para></listitem>
       </itemizedlist>
       Note that an image cannot be attached if a unit that it contains is already present
-      on the system.</para>
+      on the system. Note that this method returns only after all the listed operations are completed,
+      and due to the I/O involved it might take some time.</para>
 
       <para><function>AttachImageWithExtensions()</function> attaches a portable image to the system.
       This method is a superset of <function>AttachImage()</function> with the addition of
@@ -271,7 +272,9 @@
       <itemizedlist>
         <listitem><para>unlink</para></listitem>
       </itemizedlist>
-      Note that an image cannot be detached if a unit that it contains is running.</para>
+      Note that an image cannot be detached if a unit that it contains is running. Note that this method
+      returns only after all the listed operations are completed, and due to the I/O involved it might take
+      some time.</para>
 
       <para><function>DetachImageWithExtensions()</function> detaches a portable image from the system.
       This method is a superset of <function>DetachImage()</function> with the addition of
diff -Nru systemd-252.22/man/org.freedesktop.systemd1.xml systemd-252.23/man/org.freedesktop.systemd1.xml
--- systemd-252.22/man/org.freedesktop.systemd1.xml	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/man/org.freedesktop.systemd1.xml	2024-02-28 16:57:11.000000000 +0000
@@ -1228,7 +1228,13 @@
       and terminate all units that aren't dependencies of it. If <literal>ignore-dependencies</literal>, it
       will start a unit but ignore all its dependencies. If <literal>ignore-requirements</literal>, it will
       start a unit but only ignore the requirement dependencies. It is not recommended to make use of the
-      latter two options. On completion, this method returns the newly created job object.</para>
+      latter two options. On reply, if successful, this method returns the newly created job object
+      which has been enqueued for asynchronous activation. Callers that want to track the outcome of the
+      actual start operation need to monitor the result of this job. This can be achieved in a race-free
+      manner by first subscribing to the <function>JobRemoved()</function> signal, then calling
+      <function>StartUnit()</function> and using the returned job object to filter out unrelated
+      <function>JobRemoved()</function> signals, until the desired one is received, which will then carry
+      the result of the start operation.</para>
 
       <para><function>StartUnitReplace()</function> is similar to <function>StartUnit()</function> but
       replaces a job that is queued for one unit by a job for another unit.</para>
diff -Nru systemd-252.22/man/systemd.exec.xml systemd-252.23/man/systemd.exec.xml
--- systemd-252.22/man/systemd.exec.xml	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/man/systemd.exec.xml	2024-02-28 16:57:11.000000000 +0000
@@ -1101,9 +1101,9 @@
       <varlistentry>
         <term><varname>IgnoreSIGPIPE=</varname></term>
 
-        <listitem><para>Takes a boolean argument. If true, causes <constant>SIGPIPE</constant> to be ignored in the
-        executed process. Defaults to true because <constant>SIGPIPE</constant> generally is useful only in shell
-        pipelines.</para></listitem>
+        <listitem><para>Takes a boolean argument. If true, <constant>SIGPIPE</constant> is ignored in the
+        executed process. Defaults to true since <constant>SIGPIPE</constant> is generally only useful in
+        shell pipelines.</para></listitem>
       </varlistentry>
 
     </variablelist>
diff -Nru systemd-252.22/man/systemd-nspawn.xml systemd-252.23/man/systemd-nspawn.xml
--- systemd-252.22/man/systemd-nspawn.xml	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/man/systemd-nspawn.xml	2024-02-28 16:57:11.000000000 +0000
@@ -1317,7 +1317,8 @@
         and the subdirectory is symlinked into the host at the same
         location. <literal>try-host</literal> and
         <literal>try-guest</literal> do the same but do not fail if
-        the host does not have persistent journaling enabled. If
+        the host does not have persistent journaling enabled, or if
+        the container is in the <option>--ephemeral</option> mode. If
         <literal>auto</literal> (the default), and the right
         subdirectory of <filename>/var/log/journal</filename> exists,
         it will be bind mounted into the container. If the
diff -Nru systemd-252.22/man/systemd.service.xml systemd-252.23/man/systemd.service.xml
--- systemd-252.22/man/systemd.service.xml	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/man/systemd.service.xml	2024-02-28 16:57:11.000000000 +0000
@@ -765,62 +765,41 @@
 
       <varlistentry>
         <term><varname>Restart=</varname></term>
-        <listitem><para>Configures whether the service shall be
-        restarted when the service process exits, is killed, or a
-        timeout is reached. The service process may be the main
-        service process, but it may also be one of the processes
-        specified with <varname>ExecStartPre=</varname>,
-        <varname>ExecStartPost=</varname>,
-        <varname>ExecStop=</varname>,
-        <varname>ExecStopPost=</varname>, or
-        <varname>ExecReload=</varname>. When the death of the process
-        is a result of systemd operation (e.g. service stop or
-        restart), the service will not be restarted. Timeouts include
-        missing the watchdog "keep-alive ping" deadline and a service
-        start, reload, and stop operation timeouts.</para>
+        <listitem><para>Configures whether the service shall be restarted when the service process exits,
+        is killed, or a timeout is reached. The service process may be the main service process, but it may
+        also be one of the processes specified with <varname>ExecStartPre=</varname>,
+        <varname>ExecStartPost=</varname>, <varname>ExecStop=</varname>, <varname>ExecStopPost=</varname>,
+        or <varname>ExecReload=</varname>. When the death of the process is a result of systemd operation
+        (e.g. service stop or restart), the service will not be restarted. Timeouts include missing the watchdog
+        "keep-alive ping" deadline and a service start, reload, and stop operation timeouts.</para>
 
-        <para>Takes one of
-        <option>no</option>,
-        <option>on-success</option>,
-        <option>on-failure</option>,
-        <option>on-abnormal</option>,
-        <option>on-watchdog</option>,
-        <option>on-abort</option>, or
-        <option>always</option>.
-        If set to <option>no</option> (the default), the service will
-        not be restarted. If set to <option>on-success</option>, it
-        will be restarted only when the service process exits cleanly.
+        <para>Takes one of <option>no</option>, <option>on-success</option>, <option>on-failure</option>,
+        <option>on-abnormal</option>, <option>on-watchdog</option>, <option>on-abort</option>, or
+        <option>always</option>. If set to <option>no</option> (the default), the service will not be restarted.
+        If set to <option>on-success</option>, it will be restarted only when the service process exits cleanly.
         In this context, a clean exit means any of the following:
         <itemizedlist>
             <listitem><simpara>exit code of 0;</simpara></listitem>
-            <listitem><simpara>for types other than
-            <varname>Type=oneshot</varname>, one of the signals
-                <constant>SIGHUP</constant>,
-                <constant>SIGINT</constant>,
-                <constant>SIGTERM</constant>, or
-                <constant>SIGPIPE</constant>;</simpara></listitem>
+            <listitem><simpara>for types other than <varname>Type=oneshot</varname>, one of the signals
+                <constant>SIGHUP</constant>, <constant>SIGINT</constant>,
+                <constant>SIGTERM</constant>, or <constant>SIGPIPE</constant>;
+            </simpara></listitem>
             <listitem><simpara>exit statuses and signals specified in
                 <varname>SuccessExitStatus=</varname>.</simpara></listitem>
         </itemizedlist>
-        If set to
-        <option>on-failure</option>, the service will be restarted
-        when the process exits with a non-zero exit code, is
-        terminated by a signal (including on core dump, but excluding
-        the aforementioned four signals), when an operation (such as
-        service reload) times out, and when the configured watchdog
-        timeout is triggered. If set to <option>on-abnormal</option>,
-        the service will be restarted when the process is terminated
-        by a signal (including on core dump, excluding the
-        aforementioned four signals), when an operation times out, or
-        when the watchdog timeout is triggered. If set to
-        <option>on-abort</option>, the service will be restarted only
-        if the service process exits due to an uncaught signal not
-        specified as a clean exit status. If set to
-        <option>on-watchdog</option>, the service will be restarted
-        only if the watchdog timeout for the service expires. If set
-        to <option>always</option>, the service will be restarted
-        regardless of whether it exited cleanly or not, got terminated
-        abnormally by a signal, or hit a timeout.</para>
+        If set to <option>on-failure</option>, the service will be restarted when the process exits with
+        a non-zero exit code, is terminated by a signal (including on core dump, but excluding the aforementioned
+        four signals), when an operation (such as service reload) times out, and when the configured watchdog
+        timeout is triggered. If set to <option>on-abnormal</option>, the service will be restarted when
+        the process is terminated by a signal (including on core dump, excluding the aforementioned four signals),
+        when an operation times out, or when the watchdog timeout is triggered. If set to <option>on-abort</option>,
+        the service will be restarted only if the service process exits due to an uncaught signal not specified
+        as a clean exit status. If set to <option>on-watchdog</option>, the service will be restarted
+        only if the watchdog timeout for the service expires. If set to <option>always</option>, the service
+        will be restarted regardless of whether it exited cleanly or not, got terminated abnormally by
+        a signal, or hit a timeout. Note that <varname>Type=oneshot</varname> services will never be restarted
+        on a clean exit status, i.e. <option>always</option> and <option>on-success</option> are rejected
+        for them.</para>
 
         <table>
           <title>Exit causes and the effect of the <varname>Restart=</varname> settings</title>
diff -Nru systemd-252.22/man/udev.xml systemd-252.23/man/udev.xml
--- systemd-252.22/man/udev.xml	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/man/udev.xml	2024-02-28 16:57:11.000000000 +0000
@@ -680,15 +680,16 @@
           </varlistentry>
         </variablelist>
 
-        <para>The <varname>NAME</varname>, <varname>SYMLINK</varname>,
-        <varname>PROGRAM</varname>, <varname>OWNER</varname>,
-        <varname>GROUP</varname>, <varname>MODE</varname>, <varname>SECLABEL</varname>,
-        and <varname>RUN</varname> fields support simple string substitutions.
+        <para>The <varname>ENV</varname>, <varname>GROUP</varname>,
+        <varname>MODE</varname>, <varname>NAME</varname>,
+        <varname>OWNER</varname>, <varname>PROGRAM</varname>,
+        <varname>RUN</varname>, <varname>SECLABEL</varname>, and
+        <varname>SYMLINK</varname> fields support simple string substitutions.
         The <varname>RUN</varname> substitutions are performed after all rules
         have been processed, right before the program is executed, allowing for
-        the use of device properties set by earlier matching rules. For all other
-        fields, substitutions are performed while the individual rule is being
-        processed. The available substitutions are:</para>
+        the use of device properties set by earlier matching rules. For all
+        other fields, substitutions are performed while the individual rule is
+        being processed. The available substitutions are:</para>
         <variablelist class='udev-directives'>
           <varlistentry>
             <term><option>$kernel</option>, <option>%k</option></term>
diff -Nru systemd-252.22/meson.build systemd-252.23/meson.build
--- systemd-252.22/meson.build	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/meson.build	2024-02-28 16:57:11.000000000 +0000
@@ -321,7 +321,7 @@
 want_tests = get_option('tests')
 slow_tests = want_tests != 'false' and get_option('slow-tests')
 fuzz_tests = want_tests != 'false' and get_option('fuzz-tests')
-install_tests = get_option('install-tests')
+install_tests = want_tests != 'false' and get_option('install-tests')
 
 if add_languages('cpp', required : fuzzer_build)
         #  Used only for tests
diff -Nru systemd-252.22/.semaphore/semaphore-runner.sh systemd-252.23/.semaphore/semaphore-runner.sh
--- systemd-252.22/.semaphore/semaphore-runner.sh	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/.semaphore/semaphore-runner.sh	2024-02-28 16:57:11.000000000 +0000
@@ -63,7 +63,7 @@
             sudo apt-get install -y -t "$UBUNTU_RELEASE-backports" lxc
             sudo apt-get install -y python3-debian git dpkg-dev fakeroot python3-jinja2
 
-            [ -d "$AUTOPKGTEST_DIR" ] || git clone --quiet --depth=1 https://salsa.debian.org/ci-team/autopkgtest.git "$AUTOPKGTEST_DIR"
+            [ -d "$AUTOPKGTEST_DIR" ] || git clone --quiet --branch=debian/5.32 --depth=1 https://salsa.debian.org/ci-team/autopkgtest.git "$AUTOPKGTEST_DIR"
 
             create_container
         ;;
diff -Nru systemd-252.22/src/basic/architecture.c systemd-252.23/src/basic/architecture.c
--- systemd-252.22/src/basic/architecture.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/basic/architecture.c	2024-02-28 16:57:11.000000000 +0000
@@ -70,7 +70,7 @@
                 { "parisc64",   ARCHITECTURE_PARISC64 },
                 { "parisc",     ARCHITECTURE_PARISC   },
 
-#elif defined(__loongarch64)
+#elif defined(__loongarch_lp64)
                 { "loongarch64", ARCHITECTURE_LOONGARCH64 },
 
 #elif defined(__m68k__)
diff -Nru systemd-252.22/src/basic/cgroup-util.h systemd-252.23/src/basic/cgroup-util.h
--- systemd-252.22/src/basic/cgroup-util.h	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/basic/cgroup-util.h	2024-02-28 16:57:11.000000000 +0000
@@ -66,10 +66,13 @@
         /* All real cgroup v2 controllers */
         CGROUP_MASK_V2 = CGROUP_MASK_CPU|CGROUP_MASK_CPUSET|CGROUP_MASK_IO|CGROUP_MASK_MEMORY|CGROUP_MASK_PIDS,
 
+        /* All controllers we want to delegate in case of Delegate=yes. Which are prety much the v2 controllers only, as delegation on v1 is not safe, and bpf stuff isn't a real controller */
+        CGROUP_MASK_DELEGATE = CGROUP_MASK_V2,
+
         /* All cgroup v2 BPF pseudo-controllers */
         CGROUP_MASK_BPF = CGROUP_MASK_BPF_FIREWALL|CGROUP_MASK_BPF_DEVICES|CGROUP_MASK_BPF_FOREIGN|CGROUP_MASK_BPF_SOCKET_BIND|CGROUP_MASK_BPF_RESTRICT_NETWORK_INTERFACES,
 
-        _CGROUP_MASK_ALL = CGROUP_CONTROLLER_TO_MASK(_CGROUP_CONTROLLER_MAX) - 1
+        _CGROUP_MASK_ALL = CGROUP_CONTROLLER_TO_MASK(_CGROUP_CONTROLLER_MAX) - 1,
 } CGroupMask;
 
 static inline CGroupMask CGROUP_MASK_EXTEND_JOINED(CGroupMask mask) {
diff -Nru systemd-252.22/src/basic/fd-util.c systemd-252.23/src/basic/fd-util.c
--- systemd-252.22/src/basic/fd-util.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/basic/fd-util.c	2024-02-28 16:57:11.000000000 +0000
@@ -284,7 +284,7 @@
         case 0:
                 /* Close everything. Yay! */
 
-                if (close_range(3, -1, 0) >= 0)
+                if (close_range(3, INT_MAX, 0) >= 0)
                         return 1;
 
                 if (ERRNO_IS_NOT_SUPPORTED(errno) || ERRNO_IS_PRIVILEGE(errno)) {
@@ -395,7 +395,7 @@
                                 if (sorted[n_sorted-1] >= INT_MAX) /* Dont let the addition below overflow */
                                         return 0;
 
-                                if (close_range(sorted[n_sorted-1] + 1, -1, 0) >= 0)
+                                if (close_range(sorted[n_sorted-1] + 1, INT_MAX, 0) >= 0)
                                         return 0;
 
                                 if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno))
diff -Nru systemd-252.22/src/basic/fs-util.c systemd-252.23/src/basic/fs-util.c
--- systemd-252.22/src/basic/fs-util.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/basic/fs-util.c	2024-02-28 16:57:11.000000000 +0000
@@ -118,7 +118,11 @@
 int readlinkat_malloc(int fd, const char *p, char **ret) {
         size_t l = PATH_MAX;
 
-        assert(p);
+        assert(fd >= 0 || fd == AT_FDCWD);
+
+        if (fd < 0 && isempty(p))
+                return -EISDIR; /* In this case, the fd points to the current working directory, and is
+                                 * definitely not a symlink. Let's return earlier. */
 
         for (;;) {
                 _cleanup_free_ char *c = NULL;
@@ -128,7 +132,7 @@
                 if (!c)
                         return -ENOMEM;
 
-                n = readlinkat(fd, p, c, l);
+                n = readlinkat(fd, strempty(p), c, l);
                 if (n < 0)
                         return -errno;
 
diff -Nru systemd-252.22/src/basic/missing_syscall_def.h systemd-252.23/src/basic/missing_syscall_def.h
--- systemd-252.22/src/basic/missing_syscall_def.h	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/basic/missing_syscall_def.h	2024-02-28 16:57:11.000000000 +0000
@@ -14,7 +14,7 @@
 #  elif defined(__arm__)
 #  elif defined(__i386__)
 #  elif defined(__ia64__)
-#  elif defined(__loongarch64)
+#  elif defined(__loongarch_lp64)
 #  elif defined(__m68k__)
 #  elif defined(_MIPS_SIM)
 #    if _MIPS_SIM == _MIPS_SIM_ABI32
@@ -55,7 +55,7 @@
 #    define systemd_NR_bpf 357
 #  elif defined(__ia64__)
 #    define systemd_NR_bpf 1341
-#  elif defined(__loongarch64)
+#  elif defined(__loongarch_lp64)
 #    define systemd_NR_bpf 280
 #  elif defined(__m68k__)
 #    define systemd_NR_bpf 354
@@ -123,7 +123,7 @@
 #    define systemd_NR_close_range 436
 #  elif defined(__ia64__)
 #    define systemd_NR_close_range 1460
-#  elif defined(__loongarch64)
+#  elif defined(__loongarch_lp64)
 #    define systemd_NR_close_range 436
 #  elif defined(__m68k__)
 #    define systemd_NR_close_range 436
@@ -191,7 +191,7 @@
 #    define systemd_NR_copy_file_range 377
 #  elif defined(__ia64__)
 #    define systemd_NR_copy_file_range 1347
-#  elif defined(__loongarch64)
+#  elif defined(__loongarch_lp64)
 #    define systemd_NR_copy_file_range 285
 #  elif defined(__m68k__)
 #    define systemd_NR_copy_file_range 376
@@ -314,6 +314,74 @@
 #  endif
 #endif
 
+#ifndef __IGNORE_fchmodat2
+#  if defined(__aarch64__)
+#    define systemd_NR_fchmodat2 452
+#  elif defined(__alpha__)
+#    define systemd_NR_fchmodat2 562
+#  elif defined(__arc__) || defined(__tilegx__)
+#    define systemd_NR_fchmodat2 452
+#  elif defined(__arm__)
+#    define systemd_NR_fchmodat2 452
+#  elif defined(__i386__)
+#    define systemd_NR_fchmodat2 452
+#  elif defined(__ia64__)
+#    define systemd_NR_fchmodat2 1476
+#  elif defined(__loongarch_lp64)
+#    define systemd_NR_fchmodat2 452
+#  elif defined(__m68k__)
+#    define systemd_NR_fchmodat2 452
+#  elif defined(_MIPS_SIM)
+#    if _MIPS_SIM == _MIPS_SIM_ABI32
+#      define systemd_NR_fchmodat2 4452
+#    elif _MIPS_SIM == _MIPS_SIM_NABI32
+#      define systemd_NR_fchmodat2 6452
+#    elif _MIPS_SIM == _MIPS_SIM_ABI64
+#      define systemd_NR_fchmodat2 5452
+#    else
+#      error "Unknown MIPS ABI"
+#    endif
+#  elif defined(__hppa__)
+#    define systemd_NR_fchmodat2 452
+#  elif defined(__powerpc__)
+#    define systemd_NR_fchmodat2 452
+#  elif defined(__riscv)
+#    if __riscv_xlen == 32
+#      define systemd_NR_fchmodat2 452
+#    elif __riscv_xlen == 64
+#      define systemd_NR_fchmodat2 452
+#    else
+#      error "Unknown RISC-V ABI"
+#    endif
+#  elif defined(__s390__)
+#    define systemd_NR_fchmodat2 452
+#  elif defined(__sparc__)
+#    define systemd_NR_fchmodat2 452
+#  elif defined(__x86_64__)
+#    if defined(__ILP32__)
+#      define systemd_NR_fchmodat2 (452 | /* __X32_SYSCALL_BIT */ 0x40000000)
+#    else
+#      define systemd_NR_fchmodat2 452
+#    endif
+#  elif !defined(missing_arch_template)
+#    warning "fchmodat2() syscall number is unknown for your architecture"
+#  endif
+
+/* may be an (invalid) negative number due to libseccomp, see PR 13319 */
+#  if defined __NR_fchmodat2 && __NR_fchmodat2 >= 0
+#    if defined systemd_NR_fchmodat2
+assert_cc(__NR_fchmodat2 == systemd_NR_fchmodat2);
+#    endif
+#  else
+#    if defined __NR_fchmodat2
+#      undef __NR_fchmodat2
+#    endif
+#    if defined systemd_NR_fchmodat2 && systemd_NR_fchmodat2 >= 0
+#      define __NR_fchmodat2 systemd_NR_fchmodat2
+#    endif
+#  endif
+#endif
+
 #ifndef __IGNORE_getrandom
 #  if defined(__aarch64__)
 #    define systemd_NR_getrandom 278
@@ -327,7 +395,7 @@
 #    define systemd_NR_getrandom 355
 #  elif defined(__ia64__)
 #    define systemd_NR_getrandom 1339
-#  elif defined(__loongarch64)
+#  elif defined(__loongarch_lp64)
 #    define systemd_NR_getrandom 278
 #  elif defined(__m68k__)
 #    define systemd_NR_getrandom 352
@@ -395,7 +463,7 @@
 #    define systemd_NR_memfd_create 356
 #  elif defined(__ia64__)
 #    define systemd_NR_memfd_create 1340
-#  elif defined(__loongarch64)
+#  elif defined(__loongarch_lp64)
 #    define systemd_NR_memfd_create 279
 #  elif defined(__m68k__)
 #    define systemd_NR_memfd_create 353
@@ -463,7 +531,7 @@
 #    define systemd_NR_mount_setattr 442
 #  elif defined(__ia64__)
 #    define systemd_NR_mount_setattr 1466
-#  elif defined(__loongarch64)
+#  elif defined(__loongarch_lp64)
 #    define systemd_NR_mount_setattr 442
 #  elif defined(__m68k__)
 #    define systemd_NR_mount_setattr 442
@@ -531,7 +599,7 @@
 #    define systemd_NR_move_mount 429
 #  elif defined(__ia64__)
 #    define systemd_NR_move_mount 1453
-#  elif defined(__loongarch64)
+#  elif defined(__loongarch_lp64)
 #    define systemd_NR_move_mount 429
 #  elif defined(__m68k__)
 #    define systemd_NR_move_mount 429
@@ -599,7 +667,7 @@
 #    define systemd_NR_name_to_handle_at 341
 #  elif defined(__ia64__)
 #    define systemd_NR_name_to_handle_at 1326
-#  elif defined(__loongarch64)
+#  elif defined(__loongarch_lp64)
 #    define systemd_NR_name_to_handle_at 264
 #  elif defined(__m68k__)
 #    define systemd_NR_name_to_handle_at 340
@@ -667,7 +735,7 @@
 #    define systemd_NR_open_tree 428
 #  elif defined(__ia64__)
 #    define systemd_NR_open_tree 1452
-#  elif defined(__loongarch64)
+#  elif defined(__loongarch_lp64)
 #    define systemd_NR_open_tree 428
 #  elif defined(__m68k__)
 #    define systemd_NR_open_tree 428
@@ -735,7 +803,7 @@
 #    define systemd_NR_openat2 437
 #  elif defined(__ia64__)
 #    define systemd_NR_openat2 1461
-#  elif defined(__loongarch64)
+#  elif defined(__loongarch_lp64)
 #    define systemd_NR_openat2 437
 #  elif defined(__m68k__)
 #    define systemd_NR_openat2 437
@@ -803,7 +871,7 @@
 #    define systemd_NR_pidfd_open 434
 #  elif defined(__ia64__)
 #    define systemd_NR_pidfd_open 1458
-#  elif defined(__loongarch64)
+#  elif defined(__loongarch_lp64)
 #    define systemd_NR_pidfd_open 434
 #  elif defined(__m68k__)
 #    define systemd_NR_pidfd_open 434
@@ -871,7 +939,7 @@
 #    define systemd_NR_pidfd_send_signal 424
 #  elif defined(__ia64__)
 #    define systemd_NR_pidfd_send_signal 1448
-#  elif defined(__loongarch64)
+#  elif defined(__loongarch_lp64)
 #    define systemd_NR_pidfd_send_signal 424
 #  elif defined(__m68k__)
 #    define systemd_NR_pidfd_send_signal 424
@@ -939,7 +1007,7 @@
 #    define systemd_NR_pkey_mprotect 380
 #  elif defined(__ia64__)
 #    define systemd_NR_pkey_mprotect 1354
-#  elif defined(__loongarch64)
+#  elif defined(__loongarch_lp64)
 #    define systemd_NR_pkey_mprotect 288
 #  elif defined(__m68k__)
 #    define systemd_NR_pkey_mprotect 381
@@ -1007,7 +1075,7 @@
 #    define systemd_NR_renameat2 353
 #  elif defined(__ia64__)
 #    define systemd_NR_renameat2 1338
-#  elif defined(__loongarch64)
+#  elif defined(__loongarch_lp64)
 #    define systemd_NR_renameat2 276
 #  elif defined(__m68k__)
 #    define systemd_NR_renameat2 351
@@ -1075,7 +1143,7 @@
 #    define systemd_NR_setns 346
 #  elif defined(__ia64__)
 #    define systemd_NR_setns 1330
-#  elif defined(__loongarch64)
+#  elif defined(__loongarch_lp64)
 #    define systemd_NR_setns 268
 #  elif defined(__m68k__)
 #    define systemd_NR_setns 344
@@ -1143,7 +1211,7 @@
 #    define systemd_NR_statx 383
 #  elif defined(__ia64__)
 #    define systemd_NR_statx 1350
-#  elif defined(__loongarch64)
+#  elif defined(__loongarch_lp64)
 #    define systemd_NR_statx 291
 #  elif defined(__m68k__)
 #    define systemd_NR_statx 379
diff -Nru systemd-252.22/src/basic/missing_syscall.h systemd-252.23/src/basic/missing_syscall.h
--- systemd-252.22/src/basic/missing_syscall.h	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/basic/missing_syscall.h	2024-02-28 16:57:11.000000000 +0000
@@ -383,23 +383,14 @@
 /* ======================================================================= */
 
 #if !HAVE_CLOSE_RANGE
-static inline int missing_close_range(int first_fd, int end_fd, unsigned flags) {
+static inline int missing_close_range(unsigned first_fd, unsigned end_fd, unsigned flags) {
 #  ifdef __NR_close_range
         /* Kernel-side the syscall expects fds as unsigned integers (just like close() actually), while
-         * userspace exclusively uses signed integers for fds. We don't know just yet how glibc is going to
-         * wrap this syscall, but let's assume it's going to be similar to what they do for close(),
-         * i.e. make the same unsigned → signed type change from the raw kernel syscall compared to the
-         * userspace wrapper. There's only one caveat for this: unlike for close() there's the special
-         * UINT_MAX fd value for the 'end_fd' argument. Let's safely map that to -1 here. And let's refuse
-         * any other negative values. */
-        if ((first_fd < 0) || (end_fd < 0 && end_fd != -1)) {
-                errno = -EBADF;
-                return -1;
-        }
-
+         * userspace exclusively uses signed integers for fds. glibc chose to expose it 1:1 however, hence we
+         * do so here too, even if we end up passing signed fds to it most of the time. */
         return syscall(__NR_close_range,
-                       (unsigned) first_fd,
-                       end_fd == -1 ? UINT_MAX : (unsigned) end_fd, /* Of course, the compiler should figure out that this is the identity mapping IRL */
+                       first_fd,
+                       end_fd,
                        flags);
 #  else
         errno = ENOSYS;
diff -Nru systemd-252.22/src/basic/missing_syscalls.py systemd-252.23/src/basic/missing_syscalls.py
--- systemd-252.22/src/basic/missing_syscalls.py	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/basic/missing_syscalls.py	2024-02-28 16:57:11.000000000 +0000
@@ -10,6 +10,7 @@
     'close_range',
     'copy_file_range',
     'epoll_pwait2',
+    'fchmodat2',
     'getrandom',
     'memfd_create',
     'mount_setattr',
@@ -60,7 +61,7 @@
 #    define systemd_NR_{syscall} {nr_i386}
 #  elif defined(__ia64__)
 #    define systemd_NR_{syscall} {nr_ia64}
-#  elif defined(__loongarch64)
+#  elif defined(__loongarch_lp64)
 #    define systemd_NR_{syscall} {nr_loongarch64}
 #  elif defined(__m68k__)
 #    define systemd_NR_{syscall} {nr_m68k}
diff -Nru systemd-252.22/src/basic/string-util.c systemd-252.23/src/basic/string-util.c
--- systemd-252.22/src/basic/string-util.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/basic/string-util.c	2024-02-28 16:57:11.000000000 +0000
@@ -1202,3 +1202,15 @@
 
         return n;
 }
+
+char *startswith_strv(const char *string, char **strv) {
+        char *found = NULL;
+
+        STRV_FOREACH(i, strv) {
+                found = startswith(string, *i);
+                if (found)
+                        break;
+        }
+
+        return found;
+}
diff -Nru systemd-252.22/src/basic/string-util.h systemd-252.23/src/basic/string-util.h
--- systemd-252.22/src/basic/string-util.h	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/basic/string-util.h	2024-02-28 16:57:11.000000000 +0000
@@ -243,3 +243,8 @@
 char *string_replace_char(char *str, char old_char, char new_char);
 
 size_t strspn_from_end(const char *str, const char *accept);
+
+char *startswith_strv(const char *string, char **strv);
+
+#define STARTSWITH_SET(p, ...)                                  \
+        startswith_strv(p, STRV_MAKE(__VA_ARGS__))
diff -Nru systemd-252.22/src/basic/strv.h systemd-252.23/src/basic/strv.h
--- systemd-252.22/src/basic/strv.h	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/basic/strv.h	2024-02-28 16:57:11.000000000 +0000
@@ -206,18 +206,6 @@
                 _x && strv_contains_case(STRV_MAKE(__VA_ARGS__), _x); \
         })
 
-#define STARTSWITH_SET(p, ...)                                  \
-        ({                                                      \
-                const char *_p = (p);                           \
-                char *_found = NULL;                            \
-                STRV_FOREACH(_i, STRV_MAKE(__VA_ARGS__)) {      \
-                        _found = startswith(_p, *_i);           \
-                        if (_found)                             \
-                                break;                          \
-                }                                               \
-                _found;                                         \
-        })
-
 #define ENDSWITH_SET(p, ...)                                    \
         ({                                                      \
                 const char *_p = (p);                           \
diff -Nru systemd-252.22/src/basic/user-util.c systemd-252.23/src/basic/user-util.c
--- systemd-252.22/src/basic/user-util.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/basic/user-util.c	2024-02-28 16:57:11.000000000 +0000
@@ -313,7 +313,7 @@
         if (shell) {
                 if (FLAGS_SET(flags, USER_CREDS_CLEAN) &&
                     (isempty(p->pw_shell) ||
-                     !path_is_valid(p->pw_dir) ||
+                     !path_is_valid(p->pw_shell) ||
                      !path_is_absolute(p->pw_shell) ||
                      is_nologin_shell(p->pw_shell)))
                         *shell = NULL;
diff -Nru systemd-252.22/src/basic/virt.c systemd-252.23/src/basic/virt.c
--- systemd-252.22/src/basic/virt.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/basic/virt.c	2024-02-28 16:57:11.000000000 +0000
@@ -97,7 +97,7 @@
 }
 
 static Virtualization detect_vm_device_tree(void) {
-#if defined(__arm__) || defined(__aarch64__) || defined(__powerpc__) || defined(__powerpc64__)
+#if defined(__arm__) || defined(__aarch64__) || defined(__powerpc__) || defined(__powerpc64__) || defined(__riscv)
         _cleanup_free_ char *hvtype = NULL;
         int r;
 
@@ -154,7 +154,7 @@
 #endif
 }
 
-#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || defined(__loongarch64)
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || defined(__loongarch_lp64) || defined(__riscv)
 static Virtualization detect_vm_dmi_vendor(void) {
         static const char* const dmi_vendors[] = {
                 "/sys/class/dmi/id/product_name", /* Test this before sys_vendor to detect KVM over QEMU */
@@ -245,10 +245,10 @@
         log_debug("DMI BIOS Extension table does not indicate virtualization.");
         return SMBIOS_VM_BIT_UNSET;
 }
-#endif /* defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || defined(__loongarch64) */
+#endif /* defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || defined(__loongarch_lp64) */
 
 static Virtualization detect_vm_dmi(void) {
-#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || defined(__loongarch64)
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || defined(__loongarch_lp64)
 
         int r;
         r = detect_vm_dmi_vendor();
@@ -454,7 +454,7 @@
 
         /* We have to use the correct order here:
          *
-         * → First, try to detect Oracle Virtualbox, Amazon EC2 Nitro, and Parallels, even if they use KVM,
+         * → First, try to detect Oracle Virtualbox, Amazon EC2 Nitro, Parallels, and Google Compute Engine, even if they use KVM,
          *   as well as Xen even if it cloaks as Microsoft Hyper-V. Attempt to detect uml at this stage also
          *   since it runs as a user-process nested inside other VMs. Also check for Xen now, because Xen PV
          *   mode does not override CPUID when nested inside another hypervisor.
@@ -469,7 +469,8 @@
                    VIRTUALIZATION_ORACLE,
                    VIRTUALIZATION_XEN,
                    VIRTUALIZATION_AMAZON,
-                   VIRTUALIZATION_PARALLELS)) {
+                   VIRTUALIZATION_PARALLELS,
+                   VIRTUALIZATION_GOOGLE)) {
                 v = dmi;
                 goto finish;
         }
diff -Nru systemd-252.22/src/core/dbus-cgroup.c systemd-252.23/src/core/dbus-cgroup.c
--- systemd-252.22/src/core/dbus-cgroup.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/core/dbus-cgroup.c	2024-02-28 16:57:11.000000000 +0000
@@ -519,7 +519,7 @@
 
                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->delegate = b;
-                        c->delegate_controllers = b ? _CGROUP_MASK_ALL : 0;
+                        c->delegate_controllers = b ? CGROUP_MASK_DELEGATE : 0;
 
                         unit_write_settingf(u, flags, name, "Delegate=%s", yes_no(b));
                 }
diff -Nru systemd-252.22/src/core/dbus-execute.c systemd-252.23/src/core/dbus-execute.c
--- systemd-252.22/src/core/dbus-execute.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/core/dbus-execute.c	2024-02-28 16:57:11.000000000 +0000
@@ -728,7 +728,7 @@
                                 c->bind_mounts[i].source,
                                 c->bind_mounts[i].destination,
                                 c->bind_mounts[i].ignore_enoent,
-                                c->bind_mounts[i].recursive ? (uint64_t) MS_REC : (uint64_t) 0);
+                                c->bind_mounts[i].recursive ? (uint64_t) MS_REC : UINT64_C(0));
                 if (r < 0)
                         return r;
         }
@@ -1100,7 +1100,7 @@
 
         for (size_t i = 0; i < d->n_items; i++)
                 STRV_FOREACH(dst, d->items[i].symlinks) {
-                        r = sd_bus_message_append(reply, "(sst)", d->items[i].path, *dst, 0 /* flags, unused for now */);
+                        r = sd_bus_message_append(reply, "(sst)", d->items[i].path, *dst, UINT64_C(0) /* flags, unused for now */);
                         if (r < 0)
                                 return r;
                 }
diff -Nru systemd-252.22/src/core/execute.c systemd-252.23/src/core/execute.c
--- systemd-252.22/src/core/execute.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/core/execute.c	2024-02-28 16:57:11.000000000 +0000
@@ -4512,6 +4512,16 @@
         }
 
         if (context->utmp_id) {
+                _cleanup_free_ char *username_alloc = NULL;
+
+                if (!username && context->utmp_mode == EXEC_UTMP_USER) {
+                        username_alloc = uid_to_name(uid_is_valid(uid) ? uid : saved_uid);
+                        if (!username_alloc) {
+                                *exit_status = EXIT_USER;
+                                return log_oom();
+                        }
+                }
+
                 const char *line = context->tty_path ?
                         (path_startswith(context->tty_path, "/dev/") ?: context->tty_path) :
                         NULL;
@@ -4520,7 +4530,7 @@
                                       context->utmp_mode == EXEC_UTMP_INIT  ? INIT_PROCESS :
                                       context->utmp_mode == EXEC_UTMP_LOGIN ? LOGIN_PROCESS :
                                       USER_PROCESS,
-                                      username);
+                                      username ?: username_alloc);
         }
 
         if (uid_is_valid(uid)) {
diff -Nru systemd-252.22/src/core/kmod-setup.c systemd-252.23/src/core/kmod-setup.c
--- systemd-252.22/src/core/kmod-setup.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/core/kmod-setup.c	2024-02-28 16:57:11.000000000 +0000
@@ -30,7 +30,7 @@
         REENABLE_WARNING;
 }
 
-static int has_virtio_rng_recurse_dir_cb(
+static int match_modalias_recurse_dir_cb(
                 RecurseDirEvent event,
                 const char *path,
                 int dir_fd,
@@ -40,6 +40,7 @@
                 void *userdata) {
 
         _cleanup_free_ char *alias = NULL;
+        char **modaliases = ASSERT_PTR(userdata);
         int r;
 
         if (event != RECURSE_DIR_ENTRY)
@@ -57,13 +58,13 @@
                 return RECURSE_DIR_LEAVE_DIRECTORY;
         }
 
-        if (STARTSWITH_SET(alias, "pci:v00001AF4d00001005", "pci:v00001AF4d00001044"))
+        if (startswith_strv(alias, modaliases))
                 return 1;
 
         return RECURSE_DIR_LEAVE_DIRECTORY;
 }
 
-static bool has_virtio_rng(void) {
+static bool has_virtio_feature(const char *name, char **modaliases) {
         int r;
 
         /* Directory traversal might be slow, hence let's do a cheap check first if it's even worth it */
@@ -74,16 +75,28 @@
                         AT_FDCWD,
                         "/sys/devices/pci0000:00",
                         /* statx_mask= */ 0,
-                        /* n_depth_max= */ 2,
+                        /* n_depth_max= */ 3,
                         RECURSE_DIR_ENSURE_TYPE,
-                        has_virtio_rng_recurse_dir_cb,
-                        NULL);
+                        match_modalias_recurse_dir_cb,
+                        modaliases);
         if (r < 0)
-                log_debug_errno(r, "Failed to determine whether host has virtio-rng device, ignoring: %m");
+                log_debug_errno(r, "Failed to determine whether host has %s device, ignoring: %m", name);
 
         return r > 0;
 }
 
+static bool has_virtio_rng(void) {
+        return has_virtio_feature("virtio-rng", STRV_MAKE("pci:v00001AF4d00001005", "pci:v00001AF4d00001044"));
+}
+
+static bool has_virtiofs(void) {
+        return has_virtio_feature("virtiofs", STRV_MAKE("virtio:d0000001Av"));
+}
+
+static bool has_virtio_pci(void) {
+        return has_virtio_feature("virtio-pci", STRV_MAKE("pci:v00001AF4d"));
+}
+
 static bool in_qemu(void) {
         return IN_SET(detect_vm(), VIRTUALIZATION_KVM, VIRTUALIZATION_QEMU);
 }
@@ -117,6 +130,15 @@
                 /* virtio_rng would be loaded by udev later, but real entropy might be needed very early */
                 { "virtio_rng", NULL,                       false,  false,   has_virtio_rng },
 
+                /* We can't wait for specific virtiofs tags to show up as device nodes so we have to load the
+                 * virtiofs and virtio_pci modules early to make sure the virtiofs tags are found when
+                 * sysroot.mount is started.
+                 *
+                 * TODO: Remove these again once https://gitlab.com/virtio-fs/virtiofsd/-/issues/128 is
+                 * resolved and the kernel fix is widely available. */
+                { "virtiofs",                   "/sys/module/virtiofs",      false, false, has_virtiofs       },
+                { "virtio_pci",                 "/sys/module/virtio_pci",    false, false, has_virtio_pci     },
+
                 /* qemu_fw_cfg would be loaded by udev later, but we want to import credentials from it super early */
                 { "qemu_fw_cfg", "/sys/firmware/qemu_fw_cfg", false, false,  in_qemu   },
 
diff -Nru systemd-252.22/src/core/load-fragment.c systemd-252.23/src/core/load-fragment.c
--- systemd-252.22/src/core/load-fragment.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/core/load-fragment.c	2024-02-28 16:57:11.000000000 +0000
@@ -3990,7 +3990,7 @@
 
         } else if (r > 0) {
                 c->delegate = true;
-                c->delegate_controllers = _CGROUP_MASK_ALL;
+                c->delegate_controllers = CGROUP_MASK_DELEGATE;
         } else {
                 c->delegate = false;
                 c->delegate_controllers = 0;
diff -Nru systemd-252.22/src/core/service.c systemd-252.23/src/core/service.c
--- systemd-252.22/src/core/service.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/core/service.c	2024-02-28 16:57:11.000000000 +0000
@@ -594,8 +594,7 @@
         if (s->type != SERVICE_ONESHOT && s->exec_command[SERVICE_EXEC_START]->command_next)
                 return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(ENOEXEC), "Service has more than one ExecStart= setting, which is only allowed for Type=oneshot services. Refusing.");
 
-        if (s->type == SERVICE_ONESHOT &&
-            !IN_SET(s->restart, SERVICE_RESTART_NO, SERVICE_RESTART_ON_FAILURE, SERVICE_RESTART_ON_ABNORMAL, SERVICE_RESTART_ON_WATCHDOG, SERVICE_RESTART_ON_ABORT))
+        if (s->type == SERVICE_ONESHOT && IN_SET(s->restart, SERVICE_RESTART_ALWAYS, SERVICE_RESTART_ON_SUCCESS))
                 return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(ENOEXEC), "Service has Restart= set to either always or on-success, which isn't allowed for Type=oneshot services. Refusing.");
 
         if (s->type == SERVICE_ONESHOT && !exit_status_set_is_empty(&s->restart_force_status))
diff -Nru systemd-252.22/src/libsystemd/sd-bus/bus-socket.c systemd-252.23/src/libsystemd/sd-bus/bus-socket.c
--- systemd-252.22/src/libsystemd/sd-bus/bus-socket.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/libsystemd/sd-bus/bus-socket.c	2024-02-28 16:57:11.000000000 +0000
@@ -725,12 +725,12 @@
         assert(b->sockaddr.sa.sa_family == AF_UNIX);
         assert(b->sockaddr.un.sun_path[0] != 0);
 
-        /* Sets up an inotify fd in case watch_bind is enabled: wait until the configured AF_UNIX file system socket
-         * appears before connecting to it. The implemented is pretty simplistic: we just subscribe to relevant changes
-         * to all prefix components of the path, and every time we get an event for that we try to reconnect again,
-         * without actually caring what precisely the event we got told us. If we still can't connect we re-subscribe
-         * to all relevant changes of anything in the path, so that our watches include any possibly newly created path
-         * components. */
+        /* Sets up an inotify fd in case watch_bind is enabled: wait until the configured AF_UNIX file system
+         * socket appears before connecting to it. The implemented is pretty simplistic: we just subscribe to
+         * relevant changes to all components of the path, and every time we get an event for that we try to
+         * reconnect again, without actually caring what precisely the event we got told us. If we still
+         * can't connect we re-subscribe to all relevant changes of anything in the path, so that our watches
+         * include any possibly newly created path components. */
 
         if (b->inotify_fd < 0) {
                 b->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
@@ -749,17 +749,17 @@
         if (r < 0)
                 goto fail;
 
-        /* Watch all parent directories, and don't mind any prefix that doesn't exist yet. For the innermost directory
-         * that exists we want to know when files are created or moved into it. For all parents of it we just care if
-         * they are removed or renamed. */
+        /* Watch all components of the path, and don't mind any prefix that doesn't exist yet. For the
+         * innermost directory that exists we want to know when files are created or moved into it. For all
+         * parents of it we just care if they are removed or renamed. */
 
         if (!GREEDY_REALLOC(new_watches, n + 1)) {
                 r = -ENOMEM;
                 goto fail;
         }
 
-        /* Start with the top-level directory, which is a bit simpler than the rest, since it can't be a symlink, and
-         * always exists */
+        /* Start with the top-level directory, which is a bit simpler than the rest, since it can't be a
+         * symlink, and always exists */
         wd = inotify_add_watch(b->inotify_fd, "/", IN_CREATE|IN_MOVED_TO);
         if (wd < 0) {
                 r = log_debug_errno(errno, "Failed to add inotify watch on /: %m");
diff -Nru systemd-252.22/src/libsystemd/sd-bus/sd-bus.c systemd-252.23/src/libsystemd/sd-bus/sd-bus.c
--- systemd-252.22/src/libsystemd/sd-bus/sd-bus.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/libsystemd/sd-bus/sd-bus.c	2024-02-28 16:57:11.000000000 +0000
@@ -3040,7 +3040,7 @@
         return r;
 }
 
-static int bus_exit_now(sd_bus *bus) {
+static int bus_exit_now(sd_bus *bus, sd_event *event) {
         assert(bus);
 
         /* Exit due to close, if this is requested. If this is bus object is attached to an event source, invokes
@@ -3057,8 +3057,11 @@
 
         log_debug("Bus connection disconnected, exiting.");
 
-        if (bus->event)
-                return sd_event_exit(bus->event, EXIT_FAILURE);
+        if (!event)
+                event = bus->event;
+
+        if (event)
+                return sd_event_exit(event, EXIT_FAILURE);
         else
                 exit(EXIT_FAILURE);
 
@@ -3120,6 +3123,7 @@
 
 static int process_closing(sd_bus *bus, sd_bus_message **ret) {
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+        _cleanup_(sd_event_unrefp) sd_event *event = NULL;
         struct reply_callback *c;
         int r;
 
@@ -3154,6 +3158,10 @@
         if (r < 0)
                 return r;
 
+        /* sd_bus_close() will deref the event and set bus->event to NULL. But in bus_exit_now() we use
+         * bus->event to decide whether to return from the event loop or exit(), but given it's always NULL
+         * at that point, it always exit(). Ref it here and pass it through further down to avoid that. */
+        event = sd_event_ref(bus->event);
         sd_bus_close(bus);
 
         bus->current_message = m;
@@ -3169,7 +3177,7 @@
 
         /* Nothing else to do, exit now, if the condition holds */
         bus->exit_triggered = true;
-        (void) bus_exit_now(bus);
+        (void) bus_exit_now(bus, event);
 
         if (ret)
                 *ret = TAKE_PTR(m);
@@ -4281,7 +4289,7 @@
         bus->exit_on_disconnect = b;
 
         /* If the exit condition was triggered already, exit immediately. */
-        return bus_exit_now(bus);
+        return bus_exit_now(bus, /* event= */ NULL);
 }
 
 _public_ int sd_bus_get_exit_on_disconnect(sd_bus *bus) {
diff -Nru systemd-252.22/src/libsystemd/sd-bus/test-bus-watch-bind.c systemd-252.23/src/libsystemd/sd-bus/test-bus-watch-bind.c
--- systemd-252.22/src/libsystemd/sd-bus/test-bus-watch-bind.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/libsystemd/sd-bus/test-bus-watch-bind.c	2024-02-28 16:57:11.000000000 +0000
@@ -7,6 +7,7 @@
 #include "sd-id128.h"
 
 #include "alloc-util.h"
+#include "bus-internal.h"
 #include "fd-util.h"
 #include "fs-util.h"
 #include "mkdir.h"
@@ -27,8 +28,11 @@
 
 static int method_exit(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
         log_info("Got Exit() call");
-        assert_se(sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), 1) >= 0);
-        return sd_bus_reply_method_return(m, NULL);
+
+        assert_se(sd_bus_reply_method_return(m, NULL) >= 0);
+        /* Simulate D-Bus going away to test the bus_exit_now() path with exit_on_disconnect set */
+        bus_enter_closing(sd_bus_message_get_bus(m));
+        return 0;
 }
 
 static const sd_bus_vtable vtable[] = {
@@ -100,6 +104,7 @@
                 log_debug("Accepted server connection");
 
                 assert_se(sd_bus_new(&bus) >= 0);
+                assert_se(sd_bus_set_exit_on_disconnect(bus, true) >= 0);
                 assert_se(sd_bus_set_description(bus, "server") >= 0);
                 assert_se(sd_bus_set_fd(bus, bus_fd, bus_fd) >= 0);
                 assert_se(sd_bus_set_server(bus, true, id) >= 0);
diff -Nru systemd-252.22/src/libsystemd/sd-id128/id128-util.c systemd-252.23/src/libsystemd/sd-id128/id128-util.c
--- systemd-252.22/src/libsystemd/sd-id128/id128-util.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/libsystemd/sd-id128/id128-util.c	2024-02-28 16:57:11.000000000 +0000
@@ -192,6 +192,8 @@
         r = id128_read("/sys/class/dmi/id/product_uuid", ID128_FORMAT_UUID, &uuid);
         if (r == -ENOENT)
                 r = id128_read("/proc/device-tree/vm,uuid", ID128_FORMAT_UUID, &uuid);
+        if (r == -ENOENT)
+                r = id128_read("/sys/hypervisor/uuid", ID128_FORMAT_UUID, &uuid);
         if (r < 0)
                 return r;
 
diff -Nru systemd-252.22/src/login/user-runtime-dir.c systemd-252.23/src/login/user-runtime-dir.c
--- systemd-252.22/src/login/user-runtime-dir.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/login/user-runtime-dir.c	2024-02-28 16:57:11.000000000 +0000
@@ -66,7 +66,7 @@
         if (r < 0)
                 return log_error_errno(r, "Failed to create /run/user: %m");
 
-        if (path_is_mount_point(runtime_path, NULL, 0) >= 0)
+        if (path_is_mount_point(runtime_path, NULL, 0) > 0)
                 log_debug("%s is already a mount point", runtime_path);
         else {
                 char options[sizeof("mode=0700,uid=,gid=,size=,nr_inodes=,smackfsroot=*")
diff -Nru systemd-252.22/src/machine/machinectl.c systemd-252.23/src/machine/machinectl.c
--- systemd-252.22/src/machine/machinectl.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/machine/machinectl.c	2024-02-28 16:57:11.000000000 +0000
@@ -1127,7 +1127,7 @@
                 return bus_log_create_error(r);
 
         if (arg_force) {
-                r = sd_bus_message_append(m, "t", MACHINE_COPY_REPLACE);
+                r = sd_bus_message_append(m, "t", (uint64_t) MACHINE_COPY_REPLACE);
                 if (r < 0)
                         return bus_log_create_error(r);
         }
diff -Nru systemd-252.22/src/network/wait-online/manager.c systemd-252.23/src/network/wait-online/manager.c
--- systemd-252.22/src/network/wait-online/manager.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/network/wait-online/manager.c	2024-02-28 16:57:11.000000000 +0000
@@ -158,7 +158,9 @@
                 r = manager_link_is_online(m, l,
                                            (LinkOperationalStateRange) { _LINK_OPERSTATE_INVALID,
                                                                          _LINK_OPERSTATE_INVALID });
-                if (r < 0 && !m->any) /* Unlike the above loop, unmanaged interfaces are ignored here. */
+                /* Unlike the above loop, unmanaged interfaces are ignored here. Also, Configured but offline
+                 * interfaces are ignored. See issue #29506. */
+                if (r < 0 && r != -EADDRNOTAVAIL && !m->any)
                         return false;
                 if (r > 0) {
                         if (m->any)
diff -Nru systemd-252.22/src/nspawn/nspawn.c systemd-252.23/src/nspawn/nspawn.c
--- systemd-252.22/src/nspawn/nspawn.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/nspawn/nspawn.c	2024-02-28 16:57:11.000000000 +0000
@@ -1805,8 +1805,10 @@
         if (arg_ephemeral && arg_template)
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--ephemeral and --template= may not be combined.");
 
-        if (arg_ephemeral && !IN_SET(arg_link_journal, LINK_NO, LINK_AUTO))
-                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--ephemeral and --link-journal= may not be combined.");
+        /* Permit --ephemeral with --link-journal=try-* to satisfy principle of the least astonishment
+         * (by common sense, "try" means "do not fail if not possible") */
+        if (arg_ephemeral && !IN_SET(arg_link_journal, LINK_NO, LINK_AUTO) && !arg_link_journal_try)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--ephemeral and --link-journal={host,guest} may not be combined.");
 
         if (arg_userns_mode != USER_NAMESPACE_NO && !userns_supported())
                 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "--private-users= is not supported, kernel compiled without user namespace support.");
diff -Nru systemd-252.22/src/portable/portablectl.c systemd-252.23/src/portable/portablectl.c
--- systemd-252.22/src/portable/portablectl.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/portable/portablectl.c	2024-02-28 16:57:11.000000000 +0000
@@ -1157,7 +1157,7 @@
                 return r;
 
         if (!strv_isempty(arg_extension_images)) {
-                r = sd_bus_message_append(m, "t", 0);
+                r = sd_bus_message_append(m, "t", UINT64_C(0));
                 if (r < 0)
                         return bus_log_create_error(r);
         }
diff -Nru systemd-252.22/src/resolve/resolved-dns-dnssec.c systemd-252.23/src/resolve/resolved-dns-dnssec.c
--- systemd-252.22/src/resolve/resolved-dns-dnssec.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/resolve/resolved-dns-dnssec.c	2024-02-28 16:57:11.000000000 +0000
@@ -27,8 +27,9 @@
 /* Permit a maximum clock skew of 1h 10min. This should be enough to deal with DST confusion */
 #define SKEW_MAX (1*USEC_PER_HOUR + 10*USEC_PER_MINUTE)
 
-/* Maximum number of NSEC3 iterations we'll do. RFC5155 says 2500 shall be the maximum useful value */
-#define NSEC3_ITERATIONS_MAX 2500
+/* Maximum number of NSEC3 iterations we'll do. RFC5155 says 2500 shall be the maximum useful value, but
+ * RFC9276 § 3.2 says that we should reduce the acceptable iteration count */
+#define NSEC3_ITERATIONS_MAX 100
 
 /*
  * The DNSSEC Chain of trust:
@@ -1176,6 +1177,7 @@
                 DnsResourceRecord **ret_rrsig) {
 
         bool found_rrsig = false, found_invalid = false, found_expired_rrsig = false, found_unsupported_algorithm = false;
+        unsigned nvalidations = 0;
         DnsResourceRecord *rrsig;
         int r;
 
@@ -1221,6 +1223,14 @@
                         if (realtime == USEC_INFINITY)
                                 realtime = now(CLOCK_REALTIME);
 
+                        /* Have we seen an unreasonable number of invalid signaures? */
+                        if (nvalidations > DNSSEC_INVALID_MAX) {
+                                if (ret_rrsig)
+                                        *ret_rrsig = NULL;
+                                *result = DNSSEC_TOO_MANY_VALIDATIONS;
+                                return (int) nvalidations;
+                        }
+
                         /* Yay, we found a matching RRSIG with a matching
                          * DNSKEY, awesome. Now let's verify all entries of
                          * the RRSet against the RRSIG and DNSKEY
@@ -1230,6 +1240,8 @@
                         if (r < 0)
                                 return r;
 
+                        nvalidations++;
+
                         switch (one_result) {
 
                         case DNSSEC_VALIDATED:
@@ -1240,7 +1252,7 @@
                                         *ret_rrsig = rrsig;
 
                                 *result = one_result;
-                                return 0;
+                                return (int) nvalidations;
 
                         case DNSSEC_INVALID:
                                 /* If the signature is invalid, let's try another
@@ -1287,7 +1299,7 @@
         if (ret_rrsig)
                 *ret_rrsig = NULL;
 
-        return 0;
+        return (int) nvalidations;
 }
 
 int dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key) {
@@ -2571,6 +2583,7 @@
         [DNSSEC_FAILED_AUXILIARY]      = "failed-auxiliary",
         [DNSSEC_NSEC_MISMATCH]         = "nsec-mismatch",
         [DNSSEC_INCOMPATIBLE_SERVER]   = "incompatible-server",
+        [DNSSEC_TOO_MANY_VALIDATIONS]  = "too-many-validations",
 };
 DEFINE_STRING_TABLE_LOOKUP(dnssec_result, DnssecResult);
 
diff -Nru systemd-252.22/src/resolve/resolved-dns-dnssec.h systemd-252.23/src/resolve/resolved-dns-dnssec.h
--- systemd-252.22/src/resolve/resolved-dns-dnssec.h	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/resolve/resolved-dns-dnssec.h	2024-02-28 16:57:11.000000000 +0000
@@ -9,12 +9,13 @@
 #include "resolved-dns-rr.h"
 
 enum DnssecResult {
-        /* These five are returned by dnssec_verify_rrset() */
+        /* These six are returned by dnssec_verify_rrset() */
         DNSSEC_VALIDATED,
         DNSSEC_VALIDATED_WILDCARD, /* Validated via a wildcard RRSIG, further NSEC/NSEC3 checks necessary */
         DNSSEC_INVALID,
         DNSSEC_SIGNATURE_EXPIRED,
         DNSSEC_UNSUPPORTED_ALGORITHM,
+        DNSSEC_TOO_MANY_VALIDATIONS,
 
         /* These two are added by dnssec_verify_rrset_search() */
         DNSSEC_NO_SIGNATURE,
@@ -45,6 +46,12 @@
 /* The longest digest we'll ever generate, of all digest algorithms we support */
 #define DNSSEC_HASH_SIZE_MAX (MAX(20, 32))
 
+/* The most invalid signatures we will tolerate for a single rrset */
+#define DNSSEC_INVALID_MAX 5
+
+/* The total number of signature validations we will tolerate for a single transaction */
+#define DNSSEC_VALIDATION_MAX 64
+
 int dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, bool revoked_ok);
 int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig);
 
diff -Nru systemd-252.22/src/resolve/resolved-dns-transaction.c systemd-252.23/src/resolve/resolved-dns-transaction.c
--- systemd-252.22/src/resolve/resolved-dns-transaction.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/resolve/resolved-dns-transaction.c	2024-02-28 16:57:11.000000000 +0000
@@ -3172,11 +3172,14 @@
                 DnsTransaction *t,
                 Phase phase,
                 bool *have_nsec,
+                unsigned *nvalidations,
                 DnsAnswer **validated) {
 
         DnsResourceRecord *rr;
         int r;
 
+        assert(nvalidations);
+
         /* Returns negative on error, 0 if validation failed, 1 to restart validation, 2 when finished. */
 
         DNS_ANSWER_FOREACH(rr, t->answer) {
@@ -3218,6 +3221,7 @@
                                 &rrsig);
                 if (r < 0)
                         return r;
+                *nvalidations += r;
 
                 log_debug("Looking at %s: %s", strna(dns_resource_record_to_string(rr)), dnssec_result_to_string(result));
 
@@ -3415,7 +3419,8 @@
                                            DNSSEC_SIGNATURE_EXPIRED,
                                            DNSSEC_NO_SIGNATURE))
                                         manager_dnssec_verdict(t->scope->manager, DNSSEC_BOGUS, rr->key);
-                                else /* DNSSEC_MISSING_KEY or DNSSEC_UNSUPPORTED_ALGORITHM */
+                                else /* DNSSEC_MISSING_KEY, DNSSEC_UNSUPPORTED_ALGORITHM,
+                                        or DNSSEC_TOO_MANY_VALIDATIONS */
                                         manager_dnssec_verdict(t->scope->manager, DNSSEC_INDETERMINATE, rr->key);
 
                                 /* This is a primary response to our question, and it failed validation.
@@ -3508,13 +3513,21 @@
                 return r;
 
         phase = DNSSEC_PHASE_DNSKEY;
-        for (;;) {
+        for (unsigned nvalidations = 0;;) {
                 bool have_nsec = false;
 
-                r = dnssec_validate_records(t, phase, &have_nsec, &validated);
+                r = dnssec_validate_records(t, phase, &have_nsec, &nvalidations, &validated);
                 if (r <= 0)
                         return r;
 
+                if (nvalidations > DNSSEC_VALIDATION_MAX) {
+                        /* This reply requires an onerous number of signature validations to verify. Let's
+                         * not waste our time trying, as this shouldn't happen for well-behaved domains
+                         * anyway. */
+                        t->answer_dnssec_result = DNSSEC_TOO_MANY_VALIDATIONS;
+                        return 0;
+                }
+
                 /* Try again as long as we managed to achieve something */
                 if (r == 1)
                         continue;
diff -Nru systemd-252.22/src/shared/base-filesystem.c systemd-252.23/src/shared/base-filesystem.c
--- systemd-252.22/src/shared/base-filesystem.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/shared/base-filesystem.c	2024-02-28 16:57:11.000000000 +0000
@@ -63,7 +63,7 @@
                          "usr/lib64\0",                "ld-linux-x86-64.so.2" },
 #  define KNOW_LIB64_DIRS 1
 #elif defined(__ia64__)
-#elif defined(__loongarch64)
+#elif defined(__loongarch_lp64)
 #  define KNOW_LIB64_DIRS 1
 #  if defined(__loongarch_double_float)
         { "lib64",    0, "usr/lib/"LIB_ARCH_TUPLE"\0"
diff -Nru systemd-252.22/src/shared/bus-unit-util.c systemd-252.23/src/shared/bus-unit-util.c
--- systemd-252.22/src/shared/bus-unit-util.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/shared/bus-unit-util.c	2024-02-28 16:57:11.000000000 +0000
@@ -1282,12 +1282,12 @@
                         if (r < 0)
                                 return log_error_errno(r, "Failed to parse resource limit: %s", eq);
 
-                        r = sd_bus_message_append(m, "(sv)", field, "t", l.rlim_max);
+                        r = sd_bus_message_append(m, "(sv)", field, "t", (uint64_t) l.rlim_max);
                         if (r < 0)
                                 return bus_log_create_error(r);
 
                         sn = strjoina(field, "Soft");
-                        r = sd_bus_message_append(m, "(sv)", sn, "t", l.rlim_cur);
+                        r = sd_bus_message_append(m, "(sv)", sn, "t", (uint64_t) l.rlim_cur);
                         if (r < 0)
                                 return bus_log_create_error(r);
 
@@ -2030,7 +2030,7 @@
                                 return bus_log_create_error(r);
 
                         STRV_FOREACH_PAIR(source, destination, symlinks) {
-                                r = sd_bus_message_append(m, "(sst)", *source, *destination, 0);
+                                r = sd_bus_message_append(m, "(sst)", *source, *destination, UINT64_C(0));
                                 if (r < 0)
                                         return bus_log_create_error(r);
                         }
diff -Nru systemd-252.22/src/shared/conf-parser.c systemd-252.23/src/shared/conf-parser.c
--- systemd-252.22/src/shared/conf-parser.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/shared/conf-parser.c	2024-02-28 16:57:11.000000000 +0000
@@ -463,7 +463,7 @@
                 return -ENOMEM;
 
         path_copy = strdup(path);
-        if (!path)
+        if (!path_copy)
                 return -ENOMEM;
 
         r = hashmap_put(*stats_by_path, path_copy, st_copy);
diff -Nru systemd-252.22/src/shared/efi-loader.c systemd-252.23/src/shared/efi-loader.c
--- systemd-252.22/src/shared/efi-loader.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/shared/efi-loader.c	2024-02-28 16:57:11.000000000 +0000
@@ -99,7 +99,8 @@
         if (r < 0)
                 return r;
 
-        /* The variable contains a series of individually NUL terminated UTF-16 strings. */
+        /* The variable contains a series of individually NUL terminated UTF-16 strings. We gracefully
+         * consider the final NUL byte optional (i.e. the last string may or may not end in a NUL byte).*/
 
         for (size_t i = 0, start = 0;; i++) {
                 _cleanup_free_ char *decoded = NULL;
@@ -113,6 +114,11 @@
                 if (!end && entries[i] != 0)
                         continue;
 
+                /* Empty string at the end of variable? That's the trailer, we are done (i.e. we have a final
+                 * NUL terminator). */
+                if (end && start == i)
+                        break;
+
                 /* We reached the end of a string, let's decode it into UTF-8 */
                 decoded = utf16_to_utf8(entries + start, (i - start) * sizeof(char16_t));
                 if (!decoded)
@@ -125,7 +131,8 @@
                 } else
                         log_debug("Ignoring invalid loader entry '%s'.", decoded);
 
-                /* We reached the end of the variable */
+                /* Exit the loop if we reached the end of the variable (i.e. we do not have a final NUL
+                 * terminator) */
                 if (end)
                         break;
 
diff -Nru systemd-252.22/src/shared/generate-syscall-list.py systemd-252.23/src/shared/generate-syscall-list.py
--- systemd-252.22/src/shared/generate-syscall-list.py	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/shared/generate-syscall-list.py	2024-02-28 16:57:11.000000000 +0000
@@ -2,15 +2,6 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 import sys
-import os
-
-s390 = 's390' in os.uname().machine
-arm = 'arm' in os.uname().machine
 
 for line in open(sys.argv[1]):
-    if line.startswith('s390_') and not s390:
-        continue
-    if line.startswith('arm_') and not arm:
-        continue
-
     print('"{}\\0"'.format(line.strip()))
diff -Nru systemd-252.22/src/shared/keyring-util.c systemd-252.23/src/shared/keyring-util.c
--- systemd-252.22/src/shared/keyring-util.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/shared/keyring-util.c	2024-02-28 16:57:11.000000000 +0000
@@ -5,34 +5,31 @@
 #include "missing_syscall.h"
 
 int keyring_read(key_serial_t serial, void **ret, size_t *ret_size) {
-        size_t m = 100;
+        size_t bufsize = 100;
 
         for (;;) {
-                _cleanup_(erase_and_freep) uint8_t *p = NULL;
+                _cleanup_(erase_and_freep) uint8_t *buf = NULL;
                 long n;
 
-                p = new(uint8_t, m+1);
-                if (!p)
+                buf = new(uint8_t, bufsize + 1);
+                if (!buf)
                         return -ENOMEM;
 
-                n = keyctl(KEYCTL_READ, (unsigned long) serial, (unsigned long) p, (unsigned long) m, 0);
+                n = keyctl(KEYCTL_READ, (unsigned long) serial, (unsigned long) buf, (unsigned long) bufsize, 0);
                 if (n < 0)
                         return -errno;
 
-                if ((size_t) n <= m) {
-                        p[n] = 0; /* NUL terminate, just in case */
+                if ((size_t) n <= bufsize) {
+                        buf[n] = 0; /* NUL terminate, just in case */
 
                         if (ret)
-                                *ret = TAKE_PTR(p);
+                                *ret = TAKE_PTR(buf);
                         if (ret_size)
                                 *ret_size = n;
 
                         return 0;
                 }
 
-                if (m > (SIZE_MAX-1) / 2) /* overflow check */
-                        return -ENOMEM;
-
-                m *= 2;
+                bufsize = (size_t) n;
         }
 }
diff -Nru systemd-252.22/src/shared/loop-util.c systemd-252.23/src/shared/loop-util.c
--- systemd-252.22/src/shared/loop-util.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/shared/loop-util.c	2024-02-28 16:57:11.000000000 +0000
@@ -637,7 +637,7 @@
         else
                 direct = direct_flags != 0;
         if (fd < 0) {
-                r = -errno;
+                r = fd;
 
                 /* Retry read-only? */
                 if (open_flags >= 0 || !(ERRNO_IS_PRIVILEGE(r) || r == -EROFS))
diff -Nru systemd-252.22/src/shared/machine-id-setup.c systemd-252.23/src/shared/machine-id-setup.c
--- systemd-252.22/src/shared/machine-id-setup.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/shared/machine-id-setup.c	2024-02-28 16:57:11.000000000 +0000
@@ -60,7 +60,7 @@
                                 return 0;
                         }
 
-                } else if (IN_SET(detect_vm(), VIRTUALIZATION_KVM, VIRTUALIZATION_AMAZON, VIRTUALIZATION_QEMU)) {
+                } else if (IN_SET(detect_vm(), VIRTUALIZATION_KVM, VIRTUALIZATION_AMAZON, VIRTUALIZATION_QEMU, VIRTUALIZATION_XEN)) {
 
                         /* If we are not running in a container, see if we are running in a VM that provides
                          * a system UUID via the SMBIOS/DMI interfaces.  Such environments include QEMU/KVM
diff -Nru systemd-252.22/src/shared/seccomp-util.c systemd-252.23/src/shared/seccomp-util.c
--- systemd-252.22/src/shared/seccomp-util.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/shared/seccomp-util.c	2024-02-28 16:57:11.000000000 +0000
@@ -468,6 +468,7 @@
                 "fchdir\0"
                 "fchmod\0"
                 "fchmodat\0"
+                "fchmodat2\0"
                 "fcntl\0"
                 "fcntl64\0"
                 "fgetxattr\0"
@@ -2031,7 +2032,7 @@
 static int seccomp_restrict_sxid(scmp_filter_ctx seccomp, mode_t m) {
         /* Checks the mode_t parameter of the following system calls:
          *
-         *       → chmod() + fchmod() + fchmodat()
+         *       → chmod() + fchmod() + fchmodat() + fchmodat2()
          *       → open() + creat() + openat()
          *       → mkdir() + mkdirat()
          *       → mknod() + mknodat()
@@ -2074,6 +2075,28 @@
         else
                 any = true;
 
+#if defined(__SNR_fchmodat2)
+        r = seccomp_rule_add_exact(
+                        seccomp,
+                        SCMP_ACT_ERRNO(EPERM),
+                        SCMP_SYS(fchmodat2),
+                        1,
+                        SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
+#else
+        /* It looks like this libseccomp does not know about fchmodat2().
+         * Pretend the fchmodat2() system call is not supported at all,
+         * regardless of the kernel version. */
+        r = seccomp_rule_add_exact(
+                        seccomp,
+                        SCMP_ACT_ERRNO(ENOSYS),
+                        __NR_fchmodat2,
+                        0);
+#endif
+        if (r < 0)
+                log_debug_errno(r, "Failed to add filter for fchmodat2: %m");
+        else
+                any = true;
+
         r = seccomp_rule_add_exact(
                         seccomp,
                         SCMP_ACT_ERRNO(EPERM),
diff -Nru systemd-252.22/src/shared/utmp-wtmp.c systemd-252.23/src/shared/utmp-wtmp.c
--- systemd-252.22/src/shared/utmp-wtmp.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/shared/utmp-wtmp.c	2024-02-28 16:57:11.000000000 +0000
@@ -183,6 +183,7 @@
         int r;
 
         assert(id);
+        assert(ut_type != USER_PROCESS || user);
 
         init_timestamp(&store, 0);
 
diff -Nru systemd-252.22/src/systemd/sd-gpt.h systemd-252.23/src/systemd/sd-gpt.h
--- systemd-252.22/src/systemd/sd-gpt.h	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/systemd/sd-gpt.h	2024-02-28 16:57:11.000000000 +0000
@@ -220,7 +220,7 @@
 #  define SD_GPT_USR_NATIVE_VERITY SD_GPT_USR_IA64_VERITY
 #  define SD_GPT_USR_NATIVE_VERITY_SIG SD_GPT_USR_IA64_VERITY_SIG
 
-#elif defined(__loongarch64)
+#elif defined(__loongarch_lp64)
 #  define SD_GPT_ROOT_NATIVE SD_GPT_ROOT_LOONGARCH64
 #  define SD_GPT_ROOT_NATIVE_VERITY SD_GPT_ROOT_LOONGARCH64_VERITY
 #  define SD_GPT_ROOT_NATIVE_VERITY_SIG SD_GPT_ROOT_LOONGARCH64_VERITY_SIG
diff -Nru systemd-252.22/src/sysusers/sysusers.c systemd-252.23/src/sysusers/sysusers.c
--- systemd-252.22/src/sysusers/sysusers.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/sysusers/sysusers.c	2024-02-28 16:57:11.000000000 +0000
@@ -1973,10 +1973,12 @@
 #endif
 
                 case ARG_REPLACE:
-                        if (!path_is_absolute(optarg) ||
-                            !endswith(optarg, ".conf"))
+                        if (!path_is_absolute(optarg))
                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                                       "The argument to --replace= must an absolute path to a config file");
+                                                       "The argument to --replace= must be an absolute path.");
+                        if (!endswith(optarg, ".conf"))
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                       "The argument to --replace= must have the extension '.conf'.");
 
                         arg_replace = optarg;
                         break;
diff -Nru systemd-252.22/src/test/test-calendarspec.c systemd-252.23/src/test/test-calendarspec.c
--- systemd-252.22/src/test/test-calendarspec.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/test/test-calendarspec.c	2024-02-28 16:57:11.000000000 +0000
@@ -260,4 +260,11 @@
         assert_se(calendar_spec_from_string("*:4,30:*\n", &c) == -EINVAL);
 }
 
-DEFINE_TEST_MAIN(LOG_INFO);
+static int intro(void) {
+        /* Tests have hard-coded results that do not expect a specific timezone to be set by the caller */
+        assert_se(unsetenv("TZ") >= 0);
+
+        return EXIT_SUCCESS;
+}
+
+DEFINE_TEST_MAIN_WITH_INTRO(LOG_INFO, intro);
diff -Nru systemd-252.22/src/test/test-date.c systemd-252.23/src/test/test-date.c
--- systemd-252.22/src/test/test-date.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/test/test-date.c	2024-02-28 16:57:11.000000000 +0000
@@ -62,6 +62,9 @@
 }
 
 int main(int argc, char *argv[]) {
+        /* Tests have hard-coded results that do not expect a specific timezone to be set by the caller */
+        assert_se(unsetenv("TZ") >= 0);
+
         test_setup_logging(LOG_DEBUG);
 
         test_one("17:41");
diff -Nru systemd-252.22/src/test/test-execute.c systemd-252.23/src/test/test-execute.c
--- systemd-252.22/src/test/test-execute.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/test/test-execute.c	2024-02-28 16:57:11.000000000 +0000
@@ -391,7 +391,7 @@
 
 #elif defined(__i386__)
         test(m, "exec-personality-x86.service", 0, CLD_EXITED);
-#elif defined(__loongarch64)
+#elif defined(__loongarch_lp64)
         test(m, "exec-personality-loongarch64.service", 0, CLD_EXITED);
 #else
         log_notice("Unknown personality, skipping %s", __func__);
diff -Nru systemd-252.22/src/test/test-fs-util.c systemd-252.23/src/test/test-fs-util.c
--- systemd-252.22/src/test/test-fs-util.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/test/test-fs-util.c	2024-02-28 16:57:11.000000000 +0000
@@ -1068,4 +1068,42 @@
         return EXIT_SUCCESS;
 }
 
+TEST(readlinkat_malloc) {
+        _cleanup_(rm_rf_physical_and_freep) char *t = NULL;
+        _cleanup_close_ int tfd = -EBADF, fd = -EBADF;
+        _cleanup_free_ char *p = NULL, *q = NULL;
+        const char *expect = "hgoehogefoobar", *a;
+
+        a = strjoina(arg_test_dir ?: "/tmp", "/readlinkat-malloc.XXXXXX");
+        assert_se(mkdtemp_malloc(a, &t) >= 0);
+
+        tfd = open(t, O_PATH|O_DIRECTORY|O_CLOEXEC);
+        assert_se(tfd >= 0);
+
+        assert_se(symlinkat(expect, tfd, "linkname") >= 0);
+
+        assert_se(readlinkat_malloc(tfd, "linkname", &p) >= 0);
+        assert_se(streq(p, expect));
+        p = mfree(p);
+
+        fd = openat(tfd, "linkname", O_PATH | O_NOFOLLOW | O_CLOEXEC);
+        assert_se(fd >= 0);
+        assert_se(readlinkat_malloc(fd, NULL, &p) >= 0);
+        assert_se(streq(p, expect));
+        p = mfree(p);
+        assert_se(readlinkat_malloc(fd, "", &p) >= 0);
+        assert_se(streq(p, expect));
+        p = mfree(p);
+        fd = safe_close(fd);
+
+        assert_se(q = path_join(t, "linkname"));
+        assert_se(readlinkat_malloc(AT_FDCWD, q, &p) >= 0);
+        assert_se(streq(p, expect));
+        p = mfree(p);
+        assert_se(readlinkat_malloc(INT_MAX, q, &p) >= 0);
+        assert_se(streq(p, expect));
+        p = mfree(p);
+        q = mfree(q);
+}
+
 DEFINE_TEST_MAIN_WITH_INTRO(LOG_INFO, intro);
diff -Nru systemd-252.22/src/test/test-namespace.c systemd-252.23/src/test/test-namespace.c
--- systemd-252.22/src/test/test-namespace.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/test/test-namespace.c	2024-02-28 16:57:11.000000000 +0000
@@ -94,7 +94,7 @@
                 return;
         }
 
-        assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, s) >= 0);
+        assert_se(socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, s) >= 0);
 
         pid1 = fork();
         assert_se(pid1 >= 0);
diff -Nru systemd-252.22/src/test/test-nss-hosts.c systemd-252.23/src/test/test-nss-hosts.c
--- systemd-252.22/src/test/test-nss-hosts.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/test/test-nss-hosts.c	2024-02-28 16:57:11.000000000 +0000
@@ -451,7 +451,11 @@
         } else {
                 _cleanup_free_ char *hostname = NULL;
                 assert_se(hostname = gethostname_malloc());
-                assert_se(names = strv_new("localhost", "_gateway", "_outbound", "foo_no_such_host", hostname));
+                assert_se(names = strv_new("localhost",
+                                           "_gateway",
+                                           "_outbound",
+                                           hostname,
+                                           slow_tests_enabled() ? "foo_no_such_host" : NULL));
 
                 n = make_addresses(&addrs);
                 assert_se(n >= 0);
diff -Nru systemd-252.22/src/test/test-seccomp.c systemd-252.23/src/test/test-seccomp.c
--- systemd-252.22/src/test/test-seccomp.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/test/test-seccomp.c	2024-02-28 16:57:11.000000000 +0000
@@ -21,6 +21,7 @@
 #include "macro.h"
 #include "memory-util.h"
 #include "missing_sched.h"
+#include "missing_syscall_def.h"
 #include "nsflags.h"
 #include "nulstr-util.h"
 #include "process-util.h"
@@ -1003,6 +1004,23 @@
 #endif
 }
 
+static int try_fchmodat2(int dirfd, const char *path, int flags, mode_t mode) {
+        /* glibc does not provide a direct wrapper for fchmodat2(). Let's hence define our own wrapper for
+         * testing purposes that calls the real syscall, on architectures and in environments where
+         * SYS_fchmodat2 is defined. Otherwise, let's just fall back to the glibc fchmodat() call. */
+
+#if defined __NR_fchmodat2 && __NR_fchmodat2 >= 0
+        int r;
+        r = (int) syscall(__NR_fchmodat2, dirfd, path, flags, mode);
+        /* The syscall might still be unsupported by kernel or libseccomp. */
+        if (r < 0 && errno == ENOSYS)
+                return fchmodat(dirfd, path, flags, mode);
+        return r;
+#else
+        return fchmodat(dirfd, path, flags, mode);
+#endif
+}
+
 TEST(restrict_suid_sgid) {
         pid_t pid;
 
@@ -1044,6 +1062,11 @@
                 assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID | S_ISUID, 0) >= 0);
                 assert_se(fchmodat(AT_FDCWD, path, 0755, 0) >= 0);
 
+                assert_se(try_fchmodat2(AT_FDCWD, path, 0755 | S_ISUID, 0) >= 0);
+                assert_se(try_fchmodat2(AT_FDCWD, path, 0755 | S_ISGID, 0) >= 0);
+                assert_se(try_fchmodat2(AT_FDCWD, path, 0755 | S_ISGID | S_ISUID, 0) >= 0);
+                assert_se(try_fchmodat2(AT_FDCWD, path, 0755, 0) >= 0);
+
                 k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID);
                 k = safe_close(k);
                 assert_se(unlink(z) >= 0);
@@ -1145,6 +1168,11 @@
                 assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID | S_ISUID, 0) < 0 && errno == EPERM);
                 assert_se(fchmodat(AT_FDCWD, path, 0755, 0) >= 0);
 
+                assert_se(try_fchmodat2(AT_FDCWD, path, 0755 | S_ISUID, 0) < 0 && errno == EPERM);
+                assert_se(try_fchmodat2(AT_FDCWD, path, 0755 | S_ISGID, 0) < 0 && errno == EPERM);
+                assert_se(try_fchmodat2(AT_FDCWD, path, 0755 | S_ISGID | S_ISUID, 0) < 0 && errno == EPERM);
+                assert_se(try_fchmodat2(AT_FDCWD, path, 0755, 0) >= 0);
+
                 assert_se(real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID) < 0 && errno == EPERM);
                 assert_se(real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISGID) < 0 && errno == EPERM);
                 assert_se(real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID | S_ISGID) < 0 && errno == EPERM);
diff -Nru systemd-252.22/src/test/test-time-util.c systemd-252.23/src/test/test-time-util.c
--- systemd-252.22/src/test/test-time-util.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/test/test-time-util.c	2024-02-28 16:57:11.000000000 +0000
@@ -616,6 +616,9 @@
 }
 
 static int intro(void) {
+        /* Tests have hard-coded results that do not expect a specific timezone to be set by the caller */
+        assert_se(unsetenv("TZ") >= 0);
+
         log_info("realtime=" USEC_FMT "\n"
                  "monotonic=" USEC_FMT "\n"
                  "boottime=" USEC_FMT "\n",
diff -Nru systemd-252.22/src/timesync/timesyncd-manager.c systemd-252.23/src/timesync/timesyncd-manager.c
--- systemd-252.22/src/timesync/timesyncd-manager.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/timesync/timesyncd-manager.c	2024-02-28 16:57:11.000000000 +0000
@@ -25,6 +25,7 @@
 #include "network-util.h"
 #include "ratelimit.h"
 #include "resolve-private.h"
+#include "random-util.h"
 #include "socket-util.h"
 #include "string-util.h"
 #include "strv.h"
@@ -77,13 +78,6 @@
         return ts->tv_sec + (1.0e-9 * ts->tv_nsec);
 }
 
-static uint32_t graceful_add_offset_1900_1970(time_t t) {
-        /* Adds OFFSET_1900_1970 to t and returns it as 32bit value. This is handles overflows
-         * gracefully in a deterministic and well-defined way by cutting off the top bits. */
-        uint64_t a = (uint64_t) t + OFFSET_1900_1970;
-        return (uint32_t) (a & UINT64_C(0xFFFFFFFF));
-}
-
 static int manager_timeout(sd_event_source *source, usec_t usec, void *userdata) {
         _cleanup_free_ char *pretty = NULL;
         Manager *m = ASSERT_PTR(userdata);
@@ -125,20 +119,22 @@
         }
 
         /*
-         * Set transmit timestamp, remember it; the server will send that back
-         * as the origin timestamp and we have an indication that this is the
-         * matching answer to our request.
-         *
-         * The actual value does not matter, We do not care about the correct
-         * NTP UINT_MAX fraction; we just pass the plain nanosecond value.
+         * Generate a random number as transmit timestamp, to ensure we get
+         * a full 64 bits of entropy to make it hard for off-path attackers
+         * to inject random time to us.
          */
-        assert_se(clock_gettime(CLOCK_BOOTTIME, &m->trans_time_mon) >= 0);
-        assert_se(clock_gettime(CLOCK_REALTIME, &m->trans_time) >= 0);
-        ntpmsg.trans_time.sec = htobe32(graceful_add_offset_1900_1970(m->trans_time.tv_sec));
-        ntpmsg.trans_time.frac = htobe32(m->trans_time.tv_nsec);
+        random_bytes(&m->request_nonce, sizeof(m->request_nonce));
+        ntpmsg.trans_time = m->request_nonce;
 
         server_address_pretty(m->current_server_address, &pretty);
 
+        /*
+         * Record the transmit timestamp. This should be as close as possible to
+         * the send-to to ensure the timestamp is reasonably accurate
+         */
+        assert_se(clock_gettime(CLOCK_BOOTTIME, &m->trans_time_mon) >= 0);
+        assert_se(clock_gettime(CLOCK_REALTIME, &m->trans_time) >= 0);
+
         len = sendto(m->server_socket, &ntpmsg, sizeof(ntpmsg), MSG_DONTWAIT, &m->current_server_address->sockaddr.sa, m->current_server_address->socklen);
         if (len == sizeof(ntpmsg)) {
                 m->pending = true;
@@ -456,9 +452,8 @@
 
         m->missed_replies = 0;
 
-        /* check our "time cookie" (we just stored nanoseconds in the fraction field) */
-        if (be32toh(ntpmsg.origin_time.sec) != graceful_add_offset_1900_1970(m->trans_time.tv_sec) ||
-            be32toh(ntpmsg.origin_time.frac) != (unsigned long) m->trans_time.tv_nsec) {
+        /* check the transmit request nonce was properly returned in the origin_time field */
+        if (ntpmsg.origin_time.sec != m->request_nonce.sec || ntpmsg.origin_time.frac != m->request_nonce.frac) {
                 log_debug("Invalid reply; not our transmit time. Ignoring.");
                 return 0;
         }
diff -Nru systemd-252.22/src/timesync/timesyncd-manager.h systemd-252.23/src/timesync/timesyncd-manager.h
--- systemd-252.22/src/timesync/timesyncd-manager.h	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/timesync/timesyncd-manager.h	2024-02-28 16:57:11.000000000 +0000
@@ -71,6 +71,7 @@
         /* last sent packet */
         struct timespec trans_time_mon;
         struct timespec trans_time;
+        struct ntp_ts request_nonce;
         usec_t retry_interval;
         usec_t connection_retry_usec;
         bool pending;
diff -Nru systemd-252.22/src/tmpfiles/tmpfiles.c systemd-252.23/src/tmpfiles/tmpfiles.c
--- systemd-252.22/src/tmpfiles/tmpfiles.c	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/src/tmpfiles/tmpfiles.c	2024-02-28 16:57:11.000000000 +0000
@@ -3809,10 +3809,12 @@
                         break;
 
                 case ARG_REPLACE:
-                        if (!path_is_absolute(optarg) ||
-                            !endswith(optarg, ".conf"))
+                        if (!path_is_absolute(optarg))
                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                                       "The argument to --replace= must an absolute path to a config file");
+                                                       "The argument to --replace= must be an absolute path.");
+                        if (!endswith(optarg, ".conf"))
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                       "The argument to --replace= must have the extension '.conf'.");
 
                         arg_replace = optarg;
                         break;
diff -Nru systemd-252.22/test/knot-data/knot.conf systemd-252.23/test/knot-data/knot.conf
--- systemd-252.22/test/knot-data/knot.conf	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/test/knot-data/knot.conf	2024-02-28 16:57:11.000000000 +0000
@@ -48,8 +48,8 @@
       ds-push: parent_zone_server
       ksk-lifetime: 365d
       ksk-submission: parent_zone_sbm
+      nsec3-iterations: 0
       nsec3: on
-      nsec3-iterations: 10
       propagation-delay: 1s
       signing-threads: 4
       zone-max-ttl: 1s
diff -Nru systemd-252.22/test/TEST-24-CRYPTSETUP/test.sh systemd-252.23/test/TEST-24-CRYPTSETUP/test.sh
--- systemd-252.22/test/TEST-24-CRYPTSETUP/test.sh	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/test/TEST-24-CRYPTSETUP/test.sh	2024-02-28 16:57:11.000000000 +0000
@@ -70,9 +70,10 @@
 /dev/mapper/$DM_NAME    /var    ext4    defaults 0 1
 EOF
 
-    # Forward journal messages to the console, so we have something
-    # to investigate even if we fail to mount the encrypted /var
-    echo ForwardToConsole=yes >> "$initdir/etc/systemd/journald.conf"
+    # Forward journal messages to the console, so we have something to investigate even if we fail to mount
+    # the encrypted /var
+    mkdir "$initdir/etc/systemd/journald.conf.d/"
+    echo -ne "[Journal]\nForwardToConsole=yes\n" >"$initdir/etc/systemd/journald.conf.d/99-forward.conf"
 
     # If $INITRD wasn't provided explicitly, generate a custom one with dm-crypt
     # support
diff -Nru systemd-252.22/test/TEST-55-OOMD/test.sh systemd-252.23/test/TEST-55-OOMD/test.sh
--- systemd-252.22/test/TEST-55-OOMD/test.sh	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/test/TEST-55-OOMD/test.sh	2024-02-28 16:57:11.000000000 +0000
@@ -12,19 +12,16 @@
 . "${TEST_BASE_DIR:?}/test-functions"
 
 test_append_files() {
-    # Create a swap file
-    (
-        image_install mkswap swapon swapoff stress
+    local workspace="${1:?}"
 
-        dd if=/dev/zero of="${initdir:?}/swapfile" bs=1M count=48
-        chmod 0600 "${initdir:?}/swapfile"
+    image_install mkswap swapon swapoff stress
+    image_install -o btrfs
 
-        mkdir -p "${initdir:?}/etc/systemd/system/init.scope.d/"
-        cat >>"${initdir:?}/etc/systemd/system/init.scope.d/test-55-oomd.conf" <<EOF
+    mkdir -p "${workspace:?}/etc/systemd/system/init.scope.d/"
+    cat >"${workspace:?}/etc/systemd/system/init.scope.d/test-55-oomd.conf" <<EOF
 [Scope]
 MemoryHigh=10G
 EOF
-    )
 }
 
 do_test "$@" 55
diff -Nru systemd-252.22/test/test-functions systemd-252.23/test/test-functions
--- systemd-252.22/test/test-functions	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/test/test-functions	2024-02-28 16:57:11.000000000 +0000
@@ -223,6 +223,7 @@
     useradd
     userdel
     wc
+    whoami
     xargs
     xzcat
 )
@@ -1257,10 +1258,14 @@
     local testsdir=/usr/lib/systemd/tests
     local pkgs
 
+    dinfo "Install basic filesystem structure"
+    install_rpm filesystem
+
     dinfo "Install SUSE systemd"
 
     pkgs=(
         systemd
+        systemd-boot
         systemd-container
         systemd-coredump
         systemd-experimental
@@ -3151,9 +3156,10 @@
 }
 
 test_setup() {
-    if get_bool "${TEST_REQUIRE_INSTALL_TESTS:?}" && \
-            command -v meson >/dev/null && \
-            [[ "$(meson configure "${BUILD_DIR:?}" | grep install-tests | awk '{ print $2 }')" != "true" ]]; then
+    if ! get_bool "$NO_BUILD" && \
+         get_bool "${TEST_REQUIRE_INSTALL_TESTS:?}" && \
+         command -v meson >/dev/null && \
+         [[ "$(meson configure "${BUILD_DIR:?}" | grep install-tests | awk '{ print $2 }')" != "true" ]]; then
         dfatal "$BUILD_DIR needs to be built with -Dinstall-tests=true"
         exit 1
     fi
diff -Nru systemd-252.22/test/test-shutdown.py systemd-252.23/test/test-shutdown.py
--- systemd-252.22/test/test-shutdown.py	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/test/test-shutdown.py	2024-02-28 16:57:11.000000000 +0000
@@ -4,6 +4,7 @@
 
 import argparse
 import logging
+import signal
 import sys
 
 import pexpect
@@ -90,7 +91,9 @@
     except Exception as e:
         logger.error(e)
         logger.info("killing child pid %d", console.pid)
-        console.terminate(force=True)
+
+        # Ask systemd-nspawn to stop and release the container's resources properly.
+        console.kill(signal.SIGTERM)
 
     return ret
 
diff -Nru systemd-252.22/test/test-sysusers.sh.in systemd-252.23/test/test-sysusers.sh.in
--- systemd-252.22/test/test-sysusers.sh.in	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/test/test-sysusers.sh.in	2024-02-28 16:57:11.000000000 +0000
@@ -152,7 +152,7 @@
     echo "*** Running test $f"
     prepare_testdir ${f%.input}
     cp $f $TESTDIR/usr/lib/sysusers.d/test.conf
-    $SYSUSERS --root=$TESTDIR 2>&1 | tail -n1 | sed -r 's/^[^:]+:[^:]+://' >$TESTDIR/err
+    SYSTEMD_LOG_LEVEL=info $SYSUSERS --root=$TESTDIR 2>&1 | tail -n1 | sed -r 's/^[^:]+:[^:]+://' >$TESTDIR/err
     if ! diff -u $TESTDIR/err  ${f%.*}.expected-err; then
         echo "**** Unexpected error output for $f"
         cat $TESTDIR/err
diff -Nru systemd-252.22/test/units/testsuite-23.utmp.sh systemd-252.23/test/units/testsuite-23.utmp.sh
--- systemd-252.22/test/units/testsuite-23.utmp.sh	1970-01-01 01:00:00.000000000 +0100
+++ systemd-252.23/test/units/testsuite-23.utmp.sh	2024-02-28 16:57:11.000000000 +0000
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+
+set -eux
+set -o pipefail
+
+# shellcheck source=test/units/util.sh
+. "$(dirname "$0")"/util.sh
+
+USER="test-23-utmp"
+
+cleanup() {
+    userdel "$USER"
+}
+
+trap cleanup EXIT
+useradd "$USER"
+
+assert_eq "$(systemd-run -qP -p UtmpIdentifier=test -p UtmpMode=user -p User=$USER whoami)" "$USER"
+assert_eq "$(systemd-run -qP -p UtmpIdentifier=test -p UtmpMode=user whoami)" "$(whoami)"
diff -Nru systemd-252.22/test/units/testsuite-43.sh systemd-252.23/test/units/testsuite-43.sh
--- systemd-252.22/test/units/testsuite-43.sh	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/test/units/testsuite-43.sh	2024-02-28 16:57:11.000000000 +0000
@@ -3,6 +3,11 @@
 set -eux
 set -o pipefail
 
+if [[ "$(sysctl -ne kernel.apparmor_restrict_unprivileged_userns)" -eq 1 ]]; then
+    echo "Cannot create unprivileged user namespaces" >/skipped
+    exit 0
+fi
+
 systemd-analyze log-level debug
 
 runas() {
diff -Nru systemd-252.22/test/units/testsuite-55.sh systemd-252.23/test/units/testsuite-55.sh
--- systemd-252.22/test/units/testsuite-55.sh	2024-01-26 21:35:39.000000000 +0000
+++ systemd-252.23/test/units/testsuite-55.sh	2024-02-28 16:57:11.000000000 +0000
@@ -10,15 +10,9 @@
 
 # Loose checks to ensure the environment has the necessary features for systemd-oomd
 [[ -e /proc/pressure ]] || echo "no PSI" >>/skipped
-cgroup_type="$(stat -fc %T /sys/fs/cgroup/)"
-if [[ "$cgroup_type" != *"cgroup2"* ]] && [[ "$cgroup_type" != *"0x63677270"* ]]; then
-    echo "no cgroup2" >>/skipped
-fi
-if [ ! -f /usr/lib/systemd/systemd-oomd ] && [ ! -f /lib/systemd/systemd-oomd ]; then
-    echo "no oomd" >>/skipped
-fi
-
-if [[ -e /skipped ]]; then
+[[ "$(get_cgroup_hierarchy)" == "unified" ]] || echo "no cgroupsv2" >>/skipped
+[[ -x /usr/lib/systemd/systemd-oomd ]] || echo "no oomd" >>/skipped
+if [[ -s /skipped ]]; then
     exit 0
 fi
 
@@ -26,7 +20,14 @@
 
 # Activate swap file if we are in a VM
 if systemd-detect-virt --vm --quiet; then
-    mkswap /swapfile
+    if [[ "$(findmnt -n -o FSTYPE /)" == btrfs ]]; then
+        btrfs filesystem mkswapfile -s 64M /swapfile
+    else
+        dd if=/dev/zero of=/swapfile bs=1M count=64
+        chmod 0600 /swapfile
+        mkswap /swapfile
+    fi
+
     swapon /swapfile
     swapon --show
 fi
@@ -72,27 +73,16 @@
 systemctl start testsuite-55-testbloat.service
 
 # Verify systemd-oomd is monitoring the expected units
-# Try to avoid racing the oomctl output check by checking in a loop with a timeout
-oomctl_output=$(oomctl)
-timeout="$(date -ud "1 minutes" +%s)"
-while [[ $(date -u +%s) -le $timeout ]]; do
-    if grep "/testsuite-55-workload.slice" <<< "$oomctl_output"; then
-        break
-    fi
-    oomctl_output=$(oomctl)
-    sleep 1
-done
-
-grep "/testsuite-55-workload.slice" <<< "$oomctl_output"
-grep "20.00%" <<< "$oomctl_output"
-grep "Default Memory Pressure Duration: 2s" <<< "$oomctl_output"
+timeout 1m bash -xec 'until oomctl | grep "/testsuite-55-workload.slice"; do sleep 1; done'
+oomctl | grep "/testsuite-55-workload.slice"
+oomctl | grep "20.00%"
+oomctl | grep "Default Memory Pressure Duration: 2s"
 
 systemctl status testsuite-55-testchill.service
 
 # systemd-oomd watches for elevated pressure for 2 seconds before acting.
 # It can take time to build up pressure so either wait 2 minutes or for the service to fail.
-timeout="$(date -ud "2 minutes" +%s)"
-while [[ $(date -u +%s) -le $timeout ]]; do
+for _ in {0..59}; do
     if ! systemctl status testsuite-55-testbloat.service; then
         break
     fi
@@ -105,32 +95,23 @@
 if ! systemctl status testsuite-55-testchill.service; then exit 24; fi
 
 # Make sure we also work correctly on user units.
+loginctl enable-linger testuser
 
 systemctl start --machine "testuser@.host" --user testsuite-55-testchill.service
 systemctl start --machine "testuser@.host" --user testsuite-55-testbloat.service
 
 # Verify systemd-oomd is monitoring the expected units
 # Try to avoid racing the oomctl output check by checking in a loop with a timeout
-oomctl_output=$(oomctl)
-timeout="$(date -ud "1 minutes" +%s)"
-while [[ $(date -u +%s) -le $timeout ]]; do
-    if grep -E "/user.slice.*/testsuite-55-workload.slice" <<< "$oomctl_output"; then
-        break
-    fi
-    oomctl_output=$(oomctl)
-    sleep 1
-done
-
-grep -E "/user.slice.*/testsuite-55-workload.slice" <<< "$oomctl_output"
-grep "20.00%" <<< "$oomctl_output"
-grep "Default Memory Pressure Duration: 2s" <<< "$oomctl_output"
+timeout 1m bash -xec 'until oomctl | grep "/testsuite-55-workload.slice"; do sleep 1; done'
+oomctl | grep -E "/user.slice.*/testsuite-55-workload.slice"
+oomctl | grep "20.00%"
+oomctl | grep "Default Memory Pressure Duration: 2s"
 
 systemctl --machine "testuser@.host" --user status testsuite-55-testchill.service
 
 # systemd-oomd watches for elevated pressure for 2 seconds before acting.
 # It can take time to build up pressure so either wait 2 minutes or for the service to fail.
-timeout="$(date -ud "2 minutes" +%s)"
-while [[ $(date -u +%s) -le $timeout ]]; do
+for _ in {0..59}; do
     if ! systemctl --machine "testuser@.host" --user status testsuite-55-testbloat.service; then
         break
     fi
@@ -142,6 +123,8 @@
 if systemctl --machine "testuser@.host" --user status testsuite-55-testbloat.service; then exit 42; fi
 if ! systemctl --machine "testuser@.host" --user status testsuite-55-testchill.service; then exit 24; fi
 
+loginctl disable-linger testuser
+
 # only run this portion of the test if we can set xattrs
 if setfattr -n user.xattr_test -v 1 /sys/fs/cgroup/; then
     sleep 120 # wait for systemd-oomd kill cool down and elevated memory pressure to come down
@@ -157,8 +140,7 @@
     systemctl start testsuite-55-testmunch.service
     systemctl start testsuite-55-testbloat.service
 
-    timeout="$(date -ud "2 minutes" +%s)"
-    while [[ "$(date -u +%s)" -le "$timeout" ]]; do
+    for _ in {0..59}; do
         if ! systemctl status testsuite-55-testmunch.service; then
             break
         fi

Attachment: signature.asc
Description: This is a digitally signed message part


--- End Message ---
--- Begin Message ---
Version: 12.6

The upload requested in this bug has been released as part of 12.6.

--- End Message ---

Reply to: