diff --git a/man/machine-id.xml b/man/machine-id.xml index 4ee100b4735c42..dc93ab0f473a77 100644 --- a/man/machine-id.xml +++ b/man/machine-id.xml @@ -102,7 +102,8 @@ value of the kernel command line option container_uuid, the KVM DMI product_uuid or the devicetree vm,uuid (on KVM systems), the Xen hypervisor uuid, and finally a randomly - generated UUID. + generated UUID. systemd.machine_id=firmware can be set to generate the machine id + from the firmware. After the machine ID is established, systemd1 diff --git a/src/core/main.c b/src/core/main.c index 6f91a15b22b424..ccbdf234026fd4 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -146,6 +146,7 @@ static nsec_t arg_timer_slack_nsec; static Set* arg_syscall_archs; static FILE* arg_serialization; static sd_id128_t arg_machine_id; +static bool arg_machine_id_from_firmware = false; static EmergencyAction arg_cad_burst_action; static CPUSet arg_cpu_affinity; static NUMAPolicy arg_numa_policy; @@ -354,10 +355,15 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat if (proc_cmdline_value_missing(key, value)) return 0; - r = id128_from_string_nonzero(value, &arg_machine_id); - if (r < 0) - log_warning_errno(r, "MachineID '%s' is not valid, ignoring: %m", value); - + if (streq(value, "firmware")) + arg_machine_id_from_firmware = true; + else { + r = id128_from_string_nonzero(value, &arg_machine_id); + if (r < 0) + log_warning_errno(r, "MachineID '%s' is not valid, ignoring: %m", value); + else + arg_machine_id_from_firmware = false; + } } else if (proc_cmdline_key_streq(key, "systemd.default_timeout_start_sec")) { if (proc_cmdline_value_missing(key, value)) @@ -2305,8 +2311,9 @@ static int initialize_runtime( (void) os_release_status(); (void) hostname_setup(true); - /* Force transient machine-id on first boot. */ - machine_id_setup(/* root= */ NULL, /* force_transient= */ first_boot, arg_machine_id, /* ret_machine_id */ NULL); + + machine_id_setup(/* root= */ NULL, arg_machine_id, (first_boot ? MACHINE_ID_SETUP_FORCE_TRANSIENT : 0) | + (arg_machine_id_from_firmware ? MACHINE_ID_SETUP_FORCE_FIRMWARE : 0), /* ret_machine_id */ NULL); (void) loopback_setup(); bump_unix_max_dgram_qlen(); bump_file_max_and_nr_open(); diff --git a/src/machine-id-setup/machine-id-setup-main.c b/src/machine-id-setup/machine-id-setup-main.c index bbc58945bd6e3d..0c6a77f746a27e 100644 --- a/src/machine-id-setup/machine-id-setup-main.c +++ b/src/machine-id-setup/machine-id-setup-main.c @@ -189,7 +189,7 @@ static int run(int argc, char *argv[]) { } else { sd_id128_t id; - r = machine_id_setup(arg_root, false, SD_ID128_NULL, &id); + r = machine_id_setup(arg_root, SD_ID128_NULL, /* flags = */ 0, &id); if (r < 0) return r; diff --git a/src/shared/machine-id-setup.c b/src/shared/machine-id-setup.c index df99b0b009537c..fc36ee0f48637d 100644 --- a/src/shared/machine-id-setup.c +++ b/src/shared/machine-id-setup.c @@ -30,7 +30,8 @@ #include "umask-util.h" #include "virt.h" -static int acquire_machine_id_from_credential(sd_id128_t *ret) { +static int acquire_machine_id_from_credential(sd_id128_t *ret_machine_id, bool *ret_machine_id_from_firmware) { + _cleanup_free_ char *buf = NULL; int r; @@ -40,7 +41,12 @@ static int acquire_machine_id_from_credential(sd_id128_t *ret) { if (r == 0) /* not found */ return -ENXIO; - r = sd_id128_from_string(buf, ret); + if (streq(buf, "firmware")) { + *ret_machine_id_from_firmware = true; + return 0; + } + + r = sd_id128_from_string(buf, ret_machine_id); if (r < 0) return log_warning_errno(r, "Failed to parse system.machine_id credential, ignoring: %m"); @@ -48,7 +54,7 @@ static int acquire_machine_id_from_credential(sd_id128_t *ret) { return 0; } -static int generate_machine_id(const char *root, sd_id128_t *ret) { +static int generate_machine_id(const char *root, sd_id128_t *ret, bool machine_id_from_firmware) { _cleanup_close_ int fd = -EBADF; int r; @@ -63,7 +69,7 @@ static int generate_machine_id(const char *root, sd_id128_t *ret) { if (isempty(root) && running_in_chroot() <= 0) { /* Let's use a system credential for the machine ID if we can */ - r = acquire_machine_id_from_credential(ret); + r = acquire_machine_id_from_credential(ret, &machine_id_from_firmware); if (r >= 0) return r; @@ -80,14 +86,14 @@ static int generate_machine_id(const char *root, sd_id128_t *ret) { return 0; } - } else if (IN_SET(detect_vm(), VIRTUALIZATION_KVM, VIRTUALIZATION_AMAZON, VIRTUALIZATION_QEMU, VIRTUALIZATION_XEN)) { + } else if (IN_SET(detect_vm(), VIRTUALIZATION_KVM, VIRTUALIZATION_AMAZON, VIRTUALIZATION_QEMU, VIRTUALIZATION_XEN) || machine_id_from_firmware) { /* If we are not running in a container, see if we are running in a VM that provides * a system UUID via the SMBIOS/DMI interfaces. Such environments include QEMU/KVM * with the -uuid on the qemu command line or the Amazon EC2 Nitro hypervisor. */ if (id128_get_product(ret) >= 0) { - log_info("Initializing machine ID from VM UUID."); + log_info("Initializing machine ID from SMBIOS/DMI UUID."); return 0; } } @@ -102,12 +108,16 @@ static int generate_machine_id(const char *root, sd_id128_t *ret) { return 0; } -int machine_id_setup(const char *root, bool force_transient, sd_id128_t machine_id, sd_id128_t *ret) { +int machine_id_setup(const char *root, sd_id128_t machine_id, MachineIdSetupFlags flags, sd_id128_t *ret) { const char *etc_machine_id, *run_machine_id; _cleanup_close_ int fd = -EBADF; bool writable; + bool machine_id_from_firmware = false; int r; + if (flags & MACHINE_ID_SETUP_FORCE_FIRMWARE) + machine_id_from_firmware = true; + etc_machine_id = prefix_roota(root, "/etc/machine-id"); WITH_UMASK(0000) { @@ -140,14 +150,14 @@ int machine_id_setup(const char *root, bool force_transient, sd_id128_t machine_ } /* A we got a valid machine ID argument, that's what counts */ - if (sd_id128_is_null(machine_id)) { + if (sd_id128_is_null(machine_id) || machine_id_from_firmware) { /* Try to read any existing machine ID */ if (id128_read_fd(fd, ID128_FORMAT_PLAIN, &machine_id) >= 0) goto finish; /* Hmm, so, the id currently stored is not useful, then let's generate one */ - r = generate_machine_id(root, &machine_id); + r = generate_machine_id(root, &machine_id, machine_id_from_firmware); if (r < 0) return r; } @@ -163,7 +173,7 @@ int machine_id_setup(const char *root, bool force_transient, sd_id128_t machine_ * disk and overmount it with a transient file. * * Otherwise write the machine-id directly to disk. */ - if (force_transient) { + if (FLAGS_SET(flags, MACHINE_ID_SETUP_FORCE_TRANSIENT)) { r = loop_write(fd, "uninitialized\n", SIZE_MAX); if (r < 0) return log_error_errno(r, "Failed to write uninitialized %s: %m", etc_machine_id); @@ -201,7 +211,7 @@ int machine_id_setup(const char *root, bool force_transient, sd_id128_t machine_ return r; } - log_full(force_transient ? LOG_DEBUG : LOG_INFO, "Installed transient %s file.", etc_machine_id); + log_full(FLAGS_SET(flags, MACHINE_ID_SETUP_FORCE_TRANSIENT) ? LOG_DEBUG : LOG_INFO, "Installed transient %s file.", etc_machine_id); /* Mark the mount read-only */ r = mount_follow_verbose(LOG_WARNING, NULL, etc_machine_id, NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, NULL); diff --git a/src/shared/machine-id-setup.h b/src/shared/machine-id-setup.h index cce58192e526a1..e733471afc9ae0 100644 --- a/src/shared/machine-id-setup.h +++ b/src/shared/machine-id-setup.h @@ -3,5 +3,10 @@ #include +typedef enum MachineIdSetupFlags { + MACHINE_ID_SETUP_FORCE_TRANSIENT = 1 << 0, + MACHINE_ID_SETUP_FORCE_FIRMWARE = 1 << 1, +} MachineIdSetupFlags; + int machine_id_commit(const char *root); -int machine_id_setup(const char *root, bool force_transient, sd_id128_t requested, sd_id128_t *ret); +int machine_id_setup(const char *root, sd_id128_t machine_id, MachineIdSetupFlags flags, sd_id128_t *ret);