diff --git a/man/bootctl.xml b/man/bootctl.xml index 878f24742e8..5dfed110ddd 100644 --- a/man/bootctl.xml +++ b/man/bootctl.xml @@ -237,6 +237,19 @@ cannot be written. Currently only applies to random seed operations. + + + Control creation and deletion of $ESP/$MACHINE_ID during + and , respectively. + auto is equivalent to to yes if /etc/machine-id + resides on a filesystem other than tmpfs and no otherwise. + Defaults to auto. + + Overriding this may be desired to hide the machine ID from the (unencrypted) ESP, + configure a kernel-install8 script, or, + conversely, commit a machine-id that only appears transient. + + diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index a684717bb05..34f0c14b44a 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -29,6 +29,7 @@ #include "main-func.h" #include "mkdir.h" #include "pager.h" +#include "parse-argument.h" #include "parse-util.h" #include "pretty-print.h" #include "random-util.h" @@ -52,6 +53,7 @@ static bool arg_print_dollar_boot_path = false; static bool arg_touch_variables = true; static PagerFlags arg_pager_flags = 0; static bool arg_graceful = false; +static int arg_make_machine_id_directory = -1; STATIC_DESTRUCTOR_REGISTER(arg_esp_path, freep); STATIC_DESTRUCTOR_REGISTER(arg_xbootldr_path, freep); @@ -112,6 +114,19 @@ static int acquire_xbootldr(bool unprivileged_mode, sd_id128_t *ret_uuid) { return 1; } +static void settle_make_machine_id_directory(void) { + int r; + + if (arg_make_machine_id_directory >= 0) + return; + + r = path_is_temporary_fs("/etc/machine-id"); + if (r < 0) + log_debug_errno(r, "Couldn't determine whether /etc/machine-id is on a temporary file system, assuming so."); + + arg_make_machine_id_directory = r == 0; +} + /* search for "#### LoaderInfo: systemd-boot 218 ####" string inside the binary */ static int get_file_version(int fd, char **v) { struct stat st; @@ -888,6 +903,24 @@ static int remove_subdirs(const char *root, const char *const *subdirs) { return r < 0 ? r : q; } +static int remove_machine_id_directory(const char *root) { + sd_id128_t machine_id; + char buf[SD_ID128_STRING_MAX]; + int r; + + assert(root); + assert(arg_make_machine_id_directory >= 0); + + if (!arg_make_machine_id_directory) + return 0; + + r = sd_id128_get_machine(&machine_id); + if (r < 0) + return log_error_errno(r, "Failed to get machine id: %m"); + + return rmdir_one(root, sd_id128_to_string(machine_id, buf)); +} + static int remove_binaries(const char *esp_path) { const char *p; int r, q; @@ -974,9 +1007,13 @@ static int install_loader_config(const char *esp_path) { _cleanup_(unlink_and_freep) char *t = NULL; _cleanup_fclose_ FILE *f = NULL; _cleanup_close_ int fd = -1; + sd_id128_t machine_id; + char machine_string[SD_ID128_STRING_MAX]; const char *p; int r; + assert(arg_make_machine_id_directory >= 0); + p = prefix_roota(esp_path, "/loader/loader.conf"); if (access(p, F_OK) >= 0) /* Silently skip creation if the file already exists (early check) */ return 0; @@ -991,6 +1028,13 @@ static int install_loader_config(const char *esp_path) { fprintf(f, "#timeout 3\n" "#console-mode keep\n"); + if (arg_make_machine_id_directory) { + r = sd_id128_get_machine(&machine_id); + if (r < 0) + return log_error_errno(r, "Failed to get machine id: %m"); + + fprintf(f, "default %s-*\n", sd_id128_to_string(machine_id, machine_string)); + } r = fflush_sync_and_check(f); if (r < 0) @@ -1006,6 +1050,24 @@ static int install_loader_config(const char *esp_path) { return 1; } +static int install_machine_id_directory(const char *root) { + sd_id128_t machine_id; + char buf[SD_ID128_STRING_MAX]; + int r; + + assert(root); + assert(arg_make_machine_id_directory >= 0); + + if (!arg_make_machine_id_directory) + return 0; + + r = sd_id128_get_machine(&machine_id); + if (r < 0) + return log_error_errno(r, "Failed to get machine id: %m"); + + return mkdir_one(root, sd_id128_to_string(machine_id, buf)); +} + static int help(int argc, char *argv[], void *userdata) { _cleanup_free_ char *link = NULL; int r; @@ -1043,6 +1105,8 @@ static int help(int argc, char *argv[], void *userdata) { " --no-pager Do not pipe output into a pager\n" " --graceful Don't fail when the ESP cannot be found or EFI\n" " variables cannot be written\n" + " --make-machine-id-directory=yes|no|auto\n" + " Create $BOOT/$MACHINE_ID\n" "\nSee the %2$s for details.\n", program_invocation_short_name, link, @@ -1062,24 +1126,27 @@ static int parse_argv(int argc, char *argv[]) { ARG_NO_VARIABLES, ARG_NO_PAGER, ARG_GRACEFUL, + ARG_MAKE_MACHINE_ID_DIRECTORY, }; static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "esp-path", required_argument, NULL, ARG_ESP_PATH }, - { "path", required_argument, NULL, ARG_ESP_PATH }, /* Compatibility alias */ - { "boot-path", required_argument, NULL, ARG_BOOT_PATH }, - { "print-esp-path", no_argument, NULL, 'p' }, - { "print-path", no_argument, NULL, 'p' }, /* Compatibility alias */ - { "print-boot-path", no_argument, NULL, 'x' }, - { "no-variables", no_argument, NULL, ARG_NO_VARIABLES }, - { "no-pager", no_argument, NULL, ARG_NO_PAGER }, - { "graceful", no_argument, NULL, ARG_GRACEFUL }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "esp-path", required_argument, NULL, ARG_ESP_PATH }, + { "path", required_argument, NULL, ARG_ESP_PATH }, /* Compatibility alias */ + { "boot-path", required_argument, NULL, ARG_BOOT_PATH }, + { "print-esp-path", no_argument, NULL, 'p' }, + { "print-path", no_argument, NULL, 'p' }, /* Compatibility alias */ + { "print-boot-path", no_argument, NULL, 'x' }, + { "no-variables", no_argument, NULL, ARG_NO_VARIABLES }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "graceful", no_argument, NULL, ARG_GRACEFUL }, + { "make-machine-id-directory", required_argument, NULL, ARG_MAKE_MACHINE_ID_DIRECTORY }, {} }; int c, r; + bool b; assert(argc >= 0); assert(argv); @@ -1132,6 +1199,17 @@ static int parse_argv(int argc, char *argv[]) { arg_graceful = true; break; + case ARG_MAKE_MACHINE_ID_DIRECTORY: + if (streq(optarg, "auto")) + arg_make_machine_id_directory = -1; /* default */ + else { + r = parse_boolean_argument("--make-machine-id-directory=", optarg, &b); + if (r < 0) + return r; + arg_make_machine_id_directory = b; + } + break; + case '?': return -EINVAL; @@ -1530,6 +1608,8 @@ static int verb_install(int argc, char *argv[], void *userdata) { if (r < 0) return r; + settle_make_machine_id_directory(); + install = streq(argv[0], "install"); RUN_WITH_UMASK(0002) { @@ -1555,6 +1635,10 @@ static int verb_install(int argc, char *argv[], void *userdata) { if (r < 0) return r; + r = install_machine_id_directory(arg_dollar_boot_path()); + if (r < 0) + return r; + r = install_random_seed(arg_esp_path); if (r < 0) return r; @@ -1584,6 +1668,8 @@ static int verb_remove(int argc, char *argv[], void *userdata) { if (r < 0) return r; + settle_make_machine_id_directory(); + r = remove_binaries(arg_esp_path); q = remove_file(arg_esp_path, "/loader/loader.conf"); @@ -1602,11 +1688,19 @@ static int verb_remove(int argc, char *argv[], void *userdata) { if (q < 0 && r >= 0) r = q; + q = remove_machine_id_directory(arg_esp_path); + if (q < 0 && r >= 0) + r = 1; + if (arg_xbootldr_path) { /* Remove the latter two also in the XBOOTLDR partition if it exists */ q = remove_subdirs(arg_xbootldr_path, dollar_boot_subdirs); if (q < 0 && r >= 0) r = q; + + q = remove_machine_id_directory(arg_xbootldr_path); + if (q < 0 && r >= 0) + r = q; } (void) sync_everything();