Version in base suite: 252.36-1~deb12u1 Base version: systemd_252.36-1~deb12u1 Target version: systemd_252.38-1~deb12u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/s/systemd/systemd_252.36-1~deb12u1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/s/systemd/systemd_252.38-1~deb12u1.dsc .github/workflows/mkosi.yml | 3 debian/changelog | 7 debian/patches/debian/Revert-core-set-RLIMIT_CORE-to-unlimited-by-default.patch | 4 man/common-variables.xml | 86 ++-- man/journald.conf.xml | 2 man/org.freedesktop.systemd1.xml | 2 man/sd_bus_emit_signal.xml | 6 man/sd_bus_slot_set_floating.xml | 4 man/systemctl.xml | 7 man/systemd-coredump.xml | 11 man/systemd-networkd.service.xml | 22 - man/systemd-remount-fs.service.xml | 2 man/systemd.link.xml | 22 - man/systemd.network.xml | 8 man/systemd.swap.xml | 2 man/systemd.xml | 9 shell-completion/zsh/_systemctl.in | 2 src/basic/locale-util.c | 5 src/basic/log.h | 2 src/basic/macro.h | 9 src/basic/socket-util.c | 49 ++ src/basic/socket-util.h | 1 src/busctl/busctl.c | 14 src/core/cgroup.c | 10 src/core/core-varlink.c | 2 src/core/dbus-manager.c | 2 src/core/dbus.c | 2 src/core/main.c | 2 src/core/manager.c | 28 + src/core/meson.build | 2 src/core/socket.c | 8 src/coredump/coredump.c | 70 ++- src/getty-generator/getty-generator.c | 6 src/home/homed-manager.c | 2 src/home/homework-mount.c | 4 src/initctl/initctl.c | 3 src/libsystemd/sd-bus/sd-bus.c | 6 src/libsystemd/sd-device/test-sd-device.c | 10 src/shared/calendarspec.c | 48 ++ src/shared/pager.c | 29 - src/test/test-calendarspec.c | 4 src/test/test-macro.c | 184 +++++++++ src/test/test-specifier.c | 26 - src/udev/udevadm-test-builtin.c | 13 sysctl.d/50-coredump.conf.in | 2 test/networkd-test.py | 6 test/test-network/systemd-networkd-tests.py | 6 test/units/testsuite-73.sh | 4 test/units/testsuite-74.coredump.sh | 200 ++++++++++ test/units/testsuite-75.sh | 14 50 files changed, 826 insertions(+), 146 deletions(-) diff: /srv/release.debian.org/tmp/tBYReILWfh/systemd-252.36/test/testdata: recursive directory loop diff -Nru systemd-252.36/.github/workflows/mkosi.yml systemd-252.38/.github/workflows/mkosi.yml --- systemd-252.36/.github/workflows/mkosi.yml 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/.github/workflows/mkosi.yml 2025-05-29 17:44:54.000000000 +0000 @@ -60,6 +60,9 @@ - name: Configure run: | + # mkosi GHA clones and builds from main but tools are not compatible with this branch, 24.04 ships 255 which is enough + sudo apt install --reinstall systemd systemd-container systemd-boot systemd-ukify + tee mkosi.default <<- EOF [Distribution] Distribution=${{ matrix.distro }} diff -Nru systemd-252.36/debian/changelog systemd-252.38/debian/changelog --- systemd-252.36/debian/changelog 2025-03-06 14:56:14.000000000 +0000 +++ systemd-252.38/debian/changelog 2025-05-29 17:04:02.000000000 +0000 @@ -1,3 +1,10 @@ +systemd (252.38-1~deb12u1) bookworm-security; urgency=medium + + * New upstream version 252.38 (fixes CVE-2025-4598) + * Refresh patch to remove fuzz from 252.38 + + -- Luca Boccassi Thu, 29 May 2025 18:04:02 +0100 + systemd (252.36-1~deb12u1) bookworm; urgency=medium * New upstream version 252.36 diff -Nru systemd-252.36/debian/patches/debian/Revert-core-set-RLIMIT_CORE-to-unlimited-by-default.patch systemd-252.38/debian/patches/debian/Revert-core-set-RLIMIT_CORE-to-unlimited-by-default.patch --- systemd-252.36/debian/patches/debian/Revert-core-set-RLIMIT_CORE-to-unlimited-by-default.patch 2025-03-06 14:56:14.000000000 +0000 +++ systemd-252.38/debian/patches/debian/Revert-core-set-RLIMIT_CORE-to-unlimited-by-default.patch 2025-05-29 17:04:02.000000000 +0000 @@ -64,8 +64,8 @@ # the core dump. # # See systemd-coredump(8) and core(5). --kernel.core_pattern=|{{ROOTLIBEXECDIR}}/systemd-coredump %P %u %g %s %t %c %h -+kernel.core_pattern=|{{ROOTLIBEXECDIR}}/systemd-coredump %P %u %g %s %t 9223372036854775808 %h +-kernel.core_pattern=|{{ROOTLIBEXECDIR}}/systemd-coredump %P %u %g %s %t %c %h %d ++kernel.core_pattern=|{{ROOTLIBEXECDIR}}/systemd-coredump %P %u %g %s %t 9223372036854775808 %h %d # Allow 16 coredumps to be dispatched in parallel by the kernel. # We collect metadata from /proc/%P/, and thus need to make sure the crashed diff -Nru systemd-252.36/man/common-variables.xml systemd-252.38/man/common-variables.xml --- systemd-252.36/man/common-variables.xml 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/man/common-variables.xml 2025-05-29 17:44:54.000000000 +0000 @@ -83,17 +83,22 @@ $SYSTEMD_PAGER + $PAGER - Pager to use when is not given; overrides - $PAGER. If neither $SYSTEMD_PAGER nor $PAGER are set, a - set of well-known pager implementations are tried in turn, including - less1 and - more1, until one is found. If - no pager implementation is discovered no pager is invoked. Setting this environment variable to an empty string - or the value cat is equivalent to passing . + Pager to use when is not given. + $SYSTEMD_PAGER is used if set; otherwise $PAGER is used. + If neither $SYSTEMD_PAGER nor $PAGER are set, a set of well-known + pager implementations is tried in turn, including + less1 + and + more1, + until one is found. If no pager implementation is discovered, no pager is invoked. Setting those + environment variables to an empty string or the value cat is equivalent to passing + . Note: if $SYSTEMD_PAGERSECURE is not set, $SYSTEMD_PAGER - (as well as $PAGER) will be silently ignored. + and $PAGER can only be used to disable the pager (with cat or + ), and are otherwise ignored. @@ -150,28 +155,53 @@ $SYSTEMD_PAGERSECURE - Takes a boolean argument. When true, the "secure" mode of the pager is enabled; if - false, disabled. If $SYSTEMD_PAGERSECURE is not set at all, secure mode is enabled - if the effective UID is not the same as the owner of the login session, see - geteuid2 - and sd_pid_get_owner_uid3. - In secure mode, will be set when invoking the pager, and the pager shall - disable commands that open or create new files or start new subprocesses. When - $SYSTEMD_PAGERSECURE is not set at all, pagers which are not known to implement - secure mode will not be used. (Currently only - less1 - implements secure mode.) - - Note: when commands are invoked with elevated privileges, for example under + Common pager commands like less1, in + addition to "paging", i.e. scrolling through the output, support opening of or writing to other files + and running arbitrary shell commands. When commands are invoked with elevated privileges, for example + under sudo8 or pkexec1, care - must be taken to ensure that unintended interactive features are not enabled. "Secure" mode for the - pager may be enabled automatically as describe above. Setting SYSTEMD_PAGERSECURE=0 - or not removing it from the inherited environment allows the user to invoke arbitrary commands. Note - that if the $SYSTEMD_PAGER or $PAGER variables are to be - honoured, $SYSTEMD_PAGERSECURE must be set too. It might be reasonable to completely - disable the pager using instead. + project='die-net'>pkexec1, the + pager becomes a security boundary. Care must be taken that only programs with strictly limited + functionality are used as pagers, and unintended interactive features like opening or creation of new + files or starting of subprocesses are not allowed. "Secure mode" for the pager may be enabled as + described below, if the pager supports that (most pagers are not written in a way + that takes this into consideration). It is recommended to either explicitly enable "secure mode" or to + completely disable the pager using or PAGER=cat when + allowing untrusted users to execute commands with elevated privileges. + + This option takes a boolean argument. When set to true, the "secure mode" of the pager is + enabled. In "secure mode", will be set when invoking the pager, which + instructs the pager to disable commands that open or create new files or start new subprocesses. + Currently only less1 is known + to understand this variable and implement "secure mode". + + When set to false, no limitation is placed on the pager. Setting + SYSTEMD_PAGERSECURE=0 or not removing it from the inherited environment may allow + the user to invoke arbitrary commands. + + When $SYSTEMD_PAGERSECURE is not set, systemd tools attempt to automatically + figure out if "secure mode" should be enabled and whether the pager supports it. "Secure mode" is + enabled if the effective UID is not the same as the owner of the login session, see + geteuid2 + and + sd_pid_get_owner_uid3, + or when running under + sudo8 or similar + tools ($SUDO_UID is set + It is recommended for other tools to set and check $SUDO_UID as appropriate, + treating it is a common interface.). In those cases, + SYSTEMD_PAGERSECURE=1 will be set and pagers which are not known to implement + "secure mode" will not be used at all. Note that this autodetection only covers the most common + mechanisms to elevate privileges and is intended as convenience. It is recommended to explicitly set + $SYSTEMD_PAGERSECURE or disable the pager. + + Note that if the $SYSTEMD_PAGER or $PAGER variables are to + be honoured, other than to disable the pager, $SYSTEMD_PAGERSECURE must be set + too. diff -Nru systemd-252.36/man/journald.conf.xml systemd-252.38/man/journald.conf.xml --- systemd-252.36/man/journald.conf.xml 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/man/journald.conf.xml 2025-05-29 17:44:54.000000000 +0000 @@ -257,7 +257,7 @@ and use the smaller of the two values. The first pair defaults to 10% and the second to 15% of - the size of the respective file system, but each value is + the size of the respective file system, but each of the calculated default values is capped to 4G. If the file system is nearly full and either SystemKeepFree= or RuntimeKeepFree= are violated when diff -Nru systemd-252.36/man/org.freedesktop.systemd1.xml systemd-252.38/man/org.freedesktop.systemd1.xml --- systemd-252.36/man/org.freedesktop.systemd1.xml 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/man/org.freedesktop.systemd1.xml 2025-05-29 17:44:54.000000000 +0000 @@ -8007,7 +8007,7 @@ elapsation point on the CLOCK_REALTIME clock, relative to its epoch. NextElapseUSecRealtime contains the next elapsation point on the - CLOCK_REALTIME clock in miscroseconds since the epoch, or 0 if this timer event + CLOCK_REALTIME clock in microseconds since the epoch, or 0 if this timer event does not include at least one calendar event. Similarly, NextElapseUSecMonotonic contains the next elapsation point on the diff -Nru systemd-252.36/man/sd_bus_emit_signal.xml systemd-252.38/man/sd_bus_emit_signal.xml --- systemd-252.36/man/sd_bus_emit_signal.xml 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/man/sd_bus_emit_signal.xml 2025-05-29 17:44:54.000000000 +0000 @@ -67,7 +67,7 @@ int sd_bus_emit_interfaces_added_strv sd_bus *bus const char *path - const char **interfaces + char **interfaces @@ -82,7 +82,7 @@ int sd_bus_emit_interfaces_removed_strv sd_bus *bus const char *path - const char **interfaces + char **interfaces @@ -99,7 +99,7 @@ sd_bus *bus const char *path const char *interface - const char **names + char **names diff -Nru systemd-252.36/man/sd_bus_slot_set_floating.xml systemd-252.38/man/sd_bus_slot_set_floating.xml --- systemd-252.36/man/sd_bus_slot_set_floating.xml 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/man/sd_bus_slot_set_floating.xml 2025-05-29 17:44:54.000000000 +0000 @@ -51,8 +51,8 @@ referenced bus slot object around. The floating state hence controls the direction of referencing between the bus object and the bus slot objects: if floating the bus pins the bus slot, and otherwise the bus slot pins the bus objects. Use sd_bus_slot_set_floating() to switch between both modes: if the - b parameter is zero, the slot object is considered floating, otherwise it is made a regular - (non-floating) slot object. + b parameter is zero, the slot object is made into a regular (non-floating) slot object, + otherwise it is made into a floating slot object. Bus slot objects may be allocated with calls such as sd_bus_add_match3. If the diff -Nru systemd-252.36/man/systemctl.xml systemd-252.38/man/systemctl.xml --- systemd-252.36/man/systemctl.xml 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/man/systemctl.xml 2025-05-29 17:44:54.000000000 +0000 @@ -139,10 +139,9 @@ shown. Produces output similar to LISTEN UNIT ACTIVATES -/dev/initctl systemd-initctl.socket systemd-initctl.service -… -[::]:22 sshd.socket sshd.service kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service +/dev/rfkill systemd-rfkill.socket systemd-rfkill.service +… 5 sockets listed. Note: because the addresses might contains spaces, this output @@ -837,7 +836,7 @@ preset UNIT - Reset the enable/disable status one or more unit files, as specified on + Reset the enable/disable status of one or more unit files, as specified on the command line, to the defaults configured in the preset policy files. This has the same effect as disable or enable, depending how the unit is listed in the preset diff -Nru systemd-252.36/man/systemd-coredump.xml systemd-252.38/man/systemd-coredump.xml --- systemd-252.36/man/systemd-coredump.xml 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/man/systemd-coredump.xml 2025-05-29 17:44:54.000000000 +0000 @@ -274,6 +274,17 @@ + COREDUMP_DUMPABLE= + + The PR_GET_DUMPABLE field as reported by the kernel, see + prctl2. + + + + + + COREDUMP_OPEN_FDS= Information about open file descriptors, in the following format: diff -Nru systemd-252.36/man/systemd-networkd.service.xml systemd-252.38/man/systemd-networkd.service.xml --- systemd-252.36/man/systemd-networkd.service.xml 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/man/systemd-networkd.service.xml 2025-05-29 17:44:54.000000000 +0000 @@ -33,12 +33,16 @@ manages networks. It detects and configures network devices as they appear, as well as creating virtual network devices. - To configure low-level link settings independently of - networks, see - systemd.link5. + Certain low-level settings of physical network devices (e.g. device + names and altnames) as well as the creation of SR-IOV virtual functions on + physical network interfaces may be managed by + systemd-udevd8 + according to the contents of + systemd.link5 + files. - systemd-networkd will create network devices based - on the configuration in + systemd-networkd will create "virtual" network + devices (e.g. bridges and tunnels) based on the configuration in systemd.netdev5 files, respecting the [Match] sections in those files. @@ -47,10 +51,10 @@ with an appropriate [Match] section, see systemd.network5. For those links, it will flush existing network addresses and routes when - bringing up the device. Any links not matched by one of the - .network files will be ignored. It is also possible to - explicitly tell systemd-networkd to ignore a link by - using Unmanaged=yes option, see + bringing up the device (except when directed not to). Any links not matched + by one of the .network files will be ignored. It is + also possible to explicitly tell systemd-networkd to + ignore a link by using the Unmanaged=yes option, see systemd.network5. diff -Nru systemd-252.36/man/systemd-remount-fs.service.xml systemd-252.38/man/systemd-remount-fs.service.xml --- systemd-252.36/man/systemd-remount-fs.service.xml 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/man/systemd-remount-fs.service.xml 2025-05-29 17:44:54.000000000 +0000 @@ -51,7 +51,7 @@ Note: systemd-remount-fs.service is usually pulled in by systemd-fstab-generator8, hence it is also affected by the kernel command line option fstab=, which may be used - to disable the generator. It may also pulled in by + to disable the generator. It may also be pulled in by systemd-gpt-auto-generator8, which is affected by systemd.gpt_auto and other options. diff -Nru systemd-252.36/man/systemd.link.xml systemd-252.38/man/systemd.link.xml --- systemd-252.36/man/systemd.link.xml 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/man/systemd.link.xml 2025-05-29 17:44:54.000000000 +0000 @@ -32,6 +32,11 @@ systemd.syntax7 for a general description of the syntax. + Note that some distributions may incorporate .link files in their early boot + facilities (e.g. by including copies of the .link files in initramfs). As such it + may be necessary to take manual steps to ensure that any local changes are consistent with early-boot + storage facilities. The relevant distribution-specific documentation should be consulted. + The .link files are read from the files located in the system network directory /usr/lib/systemd/network and /usr/local/lib/systemd/network, the volatile runtime network directory @@ -1018,11 +1023,18 @@ [SR-IOV] Section Options - The [SR-IOV] section accepts the following keys. Specify several [SR-IOV] sections to - configure several SR-IOVs. SR-IOV provides the ability to partition a single physical PCI resource - into virtual PCI functions which can then be injected into a VM. In the case of network VFs, SR-IOV - improves north-south network performance (that is, traffic with endpoints outside the host machine) - by allowing traffic to bypass the host machine’s network stack. + SR-IOV provides the ability to partition a single physical PCI resource into virtual PCI + functions which can then be e.g. injected into a VM. In the case of network VFs, SR-IOV reduces + latency and CPU utilisation for north-south network traffic (that is, traffic with endpoints + outside the host machine), by allowing traffic to bypass the host machine’s network stack. + + + The presence of an [SR-IOV] section in a .link file will cause the creation and + configuration of the specified virtual function. Within a .network file, the specified virtual + function will be configured, but must already exist. Specify several [SR-IOV] sections to + configure several SR-IOVs. + + The [SR-IOV] section accepts the following keys. diff -Nru systemd-252.36/man/systemd.network.xml systemd-252.38/man/systemd.network.xml --- systemd-252.36/man/systemd.network.xml 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/man/systemd.network.xml 2025-05-29 17:44:54.000000000 +0000 @@ -37,6 +37,14 @@ The main network file must have the extension .network; other extensions are ignored. Networks are applied to links whenever the links appear. + Note that not all settings and configurations can be made with .network + files, and that it may be necessary to use + systemd.link5) + or + systemd.netdev5) + files in conjuction with .network files when working with physical and virtual + network devices respectively. + The .network files are read from the files located in the system network directories /usr/lib/systemd/network and /usr/local/lib/systemd/network, the volatile runtime network directory diff -Nru systemd-252.36/man/systemd.swap.xml systemd-252.38/man/systemd.swap.xml --- systemd-252.36/man/systemd.swap.xml 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/man/systemd.swap.xml 2025-05-29 17:44:54.000000000 +0000 @@ -72,7 +72,7 @@ All swap units automatically get the - BindsTo= and After= + Requires= and After= dependencies on the device units or the mount units of the files they are activated from. diff -Nru systemd-252.36/man/systemd.xml systemd-252.38/man/systemd.xml --- systemd-252.36/man/systemd.xml 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/man/systemd.xml 2025-05-29 17:44:54.000000000 +0000 @@ -976,12 +976,9 @@ 5 Boot into the specified legacy SysV runlevel. - These are equivalent to - systemd.unit=runlevel2.target, - systemd.unit=runlevel3.target, - systemd.unit=runlevel4.target, and - systemd.unit=runlevel5.target, - respectively, and provided for compatibility reasons and to be + 2, 3, and 4 are equivalent to + systemd.unit=multi-user.target; and 5 is equivalent to + systemd.unit=graphical.target, and provided for compatibility reasons and to be easier to type. diff -Nru systemd-252.36/shell-completion/zsh/_systemctl.in systemd-252.38/shell-completion/zsh/_systemctl.in --- systemd-252.36/shell-completion/zsh/_systemctl.in 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/shell-completion/zsh/_systemctl.in 2025-05-29 17:44:54.000000000 +0000 @@ -408,7 +408,7 @@ suf='-S=' fi _wanted systemd-environment expl 'environment variable' \ - compadd "$@" ${suf} - ${${(f)"$(systemctl show-environment)"}%%=*} + compadd "$@" ${suf} - ${${(f)"$(systemctl "$_sys_service_mgr" show-environment)"}%%=*} } done diff -Nru systemd-252.36/src/basic/locale-util.c systemd-252.38/src/basic/locale-util.c --- systemd-252.36/src/basic/locale-util.c 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/basic/locale-util.c 2025-05-29 17:44:54.000000000 +0000 @@ -97,7 +97,6 @@ const struct namehashent *e; const void *p = MAP_FAILED; _cleanup_close_ int fd = -1; - size_t sz = 0; struct stat st; int r; @@ -154,9 +153,9 @@ r = 0; - finish: +finish: if (p != MAP_FAILED) - munmap((void*) p, sz); + munmap((void*) p, st.st_size); return r; } diff -Nru systemd-252.36/src/basic/log.h systemd-252.38/src/basic/log.h --- systemd-252.36/src/basic/log.h 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/basic/log.h 2025-05-29 17:44:54.000000000 +0000 @@ -94,8 +94,8 @@ const char *func, const char *object_field, const char *object, - const char *extra, const char *extra_field, + const char *extra, char *buffer); int log_internal( diff -Nru systemd-252.36/src/basic/macro.h systemd-252.38/src/basic/macro.h --- systemd-252.36/src/basic/macro.h 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/basic/macro.h 2025-05-29 17:44:54.000000000 +0000 @@ -439,4 +439,13 @@ _q && _q > (base) ? &_q[-1] : NULL; \ }) +/* Iterate through each variadic arg. All must be the same type as 'entry' or must be implicitly + * convertable. The iteration variable 'entry' must already be defined. */ +#define VA_ARGS_FOREACH(entry, ...) \ + _VA_ARGS_FOREACH(entry, UNIQ_T(_entries_, UNIQ), UNIQ_T(_current_, UNIQ), UNIQ_T(_va_sentinel_, UNIQ), ##__VA_ARGS__) +#define _VA_ARGS_FOREACH(entry, _entries_, _current_, _va_sentinel_, ...) \ + for (typeof(entry) _va_sentinel_[1] = {}, _entries_[] = { __VA_ARGS__ __VA_OPT__(,) _va_sentinel_[0] }, *_current_ = _entries_; \ + ((long)(_current_ - _entries_) < (long)(ELEMENTSOF(_entries_) - 1)) && ({ entry = *_current_; true; }); \ + _current_++) + #include "log.h" diff -Nru systemd-252.36/src/basic/socket-util.c systemd-252.38/src/basic/socket-util.c --- systemd-252.36/src/basic/socket-util.c 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/basic/socket-util.c 2025-05-29 17:44:54.000000000 +0000 @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -1157,6 +1158,54 @@ } } +ssize_t flush_mqueue(int fd) { + _cleanup_free_ char *buf = NULL; + struct mq_attr attr; + ssize_t count = 0; + int r; + + assert(fd >= 0); + + /* Similar to flush_fd() but flushes all messages from a POSIX message queue. */ + + for (;;) { + ssize_t l; + + r = fd_wait_for_event(fd, POLLIN, /* timeout= */ 0); + if (r < 0) { + if (r == -EINTR) + continue; + + return r; + } + if (r == 0) + return count; + + if (!buf) { + /* Buffer must be at least as large as mq_msgsize. */ + if (mq_getattr(fd, &attr) < 0) + return -errno; + + buf = malloc(attr.mq_msgsize); + if (!buf) + return -ENOMEM; + } + + l = mq_receive(fd, buf, attr.mq_msgsize, /* msg_prio = */ NULL); + if (l < 0) { + if (errno == EINTR) + continue; + + if (errno == EAGAIN) + return count; + + return -errno; + } + + count += l; + } +} + struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length) { struct cmsghdr *cmsg; diff -Nru systemd-252.36/src/basic/socket-util.h systemd-252.38/src/basic/socket-util.h --- systemd-252.36/src/basic/socket-util.h 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/basic/socket-util.h 2025-05-29 17:44:54.000000000 +0000 @@ -171,6 +171,7 @@ ssize_t next_datagram_size_fd(int fd); int flush_accept(int fd); +ssize_t flush_mqueue(int fd); #define CMSG_FOREACH(cmsg, mh) \ for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg))) diff -Nru systemd-252.36/src/busctl/busctl.c systemd-252.38/src/busctl/busctl.c --- systemd-252.36/src/busctl/busctl.c 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/busctl/busctl.c 2025-05-29 17:44:54.000000000 +0000 @@ -2161,6 +2161,13 @@ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; + if (!service_name_is_valid(argv[1])) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid service name: %s", argv[1]); + if (!object_path_is_valid(argv[2])) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid object path: %s", argv[2]); + if (!interface_name_is_valid(argv[3])) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid interface name: %s", argv[3]); + r = acquire_bus(false, &bus); if (r < 0) return r; @@ -2230,6 +2237,13 @@ char **p; int r; + if (!service_name_is_valid(argv[1])) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid service name: %s", argv[1]); + if (!object_path_is_valid(argv[2])) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid object path: %s", argv[2]); + if (!interface_name_is_valid(argv[3])) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid interface name: %s", argv[3]); + r = acquire_bus(false, &bus); if (r < 0) return r; diff -Nru systemd-252.36/src/core/cgroup.c systemd-252.38/src/core/cgroup.c --- systemd-252.36/src/core/cgroup.c 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/core/cgroup.c 2025-05-29 17:44:54.000000000 +0000 @@ -51,6 +51,8 @@ * out specific attributes from us. */ #define LOG_LEVEL_CGROUP_WRITE(r) (IN_SET(abs(r), ENOENT, EROFS, EACCES, EPERM) ? LOG_DEBUG : LOG_WARNING) +static void unit_remove_from_cgroup_empty_queue(Unit *u); + uint64_t tasks_max_resolve(const TasksMax *tasks_max) { if (tasks_max->scale == 0) return tasks_max->value; @@ -2366,6 +2368,10 @@ else { if (ret >= 0) ret++; /* Count successful additions */ + + /* the cgroup is definitely not empty now, in case the unit was in + * the cgroup empty queue, drop it from there */ + unit_remove_from_cgroup_empty_queue(u); continue; /* When the bus thing worked via the bus we are fully done for this PID. */ } } @@ -2374,8 +2380,10 @@ ret = r; /* Remember first error */ continue; - } else if (ret >= 0) + } else if (ret >= 0) { + unit_remove_from_cgroup_empty_queue(u); ret++; /* Count successful additions */ + } r = cg_all_unified(); if (r < 0) diff -Nru systemd-252.36/src/core/core-varlink.c systemd-252.38/src/core/core-varlink.c --- systemd-252.36/src/core/core-varlink.c 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/core/core-varlink.c 2025-05-29 17:44:54.000000000 +0000 @@ -500,7 +500,7 @@ bool fresh = r > 0; if (!MANAGER_IS_TEST_RUN(m)) { - (void) mkdir_p_label("/run/systemd/userdb", 0755); + (void) mkdir_label("/run/systemd/userdb", 0755); FOREACH_STRING(address, "/run/systemd/userdb/io.systemd.DynamicUser", VARLINK_ADDR_PATH_MANAGED_OOM_SYSTEM) { if (!fresh) { diff -Nru systemd-252.36/src/core/dbus-manager.c systemd-252.38/src/core/dbus-manager.c --- systemd-252.36/src/core/dbus-manager.c 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/core/dbus-manager.c 2025-05-29 17:44:54.000000000 +0000 @@ -2829,7 +2829,7 @@ SD_BUS_WRITABLE_PROPERTY("ServiceWatchdogs", "b", bus_property_get_bool, bus_property_set_bool, offsetof(Manager, service_watchdogs), 0), SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Manager, cgroup_root), 0), SD_BUS_PROPERTY("SystemState", "s", property_get_system_state, 0, 0), - SD_BUS_PROPERTY("ExitCode", "y", bus_property_get_unsigned, offsetof(Manager, return_value), 0), + SD_BUS_PROPERTY("ExitCode", "y", NULL, offsetof(Manager, return_value), 0), SD_BUS_PROPERTY("DefaultTimerAccuracyUSec", "t", bus_property_get_usec, offsetof(Manager, default_timer_accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultTimeoutStartUSec", "t", bus_property_get_usec, offsetof(Manager, default_timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultTimeoutStopUSec", "t", bus_property_get_usec, offsetof(Manager, default_timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST), diff -Nru systemd-252.36/src/core/dbus.c systemd-252.38/src/core/dbus.c --- systemd-252.36/src/core/dbus.c 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/core/dbus.c 2025-05-29 17:44:54.000000000 +0000 @@ -33,7 +33,6 @@ #include "fd-util.h" #include "fs-util.h" #include "log.h" -#include "mkdir-label.h" #include "process-util.h" #include "selinux-access.h" #include "serialize.h" @@ -940,7 +939,6 @@ return log_error_errno(r, "Can't set path for AF_UNIX socket to bind to: %m"); sa_len = r; - (void) mkdir_parents_label(sa.un.sun_path, 0755); (void) sockaddr_un_unlink(&sa.un); fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); diff -Nru systemd-252.36/src/core/main.c systemd-252.38/src/core/main.c --- systemd-252.36/src/core/main.c 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/core/main.c 2025-05-29 17:44:54.000000000 +0000 @@ -2684,7 +2684,7 @@ l = strv_copy(environ); if (!l) - return -ENOMEM; + return log_oom(); strv_free_and_replace(saved_env, l); return 0; diff -Nru systemd-252.36/src/core/manager.c systemd-252.38/src/core/manager.c --- systemd-252.36/src/core/manager.c 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/core/manager.c 2025-05-29 17:44:54.000000000 +0000 @@ -302,7 +302,7 @@ if (!m->ask_password_event_source) { assert(m->ask_password_inotify_fd < 0); - (void) mkdir_p_label("/run/systemd/ask-password", 0755); + (void) mkdir_label("/run/systemd/ask-password", 0755); m->ask_password_inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); if (m->ask_password_inotify_fd < 0) @@ -941,7 +941,7 @@ r = xdg_user_runtime_dir(&units_path, "/systemd/units"); if (r < 0) return r; - r = mkdir_p_label(units_path, 0755); + r = mkdir_label(units_path, 0755); } if (r < 0 && r != -EEXIST) @@ -991,7 +991,6 @@ m->notify_socket); sa_len = r; - (void) mkdir_parents_label(m->notify_socket, 0755); (void) sockaddr_un_unlink(&sa.un); r = mac_selinux_bind(fd, &sa.sa, sa_len); @@ -1726,6 +1725,9 @@ static void manager_setup_bus(Manager *m) { assert(m); + if (MANAGER_IS_TEST_RUN(m)) + return; + /* Let's set up our private bus connection now, unconditionally */ (void) bus_init_private(m); @@ -1802,11 +1804,31 @@ } } +static int manager_make_runtime_dir(Manager *m) { + int r; + + assert(m); + + _cleanup_free_ char *d = path_join(m->prefix[EXEC_DIRECTORY_RUNTIME], "systemd"); + if (!d) + return log_oom(); + + r = mkdir_label(d, 0755); + if (r < 0 && r != -EEXIST) + return log_error_errno(r, "Failed to create directory '%s/': %m", d); + + return 0; +} + int manager_startup(Manager *m, FILE *serialization, FDSet *fds, const char *root) { int r; assert(m); + r = manager_make_runtime_dir(m); + if (r < 0) + return r; + /* If we are running in test mode, we still want to run the generators, * but we should not touch the real generator directories. */ r = lookup_paths_init_or_warn(&m->lookup_paths, m->unit_file_scope, diff -Nru systemd-252.36/src/core/meson.build systemd-252.38/src/core/meson.build --- systemd-252.36/src/core/meson.build 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/core/meson.build 2025-05-29 17:44:54.000000000 +0000 @@ -234,9 +234,11 @@ install_data('org.freedesktop.systemd1.service', install_dir : dbussystemservicedir) +meson.add_install_script('sh', '-c', mkdir_p.format(systemenvgeneratordir)) meson.add_install_script('sh', '-c', mkdir_p.format(systemshutdowndir)) meson.add_install_script('sh', '-c', mkdir_p.format(systemsleepdir)) meson.add_install_script('sh', '-c', mkdir_p.format(systemgeneratordir)) +meson.add_install_script('sh', '-c', mkdir_p.format(userenvgeneratordir)) meson.add_install_script('sh', '-c', mkdir_p.format(usergeneratordir)) if install_sysconfdir diff -Nru systemd-252.36/src/core/socket.c systemd-252.38/src/core/socket.c --- systemd-252.36/src/core/socket.c 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/core/socket.c 2025-05-29 17:44:54.000000000 +0000 @@ -2292,8 +2292,12 @@ if (p->fd < 0) continue; - (void) flush_accept(p->fd); - (void) flush_fd(p->fd); + if (p->type == SOCKET_MQUEUE) + (void) flush_mqueue(p->fd); + else { + (void) flush_accept(p->fd); + (void) flush_fd(p->fd); + } } } diff -Nru systemd-252.36/src/coredump/coredump.c systemd-252.38/src/coredump/coredump.c --- systemd-252.36/src/coredump/coredump.c 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/coredump/coredump.c 2025-05-29 17:44:54.000000000 +0000 @@ -79,7 +79,7 @@ * size. See DATA_SIZE_MAX in journal-importer.h. */ assert_cc(JOURNAL_SIZE_MAX <= DATA_SIZE_MAX); -enum { +typedef enum { /* We use these as array indexes for our process metadata cache. * * The first indices of the cache stores the same metadata as the ones passed by @@ -92,7 +92,12 @@ META_ARGV_SIGNAL, /* %s: number of signal causing dump */ META_ARGV_TIMESTAMP, /* %t: time of dump, expressed as seconds since the Epoch (we expand this to µs granularity) */ META_ARGV_RLIMIT, /* %c: core file size soft resource limit */ - META_ARGV_HOSTNAME, /* %h: hostname */ + _META_ARGV_REQUIRED, + /* The fields below were added to kernel/core_pattern at later points, so they might be missing. */ + META_ARGV_HOSTNAME = _META_ARGV_REQUIRED, /* %h: hostname */ + META_ARGV_DUMPABLE, /* %d: as set by the kernel */ + /* If new fields are added, they should be added here, to maintain compatibility + * with callers which don't know about the new fields. */ _META_ARGV_MAX, /* The following indexes are cached for a couple of special fields we use (and @@ -101,16 +106,15 @@ * environment. */ META_COMM = _META_ARGV_MAX, - _META_MANDATORY_MAX, /* The rest are similar to the previous ones except that we won't fail if one of - * them is missing. */ + * them is missing in a message sent over the socket. */ - META_EXE = _META_MANDATORY_MAX, + META_EXE, META_UNIT, META_PROC_AUXV, _META_MAX -}; +} meta_argv_t; static const char * const meta_field_names[_META_MAX] = { [META_ARGV_PID] = "COREDUMP_PID=", @@ -120,6 +124,7 @@ [META_ARGV_TIMESTAMP] = "COREDUMP_TIMESTAMP=", [META_ARGV_RLIMIT] = "COREDUMP_RLIMIT=", [META_ARGV_HOSTNAME] = "COREDUMP_HOSTNAME=", + [META_ARGV_DUMPABLE] = "COREDUMP_DUMPABLE=", [META_COMM] = "COREDUMP_COMM=", [META_EXE] = "COREDUMP_EXE=", [META_UNIT] = "COREDUMP_UNIT=", @@ -130,6 +135,7 @@ const char *meta[_META_MAX]; size_t meta_size[_META_MAX]; pid_t pid; + unsigned dumpable; bool is_pid1; bool is_journald; } Context; @@ -445,14 +451,16 @@ if (r < 0) return r; - /* We allow access if we got all the data and at_secure is not set and - * the uid/gid matches euid/egid. */ + /* We allow access if dumpable on the command line was exactly 1, we got all the data, + * at_secure is not set, and the uid/gid match euid/egid. */ bool ret = + context->dumpable == 1 && at_secure == 0 && uid != UID_INVALID && euid != UID_INVALID && uid == euid && gid != GID_INVALID && egid != GID_INVALID && gid == egid; - log_debug("Will %s access (uid="UID_FMT " euid="UID_FMT " gid="GID_FMT " egid="GID_FMT " at_secure=%s)", + log_debug("Will %s access (dumpable=%u uid="UID_FMT " euid="UID_FMT " gid="GID_FMT " egid="GID_FMT " at_secure=%s)", ret ? "permit" : "restrict", + context->dumpable, uid, euid, gid, egid, yes_no(at_secure)); return ret; } @@ -1077,7 +1085,6 @@ assert(context); assert(iovw); - assert(iovw->count >= _META_ARGV_MAX); /* The context does not allocate any memory on its own */ @@ -1107,6 +1114,16 @@ if (r < 0) return log_error_errno(r, "Failed to parse PID \"%s\": %m", context->meta[META_ARGV_PID]); + /* The value is set to contents of /proc/sys/fs/suid_dumpable, which we set to 2, + * if the process is marked as not dumpable, see PR_SET_DUMPABLE(2const). */ + if (context->meta[META_ARGV_DUMPABLE]) { + r = safe_atou(context->meta[META_ARGV_DUMPABLE], &context->dumpable); + if (r < 0) + return log_error_errno(r, "Failed to parse dumpable field \"%s\": %m", context->meta[META_ARGV_DUMPABLE]); + if (context->dumpable > 2) + log_notice("Got unexpected %%d/dumpable value %u.", context->dumpable); + } + unit = context->meta[META_UNIT]; context->is_pid1 = streq(context->meta[META_ARGV_PID], "1") || streq_ptr(unit, SPECIAL_INIT_SCOPE); context->is_journald = streq_ptr(unit, SPECIAL_JOURNALD_SERVICE); @@ -1196,12 +1213,24 @@ if (r < 0) goto finish; - /* Make sure we received at least all fields we need. */ - for (int i = 0; i < _META_MANDATORY_MAX; i++) + /* Make sure we received all the expected fields. We support being called by an *older* + * systemd-coredump from the outside, so we require only the basic set of fields that + * was being sent when the support for sending to containers over a socket was added + * in a108c43e36d3ceb6e34efe37c014fc2cda856000. */ + meta_argv_t i; + VA_ARGS_FOREACH(i, + META_ARGV_PID, + META_ARGV_UID, + META_ARGV_GID, + META_ARGV_SIGNAL, + META_ARGV_TIMESTAMP, + META_ARGV_RLIMIT, + META_ARGV_HOSTNAME, + META_COMM) if (!context.meta[i]) { r = log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "A mandatory argument (%i) has not been sent, aborting.", - i); + "Mandatory argument %s not received on socket, aborting.", + meta_field_names[i]); goto finish; } @@ -1282,14 +1311,17 @@ char *t; /* We gather all metadata that were passed via argv[] into an array of iovecs that - * we'll forward to the socket unit */ + * we'll forward to the socket unit. + * + * We require at least _META_ARGV_REQUIRED args, but will accept more. + * We know how to parse _META_ARGV_MAX args. The rest will be ignored. */ - if (argc < _META_ARGV_MAX) + if (argc < _META_ARGV_REQUIRED) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Not enough arguments passed by the kernel (%i, expected %i).", - argc, _META_ARGV_MAX); + "Not enough arguments passed by the kernel (%i, expected between %i and %i).", + argc, _META_ARGV_REQUIRED, _META_ARGV_MAX); - for (int i = 0; i < _META_ARGV_MAX; i++) { + for (int i = 0; i < MIN(argc, _META_ARGV_MAX); i++) { t = argv[i]; diff -Nru systemd-252.36/src/getty-generator/getty-generator.c systemd-252.38/src/getty-generator/getty-generator.c --- systemd-252.36/src/getty-generator/getty-generator.c 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/getty-generator/getty-generator.c 2025-05-29 17:44:54.000000000 +0000 @@ -215,17 +215,17 @@ return r; } - /* Automatically add in a serial getty on the first virtualizer console */ + /* Automatically add a serial getty to each available virtualizer console. */ FOREACH_STRING(j, "hvc0", "xvc0", "hvsi0", "sclp_line0", "ttysclp0", - "3270!tty1") { + "3270/tty1") { _cleanup_free_ char *p = NULL; - p = path_join("/sys/class/tty", j); + p = path_join("/dev", j); if (!p) return -ENOMEM; if (access(p, F_OK) < 0) diff -Nru systemd-252.36/src/home/homed-manager.c systemd-252.38/src/home/homed-manager.c --- systemd-252.36/src/home/homed-manager.c 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/home/homed-manager.c 2025-05-29 17:44:54.000000000 +0000 @@ -543,7 +543,7 @@ if ((FLAGS_SET(req.dqb_valid, QIF_SPACE) && req.dqb_curspace > 0) || (FLAGS_SET(req.dqb_valid, QIF_INODES) && req.dqb_curinodes > 0)) { - log_debug_errno(errno, "Quota reports UID " UID_FMT " occupies disk space on %s.", uid, where); + log_debug("Quota reports UID " UID_FMT " occupies disk space on %s.", uid, where); return 1; } } diff -Nru systemd-252.36/src/home/homework-mount.c systemd-252.38/src/home/homework-mount.c --- systemd-252.36/src/home/homework-mount.c 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/home/homework-mount.c 2025-05-29 17:44:54.000000000 +0000 @@ -142,7 +142,9 @@ } else d = HOME_RUNTIME_WORK_DIR; - (void) mkdir_p(target, 0700); + r = mkdir_p(target, 0700); + if (r < 0) + return log_error_errno(r, "Failed to create directory '%s': %m", target); r = mount_nofollow_verbose(LOG_ERR, d, target, NULL, MS_BIND, NULL); if (r < 0) diff -Nru systemd-252.36/src/initctl/initctl.c systemd-252.38/src/initctl/initctl.c --- systemd-252.36/src/initctl/initctl.c 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/initctl/initctl.c 2025-05-29 17:44:54.000000000 +0000 @@ -324,8 +324,7 @@ n = sd_listen_fds(true); if (n < 0) - return log_error_errno(errno, - "Failed to read listening file descriptors from environment: %m"); + return log_error_errno(n, "Failed to read listening file descriptors from environment: %m"); if (n <= 0 || n > SERVER_FD_MAX) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), diff -Nru systemd-252.36/src/libsystemd/sd-bus/sd-bus.c systemd-252.38/src/libsystemd/sd-bus/sd-bus.c --- systemd-252.36/src/libsystemd/sd-bus/sd-bus.c 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/libsystemd/sd-bus/sd-bus.c 2025-05-29 17:44:54.000000000 +0000 @@ -1717,8 +1717,10 @@ assert_return(user_and_machine, -EINVAL); assert_return(ret, -EINVAL); - /* Shortcut things if we'd end up on this host and as the same user. */ - if (user_and_machine_equivalent(user_and_machine)) + /* Shortcut things if we'd end up on this host and as the same user and have one of the necessary + * environment variables set already. */ + if (user_and_machine_equivalent(user_and_machine) && + (secure_getenv("DBUS_SESSION_BUS_ADDRESS") || secure_getenv("XDG_RUNTIME_DIR"))) return sd_bus_open_user(ret); r = user_and_machine_valid(user_and_machine); diff -Nru systemd-252.36/src/libsystemd/sd-device/test-sd-device.c systemd-252.38/src/libsystemd/sd-device/test-sd-device.c --- systemd-252.36/src/libsystemd/sd-device/test-sd-device.c 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/libsystemd/sd-device/test-sd-device.c 2025-05-29 17:44:54.000000000 +0000 @@ -430,6 +430,8 @@ TEST(sd_device_enumerator_add_match_parent) { _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; sd_device *dev; + /* Some devices have thousands of children. Avoid spending too much time in the double loop below. */ + unsigned iterations = 200; int r; assert_se(sd_device_enumerator_new(&e) >= 0); @@ -447,6 +449,9 @@ const char *syspath; sd_device *parent; + if (iterations-- == 0) + break; + assert_se(sd_device_get_syspath(dev, &syspath) >= 0); r = sd_device_get_parent(dev, &parent); @@ -476,6 +481,8 @@ TEST(sd_device_get_child) { _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; sd_device *dev; + /* Some devices have thousands of children. Avoid spending too much time in the double loop below. */ + unsigned iterations = 3000; int r; assert_se(sd_device_enumerator_new(&e) >= 0); @@ -509,6 +516,9 @@ FOREACH_DEVICE_CHILD_WITH_SUFFIX(parent, child, suffix) { const char *s; + if (iterations-- == 0) + return; + assert_se(child); assert_se(suffix); diff -Nru systemd-252.36/src/shared/calendarspec.c systemd-252.38/src/shared/calendarspec.c --- systemd-252.36/src/shared/calendarspec.c 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/shared/calendarspec.c 2025-05-29 17:44:54.000000000 +0000 @@ -1239,14 +1239,43 @@ return (weekdays_bits & (1 << k)); } +static int tm_compare(const struct tm *t1, const struct tm *t2) { + int r; + + assert(t1); + assert(t2); + + r = CMP(t1->tm_year, t2->tm_year); + if (r != 0) + return r; + + r = CMP(t1->tm_mon, t2->tm_mon); + if (r != 0) + return r; + + r = CMP(t1->tm_mday, t2->tm_mday); + if (r != 0) + return r; + + r = CMP(t1->tm_hour, t2->tm_hour); + if (r != 0) + return r; + + r = CMP(t1->tm_min, t2->tm_min); + if (r != 0) + return r; + + return CMP(t1->tm_sec, t2->tm_sec); +} + /* A safety valve: if we get stuck in the calculation, return an error. * C.f. https://bugzilla.redhat.com/show_bug.cgi?id=1941335. */ #define MAX_CALENDAR_ITERATIONS 1000 static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) { struct tm c; - int tm_usec; - int r; + int tm_usec, r; + bool invalidate_dst = false; /* Returns -ENOENT if the expression is not going to elapse anymore */ @@ -1259,7 +1288,8 @@ for (unsigned iteration = 0; iteration < MAX_CALENDAR_ITERATIONS; iteration++) { /* Normalize the current date */ (void) mktime_or_timegm(&c, spec->utc); - c.tm_isdst = spec->dst; + if (!invalidate_dst) + c.tm_isdst = spec->dst; c.tm_year += 1900; r = find_matching_component(spec, spec->year, &c, &c.tm_year); @@ -1349,6 +1379,18 @@ if (r == 0) continue; + r = tm_compare(tm, &c); + if (r == 0) { + assert(tm_usec + 1 <= 1000000); + r = CMP(*usec, (usec_t) tm_usec + 1); + } + if (r >= 0) { + /* We're stuck - advance, let mktime determine DST transition and try again. */ + invalidate_dst = true; + c.tm_hour++; + continue; + } + *tm = c; *usec = tm_usec; return 0; diff -Nru systemd-252.36/src/shared/pager.c systemd-252.38/src/shared/pager.c --- systemd-252.36/src/shared/pager.c 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/shared/pager.c 2025-05-29 17:44:54.000000000 +0000 @@ -83,6 +83,22 @@ return r; } +static bool running_with_escalated_privileges(void) { + int r; + + if (getenv("SUDO_UID")) + return true; + + uid_t uid; + r = sd_pid_get_owner_uid(0, &uid); + if (r < 0) { + log_debug_errno(r, "sd_pid_get_owner_uid() failed, enabling pager secure mode: %m"); + return true; + } + + return uid != geteuid(); +} + void pager_open(PagerFlags flags) { _cleanup_close_pair_ int fd[2] = { -1, -1 }, exe_name_pipe[2] = { -1, -1 }; _cleanup_strv_free_ char **pager_args = NULL; @@ -178,16 +194,9 @@ * know to be good. */ int use_secure_mode = getenv_bool_secure("SYSTEMD_PAGERSECURE"); bool trust_pager = use_secure_mode >= 0; - if (use_secure_mode == -ENXIO) { - uid_t uid; - - r = sd_pid_get_owner_uid(0, &uid); - if (r < 0) - log_debug_errno(r, "sd_pid_get_owner_uid() failed, enabling pager secure mode: %m"); - - use_secure_mode = r < 0 || uid != geteuid(); - - } else if (use_secure_mode < 0) { + if (use_secure_mode == -ENXIO) + use_secure_mode = running_with_escalated_privileges(); + else if (use_secure_mode < 0) { log_warning_errno(use_secure_mode, "Unable to parse $SYSTEMD_PAGERSECURE, assuming true: %m"); use_secure_mode = true; } diff -Nru systemd-252.36/src/test/test-calendarspec.c systemd-252.38/src/test/test-calendarspec.c --- systemd-252.36/src/test/test-calendarspec.c 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/test/test-calendarspec.c 2025-05-29 17:44:54.000000000 +0000 @@ -48,7 +48,7 @@ if (old_tz) old_tz = strdupa_safe(old_tz); - if (!isempty(new_tz)) + if (!isempty(new_tz) && !strchr(new_tz, ',')) new_tz = strjoina(":", new_tz); assert_se(set_unset_env("TZ", new_tz, true) == 0); @@ -225,6 +225,8 @@ /* Check that we don't start looping if mktime() moves us backwards */ test_next("Sun *-*-* 01:00:00 Europe/Dublin", "", 1616412478000000, 1617494400000000); test_next("Sun *-*-* 01:00:00 Europe/Dublin", "IST", 1616412478000000, 1617494400000000); + /* Europe/Dublin TZ that moves DST backwards */ + test_next("hourly", "IST-1GMT-0,M10.5.0/1,M3.5.0/1", 1743292800000000, 1743296400000000); } TEST(calendar_spec_from_string) { diff -Nru systemd-252.36/src/test/test-macro.c systemd-252.38/src/test/test-macro.c --- systemd-252.36/src/test/test-macro.c 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/test/test-macro.c 2025-05-29 17:44:54.000000000 +0000 @@ -290,6 +290,190 @@ assert_se(k == 11); } +TEST(foreach_va_args) { + size_t i; + + i = 0; + uint8_t u8, u8_1 = 1, u8_2 = 2, u8_3 = 3; + VA_ARGS_FOREACH(u8, u8_2, 8, 0xff, u8_1, u8_3, 0, 1) { + switch(i++) { + case 0: assert_se(u8 == u8_2); break; + case 1: assert_se(u8 == 8); break; + case 2: assert_se(u8 == 0xff); break; + case 3: assert_se(u8 == u8_1); break; + case 4: assert_se(u8 == u8_3); break; + case 5: assert_se(u8 == 0); break; + case 6: assert_se(u8 == 1); break; + default: assert_se(false); + } + } + assert_se(i == 7); + i = 0; + VA_ARGS_FOREACH(u8, 0) { + assert_se(u8 == 0); + assert_se(i++ == 0); + } + assert_se(i == 1); + i = 0; + VA_ARGS_FOREACH(u8, 0xff) { + assert_se(u8 == 0xff); + assert_se(i++ == 0); + } + assert_se(i == 1); + VA_ARGS_FOREACH(u8) + assert_se(false); + + i = 0; + uint32_t u32, u32_1 = 0xffff0000, u32_2 = 10, u32_3 = 0xffff; + VA_ARGS_FOREACH(u32, 1, 100, u32_2, 1000, u32_3, u32_1, 1, 0) { + switch(i++) { + case 0: assert_se(u32 == 1); break; + case 1: assert_se(u32 == 100); break; + case 2: assert_se(u32 == u32_2); break; + case 3: assert_se(u32 == 1000); break; + case 4: assert_se(u32 == u32_3); break; + case 5: assert_se(u32 == u32_1); break; + case 6: assert_se(u32 == 1); break; + case 7: assert_se(u32 == 0); break; + default: assert_se(false); + } + } + assert_se(i == 8); + i = 0; + VA_ARGS_FOREACH(u32, 0) { + assert_se(u32 == 0); + assert_se(i++ == 0); + } + assert_se(i == 1); + i = 0; + VA_ARGS_FOREACH(u32, 1000) { + assert_se(u32 == 1000); + assert_se(i++ == 0); + } + assert_se(i == 1); + VA_ARGS_FOREACH(u32) + assert_se(false); + + i = 0; + uint64_t u64, u64_1 = 0xffffffffffffffff, u64_2 = 50, u64_3 = 0xffff; + VA_ARGS_FOREACH(u64, 44, 0, u64_3, 100, u64_2, u64_1, 50000) { + switch(i++) { + case 0: assert_se(u64 == 44); break; + case 1: assert_se(u64 == 0); break; + case 2: assert_se(u64 == u64_3); break; + case 3: assert_se(u64 == 100); break; + case 4: assert_se(u64 == u64_2); break; + case 5: assert_se(u64 == u64_1); break; + case 6: assert_se(u64 == 50000); break; + default: assert_se(false); + } + } + assert_se(i == 7); + i = 0; + VA_ARGS_FOREACH(u64, 0) { + assert_se(u64 == 0); + assert_se(i++ == 0); + } + assert_se(i == 1); + i = 0; + VA_ARGS_FOREACH(u64, 0xff00ff00000000) { + assert_se(u64 == 0xff00ff00000000); + assert_se(i++ == 0); + } + assert_se(i == 1); + VA_ARGS_FOREACH(u64) + assert_se(false); + + struct test { + int a; + char b; + }; + + i = 0; + struct test s, + s_1 = { .a = 0, .b = 'c', }, + s_2 = { .a = 100000, .b = 'z', }, + s_3 = { .a = 0xff, .b = 'q', }, + s_4 = { .a = 1, .b = 'x', }; + VA_ARGS_FOREACH(s, s_1, (struct test){ .a = 10, .b = 'd', }, s_2, (struct test){}, s_3, s_4) { + switch(i++) { + case 0: assert_se(s.a == 0 ); assert_se(s.b == 'c'); break; + case 1: assert_se(s.a == 10 ); assert_se(s.b == 'd'); break; + case 2: assert_se(s.a == 100000); assert_se(s.b == 'z'); break; + case 3: assert_se(s.a == 0 ); assert_se(s.b == 0 ); break; + case 4: assert_se(s.a == 0xff ); assert_se(s.b == 'q'); break; + case 5: assert_se(s.a == 1 ); assert_se(s.b == 'x'); break; + default: assert_se(false); + } + } + assert_se(i == 6); + i = 0; + VA_ARGS_FOREACH(s, (struct test){ .a = 1, .b = 'A', }) { + assert_se(s.a == 1); + assert_se(s.b == 'A'); + assert_se(i++ == 0); + } + assert_se(i == 1); + VA_ARGS_FOREACH(s) + assert_se(false); + + i = 0; + struct test *p, *p_1 = &s_1, *p_2 = &s_2, *p_3 = &s_3, *p_4 = &s_4; + VA_ARGS_FOREACH(p, p_1, NULL, p_2, p_3, NULL, p_4, NULL) { + switch(i++) { + case 0: assert_se(p == p_1); break; + case 1: assert_se(p == NULL); break; + case 2: assert_se(p == p_2); break; + case 3: assert_se(p == p_3); break; + case 4: assert_se(p == NULL); break; + case 5: assert_se(p == p_4); break; + case 6: assert_se(p == NULL); break; + default: assert_se(false); + } + } + assert_se(i == 7); + i = 0; + VA_ARGS_FOREACH(p, p_3) { + assert_se(p == p_3); + assert_se(i++ == 0); + } + assert_se(i == 1); + VA_ARGS_FOREACH(p) + assert_se(false); + + i = 0; + void *v, *v_1 = p_1, *v_2 = p_2, *v_3 = p_3; + uint32_t *u32p = &u32; + VA_ARGS_FOREACH(v, v_1, NULL, u32p, v_3, p_2, p_4, v_2, NULL) { + switch(i++) { + case 0: assert_se(v == v_1); break; + case 1: assert_se(v == NULL); break; + case 2: assert_se(v == u32p); break; + case 3: assert_se(v == v_3); break; + case 4: assert_se(v == p_2); break; + case 5: assert_se(v == p_4); break; + case 6: assert_se(v == v_2); break; + case 7: assert_se(v == NULL); break; + default: assert_se(false); + } + } + assert_se(i == 8); + i = 0; + VA_ARGS_FOREACH(v, NULL) { + assert_se(v == NULL); + assert_se(i++ == 0); + } + assert_se(i == 1); + i = 0; + VA_ARGS_FOREACH(v, v_1) { + assert_se(v == v_1); + assert_se(i++ == 0); + } + assert_se(i == 1); + VA_ARGS_FOREACH(v) + assert_se(false); +} + TEST(align_to) { assert_se(ALIGN_TO(0, 1) == 0); assert_se(ALIGN_TO(1, 1) == 1); diff -Nru systemd-252.36/src/test/test-specifier.c systemd-252.38/src/test/test-specifier.c --- systemd-252.36/src/test/test-specifier.c 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/test/test-specifier.c 2025-05-29 17:44:54.000000000 +0000 @@ -3,7 +3,9 @@ #include "sd-id128.h" #include "alloc-util.h" +#include "format-util.h" #include "log.h" +#include "process-util.h" #include "specifier.h" #include "stat-util.h" #include "stdio-util.h" @@ -89,25 +91,27 @@ TEST(specifier_real_path) { static const Specifier table[] = { - { 'p', specifier_string, "/dev/initctl" }, - { 'y', specifier_real_path, "/dev/initctl" }, - { 'Y', specifier_real_directory, "/dev/initctl" }, + { 'p', specifier_string, "/dev/fd" }, + { 'y', specifier_real_path, "/dev/fd" }, + { 'Y', specifier_real_directory, "/dev/fd" }, { 'w', specifier_real_path, "/dev/tty" }, { 'W', specifier_real_directory, "/dev/tty" }, {} }; - _cleanup_free_ char *w = NULL; + _cleanup_free_ char *w = NULL, *expected = NULL; int r; r = specifier_printf("p=%p y=%y Y=%Y w=%w W=%W", SIZE_MAX, table, NULL, NULL, &w); - assert_se(r >= 0 || r == -ENOENT); - assert_se(w || r == -ENOENT); - puts(strnull(w)); - - /* /dev/initctl should normally be a symlink to /run/initctl */ - if (files_same("/dev/initctl", "/run/initctl", 0) > 0) - assert_se(streq(w, "p=/dev/initctl y=/run/initctl Y=/run w=/dev/tty W=/dev")); + if (r < 0) { + assert_se(r == -ENOENT); + return (void) log_tests_skipped_errno(r, "/dev/fd and/or /dev/tty do not exist"); + } + + assert_se(asprintf(&expected, + "p=/dev/fd y=/proc/"PID_FMT"/fd Y=/proc/"PID_FMT" w=/dev/tty W=/dev", + getpid_cached(), getpid_cached()) >= 0); + assert_se(streq(w, expected)); } TEST(specifier_real_path_missing_file) { diff -Nru systemd-252.36/src/udev/udevadm-test-builtin.c systemd-252.38/src/udev/udevadm-test-builtin.c --- systemd-252.36/src/udev/udevadm-test-builtin.c 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/src/udev/udevadm-test-builtin.c 2025-05-29 17:44:54.000000000 +0000 @@ -58,16 +58,11 @@ assert_not_reached(); } - arg_command = argv[optind++]; - if (!arg_command) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Command missing."); - - arg_syspath = argv[optind++]; - if (!arg_syspath) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "device is missing."); + if (argc != optind + 2) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Expected two arguments: command string and device path."); + arg_command = ASSERT_PTR(argv[optind]); + arg_syspath = ASSERT_PTR(argv[optind+1]); return 1; } diff -Nru systemd-252.36/sysctl.d/50-coredump.conf.in systemd-252.38/sysctl.d/50-coredump.conf.in --- systemd-252.36/sysctl.d/50-coredump.conf.in 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/sysctl.d/50-coredump.conf.in 2025-05-29 17:44:54.000000000 +0000 @@ -13,7 +13,7 @@ # the core dump. # # See systemd-coredump(8) and core(5). -kernel.core_pattern=|{{ROOTLIBEXECDIR}}/systemd-coredump %P %u %g %s %t %c %h +kernel.core_pattern=|{{ROOTLIBEXECDIR}}/systemd-coredump %P %u %g %s %t %c %h %d # Allow 16 coredumps to be dispatched in parallel by the kernel. # We collect metadata from /proc/%P/, and thus need to make sure the crashed diff -Nru systemd-252.36/test/networkd-test.py systemd-252.38/test/networkd-test.py --- systemd-252.36/test/networkd-test.py 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/test/networkd-test.py 2025-05-29 17:44:54.000000000 +0000 @@ -47,6 +47,12 @@ global tmpmounts """Initialize the environment, and perform sanity checks on it.""" + + if shutil.which('networkctl') is None: + raise unittest.SkipTest('networkd not installed') + if shutil.which('resolvectl') is None: + raise unittest.SkipTest('resolved not installed') + if NETWORKD_WAIT_ONLINE is None: raise OSError(errno.ENOENT, 'systemd-networkd-wait-online not found') diff -Nru systemd-252.36/test/test-network/systemd-networkd-tests.py systemd-252.38/test/test-network/systemd-networkd-tests.py --- systemd-252.36/test/test-network/systemd-networkd-tests.py 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/test/test-network/systemd-networkd-tests.py 2025-05-29 17:44:54.000000000 +0000 @@ -3772,7 +3772,7 @@ output = check_output('tc qdisc show dev dummy98') print(output) self.assertRegex(output, 'qdisc tbf 35: root') - self.assertRegex(output, 'rate 1Gbit burst 5000b peakrate 100Gbit minburst 987500b lat 70(.0)?ms') + self.assertRegex(output, 'rate 1Gbit burst 5000b peakrate 100Gbit minburst (987500b|999200b) lat 70(.0)?ms') @expectedFailureIfModuleIsNotAvailable('sch_teql') def test_qdisc_teql(self): @@ -5767,6 +5767,10 @@ if not os.path.exists(os.path.join(systemd_source_dir, "meson_options.txt")): raise RuntimeError(f"{systemd_source_dir} doesn't appear to be a systemd source tree") + if networkd_bin is None or resolved_bin is None or timesyncd_bin is None: + print("networkd tests require networkd/resolved/timesyncd to be enabled") + sys.exit(77) + use_valgrind = ns.use_valgrind enable_debug = ns.enable_debug asan_options = ns.asan_options diff -Nru systemd-252.36/test/units/testsuite-73.sh systemd-252.38/test/units/testsuite-73.sh --- systemd-252.36/test/units/testsuite-73.sh 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/test/units/testsuite-73.sh 2025-05-29 17:44:54.000000000 +0000 @@ -243,6 +243,10 @@ rm -f /etc/X11/xorg.conf.d/00-keyboard.conf /etc/default/keyboard # set VC keymap + + # Skip lv keymap and friends, otherwise the sanitizer detects heap-buffer-overflow in libxkbcommon. + [[ "$i" =~ ^lv ]] && continue + assert_rc 0 localectl set-keymap "$i" output=$(localectl) diff -Nru systemd-252.36/test/units/testsuite-74.coredump.sh systemd-252.38/test/units/testsuite-74.coredump.sh --- systemd-252.36/test/units/testsuite-74.coredump.sh 1970-01-01 00:00:00.000000000 +0000 +++ systemd-252.38/test/units/testsuite-74.coredump.sh 2025-05-29 17:44:54.000000000 +0000 @@ -0,0 +1,200 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: LGPL-2.1-or-later +set -eux +set -o pipefail + +# Make sure the binary name fits into 15 characters +CORE_TEST_BIN="/tmp/test-dump" +CORE_TEST_UNPRIV_BIN="/tmp/test-usr-dump" +MAKE_DUMP_SCRIPT="/tmp/make-dump" +# Unset $PAGER so we don't have to use --no-pager everywhere +export PAGER= + +at_exit() { + rm -fv -- "$CORE_TEST_BIN" "$CORE_TEST_UNPRIV_BIN" "$MAKE_DUMP_SCRIPT" +} + +trap at_exit EXIT + +if systemd-detect-virt -cq; then + echo "Running in a container, skipping the systemd-coredump test..." + exit 0 +fi + +# To make all coredump entries stored in system.journal. +journalctl --rotate + +# Check that we're the ones to receive coredumps +sysctl kernel.core_pattern | grep systemd-coredump + +# Prepare "fake" binaries for coredumps, so we can properly exercise +# the matching stuff too +cp -vf /bin/sleep "${CORE_TEST_BIN:?}" +cp -vf /bin/sleep "${CORE_TEST_UNPRIV_BIN:?}" +# Simple script that spawns given "fake" binary and then kills it with +# given signal +cat >"${MAKE_DUMP_SCRIPT:?}" <<\EOF +#!/bin/bash -ex + +bin="${1:?}" +sig="${2:?}" + +ulimit -c unlimited +"$bin" infinity & +pid=$! +# Sync with the "fake" binary, so we kill it once it's fully forked off, +# otherwise we might kill it during fork and kernel would then report +# "wrong" binary name (i.e. $MAKE_DUMP_SCRIPT instead of $CORE_TEST_BIN). +# In this case, wait until the "fake" binary (sleep in this case) enters +# the "interruptible sleep" state, at which point it should be ready +# to be sacrificed. +for _ in {0..9}; do + read -ra self_stat <"/proc/$pid/stat" + [[ "${self_stat[2]}" == S ]] && break + sleep .5 +done +kill -s "$sig" "$pid" +# This should always fail +! wait "$pid" +EOF +chmod +x "$MAKE_DUMP_SCRIPT" + +# Privileged stuff +[[ "$(id -u)" -eq 0 ]] +# Trigger a couple of coredumps +"$MAKE_DUMP_SCRIPT" "$CORE_TEST_BIN" "SIGTRAP" +"$MAKE_DUMP_SCRIPT" "$CORE_TEST_BIN" "SIGABRT" +# In the tests we store the coredumps in journals, so let's generate a couple +# with Storage=external as well +mkdir -p /run/systemd/coredump.conf.d/ +printf '[Coredump]\nStorage=external' >/run/systemd/coredump.conf.d/99-external.conf +"$MAKE_DUMP_SCRIPT" "$CORE_TEST_BIN" "SIGTRAP" +"$MAKE_DUMP_SCRIPT" "$CORE_TEST_BIN" "SIGABRT" +rm -fv /run/systemd/coredump.conf.d/99-external.conf +# Wait a bit for the coredumps to get processed +timeout 30 bash -c "while [[ \$(coredumpctl list -q --no-legend $CORE_TEST_BIN | wc -l) -lt 4 ]]; do sleep 1; done" + +coredumpctl +SYSTEMD_LOG_LEVEL=debug coredumpctl +coredumpctl --help +coredumpctl --version +coredumpctl --no-pager --no-legend +coredumpctl --all +coredumpctl -1 +coredumpctl -n 1 +coredumpctl --reverse +coredumpctl -F COREDUMP_EXE +coredumpctl --json=short | jq +coredumpctl --json=pretty | jq +coredumpctl --json=off +coredumpctl --root=/ +coredumpctl --directory=/var/log/journal +coredumpctl --file="/var/log/journal/$(/tmp/core.redirected +test -s /tmp/core.redirected +coredumpctl dump -o /tmp/core.output "${CORE_TEST_BIN##*/}" +test -s /tmp/core.output +rm -f /tmp/core.{output,redirected} + +# Unprivileged stuff +# Related issue: https://github.com/systemd/systemd/issues/26912 +UNPRIV_CMD=(systemd-run --user --wait --pipe -M "testuser@.host" --) +# Trigger a couple of coredumps as an unprivileged user +"${UNPRIV_CMD[@]}" "$MAKE_DUMP_SCRIPT" "$CORE_TEST_UNPRIV_BIN" "SIGTRAP" +"${UNPRIV_CMD[@]}" "$MAKE_DUMP_SCRIPT" "$CORE_TEST_UNPRIV_BIN" "SIGABRT" +# In the tests we store the coredumps in journals, so let's generate a couple +# with Storage=external as well +mkdir -p /run/systemd/coredump.conf.d/ +printf '[Coredump]\nStorage=external' >/run/systemd/coredump.conf.d/99-external.conf +"${UNPRIV_CMD[@]}" "$MAKE_DUMP_SCRIPT" "$CORE_TEST_UNPRIV_BIN" "SIGTRAP" +"${UNPRIV_CMD[@]}" "$MAKE_DUMP_SCRIPT" "$CORE_TEST_UNPRIV_BIN" "SIGABRT" +rm -fv /run/systemd/coredump.conf.d/99-external.conf +# Wait a bit for the coredumps to get processed +timeout 30 bash -c "while [[ \$(coredumpctl list -q --no-legend $CORE_TEST_UNPRIV_BIN | wc -l) -lt 4 ]]; do sleep 1; done" + +# root should see coredumps from both binaries +coredumpctl info "$CORE_TEST_UNPRIV_BIN" +coredumpctl info "${CORE_TEST_UNPRIV_BIN##*/}" +# The test user should see only their own coredumps +"${UNPRIV_CMD[@]}" coredumpctl +"${UNPRIV_CMD[@]}" coredumpctl info "$CORE_TEST_UNPRIV_BIN" +"${UNPRIV_CMD[@]}" coredumpctl info "${CORE_TEST_UNPRIV_BIN##*/}" +(! "${UNPRIV_CMD[@]}" coredumpctl info --all "$CORE_TEST_BIN") +(! "${UNPRIV_CMD[@]}" coredumpctl info --all "${CORE_TEST_BIN##*/}") +# We should have a couple of externally stored coredumps +"${UNPRIV_CMD[@]}" coredumpctl --field=COREDUMP_FILENAME | tee /tmp/coredumpctl.out +grep "/var/lib/systemd/coredump/core" /tmp/coredumpctl.out +rm -f /tmp/coredumpctl.out + +"${UNPRIV_CMD[@]}" coredumpctl debug --debugger=/bin/true "$CORE_TEST_UNPRIV_BIN" +"${UNPRIV_CMD[@]}" coredumpctl debug --debugger=/bin/true --debugger-arguments="-this --does --not 'do anything' -a -t --all" "${CORE_TEST_UNPRIV_BIN##*/}" + +"${UNPRIV_CMD[@]}" coredumpctl dump "$CORE_TEST_UNPRIV_BIN" >/tmp/core.redirected +test -s /tmp/core.redirected +"${UNPRIV_CMD[@]}" coredumpctl dump -o /tmp/core.output "${CORE_TEST_UNPRIV_BIN##*/}" +test -s /tmp/core.output +rm -f /tmp/core.{output,redirected} +(! "${UNPRIV_CMD[@]}" coredumpctl dump "$CORE_TEST_BIN" >/dev/null) + +# --backtrace mode +# Pass one of the existing journal coredump records to systemd-coredump. +# Use our PID as the source to be able to create a PIDFD and to make matching easier. +# systemd-coredump args: PID UID GID SIGNUM TIMESTAMP CORE_SOFT_RLIMIT [HOSTNAME] +journalctl -b -n 1 --output=export --output-fields=MESSAGE,COREDUMP COREDUMP_EXE="/usr/bin/test-dump" | + /usr/lib/systemd/systemd-coredump --backtrace $$ 0 0 6 1679509900 12345 +journalctl -b -n 1 --output=export --output-fields=MESSAGE,COREDUMP COREDUMP_EXE="/usr/bin/test-dump" | + /usr/lib/systemd/systemd-coredump --backtrace $$ 0 0 6 1679509901 12345 mymachine +journalctl -b -n 1 --output=export --output-fields=MESSAGE,COREDUMP COREDUMP_EXE="/usr/bin/test-dump" | + /usr/lib/systemd/systemd-coredump --backtrace $$ 0 0 6 1679509902 12345 youmachine 1 +# Wait a bit for the coredumps to get processed +timeout 30 bash -c "while [[ \$(coredumpctl list -q --no-legend $$ | wc -l) -lt 2 ]]; do sleep 1; done" +coredumpctl info $$ +coredumpctl info COREDUMP_TIMESTAMP=1679509900000000 +coredumpctl info COREDUMP_TIMESTAMP=1679509901000000 +coredumpctl info COREDUMP_HOSTNAME="mymachine" +coredumpctl info COREDUMP_TIMESTAMP=1679509902000000 +coredumpctl info COREDUMP_HOSTNAME="youmachine" +coredumpctl info COREDUMP_DUMPABLE="1" + +# This used to cause a stack overflow +systemd-run -t --property CoredumpFilter=all ls /tmp +systemd-run -t --property CoredumpFilter=default ls /tmp + +(! coredumpctl --hello-world) +(! coredumpctl -n 0) +(! coredumpctl -n -1) +(! coredumpctl --file=/dev/null) +(! coredumpctl --since=0) +(! coredumpctl --until='') +(! coredumpctl --since=today --until=yesterday) +(! coredumpctl --directory=/ --root=/) +(! coredumpctl --json=foo) +(! coredumpctl -F foo -F bar) +(! coredumpctl list 0) +(! coredumpctl list -- -1) +(! coredumpctl list '') +(! coredumpctl info /../.~=) +(! coredumpctl info '') +(! coredumpctl dump --output=/dev/full "$CORE_TEST_BIN") +(! coredumpctl dump --output=/dev/null --output=/dev/null "$CORE_TEST_BIN") +(! coredumpctl debug --debugger=/bin/false) +(! coredumpctl debug --debugger=/bin/true --debugger-arguments='"') diff -Nru systemd-252.36/test/units/testsuite-75.sh systemd-252.38/test/units/testsuite-75.sh --- systemd-252.36/test/units/testsuite-75.sh 2025-03-06 11:43:10.000000000 +0000 +++ systemd-252.38/test/units/testsuite-75.sh 2025-05-29 17:44:54.000000000 +0000 @@ -10,6 +10,11 @@ : >/failed +if ! command -v resolvectl >/dev/null || ! command -v networkctl >/dev/null; then + echo "resolved/networkd not found, skipping..." | tee --append /skipped + exit 77 +fi + RUN_OUT="$(mktemp)" run() { @@ -102,10 +107,13 @@ # Create a trust anchor for resolved with our root zone keymgr . ds | sed 's/ DS/ IN DS/g' >/etc/dnssec-trust-anchors.d/root.positive # Create a bind-compatible trust anchor (for delv) -# Note: the trust-anchors directive is relatively new, so use the original -# managed-keys one until it's widespread enough +# Note: managed-keys was removed in version 9.21, use the newer trust-anchors directive { - echo 'managed-keys {' + if systemd-analyze compare-versions "$(delv -v | awk '{print $2}')" ge 9.21; then + echo 'trust-anchors {' + else + echo 'managed-keys {' + fi keymgr . dnskey | sed -r 's/^\. DNSKEY ([0-9]+ [0-9]+ [0-9]+) (.+)$/. static-key \1 "\2";/g' echo '};' } >/etc/bind.keys