From 7bd5496befa2184aa132d50218c9b888573563a4 Mon Sep 17 00:00:00 2001 From: Arian van Putten Date: Wed, 16 Sep 2026 12:12:57 +0200 Subject: [PATCH 1/2] imds: make DMI device ordering of early network unit effective systemd-imds-early-network.service carries After=sys-devices-virtual-dmi-id.device, so that systemd-imdsd --setup-network sees the IMDS_* properties that udev applies to the DMI device from hwdb data. Ordering dependencies only take effect if both units are part of the same transaction though, and nothing ever pulled the device unit in: the generator hooks the service into sysinit.target.wants/ only, and the unit sets DefaultDependencies=no. The ordering was therefore a nop, and the service raced udev's coldplugging. When it lost that race the failure was silent: smbios_server_info() found no IMDS_VENDOR= property, so no endpoint got configured, cmdline_run() returned EXIT_NOTCONFIGURED, the unit's SuccessExitStatus=NOTCONFIGURED reported that as success, and no 85-imds-early.network was written at all. Give the unit the same drop-in we already write for systemd-imdsd@.service, which adds Wants= in addition to After= for the device unit, and factor it out into a helper. We only get here once the DMI device has been found in the hwdb, hence pulling the device unit into the transaction is safe. Note that with the race fixed I have yet to see systemd-imdsd actually work in locked mode: it appears to end up locked out by the "prohibit" route itself, despite the fwmark bypass. That is a separate issue, and left for somebody else to look into. --- src/imds/imds-generator.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/src/imds/imds-generator.c b/src/imds/imds-generator.c index 08175df3e5..d79b3c341d 100644 --- a/src/imds/imds-generator.c +++ b/src/imds/imds-generator.c @@ -126,6 +126,26 @@ static int smbios_query(void) { return false; } +static int add_dmi_id_dependency(const char *dest, const char *unit) { + int r; + + /* We now know the SMBIOS device exists, hence it's safe now to order the IMDS service after it, so + * that it has all properties properly initialized. */ + + r = write_drop_in( + dest, + unit, + 50, "dmi-id", + "# Automatically generated by systemd-imds-generator\n\n" + "[Unit]\n" + "Wants=sys-devices-virtual-dmi-id.device\n" + "After=sys-devices-virtual-dmi-id.device\n"); + if (r < 0) + return log_error_errno(r, "Failed to hook DMI id device before %s: %m", unit); + + return 0; +} + static int run(const char *dest, const char *dest_early, const char *dest_late) { int r; @@ -161,6 +181,10 @@ static int run(const char *dest, const char *dest_early, const char *dest_late) r = generator_add_symlink(dest_early, SPECIAL_SYSINIT_TARGET, "wants", SYSTEM_DATA_UNIT_DIR "/systemd-imds-early-network.service"); if (r < 0) return log_error_errno(r, "Failed to hook in systemd-imds-early-network.service: %m"); + + r = add_dmi_id_dependency(dest_early, "systemd-imds-early-network.service"); + if (r < 0) + return r; } /* Enable the IMDS service socket */ @@ -168,18 +192,9 @@ static int run(const char *dest, const char *dest_early, const char *dest_late) if (r < 0) return log_error_errno(r, "Failed to hook in systemd-imdsd.socket: %m"); - /* We now know the SMBIOS device exists, hence it's safe now to order the IMDS service after it, so - * that it has all properties properly initialized. */ - r = write_drop_in( - dest_early, - "systemd-imdsd@.service", - 50, "dmi-id", - "# Automatically generated by systemd-imds-generator\n\n" - "[Unit]\n" - "Wants=sys-devices-virtual-dmi-id.device\n" - "After=sys-devices-virtual-dmi-id.device\n"); + r = add_dmi_id_dependency(dest_early, "systemd-imdsd@.service"); if (r < 0) - return log_error_errno(r, "Failed to hook DMI id device before systemd-imdsd@.service: %m"); + return r; if (arg_import < 0) arg_import = in_initrd(); From bb2c842b1f89632e6e487df600244b1c526f66ee Mon Sep 17 00:00:00 2001 From: Arian van Putten Date: Wed, 16 Sep 2026 11:57:03 +0200 Subject: [PATCH 2/2] imds: actually default to the build-time IMDS network mode The imds-network= meson option has never had an effect on the generated network configuration. It arrived in 168a7f7770 together with the IMDS generator, which wired IMDS_NETWORK_LOCKED_DEFAULT (turned into IMDS_NETWORK_DEFAULT by c3e4e8a527) into the generator's arg_network_mode. But the generator only ever compares that variable against IMDS_NETWORK_OFF, to decide whether to pull systemd-imds-early-network.service into the initial transaction, and "off" is not one of the option's choices. It also never forwards the mode on to systemd-imds-early-network.service, neither as a command line switch nor via a drop-in. 85-imds-early.network is written by systemd-imds-early-network.service, which runs "systemd-imdsd --setup-network", and that code path's arg_network_mode was left at _IMDS_NETWORK_MODE_INVALID. As setup_network() requires "!= IMDS_NETWORK_UNLOCKED" before emitting the "prohibit" routes, the unset sentinel behaves exactly like "locked". At first that went unnoticed, because the option defaulted to "locked" as well: the documented default matched the implemented behaviour by accident, and only "-Dimds-network=unlocked" was quietly ignored. 6240d420d6 ("meson: unlock imds network by default") then flipped the default by reordering the option's choices, i.e. moved a macro that nothing consumed. From that point on the default was wrong for everybody: unless systemd.imds.network= is passed on the kernel command line, every generated network file locks the IMDS endpoint down, no matter how the build is configured. ac64b2dfa3 later documented the new default in man:systemd-imdsd@.service(8) (#42687), which meant the documentation now described behaviour that does not exist. In practice this rarely became visible until the previous commit, since systemd-imdsd --setup-network mostly lost its race against udev and wrote no network file at all. Initialize arg_network_mode from IMDS_NETWORK_DEFAULT, the same way imds-generator.c does. No other code distinguishes the INVALID sentinel from a real mode; the remaining users compare against IMDS_NETWORK_OFF and IMDS_NETWORK_UNLOCKED only. The kernel command line still overrides the build-time default, and the only difference in the generated network file are the two "prohibit" routes: the fwmark routing table and the matching routing policy rule are written in either mode, as before. --- src/imds/imdsd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/imds/imdsd.c b/src/imds/imdsd.c index 6f71e50e17..39a337d4e5 100644 --- a/src/imds/imdsd.c +++ b/src/imds/imdsd.c @@ -108,7 +108,7 @@ static char* arg_key = NULL; static bool arg_cache = true; static bool arg_wait = false; static bool arg_varlink = false; -static ImdsNetworkMode arg_network_mode = _IMDS_NETWORK_MODE_INVALID; +static ImdsNetworkMode arg_network_mode = IMDS_NETWORK_DEFAULT; static bool arg_setup_network = false; /* The follow configure the IMDS service endpoint details */