From 795172d87d1c878742acfad8bfb5ab23904de8f3 Mon Sep 17 00:00:00 2001 From: Alex Cortelyou Date: Sat, 24 Oct 2026 09:57:05 -0700 Subject: [PATCH] Fix systemd-networkd recovery after interface failures Backport systemd's rate-limited failed-interface recovery and its initialized-state and DHCP-client follow-ups, including f8cdd37d0aed8423d6744dd6637955760346939a. Keep each mainline commit in its own patch with original metadata and minimal v255 adaptations. Include separate downstream regression coverage and the upstream OpenSSL test compatibility fix. Synchronize the unsigned and signed boot package releases at 255-35. --- .../systemd-boot-signed.spec | 5 +- ...automatically-reconfigure-on-failure.patch | 76 ++++++++++ ...nk-initialize-before-reconfiguration.patch | 46 ++++++ ...nt-avoid-duplicate-stop-notification.patch | 68 +++++++++ ...handle-stopped-renew-release-decline.patch | 73 +++++++++ SPECS/systemd/systemd.spec | 21 ++- ...work-flip-interface-state-frequently.patch | 59 ++++++++ ...failed-link-and-dhcp-client-recovery.patch | 138 ++++++++++++++++++ ...est-handle-openssl-issuer-whitespace.patch | 38 +++++ 9 files changed, 522 insertions(+), 2 deletions(-) create mode 100644 SPECS/systemd/network-link-automatically-reconfigure-on-failure.patch create mode 100644 SPECS/systemd/network-link-initialize-before-reconfiguration.patch create mode 100644 SPECS/systemd/sd-dhcp-client-avoid-duplicate-stop-notification.patch create mode 100644 SPECS/systemd/sd-dhcp-client-handle-stopped-renew-release-decline.patch create mode 100644 SPECS/systemd/test-network-flip-interface-state-frequently.patch create mode 100644 SPECS/systemd/test-networkd-failed-link-and-dhcp-client-recovery.patch create mode 100644 SPECS/systemd/ukify-test-handle-openssl-issuer-whitespace.patch diff --git a/SPECS-SIGNED/systemd-boot-signed/systemd-boot-signed.spec b/SPECS-SIGNED/systemd-boot-signed/systemd-boot-signed.spec index 73238100e8d..66a46b2171b 100644 --- a/SPECS-SIGNED/systemd-boot-signed/systemd-boot-signed.spec +++ b/SPECS-SIGNED/systemd-boot-signed/systemd-boot-signed.spec @@ -20,7 +20,7 @@ Version: 255 # determine the build information from local checkout Version: %(tools/meson-vcs-tag.sh . error | sed -r 's/-([0-9])/.^\1/; s/-g/_g/') %endif -Release: 34%{?dist} +Release: 35%{?dist} License: LGPL-2.1-or-later AND MIT AND GPL-2.0-or-later Vendor: Microsoft Corporation Distribution: Azure Linux @@ -98,6 +98,9 @@ popd /boot/efi/EFI/BOOT/%{grubefiname} %changelog +* Thu Oct 22 2026 Alex Cortelyou - 255-35 +- Bump release to match systemd spec. + * Mon Aug 17 2026 Aditya Singh - 255-34 - Bump release to match systemd spec. diff --git a/SPECS/systemd/network-link-automatically-reconfigure-on-failure.patch b/SPECS/systemd/network-link-automatically-reconfigure-on-failure.patch new file mode 100644 index 00000000000..6e6d32a1b75 --- /dev/null +++ b/SPECS/systemd/network-link-automatically-reconfigure-on-failure.patch @@ -0,0 +1,76 @@ +From c2eb7753dd47ec04ae0d66400e70bc87fbf1adcc Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Mon, 15 Jan 2024 15:40:54 +0900 +Subject: [PATCH] network/link: automatically reconfigure interface on failure + +Closes #29246. +--- + src/network/networkd-link.c | 20 +++++++++++++++++++- + src/network/networkd-link.h | 2 ++ + 2 files changed, 21 insertions(+), 1 deletion(-) + +diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c +index 4e5ad3c035e2..9e69624fd2b5 100644 +--- a/src/network/networkd-link.c ++++ b/src/network/networkd-link.c +@@ -381,6 +381,8 @@ int link_stop_engines(Link *link, bool may_keep_dhcp) { + } + + void link_enter_failed(Link *link) { ++ int r; ++ + assert(link); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) +@@ -390,7 +392,22 @@ void link_enter_failed(Link *link) { + + link_set_state(link, LINK_STATE_FAILED); + +- (void) link_stop_engines(link, false); ++ if (!ratelimit_below(&link->automatic_reconfigure_ratelimit)) { ++ log_link_warning(link, "The interface entered the failed state frequently, refusing to reconfigure it automatically."); ++ goto stop; ++ } ++ ++ log_link_info(link, "Trying to reconfigure the interface."); ++ r = link_reconfigure(link, /* force = */ true); ++ if (r < 0) { ++ log_link_warning_errno(link, r, "Failed to reconfigure interface: %m"); ++ goto stop; ++ } ++ ++ return; ++ ++stop: ++ (void) link_stop_engines(link, /* may_keep_dhcp = */ false); + } + + void link_check_ready(Link *link) { +@@ -2552,6 +2569,7 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) { + .n_ref = 1, + .state = LINK_STATE_PENDING, + .online_state = _LINK_ONLINE_STATE_INVALID, ++ .automatic_reconfigure_ratelimit = (const RateLimit) { .interval = 10 * USEC_PER_SEC, .burst = 5 }, + .ifindex = ifindex, + .iftype = iftype, + .ifname = TAKE_PTR(ifname), +diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h +index cad9fa841068..05b028dff31d 100644 +--- a/src/network/networkd-link.h ++++ b/src/network/networkd-link.h +@@ -25,6 +25,7 @@ + #include "networkd-ipv6ll.h" + #include "networkd-util.h" + #include "ordered-set.h" ++#include "ratelimit.h" + #include "resolve-util.h" + #include "set.h" + +@@ -106,6 +107,7 @@ typedef struct Link { + LinkAddressState ipv4_address_state; + LinkAddressState ipv6_address_state; + LinkOnlineState online_state; ++ RateLimit automatic_reconfigure_ratelimit; + + unsigned static_address_messages; + unsigned static_address_label_messages; diff --git a/SPECS/systemd/network-link-initialize-before-reconfiguration.patch b/SPECS/systemd/network-link-initialize-before-reconfiguration.patch new file mode 100644 index 00000000000..3571c0a976a --- /dev/null +++ b/SPECS/systemd/network-link-initialize-before-reconfiguration.patch @@ -0,0 +1,46 @@ +From 685fd0d729718aab45a19567a889c8baa2e6cc65 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 21 Aug 2024 07:01:47 +0900 +Subject: [PATCH] network: enter initialized state when the interface will be + reconfigured + +When the interface is in the failed state, link_getlink_handler_internal() +will do nothing and return zero, thus the interface will not be +reconfigured, especially when the reconfiguration is triggered in +link_enter_failed(). + +Follow-up for c2eb7753dd47ec04ae0d66400e70bc87fbf1adcc. +--- +[Backport to v255: omit only the link_reconfigure_on_bus_method_reload() +hunk; that helper does not exist in v255. Retain both other hunks unchanged.] + + src/network/networkd-link-bus.c | 1 - + src/network/networkd-link.c | 3 +++ + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/network/networkd-link-bus.c b/src/network/networkd-link-bus.c +index 84ed42987c51..ef2e81125577 100644 +--- a/src/network/networkd-link-bus.c ++++ b/src/network/networkd-link-bus.c +@@ -669,7 +669,6 @@ int bus_link_method_reconfigure(sd_bus_message *message, void *userdata, sd_bus_ + if (r < 0) + return r; + if (r > 0) { +- link_set_state(l, LINK_STATE_INITIALIZED); + r = link_save_and_clean_full(l, /* also_save_manager = */ true); + if (r < 0) + return r; +diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c +index 3940aa79b37e..2f7aaec2e509 100644 +--- a/src/network/networkd-link.c ++++ b/src/network/networkd-link.c +@@ -1454,6 +1454,9 @@ int link_reconfigure(Link *link, bool force) { + if (r < 0) + return r; + ++ if (force || link->state == LINK_STATE_FAILED) ++ link_set_state(link, LINK_STATE_INITIALIZED); ++ + return 1; /* 1 means the interface will be reconfigured. */ + } + diff --git a/SPECS/systemd/sd-dhcp-client-avoid-duplicate-stop-notification.patch b/SPECS/systemd/sd-dhcp-client-avoid-duplicate-stop-notification.patch new file mode 100644 index 00000000000..07fbc3c2d01 --- /dev/null +++ b/SPECS/systemd/sd-dhcp-client-avoid-duplicate-stop-notification.patch @@ -0,0 +1,68 @@ +From e5b19cbed2032db214eec9a6191866f6f96355ef Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 21 Aug 2024 11:24:14 +0900 +Subject: [PATCH] sd-dhcp-client: do not call callback with + SD_DHCP_CLIENT_EVENT_STOP if already stopped + +When an interface enters the failed state, even if the DHCP client is +stopped, the acquired DHCP lease is not unreferenced, as the callback +dhcp4_handler() do nothing in that case. When the failed interface is +being reconfigured after that, the DHCP client is stopped again +(though it is already stopped), and SD_DHCP_CLIENT_EVENT_STOP event is +triggered and sd_dhcp_client_send_release() is called, and the +assertion in the function is triggered. + +E.g. +=== +systemd-networkd[98588]: wlp59s0: DHCPv4 address 192.168.86.250/24, gateway 192.168.86.1 acquired from 192.168.86.1 +systemd-networkd[98588]: wlp59s0: Could not set DHCPv4 route: Nexthop has invalid gateway. Network is unreachable +systemd-networkd[98588]: wlp59s0: Failed +systemd-networkd[98588]: wlp59s0: State changed: configuring -> failed +systemd-networkd[98588]: wlp59s0: The interface entered the failed state frequently, refusing to reconfigure it automatically. +systemd-networkd[98588]: wlp59s0: DHCPv4 client: STOPPED +systemd-networkd[98588]: wlp59s0: DHCPv4 client: State changed: bound -> stopped +systemd-networkd[98588]: Got message type=method_call sender=:1.449 destination=org.freedesktop.network1 path=/org/freedesktop/network1 interface=org.freedesktop.network1.Manager member=ReconfigureLink ... +systemd-networkd[98588]: wlp59s0: State changed: failed -> initialized +systemd-networkd[98588]: wlp59s0: found matching network '/etc/systemd/network/50-wifi.network'. +systemd-networkd[98588]: wlp59s0: Configuring with /etc/systemd/network/50-wifi.network. +systemd-networkd[98588]: wlp59s0: DHCPv4 client: STOPPED +systemd-networkd[98588]: Assertion 'sd_dhcp_client_is_running(client)' failed at src/libsystemd-network/sd-dhcp-client.c:2197, function sd_dhcp_client_send_release(). Aborting. +=== +--- + src/libsystemd-network/sd-dhcp-client.c | 22 ++++++++++++++-------- + 1 file changed, 14 insertions(+), 8 deletions(-) + +diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c +index 1eb8509f0f6a..8b8d0611a272 100644 +--- a/src/libsystemd-network/sd-dhcp-client.c ++++ b/src/libsystemd-network/sd-dhcp-client.c +@@ -683,15 +683,21 @@ static int client_initialize(sd_dhcp_client *client) { + + static void client_stop(sd_dhcp_client *client, int error) { + assert(client); ++ DHCP_CLIENT_DONT_DESTROY(client); + +- if (error < 0) +- log_dhcp_client_errno(client, error, "STOPPED: %m"); +- else if (error == SD_DHCP_CLIENT_EVENT_STOP) +- log_dhcp_client(client, "STOPPED"); +- else +- log_dhcp_client(client, "STOPPED: Unknown event"); +- +- client_notify(client, error); ++ if (sd_dhcp_client_is_running(client)) { ++ if (error < 0) ++ log_dhcp_client_errno(client, error, "STOPPED: %m"); ++ else if (error == SD_DHCP_CLIENT_EVENT_STOP) ++ log_dhcp_client(client, "STOPPED"); ++ else ++ log_dhcp_client(client, "STOPPED: Unknown event"); ++ ++ client_notify(client, error); ++ } else if (error < 0) { ++ log_dhcp_client_errno(client, error, "FAILED: %m"); ++ client_notify(client, error); ++ } + + client_initialize(client); + } diff --git a/SPECS/systemd/sd-dhcp-client-handle-stopped-renew-release-decline.patch b/SPECS/systemd/sd-dhcp-client-handle-stopped-renew-release-decline.patch new file mode 100644 index 00000000000..ce277bf2a8c --- /dev/null +++ b/SPECS/systemd/sd-dhcp-client-handle-stopped-renew-release-decline.patch @@ -0,0 +1,73 @@ +From f8cdd37d0aed8423d6744dd6637955760346939a Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 21 Aug 2024 10:23:06 +0900 +Subject: [PATCH] sd-dhcp-client: refuse to send RELEASE or friends gracefully + when the daemon is stopped or so + +We can easily hit the assertions without checking the internal states of +the DHCP client before calling these functions. That's annoying. +Let's do more gracefully. +--- +[Backport to v255: the retry counter is named attempt rather than +discover_attempt. Only unchanged context is adjusted.] + + src/libsystemd-network/sd-dhcp-client.c | 24 ++++++++---------------- + 1 file changed, 8 insertions(+), 16 deletions(-) + +diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c +index 8b8d0611a272..94ad5bbea956 100644 +--- a/src/libsystemd-network/sd-dhcp-client.c ++++ b/src/libsystemd-network/sd-dhcp-client.c +@@ -2138,14 +2138,8 @@ static int client_receive_message_raw( + } + + int sd_dhcp_client_send_renew(sd_dhcp_client *client) { +- assert_return(client, -EINVAL); +- assert_return(sd_dhcp_client_is_running(client), -ESTALE); +- assert_return(client->fd >= 0, -EINVAL); +- +- if (client->state != DHCP_STATE_BOUND) +- return 0; +- +- assert(client->lease); ++ if (!sd_dhcp_client_is_running(client) || client->state != DHCP_STATE_BOUND) ++ return 0; /* do nothing */ + + client->start_delay = 0; + client->attempt = 1; +@@ -2199,14 +2193,13 @@ int sd_dhcp_client_start(sd_dhcp_client *client) { + } + + int sd_dhcp_client_send_release(sd_dhcp_client *client) { +- assert_return(client, -EINVAL); +- assert_return(sd_dhcp_client_is_running(client), -ESTALE); +- assert_return(client->lease, -EUNATCH); +- + _cleanup_free_ DHCPPacket *release = NULL; + size_t optoffset, optlen; + int r; + ++ if (!sd_dhcp_client_is_running(client) || !client->lease) ++ return 0; /* do nothing */ ++ + r = client_message_init(client, &release, DHCP_RELEASE, &optlen, &optoffset); + if (r < 0) + return r; +@@ -2234,14 +2227,13 @@ int sd_dhcp_client_send_release(sd_dhcp_client *client) { + } + + int sd_dhcp_client_send_decline(sd_dhcp_client *client) { +- assert_return(client, -EINVAL); +- assert_return(sd_dhcp_client_is_running(client), -ESTALE); +- assert_return(client->lease, -EUNATCH); +- + _cleanup_free_ DHCPPacket *release = NULL; + size_t optoffset, optlen; + int r; + ++ if (!sd_dhcp_client_is_running(client) || !client->lease) ++ return 0; /* do nothing */ ++ + r = client_message_init(client, &release, DHCP_DECLINE, &optlen, &optoffset); + if (r < 0) + return r; diff --git a/SPECS/systemd/systemd.spec b/SPECS/systemd/systemd.spec index bc46e768f95..8b307e5093a 100644 --- a/SPECS/systemd/systemd.spec +++ b/SPECS/systemd/systemd.spec @@ -50,7 +50,7 @@ Version: 255 # determine the build information from local checkout Version: %(tools/meson-vcs-tag.sh . error | sed -r 's/-([0-9])/.^\1/; s/-g/_g/') %endif -Release: 34%{?dist} +Release: 35%{?dist} # FIXME - hardcode to 'stable' for now as that's what we have in our blobstore %global stable 1 @@ -161,6 +161,16 @@ Patch0913: network-also-check-ID_NET_MANAGED_BY-property-on-rec.patch Patch0914: Prevent-corruption-from-stale-alias-state-on-daemon-reload.patch Patch0915: CVE-2026-15059.patch Patch0916: CVE-2026-16742.patch +# PR 30936 and its recovery follow-ups, one upstream commit per patch. +Patch0917: network-link-automatically-reconfigure-on-failure.patch +Patch0918: test-network-flip-interface-state-frequently.patch +Patch0919: network-link-initialize-before-reconfiguration.patch +Patch0920: sd-dhcp-client-avoid-duplicate-stop-notification.patch +Patch0921: sd-dhcp-client-handle-stopped-renew-release-decline.patch +# Downstream regression coverage is separate from the upstream patches. +Patch0922: test-networkd-failed-link-and-dhcp-client-recovery.patch +# Test-only prerequisite for the build environment's OpenSSL output. +Patch0923: ukify-test-handle-openssl-issuer-whitespace.patch %ifarch %{ix86} x86_64 aarch64 %global want_bootloader 1 @@ -1259,6 +1269,15 @@ rm -f %{name}.lang # %autochangelog. So we need to continue manually maintaining the # changelog here. %changelog +* Thu Oct 22 2026 Alex Cortelyou - 255-35 +- Backport upstream PR 30936 to automatically reconfigure failed network interfaces + with rate-limited retries, including the interface-flapping regression test. +- Include upstream failed-state transition, duplicate DHCP STOP notification, + and graceful DHCP renew/release/decline follow-ups from PR 34054. +- Preserve individual upstream commits and keep downstream regression tests + separate; omit the unrelated CAN readiness cleanup. +- Backport the upstream ukify test fix for OpenSSL certificate issuer whitespace. + * Thu Aug 13 2026 Azure Linux Security Servicing Account - 255-34 - Patch for CVE-2026-16742, CVE-2026-15059 diff --git a/SPECS/systemd/test-network-flip-interface-state-frequently.patch b/SPECS/systemd/test-network-flip-interface-state-frequently.patch new file mode 100644 index 00000000000..688333a043d --- /dev/null +++ b/SPECS/systemd/test-network-flip-interface-state-frequently.patch @@ -0,0 +1,59 @@ +From 6d1cea7bc6b26695fa6121e2d4270a30af9af3b3 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Mon, 15 Jan 2024 15:17:57 +0900 +Subject: [PATCH] test-network: try to flip interface state frequently + +--- +[Backport to v255: adjust test context for the older preceding test and +networkctl invocation. All upstream additions and deletions are unchanged.] + + test/test-network/systemd-networkd-tests.py | 25 ++++++++++++++++++--- + 1 file changed, 22 insertions(+), 3 deletions(-) + +diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py +index 161032105312..44970193677f 100755 +--- a/test/test-network/systemd-networkd-tests.py ++++ b/test/test-network/systemd-networkd-tests.py +@@ -12,6 +12,7 @@ + import json + import os + import pathlib ++import random + import re + import shutil + import signal +@@ -4881,6 +4882,4 @@ def test_ipv6_prefix_delegation(self): +- def test_ipv6_token_static(self): +- copy_network_unit('25-veth.netdev', '25-ipv6-prefix.network', '25-ipv6-prefix-veth-token-static.network') +- start_networkd() ++ def check_ipv6_token_static(self): + self.wait_online(['veth99:routable', 'veth-peer:degraded']) + + output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) +@@ -5121,6 +5120,26 @@ def test_ipv6_token_static(self): + self.assertRegex(output, '2002:da8:2:0:1a:2b:3c:4d') + self.assertRegex(output, '2002:da8:2:0:fa:de:ca:fe') + ++ def test_ipv6_token_static(self): ++ copy_network_unit('25-veth.netdev', '25-ipv6-prefix.network', '25-ipv6-prefix-veth-token-static.network') ++ start_networkd() ++ ++ self.check_ipv6_token_static() ++ ++ for _ in range(20): ++ check_output('ip link set veth99 down') ++ check_output('ip link set veth99 up') ++ ++ self.check_ipv6_token_static() ++ ++ for _ in range(20): ++ check_output('ip link set veth99 down') ++ time.sleep(random.uniform(0, 0.1)) ++ check_output('ip link set veth99 up') ++ time.sleep(random.uniform(0, 0.1)) ++ ++ self.check_ipv6_token_static() ++ + def test_ipv6_token_prefixstable(self): + copy_network_unit('25-veth.netdev', '25-ipv6-prefix.network', '25-ipv6-prefix-veth-token-prefixstable.network') + start_networkd() diff --git a/SPECS/systemd/test-networkd-failed-link-and-dhcp-client-recovery.patch b/SPECS/systemd/test-networkd-failed-link-and-dhcp-client-recovery.patch new file mode 100644 index 00000000000..3f8acb2c6d0 --- /dev/null +++ b/SPECS/systemd/test-networkd-failed-link-and-dhcp-client-recovery.patch @@ -0,0 +1,138 @@ +From: Alex Cortelyou +Date: Sat, 24 Oct 2026 08:58:15 -0700 +Subject: [PATCH] test: cover failed-link recovery and stopped DHCP clients + +Azure Linux regression coverage for the automatic reconfiguration, +failed-state transition, duplicate STOP notification, and graceful DHCP +send fixes. Keep downstream coverage separate from the upstream commits. + +Verify that failed-link recovery is rate limited, repeated stops notify +only once, and renew/release/decline are harmless for absent or stopped +clients and for a running client that has not acquired a lease. +--- +diff --git a/src/network/test-network.c b/src/network/test-network.c +--- a/src/network/test-network.c ++++ b/src/network/test-network.c +@@ -11,6 +11,7 @@ + #include "hostname-setup.h" + #include "network-internal.h" + #include "networkd-address.h" ++#include "networkd-link.h" + #include "networkd-manager.h" + #include "networkd-route-util.h" + #include "string-util.h" +@@ -225,6 +226,34 @@ + + } + ++static void test_failed_link_reconfiguration(Manager *manager) { ++ Link *link; ++ ++ assert_se(link_get_by_name(manager, "lo", &link) >= 0); ++ ++ link_set_state(link, LINK_STATE_CONFIGURED); ++ for (unsigned i = 0; i < 5; i++) { ++ link_enter_failed(link); ++ assert_se(link->state == LINK_STATE_INITIALIZED); ++ link_set_state(link, LINK_STATE_CONFIGURED); ++ } ++ ++ link_enter_failed(link); ++ assert_se(link->state == LINK_STATE_FAILED); ++ assert_se(link->automatic_reconfigure_ratelimit.num == 6); ++ ++ link_enter_failed(link); ++ assert_se(link->automatic_reconfigure_ratelimit.num == 6); ++ ++ assert_se(link_reconfigure(link, /* force = */ false) > 0); ++ assert_se(link->state == LINK_STATE_INITIALIZED); ++ ++ link_set_state(link, LINK_STATE_LINGER); ++ link_enter_failed(link); ++ assert_se(link->state == LINK_STATE_LINGER); ++ assert_se(link_reconfigure(link, /* force = */ true) == 0); ++} ++ + int main(void) { + _cleanup_(manager_freep) Manager *manager = NULL; + int r; +@@ -247,5 +276,6 @@ + assert_se(r == 0); + + assert_se(manager_enumerate(manager) >= 0); ++ test_failed_link_reconfiguration(manager); + return 0; + } +diff --git a/src/libsystemd-network/test-dhcp-client.c b/src/libsystemd-network/test-dhcp-client.c +--- a/src/libsystemd-network/test-dhcp-client.c ++++ b/src/libsystemd-network/test-dhcp-client.c +@@ -276,8 +276,33 @@ + return 0; + } + ++static void test_stopped_client_sends(void) { ++ sd_dhcp_client *client; ++ ++ assert_se(sd_dhcp_client_send_renew(NULL) == 0); ++ assert_se(sd_dhcp_client_send_release(NULL) == 0); ++ assert_se(sd_dhcp_client_send_decline(NULL) == 0); ++ ++ assert_se(sd_dhcp_client_new(&client, false) >= 0); ++ assert_se(!sd_dhcp_client_is_running(client)); ++ assert_se(sd_dhcp_client_send_renew(client) == 0); ++ assert_se(sd_dhcp_client_send_release(client) == 0); ++ assert_se(sd_dhcp_client_send_decline(client) == 0); ++ sd_dhcp_client_unref(client); ++} ++ ++static int count_stop_events(sd_dhcp_client *client, int event, void *userdata) { ++ unsigned *stop_events = userdata; ++ ++ if (event == SD_DHCP_CLIENT_EVENT_STOP) ++ (*stop_events)++; ++ ++ return 0; ++} ++ + static void test_discover_message(sd_event *e) { + sd_dhcp_client *client; ++ unsigned stop_events = 0; + int res, r; + + if (verbose) +@@ -294,16 +319,26 @@ + assert_se(sd_dhcp_client_set_mac(client, hw_addr.bytes, bcast_addr.bytes, hw_addr.length, ARPHRD_ETHER) >= 0); + + assert_se(sd_dhcp_client_set_request_option(client, 248) >= 0); ++ assert_se(sd_dhcp_client_set_callback(client, count_stop_events, &stop_events) >= 0); + + callback_recv = test_discover_message_verify; + + res = sd_dhcp_client_start(client); + + assert_se(IN_SET(res, 0, -EINPROGRESS)); ++ assert_se(sd_dhcp_client_is_running(client)); ++ assert_se(sd_dhcp_client_send_renew(client) == 0); ++ assert_se(sd_dhcp_client_send_release(client) == 0); ++ assert_se(sd_dhcp_client_send_decline(client) == 0); ++ assert_se(sd_dhcp_client_is_running(client)); ++ assert_se(stop_events == 0); + + sd_event_run(e, UINT64_MAX); + +- sd_dhcp_client_stop(client); ++ assert_se(sd_dhcp_client_stop(client) >= 0); ++ assert_se(stop_events == 1); ++ assert_se(sd_dhcp_client_stop(client) >= 0); ++ assert_se(stop_events == 1); + sd_dhcp_client_unref(client); + + test_fd[1] = safe_close(test_fd[1]); +@@ -546,6 +581,7 @@ + test_request_anonymize(e); + test_checksum(); + test_dhcp_identifier_set_iaid(); ++ test_stopped_client_sends(); + + test_discover_message(e); + test_addr_acq(e); diff --git a/SPECS/systemd/ukify-test-handle-openssl-issuer-whitespace.patch b/SPECS/systemd/ukify-test-handle-openssl-issuer-whitespace.patch new file mode 100644 index 00000000000..71c223cc626 --- /dev/null +++ b/SPECS/systemd/ukify-test-handle-openssl-issuer-whitespace.patch @@ -0,0 +1,38 @@ +From 338ed5bea4fcd0b5b1cdcfb96a789edf6251bbdd Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Sat, 23 Dec 2023 12:20:03 +0100 +Subject: [PATCH] ukify: make the test happy with the latest OpenSSL + +Which dropped some whitespaces in the output: + +$ openssl version +OpenSSL 3.2.0 23 Nov 2023 (Library: OpenSSL 3.2.0 23 Nov 2023) +$ openssl x509 -in cert.pem -text -noout | grep Issuer + Issuer: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd + +$ openssl version +OpenSSL 3.0.9 30 May 2023 (Library: OpenSSL 3.0.9 30 May 2023) +$ openssl x509 -in cert.pem -text -noout | grep Issuer + Issuer: C = XX, L = Default City, O = Default Company Ltd + +Making test-ukify unhappy: + +> assert 'Issuer: CN = SecureBoot signing key on host' in out +E AssertionError: assert 'Issuer: CN = SecureBoot signing key on host' in '<...snip...>Issuer: CN=SecureBoot signing key on host archlinux2\n...' +--- + src/ukify/test/test_ukify.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/ukify/test/test_ukify.py b/src/ukify/test/test_ukify.py +index 7db7c6ba61a0..0a0a9024e96e 100755 +--- a/src/ukify/test/test_ukify.py ++++ b/src/ukify/test/test_ukify.py +@@ -859,7 +859,7 @@ def test_key_cert_generation(tmp_path): + '-noout', + ], text = True) + assert 'Certificate' in out +- assert 'Issuer: CN = SecureBoot signing key on host' in out ++ assert re.search('Issuer: CN\s?=\s?SecureBoot signing key on host', out) + + if __name__ == '__main__': + sys.exit(pytest.main(sys.argv))