arm64: add kernel config option to set securelevel when in Secure Boot mode
authorLinn Crosetto <linn@hpe.com>
Tue, 30 Aug 2016 17:54:38 +0000 (11:54 -0600)
committerAurelien Jarno <aurel32@debian.org>
Fri, 2 Mar 2018 07:52:22 +0000 (07:52 +0000)
Add a kernel configuration option to enable securelevel, to restrict
userspace's ability to modify the running kernel when UEFI Secure Boot is
enabled. Based on the x86 patch by Matthew Garrett.

Determine the state of Secure Boot in the EFI stub and pass this to the
kernel using the FDT.

Signed-off-by: Linn Crosetto <linn@hpe.com>
Gbp-Pq: Topic features/all/securelevel
Gbp-Pq: Name arm64-add-kernel-config-option-to-set-securelevel-wh.patch

arch/arm64/Kconfig
drivers/firmware/efi/arm-init.c
drivers/firmware/efi/efi.c
drivers/firmware/efi/libstub/arm-stub.c
drivers/firmware/efi/libstub/efistub.h
drivers/firmware/efi/libstub/fdt.c
include/linux/efi.h

index cf57a7799a0f3daf1183f24ef9edef14e41c6fd6..3cd5e227058d8e8183a4eeff5584a1f882c57d44 100644 (file)
@@ -987,6 +987,19 @@ config EFI
          allow the kernel to be booted as an EFI application. This
          is only useful on systems that have UEFI firmware.
 
+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 DMI
        bool "Enable support for SMBIOS (DMI) tables"
        depends on EFI
index 8efe13075c922e6b79131af4af2d897245b94a42..6089026e9d239d1d08d64cc648afe358590d1653 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/of_fdt.h>
 #include <linux/platform_device.h>
 #include <linux/screen_info.h>
+#include <linux/security.h>
 
 #include <asm/efi.h>
 
@@ -244,6 +245,12 @@ void __init efi_init(void)
             "Unexpected EFI_MEMORY_DESCRIPTOR version %ld",
              efi.memmap.desc_version);
 
+#ifdef CONFIG_EFI_SECURE_BOOT_SECURELEVEL
+       if (params.secure_boot > 0) {
+               set_securelevel(1);
+       }
+#endif
+
        if (uefi_init() < 0)
                return;
 
index 2f47c5b5f4cb8fb837f4c154a976112e06ea37d2..c58588e7be39e72b7ed564f81cc4a0a17b52b384 100644 (file)
@@ -582,7 +582,8 @@ static __initdata struct params fdt_params[] = {
        UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap),
        UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size),
        UEFI_PARAM("MemMap Desc. Size", "linux,uefi-mmap-desc-size", desc_size),
-       UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver)
+       UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver),
+       UEFI_PARAM("Secure Boot Enabled", "linux,uefi-secure-boot", secure_boot)
 };
 
 static __initdata struct params xen_fdt_params[] = {
index d1cb612ecbc9edb0fea4bc624a9c9ca754b02490..61ad972f0f8b0e57b9e74395f8ac2286e48130ce 100644 (file)
@@ -20,7 +20,7 @@
 
 bool __nokaslr;
 
-static int efi_get_secureboot(efi_system_table_t *sys_table_arg)
+int efi_get_secureboot(efi_system_table_t *sys_table_arg)
 {
        static efi_char16_t const sb_var_name[] = {
                'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 };
index fac67992bede5867ff9093f76df69583b1400492..99433afad54acdd8a79aaa92f1929c9c0887e59f 100644 (file)
@@ -54,4 +54,5 @@ efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
 
 efi_status_t check_platform_features(efi_system_table_t *sys_table_arg);
 
+int efi_get_secureboot(efi_system_table_t *sys_table_arg);
 #endif
index 260c4b4b492ec38735715859522068da40c21381..5d458baeb872988a9715ff444d408bc7bab0b555 100644 (file)
@@ -134,6 +134,13 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
                        return efi_status;
                }
        }
+
+       fdt_val32 = cpu_to_fdt32(efi_get_secureboot(sys_table));
+       status = fdt_setprop(fdt, node, "linux,uefi-secure-boot",
+                            &fdt_val32, sizeof(fdt_val32));
+       if (status)
+               goto fdt_set_fail;
+
        return EFI_SUCCESS;
 
 fdt_set_fail:
index b020dd370d3271cd205f4172980eac9fd2b6a4f1..566fa48b90f9c063264f7e06c78b91743ea3cc07 100644 (file)
@@ -717,6 +717,7 @@ struct efi_fdt_params {
        u32 mmap_size;
        u32 desc_size;
        u32 desc_ver;
+       u32 secure_boot;
 };
 
 typedef struct {