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.
This commit is contained in:
Arian van Putten
2026-09-16 12:45:11 +02:00
committed by Arian van Putten
parent f3880debd7
commit 7bd5496bef
+26 -11
View File
@@ -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();