diff --git a/0001-Revert-units-drop-runlevel-0-6-.target.patch b/0001-Revert-units-drop-runlevel-0-6-.target.patch index faf8341..4180211 100644 --- a/0001-Revert-units-drop-runlevel-0-6-.target.patch +++ b/0001-Revert-units-drop-runlevel-0-6-.target.patch @@ -1,7 +1,7 @@ -From 61750e265ce3f7783a8dba831e91140f84ad89f2 Mon Sep 17 00:00:00 2001 +From 27f4f96c4e56744ecbffec0595236e1441278804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 5 Nov 2025 17:52:16 +0100 -Subject: [PATCH 1/3] Revert "units: drop runlevel[0-6].target" +Subject: [PATCH] Revert "units: drop runlevel[0-6].target" This partially reverts commit e58ba80a40fb6e96543d56774a5bc5aa9cdadbf3. The unit are still needed for compat. @@ -10,7 +10,7 @@ The unit are still needed for compat. 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/units/meson.build b/units/meson.build -index 2e04c4aa2b..46eaac4073 100644 +index 4f47a3b2bd..34b3222f11 100644 --- a/units/meson.build +++ b/units/meson.build @@ -1,5 +1,7 @@ @@ -30,7 +30,7 @@ index 2e04c4aa2b..46eaac4073 100644 }, { 'file' : 'halt.target' }, { -@@ -142,7 +144,10 @@ units = [ +@@ -142,14 +144,20 @@ units = [ 'conditions' : ['ENABLE_MACHINED'], }, { 'file' : 'modprobe@.service' }, @@ -39,10 +39,9 @@ index 2e04c4aa2b..46eaac4073 100644 + 'file' : 'multi-user.target', + 'symlinks' : with_runlevels ? ['runlevel2.target', 'runlevel3.target', 'runlevel4.target'] : [], + }, - { - 'file' : 'systemd-mute-console.socket', - 'symlinks' : ['sockets.target.wants/'] -@@ -155,7 +160,10 @@ units = [ + { 'file' : 'network-online.target' }, + { 'file' : 'network-pre.target' }, + { 'file' : 'network.target' }, { 'file' : 'nss-lookup.target' }, { 'file' : 'nss-user-lookup.target' }, { 'file' : 'paths.target' }, @@ -54,7 +53,7 @@ index 2e04c4aa2b..46eaac4073 100644 { 'file' : 'printer.target' }, { 'file' : 'proc-sys-fs-binfmt_misc.automount', -@@ -180,7 +188,7 @@ units = [ +@@ -174,7 +182,7 @@ units = [ }, { 'file' : 'reboot.target', @@ -63,7 +62,7 @@ index 2e04c4aa2b..46eaac4073 100644 }, { 'file' : 'remote-cryptsetup.target', -@@ -200,7 +208,10 @@ units = [ +@@ -194,7 +202,10 @@ units = [ 'symlinks' : ['initrd-root-device.target.wants/'], }, { 'file' : 'rescue.service.in' }, @@ -75,7 +74,7 @@ index 2e04c4aa2b..46eaac4073 100644 { 'file' : 'rpcbind.target' }, { 'file' : 'serial-getty@.service.in' }, { 'file' : 'shutdown.target' }, -@@ -1001,4 +1012,10 @@ else +@@ -972,4 +983,10 @@ else dbussessionservicedir / 'org.freedesktop.systemd1.service')) endif diff --git a/0001-Revert-units-use-PrivateTmp-disconnected-instead-of-.patch b/0001-Revert-units-use-PrivateTmp-disconnected-instead-of-.patch new file mode 100644 index 0000000..eca67f0 --- /dev/null +++ b/0001-Revert-units-use-PrivateTmp-disconnected-instead-of-.patch @@ -0,0 +1,69 @@ +From 0792bb7a9d25a1ab8a5f208f2f5cea8a362dc1c6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Fri, 10 Jan 2025 17:00:08 +0100 +Subject: [PATCH] Revert "units: use PrivateTmp=disconnected instead of 'yes' + if DefaultDependencies=no" + +This reverts commit 1f6e1928488d461d19fd1e4b4d645b0ea5ea8bf5. +--- + units/systemd-coredump@.service.in | 2 +- + units/systemd-oomd.service.in | 2 +- + units/systemd-resolved.service.in | 2 +- + units/systemd-timesyncd.service.in | 2 +- + 4 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/units/systemd-coredump@.service.in b/units/systemd-coredump@.service.in +index c74dc7a5a1..fa3206d07b 100644 +--- a/units/systemd-coredump@.service.in ++++ b/units/systemd-coredump@.service.in +@@ -26,7 +26,7 @@ NoNewPrivileges=yes + OOMScoreAdjust=500 + PrivateDevices=yes + PrivateNetwork=yes +-PrivateTmp=disconnected ++PrivateTmp=yes + ProtectControlGroups=yes + ProtectHome=read-only + ProtectHostname=yes +diff --git a/units/systemd-oomd.service.in b/units/systemd-oomd.service.in +index 670d5e6140..82bd6245f8 100644 +--- a/units/systemd-oomd.service.in ++++ b/units/systemd-oomd.service.in +@@ -37,7 +37,7 @@ MemoryLow=64M + NoNewPrivileges=yes + OOMScoreAdjust=-900 + PrivateDevices=yes +-PrivateTmp=disconnected ++PrivateTmp=yes + ProtectClock=yes + ProtectHome=yes + ProtectHostname=yes +diff --git a/units/systemd-resolved.service.in b/units/systemd-resolved.service.in +index e181b2528a..4aa0788ac4 100644 +--- a/units/systemd-resolved.service.in ++++ b/units/systemd-resolved.service.in +@@ -29,7 +29,7 @@ LockPersonality=yes + MemoryDenyWriteExecute=yes + NoNewPrivileges=yes + PrivateDevices=yes +-PrivateTmp=disconnected ++PrivateTmp=yes + ProtectClock=yes + ProtectControlGroups=yes + ProtectHome=yes +diff --git a/units/systemd-timesyncd.service.in b/units/systemd-timesyncd.service.in +index 835d6327e7..cf233fbffd 100644 +--- a/units/systemd-timesyncd.service.in ++++ b/units/systemd-timesyncd.service.in +@@ -31,7 +31,7 @@ LockPersonality=yes + MemoryDenyWriteExecute=yes + NoNewPrivileges=yes + PrivateDevices=yes +-PrivateTmp=disconnected ++PrivateTmp=yes + ProtectProc=invisible + ProtectControlGroups=yes + ProtectHome=yes +-- +2.47.1 + diff --git a/0001-ssh-generator-split-out-common-helper-function.patch b/0001-ssh-generator-split-out-common-helper-function.patch new file mode 100644 index 0000000..0399535 --- /dev/null +++ b/0001-ssh-generator-split-out-common-helper-function.patch @@ -0,0 +1,155 @@ +From cf18131f96868cd92bf923a4d953b7bbd6e32541 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 18 Nov 2025 11:19:41 +0100 +Subject: [PATCH 1/3] ssh-generator: split out common helper function + +(cherry picked from commit 7e8fe8e29f31e2c35d16ab10b8d7a5d582b38b8c) +--- + src/ssh-generator/meson.build | 17 ++++++++++++++--- + src/ssh-generator/ssh-generator.c | 15 ++++----------- + src/ssh-generator/ssh-issue.c | 16 ++++------------ + src/ssh-generator/ssh-util.c | 23 +++++++++++++++++++++++ + src/ssh-generator/ssh-util.h | 3 +++ + 5 files changed, 48 insertions(+), 26 deletions(-) + create mode 100644 src/ssh-generator/ssh-util.c + create mode 100644 src/ssh-generator/ssh-util.h + +diff --git a/src/ssh-generator/meson.build b/src/ssh-generator/meson.build +index f281a25184..a7162e9b86 100644 +--- a/src/ssh-generator/meson.build ++++ b/src/ssh-generator/meson.build +@@ -3,15 +3,26 @@ + executables += [ + generator_template + { + 'name' : 'systemd-ssh-generator', +- 'sources' : files('ssh-generator.c'), ++ 'sources' : files( ++ 'ssh-generator.c', ++ 'ssh-util.c', ++ ), ++ 'extract' : files( ++ 'ssh-util.c', ++ ), + }, + libexec_template + { + 'name' : 'systemd-ssh-proxy', +- 'sources' : files('ssh-proxy.c'), ++ 'sources' : files( ++ 'ssh-proxy.c', ++ ), + }, + libexec_template + { + 'name' : 'systemd-ssh-issue', +- 'sources' : files('ssh-issue.c'), ++ 'sources' : files( ++ 'ssh-issue.c', ++ ), ++ 'objects' : ['systemd-ssh-generator'], + }, + ] + +diff --git a/src/ssh-generator/ssh-generator.c b/src/ssh-generator/ssh-generator.c +index 778807938b..bf807196ee 100644 +--- a/src/ssh-generator/ssh-generator.c ++++ b/src/ssh-generator/ssh-generator.c +@@ -17,6 +17,7 @@ + #include "socket-netlink.h" + #include "socket-util.h" + #include "special.h" ++#include "ssh-util.h" + #include "string-util.h" + #include "strv.h" + #include "virt.h" +@@ -211,17 +212,9 @@ static int add_vsock_socket( + return 0; + } + +- _cleanup_close_ int vsock_fd = socket(AF_VSOCK, SOCK_STREAM|SOCK_CLOEXEC, 0); +- if (vsock_fd < 0) { +- if (ERRNO_IS_NOT_SUPPORTED(errno)) { +- log_debug("Not creating AF_VSOCK ssh listener, since AF_VSOCK is not available."); +- return 0; +- } +- +- return log_error_errno(errno, "Unable to test if AF_VSOCK is available: %m"); +- } +- +- vsock_fd = safe_close(vsock_fd); ++ r = vsock_open_or_warn(/* ret= */ NULL); ++ if (r <= 0) ++ return r; + + /* Determine the local CID so that we can log it to help users to connect to this VM */ + unsigned local_cid; +diff --git a/src/ssh-generator/ssh-issue.c b/src/ssh-generator/ssh-issue.c +index 68ad66bfd0..9ad9a997bd 100644 +--- a/src/ssh-generator/ssh-issue.c ++++ b/src/ssh-generator/ssh-issue.c +@@ -16,6 +16,7 @@ + #include "parse-argument.h" + #include "pretty-print.h" + #include "socket-util.h" ++#include "ssh-util.h" + #include "string-util.h" + #include "tmpfile-util.h" + #include "virt.h" +@@ -135,18 +136,9 @@ static int acquire_cid(unsigned *ret_cid) { + return 0; + } + +- _cleanup_close_ int vsock_fd = socket(AF_VSOCK, SOCK_STREAM|SOCK_CLOEXEC, 0); +- if (vsock_fd < 0) { +- if (ERRNO_IS_NOT_SUPPORTED(errno)) { +- log_debug("Not creating issue file, since AF_VSOCK is not available."); +- *ret_cid = 0; +- return 0; +- } +- +- return log_error_errno(errno, "Unable to test if AF_VSOCK is available: %m"); +- } +- +- vsock_fd = safe_close(vsock_fd); ++ r = vsock_open_or_warn(/* ret= */ NULL); ++ if (r <= 0) ++ return r; + + unsigned local_cid; + r = vsock_get_local_cid(&local_cid); +diff --git a/src/ssh-generator/ssh-util.c b/src/ssh-generator/ssh-util.c +new file mode 100644 +index 0000000000..5723a2bf2a +--- /dev/null ++++ b/src/ssh-generator/ssh-util.c +@@ -0,0 +1,23 @@ ++/* SPDX-License-Identifier: LGPL-2.1-or-later */ ++ ++#include ++#include ++ ++#include "errno-util.h" ++#include "log.h" ++#include "ssh-util.h" ++ ++int vsock_open_or_warn(int *ret) { ++ int fd = RET_NERRNO(socket(AF_VSOCK, SOCK_STREAM|SOCK_CLOEXEC, 0)); ++ if (ERRNO_IS_NEG_NOT_SUPPORTED(fd)) ++ log_debug_errno(fd, "AF_VSOCK is not available, ignoring: %m"); ++ else if (fd < 0) ++ return log_error_errno(fd, "Unable to test if AF_VSOCK is available: %m"); ++ ++ if (ret) ++ *ret = fd; ++ else ++ close(fd); ++ ++ return fd >= 0; ++} +diff --git a/src/ssh-generator/ssh-util.h b/src/ssh-generator/ssh-util.h +new file mode 100644 +index 0000000000..60984a5401 +--- /dev/null ++++ b/src/ssh-generator/ssh-util.h +@@ -0,0 +1,3 @@ ++/* SPDX-License-Identifier: LGPL-2.1-or-later */ ++ ++int vsock_open_or_warn(int *ret); diff --git a/0002-machined-continue-without-resolve.hook-socket.patch b/0002-machined-continue-without-resolve.hook-socket.patch deleted file mode 100644 index 2903c5e..0000000 --- a/0002-machined-continue-without-resolve.hook-socket.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 8d6d86d1d7e45eeae921e88adde55d6524027c96 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= -Date: Wed, 26 Nov 2025 22:29:53 +0100 -Subject: [PATCH 3/3] machined: continue without resolve.hook socket - ---- - src/machine/machined-varlink.c | 12 +++++++++--- - 1 file changed, 9 insertions(+), 3 deletions(-) - -diff --git a/src/machine/machined-varlink.c b/src/machine/machined-varlink.c -index f83cbb8562..0b30cd0531 100644 ---- a/src/machine/machined-varlink.c -+++ b/src/machine/machined-varlink.c -@@ -894,9 +894,15 @@ static int manager_varlink_init_resolve_hook(Manager *m) { - - r = sd_varlink_server_listen_address(s, VARLINK_PATH_MACHINED_RESOLVE_HOOK, - 0666 | SD_VARLINK_SERVER_MODE_MKDIR_0755); -- if (r < 0) -- return log_error_errno(r, "Failed to bind to varlink socket %s: %m", -- VARLINK_PATH_MACHINED_RESOLVE_HOOK); -+ if (r < 0) { -+ bool ignore = ERRNO_IS_NEG_PRIVILEGE(r); -+ log_full_errno(ignore ? LOG_WARNING : LOG_ERR, -+ r, -+ "Failed to bind to varlink socket %s%s: %m", -+ VARLINK_PATH_MACHINED_RESOLVE_HOOK, -+ ignore ? ", ignoring" : ""); -+ return ignore ? 0 : r; -+ } - - r = sd_varlink_server_attach_event(s, m->event, SD_EVENT_PRIORITY_NORMAL); - if (r < 0) diff --git a/0002-ssh-generator-split-out-one-more-helper-function.patch b/0002-ssh-generator-split-out-one-more-helper-function.patch new file mode 100644 index 0000000..a69ab47 --- /dev/null +++ b/0002-ssh-generator-split-out-one-more-helper-function.patch @@ -0,0 +1,110 @@ +From df5380c79fde84a39069c9dc4489103d94a9458f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 18 Nov 2025 11:34:37 +0100 +Subject: [PATCH 2/3] ssh-generator: split out one more helper function + +(cherry picked from commit 8c019224a1ad7dd325da9fd2a4b9ab519534f659) +--- + src/ssh-generator/ssh-generator.c | 12 +++--------- + src/ssh-generator/ssh-issue.c | 16 +--------------- + src/ssh-generator/ssh-util.c | 16 ++++++++++++++++ + src/ssh-generator/ssh-util.h | 1 + + 4 files changed, 21 insertions(+), 24 deletions(-) + +diff --git a/src/ssh-generator/ssh-generator.c b/src/ssh-generator/ssh-generator.c +index bf807196ee..0820ab2de7 100644 +--- a/src/ssh-generator/ssh-generator.c ++++ b/src/ssh-generator/ssh-generator.c +@@ -218,15 +218,9 @@ static int add_vsock_socket( + + /* Determine the local CID so that we can log it to help users to connect to this VM */ + unsigned local_cid; +- r = vsock_get_local_cid(&local_cid); +- if (r < 0) { +- if (ERRNO_IS_DEVICE_ABSENT(r)) { +- log_debug("Not creating AF_VSOCK ssh listener, since /dev/vsock is not available (even though AF_VSOCK is)."); +- return 0; +- } +- +- return log_error_errno(r, "Failed to query local AF_VSOCK CID: %m"); +- } ++ r = vsock_get_local_cid_or_warn(&local_cid); ++ if (r <= 0) ++ return r; + + r = make_sshd_template_unit( + dest, +diff --git a/src/ssh-generator/ssh-issue.c b/src/ssh-generator/ssh-issue.c +index 9ad9a997bd..4ad83924f0 100644 +--- a/src/ssh-generator/ssh-issue.c ++++ b/src/ssh-generator/ssh-issue.c +@@ -15,7 +15,6 @@ + #include "mkdir.h" + #include "parse-argument.h" + #include "pretty-print.h" +-#include "socket-util.h" + #include "ssh-util.h" + #include "string-util.h" + #include "tmpfile-util.h" +@@ -140,20 +139,7 @@ static int acquire_cid(unsigned *ret_cid) { + if (r <= 0) + return r; + +- unsigned local_cid; +- r = vsock_get_local_cid(&local_cid); +- if (r < 0) { +- if (ERRNO_IS_DEVICE_ABSENT(r)) { +- log_debug("Not creating issue file, since /dev/vsock is not available (even though AF_VSOCK is)."); +- *ret_cid = 0; +- return 0; +- } +- +- return log_error_errno(r, "Failed to query local AF_VSOCK CID: %m"); +- } +- +- *ret_cid = local_cid; +- return 1; ++ return vsock_get_local_cid_or_warn(ret_cid); + } + + static int run(int argc, char* argv[]) { +diff --git a/src/ssh-generator/ssh-util.c b/src/ssh-generator/ssh-util.c +index 5723a2bf2a..d414713486 100644 +--- a/src/ssh-generator/ssh-util.c ++++ b/src/ssh-generator/ssh-util.c +@@ -5,6 +5,7 @@ + + #include "errno-util.h" + #include "log.h" ++#include "socket-util.h" + #include "ssh-util.h" + + int vsock_open_or_warn(int *ret) { +@@ -21,3 +22,18 @@ int vsock_open_or_warn(int *ret) { + + return fd >= 0; + } ++ ++int vsock_get_local_cid_or_warn(unsigned *ret) { ++ int r; ++ ++ r = vsock_get_local_cid(ret); ++ if (ERRNO_IS_NEG_DEVICE_ABSENT(r)) { ++ log_debug_errno(r, "/dev/vsock is not available (even though AF_VSOCK is), ignoring: %m"); ++ if (ret) ++ *ret = 0; /* bogus value */ ++ return 0; ++ } ++ if (r < 0) ++ return log_error_errno(r, "Failed to query local AF_VSOCK CID: %m"); ++ return 1; ++} +diff --git a/src/ssh-generator/ssh-util.h b/src/ssh-generator/ssh-util.h +index 60984a5401..2a38e1955e 100644 +--- a/src/ssh-generator/ssh-util.h ++++ b/src/ssh-generator/ssh-util.h +@@ -1,3 +1,4 @@ + /* SPDX-License-Identifier: LGPL-2.1-or-later */ + + int vsock_open_or_warn(int *ret); ++int vsock_get_local_cid_or_warn(unsigned *ret); diff --git a/0003-ssh-generator-suppress-error-message-for-vsock-EADDR.patch b/0003-ssh-generator-suppress-error-message-for-vsock-EADDR.patch new file mode 100644 index 0000000..edb0b0a --- /dev/null +++ b/0003-ssh-generator-suppress-error-message-for-vsock-EADDR.patch @@ -0,0 +1,39 @@ +From 5f97faffa0b5d16be17d2f3f571fcf8312fe4aa9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 18 Nov 2025 11:37:59 +0100 +Subject: [PATCH 3/3] ssh-generator: suppress error message for vsock + EADDRNOTAVAIL + +In logs in the Fedora OpenQA CI: +Nov 17 22:20:06 fedora systemd-ssh-generator[4117]: Failed to query local AF_VSOCK CID: Cannot assign requested address +Nov 17 22:20:06 fedora (generato[4088]: /usr/lib/systemd/system-generators/systemd-ssh-generator failed with exit status 1. +Nov 17 22:20:06 fedora systemd[1]: sshd-vsock.socket: Unit configuration changed while unit was running, and no socket file descriptors are open. Unit not functional until restarted. + +AF_VSOCK is not configured there and systemd-ssh-generator should just exit +quietly. vsock_get_local_cid() already does some logging at debug level, so we +don't need to. + +There is also a second bug, we report modifications to the unit have just +created. I think we have an issue open for this somewhere, but cannot find it. + +(cherry picked from commit 8c3acba63b40cd0ebcb9863804e598744eda0b80) +--- + src/ssh-generator/ssh-util.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/ssh-generator/ssh-util.c b/src/ssh-generator/ssh-util.c +index d414713486..48cb662b71 100644 +--- a/src/ssh-generator/ssh-util.c ++++ b/src/ssh-generator/ssh-util.c +@@ -27,8 +27,9 @@ int vsock_get_local_cid_or_warn(unsigned *ret) { + int r; + + r = vsock_get_local_cid(ret); +- if (ERRNO_IS_NEG_DEVICE_ABSENT(r)) { +- log_debug_errno(r, "/dev/vsock is not available (even though AF_VSOCK is), ignoring: %m"); ++ if (ERRNO_IS_NEG_DEVICE_ABSENT(r) || r == -EADDRNOTAVAIL) { ++ if (ERRNO_IS_NEG_DEVICE_ABSENT(r)) ++ log_debug_errno(r, "/dev/vsock is not available (even though AF_VSOCK is), ignoring: %m"); + if (ret) + *ret = 0; /* bogus value */ + return 0; diff --git a/0003-ukify-omit-.osrel-section-when-os-release-is-empty.patch b/0003-ukify-omit-.osrel-section-when-os-release-is-empty.patch deleted file mode 100644 index 5f4a1dd..0000000 --- a/0003-ukify-omit-.osrel-section-when-os-release-is-empty.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 75890d949f92c412c0936b8536b2e0dc8f7dfb40 Mon Sep 17 00:00:00 2001 -From: Nick Rosbrook -Date: Fri, 19 Dec 2025 11:01:49 -0500 -Subject: [PATCH] ukify: omit .osrel section when --os-release= is empty - -The primary motivation for this is to allow users of ukify to build -UKI-like objects, without having them later be detected as a UKI by -tools like kernel-install and bootctl. - -The common code used by these tools to determine if a PE binary is a UKI -checks that both .osrel and .linux sections are present. Hence, adding -a mechansim to skip .osrel provides a way to avoid being labeled a UKI. ---- - man/ukify.xml | 5 ++++- - src/ukify/test/test_ukify.py | 15 +++++++++++---- - src/ukify/ukify.py | 10 +++++++++- - 3 files changed, 24 insertions(+), 6 deletions(-) - -diff --git a/man/ukify.xml b/man/ukify.xml -index 829761642d..7462c5c92f 100644 ---- a/man/ukify.xml -+++ b/man/ukify.xml -@@ -365,7 +365,10 @@ - The os-release description (the .osrel section). The argument - may be a literal string, or @ followed by a path name. If not specified, the - os-release5 file -- will be picked up from the host system. -+ will be picked up from the host system. If explicitly set to an empty string, the ".osrel" section -+ is omitted from the UKI (this is not recommended in most cases, and causes the resulting artifact -+ to not be recognized as a UKI by other tools like kernel-install -+ and bootctl). - - - -diff --git a/src/ukify/test/test_ukify.py b/src/ukify/test/test_ukify.py -index f75ef0c891..224a38569f 100755 ---- a/src/ukify/test/test_ukify.py -+++ b/src/ukify/test/test_ukify.py -@@ -641,7 +641,7 @@ def test_efi_signing_pesign(kernel_initrd, tmp_path): - - shutil.rmtree(tmp_path) - --def test_inspect(kernel_initrd, tmp_path, capsys): -+def test_inspect(kernel_initrd, tmp_path, capsys, osrel=True): - if kernel_initrd is None: - pytest.skip('linux+initrd not found') - if not shutil.which('sbsign'): -@@ -653,7 +653,7 @@ def test_inspect(kernel_initrd, tmp_path, capsys): - - output = f'{tmp_path}/signed2.efi' - uname_arg='1.2.3' -- osrel_arg='Linux' -+ osrel_arg='Linux' if osrel else '' - cmdline_arg='ARG1 ARG2 ARG3' - - args = [ -@@ -680,8 +680,12 @@ def test_inspect(kernel_initrd, tmp_path, capsys): - - text = capsys.readouterr().out - -- expected_osrel = f'.osrel:\n size: {len(osrel_arg)}' -- assert expected_osrel in text -+ if osrel: -+ expected_osrel = f'.osrel:\n size: {len(osrel_arg)}' -+ assert expected_osrel in text -+ else: -+ assert '.osrel:' not in text -+ - expected_cmdline = f'.cmdline:\n size: {len(cmdline_arg)}' - assert expected_cmdline in text - expected_uname = f'.uname:\n size: {len(uname_arg)}' -@@ -694,6 +698,9 @@ def test_inspect(kernel_initrd, tmp_path, capsys): - - shutil.rmtree(tmp_path) - -+def test_inspect_no_osrel(kernel_initrd, tmp_path, capsys): -+ test_inspect(kernel_initrd, tmp_path, capsys, osrel=False) -+ - @pytest.mark.skipif(not slow_tests, reason='slow') - def test_pcr_signing(kernel_initrd, tmp_path): - if kernel_initrd is None: -diff --git a/src/ukify/ukify.py b/src/ukify/ukify.py -index c98f8e2a5d..b7542c7eca 100755 ---- a/src/ukify/ukify.py -+++ b/src/ukify/ukify.py -@@ -1477,6 +1477,9 @@ def make_uki(opts: UkifyConfig) -> None: - '.profile', - } - -+ if not opts.os_release: -+ to_import.remove('.osrel') -+ - for profile in opts.join_profiles: - pe = pefile.PE(profile, fast_load=True) - prev_len = len(uki.sections) -@@ -2412,7 +2415,12 @@ def finalize_options(opts: argparse.Namespace) -> None: - - opts.os_release = resolve_at_path(opts.os_release) - -- if not opts.os_release and opts.linux: -+ if opts.os_release == '': -+ # If --os-release= with an empty string was passed, treat that as -+ # explicitly disabling the .osrel section, and do not fallback to the -+ # system's os-release files. -+ pass -+ elif opts.os_release is None and opts.linux: - p = Path('/etc/os-release') - if not p.exists(): - p = Path('/usr/lib/os-release') --- -2.52.0 - diff --git a/0004-stub-Fix-NULL-pointer-deref-when-there-are-no-initrd.patch b/0004-stub-Fix-NULL-pointer-deref-when-there-are-no-initrd.patch deleted file mode 100644 index d6f362f..0000000 --- a/0004-stub-Fix-NULL-pointer-deref-when-there-are-no-initrd.patch +++ /dev/null @@ -1,51 +0,0 @@ -From e57e599e6b11039ab6484e5622b3deae20bfd678 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Mon, 12 Jan 2026 14:56:36 +0100 -Subject: [PATCH] stub: Fix NULL pointer deref when there are no initrds - -When n_all_initrds == 0, then all_initrds is unmodified from its initial -value of: - - _cleanup_free_ struct iovec *all_initrds = NULL; - -and in the else block of the "if (n_all_initrds > 1)" the NULL is -dereferenced: - - final_initrd = all_initrds[0]; - -Leading to the stub crashing due to a NULL pointer deref. - -Fix this by initializing final_initrd to all 0s and only -running the else block if (n_all_initrds == 1). ---- - src/boot/stub.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/src/boot/stub.c b/src/boot/stub.c -index 06ecbc7d18..65950262c6 100644 ---- a/src/boot/stub.c -+++ b/src/boot/stub.c -@@ -1302,9 +1302,9 @@ static EFI_STATUS run(EFI_HANDLE image) { - - /* Combine the initrds into one */ - _cleanup_pages_ Pages initrd_pages = {}; -- struct iovec final_initrd; -+ struct iovec final_initrd = {}; - if (n_all_initrds > 1) { -- /* There will always be a base initrd, if this counter is higher, we need to combine them */ -+ /* If there is more then 1 initrd we need to combine them */ - err = combine_initrds(all_initrds, n_all_initrds, &initrd_pages, &final_initrd.iov_len); - if (err != EFI_SUCCESS) - return err; -@@ -1313,7 +1313,7 @@ static EFI_STATUS run(EFI_HANDLE image) { - - /* Given these might be large let's free them explicitly before we pass control to Linux */ - initrds_free(&initrds); -- } else -+ } else if (n_all_initrds == 1) - final_initrd = all_initrds[0]; - - struct iovec kernel = IOVEC_MAKE( --- -2.52.0 - diff --git a/38724.patch b/38724.patch new file mode 100644 index 0000000..c639cd0 --- /dev/null +++ b/38724.patch @@ -0,0 +1,64 @@ +From 5bc3a82e81355a0aa1fd25bb6232145f868fac12 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 26 Aug 2025 15:00:02 +0200 +Subject: [PATCH] debug: disable ioctl(PIDFD_GET_INFO) + +In https://bodhi.fedoraproject.org/updates/FEDORA-2025-a0ce059969 it was +reported that the tests fail: + +> Rootless podman tests all show something like this eventually +> +> OCI runtime error: crun: join keyctl `7509a871d2ab7df6549f5cb5bd2d4daf990cc45c0022f116bd0882966ae53f30`: Disk quota exceeded +> +> Each container creates its own keyring but I assume they get leaked so at one +> point we run our of available keyrings and all following tests fail like +> that. Given I only see this on this update and from looking at the podman +> tests logs it only starts happening after we run a bunch of our own systemd +> services I wonder if systemd maybe leaks keyrings and thus it fails? + +After some very tediuos bisecting, I got the answer that +dcf0ef3f42b0ea12e199540a4088bd582875ddfa is the first bad commit. This doesn't +make much sense. I thought that maybe the answer is wrong somehow, or the fd we +pass in has problems, but everything seems to work correctly. Both +pidfd_get_pid_ioctl and pidfd_get_pid_fdinfo work fine and return the same +answer. Nevertheless, skipping the call to pidfd_get_pid_ioctl makes the +problem go away. + +bisection recipe: +1. compile systemd, systemd-executor, pam_systemd: + $ ninja -C build systemd systemd-executor pam_systemd.so + (Not all intermediate commits compile :) ) +2. use the compiled manager for the user running the tests: + # /etc/systemd/system/user@1000.service.d/override.conf + [Service] + ExecStart= + ExecStart=/home/fedora/src/systemd/build/systemd --user +3. install the new code: + # cp ~fedora/src/systemd/build/pam_systemd.so /usr/lib64/security/ && systemctl restart user@1000 +3. log out and log in again (via ssh) +4. run the test: + $ grep -Ec '[a-f0-9]{64}: empty' /proc/keys && podman run -it fedora date && grep -Ec '[a-f0-9]{64}: empty' /proc/keys + 17 + Tue Aug 26 12:47:44 UTC 2025 + 18 + +It seems that both the pam module and the user manager somehow matter. + +This smells like a kernel bug or some strange race condition. +--- + src/basic/pidfd-util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/basic/pidfd-util.c b/src/basic/pidfd-util.c +index 9910819aa79d9..b317be267f445 100644 +--- a/src/basic/pidfd-util.c ++++ b/src/basic/pidfd-util.c +@@ -74,7 +74,7 @@ int pidfd_get_namespace(int fd, unsigned long ns_type_cmd) { + } + + static int pidfd_get_info(int fd, struct pidfd_info *info) { +- static bool cached_supported = true; ++ static bool cached_supported = false; + + assert(fd >= 0); + assert(info); diff --git a/38769.patch b/38769.patch index 09a7423..35b50e4 100644 --- a/38769.patch +++ b/38769.patch @@ -1,4 +1,4 @@ -From 00d70f36a0866660693347009446b7f872a05bf4 Mon Sep 17 00:00:00 2001 +From e4e1e425394dcef01317c42b34c133768c26b765 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Sat, 30 Aug 2025 13:55:56 +0200 Subject: [PATCH] core: create userdb root directory with correct label @@ -16,18 +16,18 @@ longer is. Regression introduced in 736349958efe34089131ca88950e2e5bb391d36a. 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/core/varlink.c b/src/core/varlink.c -index 99f12c59e5..71a8ffd0e5 100644 +index 8c6b95e31d1d5..110b281842373 100644 --- a/src/core/varlink.c +++ b/src/core/varlink.c -@@ -5,6 +5,7 @@ - #include "constants.h" +@@ -6,6 +6,7 @@ #include "errno-util.h" + #include "json-util.h" #include "manager.h" +#include "mkdir-label.h" #include "path-util.h" #include "pidref.h" #include "string-util.h" -@@ -441,7 +442,11 @@ static int manager_varlink_init_system(Manager *m) { +@@ -424,7 +425,11 @@ static int manager_varlink_init_system(Manager *m) { if (!fresh && varlink_server_contains_socket(m->varlink_server, address)) continue; diff --git a/38922.patch b/38922.patch new file mode 100644 index 0000000..f15a013 --- /dev/null +++ b/38922.patch @@ -0,0 +1,733 @@ +From 993e877cdbd5cc12dcee563e6f4a004c6beac95a Mon Sep 17 00:00:00 2001 +From: gvenugo3 +Date: Tue, 23 Sep 2025 21:16:24 -0700 +Subject: [PATCH 1/7] json: add JSON_BUILD_PAIR_VARIANT_NON_EMPTY macro and fix + typos + +- Add JSON_BUILD_PAIR_VARIANT_NON_EMPTY macro to skip empty JSON objects in output +- Fix comment typos changing "two item" to "two items" throughout +--- + src/libsystemd/sd-json/json-util.h | 2 + + src/libsystemd/sd-json/sd-json.c | 60 +++++++++++++++++++++--------- + 2 files changed, 45 insertions(+), 17 deletions(-) + +diff --git a/src/libsystemd/sd-json/json-util.h b/src/libsystemd/sd-json/json-util.h +index 1b244722b8a3d..47eb7401fef83 100644 +--- a/src/libsystemd/sd-json/json-util.h ++++ b/src/libsystemd/sd-json/json-util.h +@@ -167,6 +167,7 @@ enum { + _JSON_BUILD_PAIR_STRV_NON_EMPTY, + _JSON_BUILD_PAIR_STRV_ENV_PAIR_NON_EMPTY, + _JSON_BUILD_PAIR_VARIANT_NON_NULL, ++ _JSON_BUILD_PAIR_VARIANT_NON_EMPTY, + /* _SD_JSON_BUILD_PAIR_VARIANT_ARRAY_NON_EMPTY, */ + _JSON_BUILD_PAIR_BYTE_ARRAY_NON_EMPTY, + _JSON_BUILD_PAIR_IN4_ADDR_NON_NULL, +@@ -215,6 +216,7 @@ enum { + #define JSON_BUILD_PAIR_STRV_NON_EMPTY(name, l) _JSON_BUILD_PAIR_STRV_NON_EMPTY, (const char*) { name }, (char**) { l } + #define JSON_BUILD_PAIR_STRV_ENV_PAIR_NON_EMPTY(name, l) _JSON_BUILD_PAIR_STRV_ENV_PAIR_NON_EMPTY, (const char*) { name }, (char**) { l } + #define JSON_BUILD_PAIR_VARIANT_NON_NULL(name, v) _JSON_BUILD_PAIR_VARIANT_NON_NULL, (const char*) { name }, (sd_json_variant*) { v } ++#define JSON_BUILD_PAIR_VARIANT_NON_EMPTY(name, v) _JSON_BUILD_PAIR_VARIANT_NON_EMPTY, (const char*) { name }, (sd_json_variant*) { v } + #define JSON_BUILD_PAIR_BYTE_ARRAY_NON_EMPTY(name, v, n) _JSON_BUILD_PAIR_BYTE_ARRAY_NON_EMPTY, (const char*) { name }, (const void*) { v }, (size_t) { n } + #define JSON_BUILD_PAIR_IN4_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_IN4_ADDR_NON_NULL, (const char*) { name }, (const struct in_addr*) { v } + #define JSON_BUILD_PAIR_IN6_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_IN6_ADDR_NON_NULL, (const char*) { name }, (const struct in6_addr*) { v } +diff --git a/src/libsystemd/sd-json/sd-json.c b/src/libsystemd/sd-json/sd-json.c +index 9add7be9a881e..5587e03f7dceb 100644 +--- a/src/libsystemd/sd-json/sd-json.c ++++ b/src/libsystemd/sd-json/sd-json.c +@@ -4434,7 +4434,7 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { + goto finish; + } + +- n_subtract = 2; /* we generated two item */ ++ n_subtract = 2; /* we generated two items */ + + current->expect = EXPECT_OBJECT_KEY; + break; +@@ -4464,7 +4464,7 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { + goto finish; + } + +- n_subtract = 2; /* we generated two item */ ++ n_subtract = 2; /* we generated two items */ + + current->expect = EXPECT_OBJECT_KEY; + break; +@@ -4492,7 +4492,7 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { + goto finish; + } + +- n_subtract = 2; /* we generated two item */ ++ n_subtract = 2; /* we generated two items */ + + current->expect = EXPECT_OBJECT_KEY; + break; +@@ -4519,7 +4519,7 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { + goto finish; + } + +- n_subtract = 2; /* we generated two item */ ++ n_subtract = 2; /* we generated two items */ + + current->expect = EXPECT_OBJECT_KEY; + break; +@@ -4556,7 +4556,7 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { + goto finish; + } + +- n_subtract = 2; /* we generated two item */ ++ n_subtract = 2; /* we generated two items */ + + current->expect = EXPECT_OBJECT_KEY; + break; +@@ -4582,7 +4582,33 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { + add_more = sd_json_variant_ref(v); + } + +- n_subtract = 2; /* we generated two item */ ++ n_subtract = 2; /* we generated two items */ ++ ++ current->expect = EXPECT_OBJECT_KEY; ++ break; ++ } ++ ++ case _JSON_BUILD_PAIR_VARIANT_NON_EMPTY: { ++ sd_json_variant *v; ++ const char *n; ++ ++ if (current->expect != EXPECT_OBJECT_KEY) { ++ r = -EINVAL; ++ goto finish; ++ } ++ ++ n = va_arg(ap, const char *); ++ v = va_arg(ap, sd_json_variant *); ++ ++ if (v && !sd_json_variant_is_blank_object(v) && current->n_suppress == 0) { ++ r = sd_json_variant_new_string(&add, n); ++ if (r < 0) ++ goto finish; ++ ++ add_more = sd_json_variant_ref(v); ++ } ++ ++ n_subtract = 2; /* we generated two items */ + + current->expect = EXPECT_OBJECT_KEY; + break; +@@ -4612,7 +4638,7 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { + goto finish; + } + +- n_subtract = 2; /* we generated two item */ ++ n_subtract = 2; /* we generated two items */ + + current->expect = EXPECT_OBJECT_KEY; + break; +@@ -4640,7 +4666,7 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { + goto finish; + } + +- n_subtract = 2; /* we generated two item */ ++ n_subtract = 2; /* we generated two items */ + + current->expect = EXPECT_OBJECT_KEY; + break; +@@ -4668,7 +4694,7 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { + goto finish; + } + +- n_subtract = 2; /* we generated two item */ ++ n_subtract = 2; /* we generated two items */ + + current->expect = EXPECT_OBJECT_KEY; + break; +@@ -4698,7 +4724,7 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { + goto finish; + } + +- n_subtract = 2; /* we generated two item */ ++ n_subtract = 2; /* we generated two items */ + + current->expect = EXPECT_OBJECT_KEY; + break; +@@ -4726,7 +4752,7 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { + goto finish; + } + +- n_subtract = 2; /* we generated two item */ ++ n_subtract = 2; /* we generated two items */ + + current->expect = EXPECT_OBJECT_KEY; + break; +@@ -4754,7 +4780,7 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { + goto finish; + } + +- n_subtract = 2; /* we generated two item */ ++ n_subtract = 2; /* we generated two items */ + + current->expect = EXPECT_OBJECT_KEY; + break; +@@ -4784,7 +4810,7 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { + goto finish; + } + +- n_subtract = 2; /* we generated two item */ ++ n_subtract = 2; /* we generated two items */ + + current->expect = EXPECT_OBJECT_KEY; + break; +@@ -4814,7 +4840,7 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { + goto finish; + } + +- n_subtract = 2; /* we generated two item */ ++ n_subtract = 2; /* we generated two items */ + + current->expect = EXPECT_OBJECT_KEY; + break; +@@ -4876,7 +4902,7 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { + } + } + +- n_subtract = 2; /* we generated two item */ ++ n_subtract = 2; /* we generated two items */ + + current->expect = EXPECT_OBJECT_KEY; + break; +@@ -4912,7 +4938,7 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { + goto finish; + } + +- n_subtract = 2; /* we generated two item */ ++ n_subtract = 2; /* we generated two items */ + + current->expect = EXPECT_OBJECT_KEY; + break; +@@ -4940,7 +4966,7 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { + goto finish; + } + +- n_subtract = 2; /* we generated two item */ ++ n_subtract = 2; /* we generated two items */ + + current->expect = EXPECT_OBJECT_KEY; + break; + +From c58327a9060855369f68922b9f718d078a13e0c5 Mon Sep 17 00:00:00 2001 +From: gvenugo3 +Date: Thu, 25 Sep 2025 11:23:31 -0700 +Subject: [PATCH 2/7] varlink: refactor parameter handling with asymmetric + encoding + +Rename varlink_sanitize_parameters to varlink_sanitize_incoming_parameters +to clarify its role in handling incoming messages. + +Implement canonical empty parameter encoding where: +- Incoming: NULL/null/empty object all become empty object for compatibility +- Outgoing: Empty parameters omitted entirely via JSON build system + +This avoids modifying caller parameters while maintaining wire format +optimization. +--- + src/libsystemd/sd-varlink/sd-varlink-idl.c | 9 +- + src/libsystemd/sd-varlink/sd-varlink.c | 116 ++++++++------------- + 2 files changed, 48 insertions(+), 77 deletions(-) + +diff --git a/src/libsystemd/sd-varlink/sd-varlink-idl.c b/src/libsystemd/sd-varlink/sd-varlink-idl.c +index 7e6680e0e6052..03ed52f1720b7 100644 +--- a/src/libsystemd/sd-varlink/sd-varlink-idl.c ++++ b/src/libsystemd/sd-varlink/sd-varlink-idl.c +@@ -5,6 +5,7 @@ + #include "alloc-util.h" + #include "ansi-color.h" + #include "extract-word.h" ++#include "json-internal.h" + #include "json-util.h" + #include "log.h" + #include "memstream-util.h" +@@ -1793,11 +1794,9 @@ static int varlink_idl_validate_symbol(const sd_varlink_symbol *symbol, sd_json_ + assert(symbol); + assert(!IN_SET(symbol->symbol_type, _SD_VARLINK_SYMBOL_COMMENT, _SD_VARLINK_INTERFACE_COMMENT)); + +- if (!v) { +- if (reterr_bad_field) +- *reterr_bad_field = NULL; +- return varlink_idl_log(SYNTHETIC_ERRNO(EMEDIUMTYPE), "Null object passed, refusing."); +- } ++ /* Consider a NULL pointer equivalent to an empty object */ ++ if (!v) ++ v = JSON_VARIANT_MAGIC_EMPTY_OBJECT; + + switch (symbol->symbol_type) { + +diff --git a/src/libsystemd/sd-varlink/sd-varlink.c b/src/libsystemd/sd-varlink/sd-varlink.c +index 1666162e89059..dda7a9503b612 100644 +--- a/src/libsystemd/sd-varlink/sd-varlink.c ++++ b/src/libsystemd/sd-varlink/sd-varlink.c +@@ -1061,31 +1061,30 @@ static int varlink_dispatch_disconnect(sd_varlink *v) { + return 1; + } + +-static int varlink_sanitize_parameters(sd_json_variant **v) { ++static int varlink_sanitize_incoming_parameters(sd_json_variant **v) { + int r; +- + assert(v); + +- /* Varlink always wants a parameters list, hence make one if the caller doesn't want any */ +- if (!*v) +- return sd_json_variant_new_object(v, NULL, 0); +- if (sd_json_variant_is_null(*v)) { +- sd_json_variant *empty; +- ++ /* Convert NULL or JSON null to empty object for method handlers (backward compatibility) */ ++ if (!*v || sd_json_variant_is_null(*v)) { ++ _cleanup_(sd_json_variant_unrefp) sd_json_variant *empty = NULL; + r = sd_json_variant_new_object(&empty, NULL, 0); + if (r < 0) + return r; +- ++ /* sd_json_variant_unref() is a NOP if *v is NULL */ + sd_json_variant_unref(*v); +- *v = empty; ++ *v = TAKE_PTR(empty); + return 0; + } ++ ++ /* Ensure we have an object */ + if (!sd_json_variant_is_object(*v)) + return -EINVAL; + + return 0; + } + ++ + static int varlink_dispatch_reply(sd_varlink *v) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *parameters = NULL; + sd_varlink_reply_flags_t flags = 0; +@@ -1146,7 +1145,7 @@ static int varlink_dispatch_reply(sd_varlink *v) { + if (error && FLAGS_SET(flags, SD_VARLINK_REPLY_CONTINUES)) + goto invalid; + +- r = varlink_sanitize_parameters(¶meters); ++ r = varlink_sanitize_incoming_parameters(¶meters); + if (r < 0) + goto invalid; + +@@ -1327,7 +1326,7 @@ static int varlink_dispatch_method(sd_varlink *v) { + if (!method) + goto invalid; + +- r = varlink_sanitize_parameters(¶meters); ++ r = varlink_sanitize_incoming_parameters(¶meters); + if (r < 0) + goto fail; + +@@ -1575,13 +1574,14 @@ _public_ int sd_varlink_get_current_parameters(sd_varlink *v, sd_json_variant ** + if (!v->current) + return -ENODATA; + +- p = sd_json_variant_by_key(v->current, "parameters"); +- if (!p) +- return -ENODATA; ++ if (!ret) ++ return 0; + +- if (ret) +- *ret = sd_json_variant_ref(p); ++ p = sd_json_variant_by_key(v->current, "parameters"); ++ if (!p || sd_json_variant_is_null(p)) ++ return sd_json_variant_new_object(ret, NULL, 0); + ++ *ret = sd_json_variant_ref(p); + return 0; + } + +@@ -2024,14 +2024,10 @@ _public_ int sd_varlink_send(sd_varlink *v, const char *method, sd_json_variant + if (!IN_SET(v->state, VARLINK_IDLE_CLIENT, VARLINK_AWAITING_REPLY)) + return varlink_log_errno(v, SYNTHETIC_ERRNO(EBUSY), "Connection busy."); + +- r = varlink_sanitize_parameters(¶meters); +- if (r < 0) +- return varlink_log_errno(v, r, "Failed to sanitize parameters: %m"); +- + r = sd_json_buildo( + &m, + SD_JSON_BUILD_PAIR("method", SD_JSON_BUILD_STRING(method)), +- SD_JSON_BUILD_PAIR("parameters", SD_JSON_BUILD_VARIANT(parameters)), ++ JSON_BUILD_PAIR_VARIANT_NON_EMPTY("parameters", parameters), + SD_JSON_BUILD_PAIR("oneway", SD_JSON_BUILD_BOOLEAN(true))); + if (r < 0) + return varlink_log_errno(v, r, "Failed to build json message: %m"); +@@ -2076,14 +2072,10 @@ _public_ int sd_varlink_invoke(sd_varlink *v, const char *method, sd_json_varian + if (!IN_SET(v->state, VARLINK_IDLE_CLIENT, VARLINK_AWAITING_REPLY)) + return varlink_log_errno(v, SYNTHETIC_ERRNO(EBUSY), "Connection busy."); + +- r = varlink_sanitize_parameters(¶meters); +- if (r < 0) +- return varlink_log_errno(v, r, "Failed to sanitize parameters: %m"); +- + r = sd_json_buildo( + &m, + SD_JSON_BUILD_PAIR("method", SD_JSON_BUILD_STRING(method)), +- SD_JSON_BUILD_PAIR("parameters", SD_JSON_BUILD_VARIANT(parameters))); ++ JSON_BUILD_PAIR_VARIANT_NON_EMPTY("parameters", parameters)); + if (r < 0) + return varlink_log_errno(v, r, "Failed to build json message: %m"); + +@@ -2130,14 +2122,10 @@ _public_ int sd_varlink_observe(sd_varlink *v, const char *method, sd_json_varia + if (v->state != VARLINK_IDLE_CLIENT) + return varlink_log_errno(v, SYNTHETIC_ERRNO(EBUSY), "Connection busy."); + +- r = varlink_sanitize_parameters(¶meters); +- if (r < 0) +- return varlink_log_errno(v, r, "Failed to sanitize parameters: %m"); +- + r = sd_json_buildo( + &m, + SD_JSON_BUILD_PAIR("method", SD_JSON_BUILD_STRING(method)), +- SD_JSON_BUILD_PAIR("parameters", SD_JSON_BUILD_VARIANT(parameters)), ++ JSON_BUILD_PAIR_VARIANT_NON_EMPTY("parameters", parameters), + SD_JSON_BUILD_PAIR("more", SD_JSON_BUILD_BOOLEAN(true))); + if (r < 0) + return varlink_log_errno(v, r, "Failed to build json message: %m"); +@@ -2195,14 +2183,10 @@ _public_ int sd_varlink_call_full( + * that we can assign a new reply shortly. */ + varlink_clear_current(v); + +- r = varlink_sanitize_parameters(¶meters); +- if (r < 0) +- return varlink_log_errno(v, r, "Failed to sanitize parameters: %m"); +- + r = sd_json_buildo( + &m, + SD_JSON_BUILD_PAIR("method", SD_JSON_BUILD_STRING(method)), +- SD_JSON_BUILD_PAIR("parameters", SD_JSON_BUILD_VARIANT(parameters))); ++ JSON_BUILD_PAIR_VARIANT_NON_EMPTY("parameters", parameters)); + if (r < 0) + return varlink_log_errno(v, r, "Failed to build json message: %m"); + +@@ -2353,14 +2337,10 @@ _public_ int sd_varlink_collect_full( + * that we can assign a new reply shortly. */ + varlink_clear_current(v); + +- r = varlink_sanitize_parameters(¶meters); +- if (r < 0) +- return varlink_log_errno(v, r, "Failed to sanitize parameters: %m"); +- + r = sd_json_buildo( + &m, + SD_JSON_BUILD_PAIR("method", SD_JSON_BUILD_STRING(method)), +- SD_JSON_BUILD_PAIR("parameters", SD_JSON_BUILD_VARIANT(parameters)), ++ JSON_BUILD_PAIR_VARIANT_NON_EMPTY("parameters", parameters), + SD_JSON_BUILD_PAIR("more", SD_JSON_BUILD_BOOLEAN(true))); + if (r < 0) + return varlink_log_errno(v, r, "Failed to build json message: %m"); +@@ -2501,14 +2481,7 @@ _public_ int sd_varlink_reply(sd_varlink *v, sd_json_variant *parameters) { + VARLINK_PENDING_METHOD, VARLINK_PENDING_METHOD_MORE)) + return -EBUSY; + +- r = varlink_sanitize_parameters(¶meters); +- if (r < 0) +- return varlink_log_errno(v, r, "Failed to sanitize parameters: %m"); +- +- r = sd_json_buildo(&m, SD_JSON_BUILD_PAIR("parameters", SD_JSON_BUILD_VARIANT(parameters))); +- if (r < 0) +- return varlink_log_errno(v, r, "Failed to build json message: %m"); +- ++ /* Validate parameters BEFORE sanitization */ + if (v->current_method) { + const char *bad_field = NULL; + +@@ -2519,6 +2492,10 @@ _public_ int sd_varlink_reply(sd_varlink *v, sd_json_variant *parameters) { + v->current_method->name, strna(bad_field)); + } + ++ r = sd_json_buildo(&m, JSON_BUILD_PAIR_VARIANT_NON_EMPTY("parameters", parameters)); ++ if (r < 0) ++ return varlink_log_errno(v, r, "Failed to build json message: %m"); ++ + r = varlink_enqueue_json(v, m); + if (r < 0) + return varlink_log_errno(v, r, "Failed to enqueue json message: %m"); +@@ -2588,17 +2565,7 @@ _public_ int sd_varlink_error(sd_varlink *v, const char *error_id, sd_json_varia + * the callers don't need to do this explicitly. */ + sd_varlink_reset_fds(v); + +- r = varlink_sanitize_parameters(¶meters); +- if (r < 0) +- return varlink_log_errno(v, r, "Failed to sanitize parameters: %m"); +- +- r = sd_json_buildo( +- &m, +- SD_JSON_BUILD_PAIR("error", SD_JSON_BUILD_STRING(error_id)), +- SD_JSON_BUILD_PAIR("parameters", SD_JSON_BUILD_VARIANT(parameters))); +- if (r < 0) +- return varlink_log_errno(v, r, "Failed to build json message: %m"); +- ++ /* Validate parameters BEFORE sanitization */ + sd_varlink_symbol *symbol = hashmap_get(v->server->symbols, error_id); + if (!symbol) + varlink_log(v, "No interface description defined for error '%s', not validating.", error_id); +@@ -2612,6 +2579,13 @@ _public_ int sd_varlink_error(sd_varlink *v, const char *error_id, sd_json_varia + error_id, strna(bad_field)); + } + ++ r = sd_json_buildo( ++ &m, ++ SD_JSON_BUILD_PAIR("error", SD_JSON_BUILD_STRING(error_id)), ++ JSON_BUILD_PAIR_VARIANT_NON_EMPTY("parameters", parameters)); ++ if (r < 0) ++ return varlink_log_errno(v, r, "Failed to build json message: %m"); ++ + r = varlink_enqueue_json(v, m); + if (r < 0) + return varlink_log_errno(v, r, "Failed to enqueue json message: %m"); +@@ -2726,17 +2700,7 @@ _public_ int sd_varlink_notify(sd_varlink *v, sd_json_variant *parameters) { + if (!IN_SET(v->state, VARLINK_PROCESSING_METHOD_MORE, VARLINK_PENDING_METHOD_MORE)) + return varlink_log_errno(v, SYNTHETIC_ERRNO(EBUSY), "Connection busy."); + +- r = varlink_sanitize_parameters(¶meters); +- if (r < 0) +- return varlink_log_errno(v, r, "Failed to sanitize parameters: %m"); +- +- r = sd_json_buildo( +- &m, +- SD_JSON_BUILD_PAIR("parameters", SD_JSON_BUILD_VARIANT(parameters)), +- SD_JSON_BUILD_PAIR("continues", SD_JSON_BUILD_BOOLEAN(true))); +- if (r < 0) +- return varlink_log_errno(v, r, "Failed to build json message: %m"); +- ++ /* Validate parameters BEFORE sanitization */ + if (v->current_method) { + const char *bad_field = NULL; + +@@ -2750,6 +2714,13 @@ _public_ int sd_varlink_notify(sd_varlink *v, sd_json_variant *parameters) { + v->current_method->name, strna(bad_field)); + } + ++ r = sd_json_buildo( ++ &m, ++ JSON_BUILD_PAIR_VARIANT_NON_EMPTY("parameters", parameters), ++ SD_JSON_BUILD_PAIR("continues", SD_JSON_BUILD_BOOLEAN(true))); ++ if (r < 0) ++ return varlink_log_errno(v, r, "Failed to build json message: %m"); ++ + r = varlink_enqueue_json(v, m); + if (r < 0) + return varlink_log_errno(v, r, "Failed to enqueue json message: %m"); +@@ -2783,6 +2754,7 @@ _public_ int sd_varlink_dispatch(sd_varlink *v, sd_json_variant *parameters, con + + /* A wrapper around json_dispatch_full() that returns a nice InvalidParameter error if we hit a problem with some field. */ + ++ /* sd_json_dispatch_full() now handles NULL parameters gracefully */ + r = sd_json_dispatch_full(parameters, dispatch_table, /* bad= */ NULL, /* flags= */ 0, userdata, &bad_field); + if (r < 0) { + if (bad_field) + +From dfe8fe44ee427aaffd82daae960c7c4090d47858 Mon Sep 17 00:00:00 2001 +From: gvenugo3 +Date: Thu, 25 Sep 2025 11:23:42 -0700 +Subject: [PATCH 3/7] varlink: add parameter validation to systemd service + handler + +Add assertion in systemd service handler to ensure parameters are +non-null after sanitization, providing early detection of invalid +parameter handling. +--- + src/shared/varlink-io.systemd.service.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/shared/varlink-io.systemd.service.c b/src/shared/varlink-io.systemd.service.c +index d130f0df51a5e..8cbf299e07baa 100644 +--- a/src/shared/varlink-io.systemd.service.c ++++ b/src/shared/varlink-io.systemd.service.c +@@ -47,6 +47,7 @@ int varlink_method_ping(sd_varlink *link, sd_json_variant *parameters, sd_varlin + int r; + + assert(link); ++ assert(parameters); + + r = sd_varlink_dispatch(link, parameters, /* dispatch_table= */ NULL, /* userdata= */ NULL); + if (r != 0) + +From 9fa2f9ebf3d9c1c9f317afbd5e94d8f7c17991ed Mon Sep 17 00:00:00 2001 +From: gvenugo3 +Date: Thu, 25 Sep 2025 11:23:54 -0700 +Subject: [PATCH 4/7] varlink: update tests for canonical empty parameter + handling + +Update test overload handling to verify NULL parameters are properly +handled for disconnect errors, ensuring test coverage of the new +canonical encoding behavior. +--- + src/test/test-varlink.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/test/test-varlink.c b/src/test/test-varlink.c +index b298b9cfbfed7..c853eb41d0afe 100644 +--- a/src/test/test-varlink.c ++++ b/src/test/test-varlink.c +@@ -205,6 +205,9 @@ static int overload_reply(sd_varlink *link, sd_json_variant *parameters, const c + + log_debug("Over reply triggered with error: %s", strna(error_id)); + ASSERT_STREQ(error_id, SD_VARLINK_ERROR_DISCONNECTED); ++ /* Local disconnect errors carry no parameters. Ensure we propagate ++ * absence as NULL rather than an empty object. */ ++ ASSERT_TRUE(!parameters); + sd_event_exit(sd_varlink_get_event(link), 0); + + return 0; + +From dfb11f713e5a742868e64810e969dc8938c6b52d Mon Sep 17 00:00:00 2001 +From: gvenugo3 +Date: Thu, 25 Sep 2025 11:24:04 -0700 +Subject: [PATCH 5/7] sysext: fix varlink parameter handling + +Update sysext to use proper parameter handling that's compatible with +the new canonical empty parameter encoding. +--- + src/sysext/sysext.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/sysext/sysext.c b/src/sysext/sysext.c +index c8c75d68bd077..957386890cfd3 100644 +--- a/src/sysext/sysext.c ++++ b/src/sysext/sysext.c +@@ -2219,7 +2219,6 @@ static int parse_merge_parameters(sd_varlink *link, sd_json_variant *parameters, + }; + + assert(link); +- assert(parameters); + assert(p); + + return sd_varlink_dispatch(link, parameters, dispatch_table, p); + +From 0c063940acb06a27fd2fd482ffc6058bab576e0c Mon Sep 17 00:00:00 2001 +From: gvenugo3 +Date: Thu, 25 Sep 2025 11:24:40 -0700 +Subject: [PATCH 6/7] man: document canonical empty parameter encoding behavior + +Document the asymmetric parameter handling where receivers accept +multiple formats (omitted/null/empty) for compatibility while senders +use canonical encoding (omit field entirely) for optimization. +--- + man/sd-varlink.xml | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/man/sd-varlink.xml b/man/sd-varlink.xml +index c7cfceb71252f..c57411d5bd867 100644 +--- a/man/sd-varlink.xml ++++ b/man/sd-varlink.xml +@@ -44,6 +44,13 @@ + sd-json3 API for JSON + serialization, deserialization and manipulation. + ++ Canonical encoding rules: sd-varlink omits the "parameters" member in replies, ++ errors, and notifications when there are no parameters to transmit. This reduces message size and ++ avoids ambiguity. Receivers must be tolerant and accept any of the following encodings for the ++ absence of parameters: an omitted "parameters" key (preferred), a JSON null ++ value, or an empty object {}. When decoding, sd-varlink treats JSON null ++ as if the member was omitted. ++ + The varlinkctl1 tool + makes the functionality implemented by sd-varlink available from the command line. + + +From 420241fdd4143818712ef78559db725f3d9f9d3f Mon Sep 17 00:00:00 2001 +From: gvenugo3 +Date: Sun, 28 Sep 2025 21:48:39 -0700 +Subject: [PATCH 7/7] varlink: address reviewer feedback + +- Pass empty object instead of NULL for local errors to ensure + API consistency and allow code to rely on non-null parameters +- Remove spurious empty line +- Restore necessary assertion in sysext parameter validation +- Clarify documentation to specify wire format encoding + +This improves API reliability by guaranteeing parameter objects +are always provided to callbacks, even for local disconnect errors. +--- + man/sd-varlink.xml | 2 +- + src/libsystemd/sd-varlink/sd-varlink.c | 8 ++++++-- + src/sysext/sysext.c | 1 + + src/test/test-varlink.c | 6 +++--- + 4 files changed, 11 insertions(+), 6 deletions(-) + +diff --git a/man/sd-varlink.xml b/man/sd-varlink.xml +index c57411d5bd867..282d6a330ef1f 100644 +--- a/man/sd-varlink.xml ++++ b/man/sd-varlink.xml +@@ -44,7 +44,7 @@ + sd-json3 API for JSON + serialization, deserialization and manipulation. + +- Canonical encoding rules: sd-varlink omits the "parameters" member in replies, ++ Canonical encoding rules: sd-varlink omits the "parameters" member on the wire in replies, + errors, and notifications when there are no parameters to transmit. This reduces message size and + avoids ambiguity. Receivers must be tolerant and accept any of the following encodings for the + absence of parameters: an omitted "parameters" key (preferred), a JSON null +diff --git a/src/libsystemd/sd-varlink/sd-varlink.c b/src/libsystemd/sd-varlink/sd-varlink.c +index dda7a9503b612..e3b9106ac72e7 100644 +--- a/src/libsystemd/sd-varlink/sd-varlink.c ++++ b/src/libsystemd/sd-varlink/sd-varlink.c +@@ -1020,6 +1020,7 @@ static int varlink_test_timeout(sd_varlink *v) { + } + + static int varlink_dispatch_local_error(sd_varlink *v, const char *error) { ++ _cleanup_(sd_json_variant_unrefp) sd_json_variant *empty = NULL; + int r; + + assert(v); +@@ -1028,7 +1029,11 @@ static int varlink_dispatch_local_error(sd_varlink *v, const char *error) { + if (!v->reply_callback) + return 0; + +- r = v->reply_callback(v, NULL, error, SD_VARLINK_REPLY_ERROR|SD_VARLINK_REPLY_LOCAL, v->userdata); ++ r = sd_json_variant_new_object(&empty, NULL, 0); ++ if (r < 0) ++ return r; ++ ++ r = v->reply_callback(v, empty, error, SD_VARLINK_REPLY_ERROR|SD_VARLINK_REPLY_LOCAL, v->userdata); + if (r < 0) + varlink_log_errno(v, r, "Reply callback returned error, ignoring: %m"); + +@@ -1084,7 +1089,6 @@ static int varlink_sanitize_incoming_parameters(sd_json_variant **v) { + return 0; + } + +- + static int varlink_dispatch_reply(sd_varlink *v) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *parameters = NULL; + sd_varlink_reply_flags_t flags = 0; +diff --git a/src/sysext/sysext.c b/src/sysext/sysext.c +index 957386890cfd3..c8c75d68bd077 100644 +--- a/src/sysext/sysext.c ++++ b/src/sysext/sysext.c +@@ -2219,6 +2219,7 @@ static int parse_merge_parameters(sd_varlink *link, sd_json_variant *parameters, + }; + + assert(link); ++ assert(parameters); + assert(p); + + return sd_varlink_dispatch(link, parameters, dispatch_table, p); +diff --git a/src/test/test-varlink.c b/src/test/test-varlink.c +index c853eb41d0afe..0b834fad17dad 100644 +--- a/src/test/test-varlink.c ++++ b/src/test/test-varlink.c +@@ -205,9 +205,9 @@ static int overload_reply(sd_varlink *link, sd_json_variant *parameters, const c + + log_debug("Over reply triggered with error: %s", strna(error_id)); + ASSERT_STREQ(error_id, SD_VARLINK_ERROR_DISCONNECTED); +- /* Local disconnect errors carry no parameters. Ensure we propagate +- * absence as NULL rather than an empty object. */ +- ASSERT_TRUE(!parameters); ++ /* Local disconnect errors carry empty parameters. Ensure we propagate ++ * a consistent empty object for API reliability. */ ++ ASSERT_TRUE(sd_json_variant_is_blank_object(parameters)); + sd_event_exit(sd_varlink_get_event(link), 0); + + return 0; diff --git a/plans/run-integration-tests.sh b/plans/run-integration-tests.sh index 6d2ee37..46ea433 100755 --- a/plans/run-integration-tests.sh +++ b/plans/run-integration-tests.sh @@ -66,7 +66,7 @@ WithTests=yes EOF if [[ -n "${MKOSI_REPOSITORIES:-}" ]]; then - tee --append mkosi/mkosi.local.conf <= 1.9.18 -Recommends: systemd-pam%{_isa} = %{version}-%{release} +Requires: dbus >= 1.9.18 +Requires: systemd-pam%{_isa} = %{version}-%{release} Requires(meta): (systemd-rpm-macros = %{version}-%{release} if rpm-build) Requires: systemd-libs%{_isa} = %{version}-%{release} %{?fedora:Recommends: systemd-networkd = %{version}-%{release}} @@ -341,15 +343,11 @@ Provides: /usr/sbin/halt Provides: /usr/sbin/init Provides: /usr/sbin/poweroff Provides: /usr/sbin/reboot +Provides: /usr/sbin/runlevel Provides: /usr/sbin/shutdown +Provides: /usr/sbin/telinit %endif -# libmount is always required, even in containers, so make it a hard dependency. -Requires: libmount.so.1%{?elf_suffix} -Requires: libmount.so.1(MOUNT_2.26)%{?elf_bits} -# Various systemd services have syscall filters so make libseccomp a hard dependency. -Requires: libseccomp.so.2%{?elf_suffix} - # Recommends to replace normal Requires deps for stuff that is dlopen()ed Recommends: libxkbcommon.so.0%{?elf_suffix} Recommends: libidn2.so.0%{?elf_suffix} @@ -493,9 +491,6 @@ Conflicts: systemd-networkd < %{version}-%{release} # want to load modules, so make this into a hard dependency here. Requires: libkmod.so.2%{?elf_suffix} Requires: libkmod.so.2(LIBKMOD_5)%{?elf_bits} -# udev uses libblkid in various builtins so make it a hard dependency. -Requires: libblkid.so.1%{?elf_suffix} -Requires: libblkid.so.1(BLKID_2.30)%{?elf_bits} # Recommends to replace normal Requires deps for stuff that is dlopen()ed # used by dissect, integritysetup, veritysetyp, growfs, repart, cryptenroll, home @@ -771,11 +766,7 @@ main systemd package and is meant for use in exitrds. mv %{_sourcedir}/%{name}.fedora/* %{_sourcedir} %endif -# Automatically figure out the name of the top-level directory. -# TODO: Use %%autosetup -C once we can depend on rpm >= 4.20. -%if %{undefined _build_in_place} -%autosetup -n %(tar -tf %{SOURCE0} 2>/dev/null | head -n1) -p1 -%endif +%autosetup -C -p1 # Disable user lockdown until rpm implements it natively. # https://github.com/rpm-software-management/rpm/issues/3450 @@ -1131,13 +1122,12 @@ mv -v %{buildroot}/usr/sbin/* %{buildroot}%{_bindir}/ # We skip this on upstream builds so that new users and groups # can be added without breaking the build. %if 0%{?fedora} >= 43 -IGNORED=empower \ - %{python3} %{SOURCE4} /usr/lib/sysusers.d/setup.conf %{buildroot}/usr/lib/sysusers.d/basic.conf +%{python3} %{SOURCE4} /usr/lib/sysusers.d/setup.conf %{buildroot}/usr/lib/sysusers.d/basic.conf %else %{python3} %{SOURCE4} /usr/lib/sysusers.d/20-setup-{users,groups}.conf %{buildroot}/usr/lib/sysusers.d/basic.conf %endif %endif -sed -n -r -i '1,7p; /can .do.|empower/p' %{buildroot}/usr/lib/sysusers.d/basic.conf +rm %{buildroot}/usr/lib/sysusers.d/basic.conf %endif # Disable sshd_config.d/20-systemd-userdb.conf for now. diff --git a/test_sysusers_defined.py b/test_sysusers_defined.py index 3c1e04f..f6358fb 100755 --- a/test_sysusers_defined.py +++ b/test_sysusers_defined.py @@ -1,6 +1,5 @@ #!/usr/bin/python -import os import sys def parse_sysusers_file(filename): @@ -31,9 +30,7 @@ for arg in sys.argv[1:-1]: basic_users, basic_groups = parse_sysusers_file(sys.argv[-1]) -ignored = set(os.getenv('IGNORED', '').split()) - -if d := basic_users - setup_users - ignored: +if d := basic_users - setup_users: exit(f'We have new users: {d}') -if d := basic_groups - setup_groups - ignored: +if d := basic_groups - setup_groups: exit(f'We have new groups: {d}')