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

Bug#1064993: bookworm-pu: package systemd/252.23-1~deb12u1



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


Reply to: