]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-boot: Be more precise about secure boot modes
authorJan Janssen <medhefgo@web.de>
Wed, 20 Oct 2021 08:11:45 +0000 (10:11 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 22 Oct 2021 08:08:38 +0000 (10:08 +0200)
Fixes: #11559
src/basic/efivars.c
src/basic/efivars.h
src/boot/bootctl.c
src/boot/efi/boot.c
src/boot/efi/secure-boot.c
src/boot/efi/secure-boot.h
src/fundamental/efivars-fundamental.c [new file with mode: 0644]
src/fundamental/efivars-fundamental.h [moved from src/fundamental/efi-loader-features.h with 54% similarity]
src/fundamental/meson.build
src/shared/efi-loader.h

index 3e5c5e68dd0b5906edb8577cfc60c92e4a73a34a..bb115a7b99f20ded9f2fe640d9938b3790af64b8 100644 (file)
@@ -293,13 +293,28 @@ bool is_efi_secure_boot(void) {
         return cache > 0;
 }
 
-bool is_efi_secure_boot_setup_mode(void) {
-        static int cache = -1;
+SecureBootMode efi_get_secure_boot_mode(void) {
+        static SecureBootMode cache = _SECURE_BOOT_INVALID;
 
-        if (cache < 0)
-                cache = read_flag(EFI_GLOBAL_VARIABLE(SetupMode));
+        if (cache != _SECURE_BOOT_INVALID)
+                return cache;
 
-        return cache > 0;
+        int secure = read_flag(EFI_GLOBAL_VARIABLE(SecureBoot));
+        if (secure < 0) {
+                if (secure != -ENOENT)
+                        log_debug_errno(secure, "Error reading SecureBoot EFI variable: %m");
+                return (cache = SECURE_BOOT_UNSUPPORTED);
+        }
+
+        /* We can assume false for all these if they are abscent (AuditMode and
+         * DeployedMode may not exist on older firmware). */
+        int audit    = read_flag(EFI_GLOBAL_VARIABLE(AuditMode));
+        int deployed = read_flag(EFI_GLOBAL_VARIABLE(DeployedMode));
+        int setup    = read_flag(EFI_GLOBAL_VARIABLE(SetupMode));
+        log_debug("Secure boot variables: SecureBoot=%d AuditMode=%d DeployedMode=%d SetupMode=%d",
+                  secure, audit, deployed, setup);
+
+        return (cache = decode_secure_boot_mode(secure, audit > 0, deployed > 0, setup > 0));
 }
 
 static int read_efi_options_variable(char **line) {
index cb6ad9e0a2d2286b29d96206ec972f0a2be4ca89..494154b3618e5c534b4db328d561aaaf0d641158 100644 (file)
@@ -10,6 +10,7 @@
 
 #include "sd-id128.h"
 
+#include "efivars-fundamental.h"
 #include "time-util.h"
 
 #define EFI_VENDOR_LOADER      SD_ID128_MAKE(4a,67,b0,82,0a,4c,41,cf,b6,c7,44,0b,29,bb,8c,4f)
@@ -48,7 +49,7 @@ int efi_set_variable_string(const char *variable, const char *p);
 
 bool is_efi_boot(void);
 bool is_efi_secure_boot(void);
-bool is_efi_secure_boot_setup_mode(void);
+SecureBootMode efi_get_secure_boot_mode(void);
 
 int cache_efi_options_variable(void);
 int systemd_efi_options_variable(char **line);
@@ -80,8 +81,8 @@ static inline bool is_efi_secure_boot(void) {
         return false;
 }
 
-static inline bool is_efi_secure_boot_setup_mode(void) {
-        return false;
+static inline SecureBootMode efi_get_secure_boot_mode(void) {
+        return SECURE_BOOT_UNKNOWN;
 }
 
 static inline int cache_efi_options_variable(void) {
index b0b3d4f8ae049abc745ff000d95d44251f061e16..e3e1040a4bfe5a98bf1ceab2d2399d16abd1d877 100644 (file)
@@ -1322,10 +1322,12 @@ static int verb_status(int argc, char *argv[], void *userdata) {
                 if (k < 0 && k != -ENOENT)
                         r = log_warning_errno(k, "Failed to read EFI variable LoaderDevicePartUUID: %m");
 
+                SecureBootMode secure = efi_get_secure_boot_mode();
                 printf("System:\n");
                 printf("     Firmware: %s%s (%s)%s\n", ansi_highlight(), strna(fw_type), strna(fw_info), ansi_normal());
-                printf("  Secure Boot: %sd\n", enable_disable(is_efi_secure_boot()));
-                printf("   Setup Mode: %s\n", is_efi_secure_boot_setup_mode() ? "setup" : "user");
+                printf("  Secure Boot: %sd (%s)\n",
+                       enable_disable(IN_SET(secure, SECURE_BOOT_USER, SECURE_BOOT_DEPLOYED)),
+                       secure_boot_mode_to_string(secure));
                 printf(" TPM2 Support: %s\n", yes_no(efi_has_tpm2()));
 
                 k = efi_get_reboot_to_firmware();
index 6c4ddb193988b7fea39010240e0f0d93b6af2455..ba097bf20cefc389ee07e054c31f180effbe49b7 100644 (file)
@@ -8,7 +8,7 @@
 #include "devicetree.h"
 #include "disk.h"
 #include "drivers.h"
-#include "efi-loader-features.h"
+#include "efivars-fundamental.h"
 #include "graphics.h"
 #include "linux.h"
 #include "measure.h"
@@ -434,7 +434,7 @@ static void ps_bool(const CHAR16 *fmt, BOOLEAN value) {
 static void print_status(Config *config, CHAR16 *loaded_image_path) {
         UINT64 key;
         UINTN x_max, y_max;
-        BOOLEAN setup_mode = FALSE;
+        SecureBootMode secure;
         _cleanup_freepool_ CHAR16 *device_part_uuid = NULL, *default_efivar = NULL;
 
         assert(config);
@@ -443,9 +443,9 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) {
         clear_screen(COLOR_NORMAL);
         console_query_mode(&x_max, &y_max);
 
+        secure = secure_boot_mode();
         (void) efivar_get(LOADER_GUID, L"LoaderDevicePartUUID", &device_part_uuid);
         (void) efivar_get(LOADER_GUID, L"LoaderEntryDefault", &default_efivar);
-        (void) efivar_get_boolean_u8(EFI_GLOBAL_GUID, L"SetupMode", &setup_mode);
 
         /* We employ some unusual indentation here for readability. */
 
@@ -457,8 +457,7 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) {
         ps_string(L"       firmware vendor: %s\n",      ST->FirmwareVendor);
             Print(L"      firmware version: %u.%02u\n", ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
             Print(L"        OS indications: %lu\n",     get_os_indications_supported());
-          ps_bool(L"           secure boot: %s\n",      secure_boot_enabled());
-          ps_bool(L"            setup mode: %s\n",      setup_mode);
+            Print(L"           secure boot: %s (%s)\n", yes_no(IN_SET(secure, SECURE_BOOT_USER, SECURE_BOOT_DEPLOYED)), secure_boot_mode_to_string(secure));
           ps_bool(L"                  shim: %s\n",      shim_loaded());
             Print(L"          console mode: %d/%d (%lu x %lu)\n", ST->ConOut->Mode->Mode, ST->ConOut->Mode->MaxMode - 1LL, x_max, y_max);
 
index c1dfcfc5cb0beb1c12a02962ee1c366a30528614..efea1457195ac1427117d9f136ddc4c6bc3767a0 100644 (file)
@@ -12,6 +12,23 @@ BOOLEAN secure_boot_enabled(void) {
         return !EFI_ERROR(err) && secure;
 }
 
+SecureBootMode secure_boot_mode(void) {
+        BOOLEAN secure, audit = FALSE, deployed = FALSE, setup = FALSE;
+        EFI_STATUS err;
+
+        err = efivar_get_boolean_u8(EFI_GLOBAL_GUID, L"SecureBoot", &secure);
+        if (EFI_ERROR(err))
+                return SECURE_BOOT_UNSUPPORTED;
+
+        /* We can assume FALSE for all these if they are abscent (AuditMode and
+         * DeployedMode may not exist on older firmware). */
+        (void) efivar_get_boolean_u8(EFI_GLOBAL_GUID, L"AuditMode", &audit);
+        (void) efivar_get_boolean_u8(EFI_GLOBAL_GUID, L"DeployedMode", &deployed);
+        (void) efivar_get_boolean_u8(EFI_GLOBAL_GUID, L"SetupMode", &setup);
+
+        return decode_secure_boot_mode(secure, audit, deployed, setup);
+}
+
 #ifdef SBAT_DISTRO
 static const char sbat[] _used_ _section_ (".sbat") _align_ (512) =
         "sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md\n"
index d06a7deaaa37324a4a5e5d5e1dfff024373db05c..d5f6ba82d449983b3b7949d5f526fdc436012b6f 100644 (file)
@@ -2,5 +2,7 @@
 #pragma once
 
 #include <efi.h>
+#include "efivars-fundamental.h"
 
 BOOLEAN secure_boot_enabled(void);
+SecureBootMode secure_boot_mode(void);
diff --git a/src/fundamental/efivars-fundamental.c b/src/fundamental/efivars-fundamental.c
new file mode 100644 (file)
index 0000000..6e22232
--- /dev/null
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "efivars-fundamental.h"
+
+static const sd_char * const table[_SECURE_BOOT_MAX] = {
+        [SECURE_BOOT_UNSUPPORTED] = STR_C("unsupported"),
+        [SECURE_BOOT_UNKNOWN]     = STR_C("unknown"),
+        [SECURE_BOOT_AUDIT]       = STR_C("audit"),
+        [SECURE_BOOT_DEPLOYED]    = STR_C("deployed"),
+        [SECURE_BOOT_SETUP]       = STR_C("setup"),
+        [SECURE_BOOT_USER]        = STR_C("user"),
+};
+
+const sd_char *secure_boot_mode_to_string(SecureBootMode m) {
+        return (m >= 0 && m < _SECURE_BOOT_MAX) ? table[m] : NULL;
+}
+
+SecureBootMode decode_secure_boot_mode(
+                sd_bool secure,
+                sd_bool audit,
+                sd_bool deployed,
+                sd_bool setup) {
+
+        /* See figure 32-4 Secure Boot Modes from UEFI Specification 2.9 */
+        if (secure && deployed && !audit && !setup)
+                return SECURE_BOOT_DEPLOYED;
+        if (secure && !deployed && !audit && !setup)
+                return SECURE_BOOT_USER;
+        if (!secure && !deployed && audit && setup)
+                return SECURE_BOOT_AUDIT;
+        if (!secure && !deployed && !audit && setup)
+                return SECURE_BOOT_SETUP;
+
+        /* Well, this should not happen. */
+        return SECURE_BOOT_UNKNOWN;
+}
similarity index 54%
rename from src/fundamental/efi-loader-features.h
rename to src/fundamental/efivars-fundamental.h
index 287ae3c89270958781f9225c0510dbf9f4314110..a70810a8d3678bcf8b718190ab4586acadd379b7 100644 (file)
@@ -1,6 +1,9 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #pragma once
 
+#include <errno.h>
+#include "string-util-fundamental.h"
+
 #ifndef UINT64_C
 #  define UINT64_C(c) (c ## ULL)
 #endif
 #define EFI_LOADER_FEATURE_XBOOTLDR                (UINT64_C(1) << 5)
 #define EFI_LOADER_FEATURE_RANDOM_SEED             (UINT64_C(1) << 6)
 #define EFI_LOADER_FEATURE_LOAD_DRIVER             (UINT64_C(1) << 7)
+
+typedef enum SecureBootMode {
+        SECURE_BOOT_UNSUPPORTED,
+        SECURE_BOOT_UNKNOWN,
+        SECURE_BOOT_AUDIT,
+        SECURE_BOOT_DEPLOYED,
+        SECURE_BOOT_SETUP,
+        SECURE_BOOT_USER,
+        _SECURE_BOOT_MAX,
+        _SECURE_BOOT_INVALID = -EINVAL,
+} SecureBootMode;
+
+const sd_char *secure_boot_mode_to_string(SecureBootMode m);
+SecureBootMode decode_secure_boot_mode(
+                sd_bool secure,
+                sd_bool audit,
+                sd_bool deployed,
+                sd_bool setup);
index 3aa9fab8cbf39913873bdc0b04e6c2fb9e6a927f..3c9f07b191d021d562df5cb8c3cc3c0d84a0ab25 100644 (file)
@@ -3,13 +3,14 @@
 fundamental_path = meson.current_source_dir()
 
 fundamental_headers = files(
-        'efi-loader-features.h',
+        'efivars-fundamental.h',
         'macro-fundamental.h',
         'string-util-fundamental.h',
         'sha256.h',
         'type.h')
 
 sources = '''
+        efivars-fundamental.c
         string-util-fundamental.c
         sha256.c
 '''.split()
index bc5769bb6b2ce77ccf55ac707ad487cfc8a2a839..7a100e5364282efa421e963ecf639fc96c0b72ca 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <sys/stat.h>
 
-#include "efi-loader-features.h"
+#include "efivars-fundamental.h"
 #include "efivars.h"
 
 #if ENABLE_EFI