mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 00:14:32 +09:00
boot: add an option to control action after SecureBoot enrollment (#36684)
This PR provides a new option for systemd-boot `secure-boot-enroll-action` which allows to configure the behavior after SecureBoot keys are enrolled. Provides the option to either reboot or power off. The current behavior is not changed, it will by default reboot as it did before. It also provides a small message about the action its going to take with a small delay so the user can read it.
This commit is contained in:
@@ -373,6 +373,29 @@ sbvarsign --attr "${attr}" --key KEK.key --cert KEK.pem --output db.auth db db.e
|
||||
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>secure-boot-enroll-action</term>
|
||||
<listitem>
|
||||
<para>Specifies the action to take after the automatic enrollment of secure boot keys is completed.</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>reboot</term>
|
||||
<listitem>
|
||||
<para>Reboot the system after enrollment. This is the default.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>shutdown</term>
|
||||
<listitem>
|
||||
<para>Shut down the system after enrollment.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
<para>This option is only relevant if <literal>secure-boot-enroll</literal> is enabled.</para>
|
||||
<xi:include href="version-info.xml" xpointer="v258"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>reboot-for-bitlocker</term>
|
||||
|
||||
|
||||
@@ -141,6 +141,7 @@ typedef struct {
|
||||
bool reboot_for_bitlocker;
|
||||
RebootOnError reboot_on_error;
|
||||
secure_boot_enroll secure_boot_enroll;
|
||||
secure_boot_enroll_action secure_boot_enroll_action;
|
||||
bool force_menu;
|
||||
bool use_saved_entry;
|
||||
bool use_saved_entry_efivar;
|
||||
@@ -325,34 +326,35 @@ static void print_status(Config *config, char16_t *loaded_image_path) {
|
||||
if (config->entry_oneshot)
|
||||
printf(" default (one-shot): %ls\n", config->entry_oneshot);
|
||||
if (config->entry_saved)
|
||||
printf(" saved entry: %ls\n", config->entry_saved);
|
||||
printf(" editor: %ls\n", yes_no(config->editor));
|
||||
printf(" auto-entries: %ls\n", yes_no(config->auto_entries));
|
||||
printf(" auto-firmware: %ls\n", yes_no(config->auto_firmware));
|
||||
printf(" auto-poweroff: %ls\n", yes_no(config->auto_poweroff));
|
||||
printf(" auto-reboot: %ls\n", yes_no(config->auto_reboot));
|
||||
printf(" beep: %ls\n", yes_no(config->beep));
|
||||
printf(" reboot-for-bitlocker: %ls\n", yes_no(config->reboot_for_bitlocker));
|
||||
printf(" reboot-on-error: %s\n", reboot_on_error_to_string(config->reboot_on_error));
|
||||
printf(" secure-boot-enroll: %s\n", secure_boot_enroll_to_string(config->secure_boot_enroll));
|
||||
printf(" saved entry: %ls\n", config->entry_saved);
|
||||
printf(" editor: %ls\n", yes_no(config->editor));
|
||||
printf(" auto-entries: %ls\n", yes_no(config->auto_entries));
|
||||
printf(" auto-firmware: %ls\n", yes_no(config->auto_firmware));
|
||||
printf(" auto-poweroff: %ls\n", yes_no(config->auto_poweroff));
|
||||
printf(" auto-reboot: %ls\n", yes_no(config->auto_reboot));
|
||||
printf(" beep: %ls\n", yes_no(config->beep));
|
||||
printf(" reboot-for-bitlocker: %ls\n", yes_no(config->reboot_for_bitlocker));
|
||||
printf(" reboot-on-error: %s\n", reboot_on_error_to_string(config->reboot_on_error));
|
||||
printf(" secure-boot-enroll: %s\n", secure_boot_enroll_to_string(config->secure_boot_enroll));
|
||||
printf("secure-boot-enroll-action: %s\n", secure_boot_enroll_action_to_string(config->secure_boot_enroll_action));
|
||||
|
||||
switch (config->console_mode) {
|
||||
case CONSOLE_MODE_AUTO:
|
||||
printf(" console-mode (config): auto\n");
|
||||
printf(" console-mode (config): auto\n");
|
||||
break;
|
||||
case CONSOLE_MODE_KEEP:
|
||||
printf(" console-mode (config): keep\n");
|
||||
printf(" console-mode (config): keep\n");
|
||||
break;
|
||||
case CONSOLE_MODE_FIRMWARE_MAX:
|
||||
printf(" console-mode (config): max\n");
|
||||
printf(" console-mode (config): max\n");
|
||||
break;
|
||||
default:
|
||||
printf(" console-mode (config): %" PRIi64 "\n", config->console_mode);
|
||||
printf(" console-mode (config): %" PRIi64 "\n", config->console_mode);
|
||||
}
|
||||
|
||||
/* EFI var console mode is always a concrete value or unset. */
|
||||
if (config->console_mode_efivar != CONSOLE_MODE_KEEP)
|
||||
printf("console-mode (EFI var): %" PRIi64 "\n", config->console_mode_efivar);
|
||||
printf(" console-mode (EFI var): %" PRIi64 "\n", config->console_mode_efivar);
|
||||
|
||||
if (!ps_continue())
|
||||
return;
|
||||
@@ -1080,7 +1082,14 @@ static void config_defaults_load_from_file(Config *config, char *content) {
|
||||
else
|
||||
log_error("Error parsing 'secure-boot-enroll' config option, ignoring: %s",
|
||||
value);
|
||||
|
||||
} else if (streq8(key, "secure-boot-enroll-action")) {
|
||||
if (streq8(value, "reboot"))
|
||||
config->secure_boot_enroll_action = ENROLL_ACTION_REBOOT;
|
||||
else if (streq8(value, "shutdown"))
|
||||
config->secure_boot_enroll_action = ENROLL_ACTION_SHUTDOWN;
|
||||
else
|
||||
log_error("Error parsing 'secure-boot-enroll-action' config option, ignoring: %s",
|
||||
value);
|
||||
} else if (streq8(key, "console-mode")) {
|
||||
if (streq8(value, "auto"))
|
||||
config->console_mode = CONSOLE_MODE_AUTO;
|
||||
@@ -1436,6 +1445,7 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) {
|
||||
.auto_firmware = true,
|
||||
.reboot_on_error = REBOOT_AUTO,
|
||||
.secure_boot_enroll = ENROLL_IF_SAFE,
|
||||
.secure_boot_enroll_action = ENROLL_ACTION_REBOOT,
|
||||
.idx_default_efivar = IDX_INVALID,
|
||||
.console_mode = CONSOLE_MODE_KEEP,
|
||||
.console_mode_efivar = CONSOLE_MODE_KEEP,
|
||||
@@ -2723,7 +2733,7 @@ static void save_selected_entry(const Config *config, const BootEntry *entry) {
|
||||
static EFI_STATUS call_secure_boot_enroll(const BootEntry *entry, EFI_FILE *root_dir, EFI_HANDLE parent_image) {
|
||||
assert(entry);
|
||||
|
||||
return secure_boot_enroll_at(root_dir, entry->path, /* force= */ true);
|
||||
return secure_boot_enroll_at(root_dir, entry->path, /* force= */ true, /* action= */ ENROLL_ACTION_REBOOT);
|
||||
}
|
||||
|
||||
static EFI_STATUS secure_boot_discover_keys(Config *config, EFI_FILE *root_dir) {
|
||||
@@ -2774,7 +2784,7 @@ static EFI_STATUS secure_boot_discover_keys(Config *config, EFI_FILE *root_dir)
|
||||
strcaseeq16(dirent->FileName, u"auto"))
|
||||
/* If we auto enroll successfully this call does not return.
|
||||
* If it fails we still want to add other potential entries to the menu. */
|
||||
secure_boot_enroll_at(root_dir, entry->path, config->secure_boot_enroll == ENROLL_FORCE);
|
||||
secure_boot_enroll_at(root_dir, entry->path, config->secure_boot_enroll == ENROLL_FORCE, config->secure_boot_enroll_action);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
@@ -69,7 +69,7 @@ static EFI_STATUS set_custom_mode(bool enable) {
|
||||
attr, sizeof(mode), &mode);
|
||||
}
|
||||
|
||||
EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path, bool force) {
|
||||
EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path, bool force, secure_boot_enroll_action action) {
|
||||
assert(root_dir);
|
||||
assert(path);
|
||||
|
||||
@@ -185,11 +185,21 @@ EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path, bool
|
||||
}
|
||||
}
|
||||
|
||||
printf("Custom Secure Boot keys successfully enrolled, rebooting the system now!\n");
|
||||
/* The system should be in secure boot mode now and we could continue a regular boot. But at least
|
||||
* TPM PCR7 measurements should change on next boot. Reboot now so that any OS we load does not end
|
||||
* up relying on the old PCR state. */
|
||||
RT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
|
||||
* TPM PCR7 measurements should change on next boot. Reboot/poweroff now so that any OS we load
|
||||
* does not end up relying on the old PCR state.
|
||||
*/
|
||||
|
||||
if (action == ENROLL_ACTION_SHUTDOWN) {
|
||||
printf("Custom Secure Boot keys successfully enrolled, powering off the system now!\n");
|
||||
console_key_read(/* ret_key= */ NULL, /* timeout_usec= */ 2 * 1000 * 1000); /* wait a bit so user can see the message */
|
||||
RT->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL);
|
||||
} else {
|
||||
assert(action == ENROLL_ACTION_REBOOT);
|
||||
printf("Custom Secure Boot keys successfully enrolled, rebooting the system now!\n");
|
||||
console_key_read(/* ret_key= */ NULL, /* timeout_usec= */ 2 * 1000 * 1000); /* wait a bit so user can see the message */
|
||||
RT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
|
||||
}
|
||||
assert_not_reached();
|
||||
|
||||
out_deallocate:
|
||||
@@ -295,4 +305,10 @@ static const char *secure_boot_enroll_table[_SECURE_BOOT_ENROLL_MAX] = {
|
||||
[ENROLL_FORCE] = "force"
|
||||
};
|
||||
|
||||
static const char *secure_boot_enroll_action_table[_SECURE_BOOT_ENROLL_ACTION_MAX] = {
|
||||
[ENROLL_ACTION_REBOOT] = "reboot",
|
||||
[ENROLL_ACTION_SHUTDOWN] = "shutdown"
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(secure_boot_enroll, secure_boot_enroll);
|
||||
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(secure_boot_enroll_action, secure_boot_enroll_action);
|
||||
|
||||
@@ -12,10 +12,16 @@ typedef enum {
|
||||
_SECURE_BOOT_ENROLL_MAX,
|
||||
} secure_boot_enroll;
|
||||
|
||||
typedef enum {
|
||||
ENROLL_ACTION_REBOOT, /* Reboot the system after enrollment */
|
||||
ENROLL_ACTION_SHUTDOWN, /* Shutdown the system after enrollment */
|
||||
_SECURE_BOOT_ENROLL_ACTION_MAX,
|
||||
} secure_boot_enroll_action;
|
||||
|
||||
bool secure_boot_enabled(void);
|
||||
SecureBootMode secure_boot_mode(void);
|
||||
|
||||
EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path, bool force);
|
||||
EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path, bool force, secure_boot_enroll_action action);
|
||||
|
||||
typedef bool (*security_validator_t)(
|
||||
const void *ctx,
|
||||
@@ -27,3 +33,4 @@ void install_security_override(security_validator_t validator, const void *valid
|
||||
void uninstall_security_override(void);
|
||||
|
||||
const char* secure_boot_enroll_to_string(secure_boot_enroll e) _const_;
|
||||
const char* secure_boot_enroll_action_to_string(secure_boot_enroll_action e) _const_;
|
||||
|
||||
@@ -579,3 +579,5 @@ run0.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="--pty"]
|
||||
loader.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="reboot-on-error"]/listitem/para/variablelist/varlistentry[term="yes"]
|
||||
loader.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="reboot-on-error"]/listitem/para/variablelist/varlistentry[term="no"]
|
||||
loader.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="reboot-on-error"]/listitem/para/variablelist/varlistentry[term="auto"]
|
||||
loader.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="secure-boot-enroll-action"]/listitem/variablelist/varlistentry[term="reboot"]
|
||||
loader.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="secure-boot-enroll-action"]/listitem/variablelist/varlistentry[term="shutdown"]
|
||||
|
||||
Reference in New Issue
Block a user