1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-10-26 08:55:18 +03:00

bootctl: write KERNEL_INSTALL_LAYOUT=bls and KERNEL_INSTALL_MACHINE_ID=…

This is a natural extension of d6bce6e224: if we are installing sd-boot, we
want to use the sd-boot layout, so let's write the appropriate
KERNEL_INSTALL_LAYOUT setting. Effectively, if we do 'booctl install',
kernel-install will not autodetect the layout anymore.

And 357376d0bb added support for KERNEL_INSTALL_MACHINE_ID. We need to support
it here too. We both read it, so that we create the right directories, and also
write it if it wasn't written yet and we created some directories using it, so
that kernel-install that is executed later knows the machine-id that matches
the directories we crated.

The code is changed in some places to fail if we can't figure out the current
status. When installing the boot loader it's probably better not to guess.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2021-12-17 16:06:51 +01:00
parent 641e2124de
commit 47fb161e3a
2 changed files with 166 additions and 33 deletions

View File

@ -19,6 +19,7 @@
#include "dirent-util.h"
#include "efi-loader.h"
#include "efivars.h"
#include "env-file.h"
#include "env-util.h"
#include "escape.h"
#include "fd-util.h"
@ -40,6 +41,7 @@
#include "sync-util.h"
#include "terminal-util.h"
#include "tmpfile-util.h"
#include "tmpfile-util-label.h"
#include "umask-util.h"
#include "utf8.h"
#include "util.h"
@ -54,9 +56,12 @@ 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 sd_id128_t arg_machine_id = SD_ID128_NULL;
static char *arg_install_layout = NULL;
STATIC_DESTRUCTOR_REGISTER(arg_esp_path, freep);
STATIC_DESTRUCTOR_REGISTER(arg_xbootldr_path, freep);
STATIC_DESTRUCTOR_REGISTER(arg_install_layout, freep);
static const char *arg_dollar_boot_path(void) {
/* $BOOT shall be the XBOOTLDR partition if it exists, and otherwise the ESP */
@ -119,17 +124,68 @@ static int acquire_xbootldr(bool unprivileged_mode, sd_id128_t *ret_uuid) {
return 1;
}
static void settle_make_machine_id_directory(void) {
static int load_install_machine_id_and_layout(void) {
/* Figure out the right machine-id for operations. If KERNEL_INSTALL_MACHINE_ID is configured in
* /etc/machine-info, let's use that. Otherwise, just use the real machine-id.
*
* Also load KERNEL_INSTALL_LAYOUT.
*/
_cleanup_free_ char *s = NULL, *layout = NULL;
int r;
if (arg_make_machine_id_directory >= 0)
return;
r = parse_env_file(NULL, "/etc/machine-info",
"KERNEL_INSTALL_LAYOUT", &layout,
"KERNEL_INSTALL_MACHINE_ID", &s);
if (r < 0 && r != -ENOENT)
return log_error_errno(r, "Failed to parse /etc/machine-info: %m");
r = path_is_temporary_fs("/etc/machine-id");
if (isempty(s)) {
r = sd_id128_get_machine(&arg_machine_id);
if (r < 0)
return log_error_errno(r, "Failed to get machine-id: %m");
} else {
r = sd_id128_from_string(s, &arg_machine_id);
if (r < 0)
return log_error_errno(r, "Failed to parse KERNEL_INSTALL_MACHINE_ID=%s in /etc/machine-info: %m", s);
}
log_debug("Using KERNEL_INSTALL_MACHINE_ID=%s from %s.",
SD_ID128_TO_STRING(arg_machine_id),
isempty(s) ? "/etc/machine_id" : "KERNEL_INSTALL_MACHINE_ID in /etc/machine-info");
if (!isempty(layout)) {
log_debug("KERNEL_INSTALL_LAYOUT=%s is specified in /etc/machine-info.", layout);
arg_install_layout = TAKE_PTR(layout);
}
return 0;
}
static int settle_install_machine_id(void) {
int r;
r = load_install_machine_id_and_layout();
if (r < 0)
log_debug_errno(r, "Couldn't determine whether /etc/machine-id is on a temporary file system, assuming so.");
return r;
arg_make_machine_id_directory = r == 0;
bool layout_non_bls = arg_install_layout && !streq(arg_install_layout, "bls");
if (arg_make_machine_id_directory < 0) {
if (layout_non_bls)
arg_make_machine_id_directory = 0;
else {
r = path_is_temporary_fs("/etc/machine-id");
if (r < 0)
return log_debug_errno(r, "Couldn't determine whether /etc/machine-id is on a temporary file system: %m");
arg_make_machine_id_directory = r == 0;
}
}
if (arg_make_machine_id_directory > 0 && layout_non_bls)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"KERNEL_INSTALL_LAYOUT=%s is configured, but bls directory creation was requested.",
arg_install_layout);
return 0;
}
/* search for "#### LoaderInfo: systemd-boot 218 ####" string inside the binary */
@ -924,20 +980,14 @@ static int remove_subdirs(const char *root, const char *const *subdirs) {
}
static int remove_machine_id_directory(const char *root) {
sd_id128_t machine_id;
int r;
assert(root);
assert(arg_make_machine_id_directory >= 0);
assert(!sd_id128_is_null(arg_machine_id));
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));
return rmdir_one(root, SD_ID128_TO_STRING(arg_machine_id));
}
static int remove_binaries(const char *esp_path) {
@ -1047,13 +1097,8 @@ static int install_loader_config(const char *esp_path) {
"#console-mode keep\n");
if (arg_make_machine_id_directory) {
sd_id128_t machine_id;
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));
assert(!sd_id128_is_null(arg_machine_id));
fprintf(f, "default %s-*\n", SD_ID128_TO_STRING(arg_machine_id));
}
r = fflush_sync_and_check(f);
@ -1071,20 +1116,100 @@ static int install_loader_config(const char *esp_path) {
}
static int install_machine_id_directory(const char *root) {
sd_id128_t machine_id;
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");
assert(!sd_id128_is_null(arg_machine_id));
return mkdir_one(root, SD_ID128_TO_STRING(arg_machine_id));
}
return mkdir_one(root, SD_ID128_TO_STRING(machine_id));
static int install_machine_info_config(void) {
_cleanup_free_ char *contents = NULL;
size_t length;
bool need_install_layout = true, need_machine_id;
int r;
assert(arg_make_machine_id_directory >= 0);
/* We only want to save the machine-id if we created any directories using it. */
need_machine_id = arg_make_machine_id_directory;
_cleanup_fclose_ FILE *orig = fopen("/etc/machine-info", "re");
if (!orig && errno != ENOENT)
return log_error_errno(errno, "Failed to open /etc/machine-info: %m");
if (orig) {
_cleanup_free_ char *install_layout = NULL, *machine_id = NULL;
r = parse_env_file(orig, "/etc/machine-info",
"KERNEL_INSTALL_LAYOUT", &install_layout,
"KERNEL_INSTALL_MACHINE_ID", &machine_id);
if (r < 0)
return log_error_errno(r, "Failed to parse /etc/machine-info: %m");
rewind(orig);
if (!isempty(install_layout))
need_install_layout = false;
if (!isempty(machine_id))
need_machine_id = false;
if (!need_install_layout && !need_machine_id) {
log_debug("/etc/machine-info already has KERNEL_INSTALL_MACHINE_ID=%s and KERNEL_INSTALL_LAYOUT=%s.",
machine_id, install_layout);
return 0;
}
r = read_full_stream(orig, &contents, &length);
if (r < 0)
return log_error_errno(r, "Failed to read /etc/machine-info: %m");
}
_cleanup_(unlink_and_freep) char *dst_tmp = NULL;
_cleanup_fclose_ FILE *dst = NULL;
r = fopen_temporary_label("/etc/machine-info", /* The path for which to the look up the label */
"/etc/machine-info", /* Where we want the file actually to end up */
&dst, /* The temporary file we write to */
&dst_tmp);
if (r < 0)
return log_debug_errno(r, "Failed to open temporary copy of /etc/machine-info: %m");
if (contents)
fwrite_unlocked(contents, 1, length, dst);
bool no_newline = !contents || contents[length - 1] == '\n';
if (need_install_layout) {
const char *line = "\nKERNEL_INSTALL_LAYOUT=bls\n" + no_newline;
fwrite_unlocked(line, 1, strlen(line), dst);
no_newline = false;
}
const char *mid_string = SD_ID128_TO_STRING(arg_machine_id);
if (need_machine_id)
fprintf(dst, "%sKERNEL_INSTALL_MACHINE_ID=%s\n",
no_newline ? "" : "\n",
mid_string);
r = fflush_and_check(dst);
if (r < 0)
return log_error_errno(r, "Failed to write temporary copy of /etc/machine-info: %m");
if (fchmod(fileno(dst), 0644) < 0)
return log_debug_errno(errno, "Failed to fchmod %s: %m", dst_tmp);
if (rename(dst_tmp, "/etc/machine-info") < 0)
return log_error_errno(errno, "Failed to replace /etc/machine-info: %m");
log_info("%s /etc/machine-info with%s%s%s",
orig ? "Updated" : "Created",
need_install_layout ? " KERNEL_INSTALL_LAYOUT=bls" : "",
need_machine_id ? " KERNEL_INSTALL_MACHINE_ID=" : "",
need_machine_id ? mid_string : "");
return 0;
}
static int help(int argc, char *argv[], void *userdata) {
@ -1637,7 +1762,9 @@ static int verb_install(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
settle_make_machine_id_directory();
r = settle_install_machine_id();
if (r < 0)
return r;
RUN_WITH_UMASK(0002) {
if (install) {
@ -1666,6 +1793,10 @@ static int verb_install(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
r = install_machine_info_config();
if (r < 0)
return r;
r = install_random_seed(arg_esp_path);
if (r < 0)
return r;
@ -1695,7 +1826,9 @@ static int verb_remove(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
settle_make_machine_id_directory();
r = settle_install_machine_id();
if (r < 0)
return r;
r = remove_binaries(arg_esp_path);

View File

@ -269,10 +269,10 @@ static int make_backup(const char *target, const char *x) {
return -errno;
r = fopen_temporary_label(
target, /* The path for which to the lookup the label */
target, /* The path for which to the look up the label */
x, /* Where we want the file actually to end up */
&dst,
&dst_tmp /* The temporary file we write to */);
&dst, /* The temporary file we write to */
&dst_tmp);
if (r < 0)
return r;