Add option to automatically set securelevel when in Secure Boot mode
authorMatthew Garrett <mjg59@srcf.ucam.org>
Fri, 9 Aug 2013 22:36:30 +0000 (18:36 -0400)
committerAurelien Jarno <aurel32@debian.org>
Fri, 2 Mar 2018 07:52:22 +0000 (07:52 +0000)
UEFI Secure Boot provides a mechanism for ensuring that the firmware will
only load signed bootloaders and kernels. Certain use cases may also
require that the kernel prevent userspace from inserting untrusted kernel
code at runtime. Add a configuration option that enforces this automatically
when enabled.

Signed-off-by: Matthew Garrett <mjg59@srcf.ucam.org>
Gbp-Pq: Topic features/all/securelevel
Gbp-Pq: Name add-option-to-automatically-set-securelevel-when-in-.patch

Documentation/x86/zero-page.txt
arch/x86/Kconfig
arch/x86/boot/compressed/eboot.c
arch/x86/include/uapi/asm/bootparam.h
arch/x86/kernel/setup.c

index 95a4d34af3fdd799d28046e0b992dcbc049817ce..b8527c6b76461c7ee9446630c5acb4cc65867671 100644 (file)
@@ -31,6 +31,8 @@ Offset        Proto   Name            Meaning
 1E9/001        ALL     eddbuf_entries  Number of entries in eddbuf (below)
 1EA/001        ALL     edd_mbr_sig_buf_entries Number of entries in edd_mbr_sig_buffer
                                (below)
+1EB/001        ALL     kbd_status      Numlock is enabled
+1EC/001        ALL     secure_boot     Secure boot is enabled in the firmware
 1EF/001        ALL     sentinel        Used to detect broken bootloaders
 290/040        ALL     edd_mbr_sig_buffer EDD MBR signatures
 2D0/A00        ALL     e820_map        E820 memory map table
index 447542388dd0d5f3742c2e88a7f483ca1314052b..6545bc987c439dbdc71a871d960cfcb2dea7f430 100644 (file)
@@ -1800,6 +1800,19 @@ config EFI_MIXED
 
           If unsure, say N.
 
+config EFI_SECURE_BOOT_SECURELEVEL
+        def_bool n
+       depends on SECURITY_SECURELEVEL
+       depends on EFI
+       prompt "Automatically set securelevel when UEFI Secure Boot is enabled"
+       ---help---
+         UEFI Secure Boot provides a mechanism for ensuring that the
+         firmware will only load signed bootloaders and kernels. Certain
+         use cases may also require that the kernel restrict any userspace
+         mechanism that could insert untrusted code into the kernel.
+         Say Y here to automatically enable securelevel enforcement
+         when a system boots with UEFI Secure Boot enabled.
+
 config SECCOMP
        def_bool y
        prompt "Enable seccomp to safely compute untrusted bytecode"
index cc69e37548db221f128fbadb217f1e6385991b0c..4a7d64ef72689a06fbd239dd7c7fa7b6f4603268 100644 (file)
@@ -12,6 +12,7 @@
 #include <asm/efi.h>
 #include <asm/setup.h>
 #include <asm/desc.h>
+#include <asm/bootparam_utils.h>
 
 #include "../string.h"
 #include "eboot.h"
@@ -710,6 +711,37 @@ void setup_graphics(struct boot_params *boot_params)
        }
 }
 
+static int get_secure_boot(void)
+{
+       u8 sb, setup;
+       unsigned long datasize = sizeof(sb);
+       efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID;
+       efi_status_t status;
+
+       status = efi_early->call((unsigned long)sys_table->runtime->get_variable,
+                                L"SecureBoot", &var_guid, NULL, &datasize, &sb);
+
+       if (status != EFI_SUCCESS)
+               return 0;
+
+       if (sb == 0)
+               return 0;
+
+
+       status = efi_early->call((unsigned long)sys_table->runtime->get_variable,
+                               L"SetupMode", &var_guid, NULL, &datasize,
+                               &setup);
+
+       if (status != EFI_SUCCESS)
+               return 0;
+
+       if (setup == 1)
+               return 0;
+
+       return 1;
+}
+
+
 /*
  * Because the x86 boot code expects to be passed a boot_params we
  * need to create one ourselves (usually the bootloader would create
@@ -1094,6 +1126,10 @@ struct boot_params *efi_main(struct efi_config *c,
        else
                setup_boot_services32(efi_early);
 
+       sanitize_boot_params(boot_params);
+
+       boot_params->secure_boot = get_secure_boot();
+
        setup_graphics(boot_params);
 
        setup_efi_pci(boot_params);
index c18ce67495fadffb504d30031594ebe00acb6210..2b3e5427097b4f4a25e4c385671c68f9871b4027 100644 (file)
@@ -134,7 +134,8 @@ struct boot_params {
        __u8  eddbuf_entries;                           /* 0x1e9 */
        __u8  edd_mbr_sig_buf_entries;                  /* 0x1ea */
        __u8  kbd_status;                               /* 0x1eb */
-       __u8  _pad5[3];                                 /* 0x1ec */
+       __u8  secure_boot;                              /* 0x1ec */
+       __u8  _pad5[2];                                 /* 0x1ed */
        /*
         * The sentinel is set to a nonzero value (0xff) in header.S.
         *
index 6b55012d02a372d1c02116d3cdb1246368058a22..ecaa01d77b2174a0ecfcc6fd9672b3ee5d43a1a0 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/init_ohci1394_dma.h>
 #include <linux/kvm_para.h>
 #include <linux/dma-contiguous.h>
+#include <linux/security.h>
 
 #include <linux/errno.h>
 #include <linux/kernel.h>
@@ -1174,6 +1175,12 @@ void __init setup_arch(char **cmdline_p)
 
        io_delay_init();
 
+#ifdef CONFIG_EFI_SECURE_BOOT_SECURELEVEL
+       if (boot_params.secure_boot) {
+               set_securelevel(1);
+       }
+#endif
+
        /*
         * Parse the ACPI tables for possible boot-time SMP configuration.
         */