Skip to content

Commit

Permalink
added systemd.machine_id=firmware option
Browse files Browse the repository at this point in the history
  • Loading branch information
FML128 committed May 22, 2024
1 parent aaa872a commit 2831477
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 20 deletions.
3 changes: 2 additions & 1 deletion man/machine-id.xml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@
value of the kernel command line option <varname>container_uuid</varname>, the KVM DMI
<filename>product_uuid</filename> or the devicetree <filename>vm,uuid</filename>
(on KVM systems), the Xen hypervisor <filename>uuid</filename>, and finally a randomly
generated UUID.</para>
generated UUID. <varname>systemd.machine_id=firmware</varname> can be set to generate the machine id
from the firmware.</para>

<para>After the machine ID is established,
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
Expand Down
19 changes: 13 additions & 6 deletions src/core/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion src/machine-id-setup/machine-id-setup-main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
32 changes: 21 additions & 11 deletions src/shared/machine-id-setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -40,15 +41,20 @@ 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");

log_info("Initializing machine ID from credential.");
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;

Expand All @@ -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;

Expand All @@ -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;
}
}
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
}
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
7 changes: 6 additions & 1 deletion src/shared/machine-id-setup.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,10 @@

#include <stdbool.h>

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);

0 comments on commit 2831477

Please sign in to comment.