Justin Forbes 007e505
From 478a0cff698409224330ea9e25eb332220b55dbb Mon Sep 17 00:00:00 2001
Justin Forbes 007e505
From: Jeremy Cline <jcline@redhat.com>
Justin Forbes 007e505
Date: Mon, 30 Sep 2019 21:22:47 +0000
Justin Forbes 007e505
Subject: [PATCH 1/3] security: lockdown: expose a hook to lock the kernel down
Justin Forbes 007e505
Justin Forbes 007e505
In order to automatically lock down kernels running on UEFI machines
Justin Forbes 007e505
booted in Secure Boot mode, expose the lock_kernel_down() hook.
Justin Forbes 007e505
Justin Forbes 007e505
Signed-off-by: Jeremy Cline <jcline@redhat.com>
Justin Forbes 007e505
---
Justin Forbes 007e505
 include/linux/lsm_hooks.h    | 8 ++++++++
Justin Forbes 007e505
 include/linux/security.h     | 5 +++++
Justin Forbes 007e505
 security/lockdown/lockdown.c | 1 +
Justin Forbes 007e505
 security/security.c          | 6 ++++++
Justin Forbes 007e505
 4 files changed, 20 insertions(+)
Justin Forbes 007e505
Justin Forbes 007e505
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
Justin Forbes 007e505
index a3763247547c..8d76d1f153ed 100644
Justin Forbes 007e505
--- a/include/linux/lsm_hooks.h
Justin Forbes 007e505
+++ b/include/linux/lsm_hooks.h
Justin Forbes 007e505
@@ -1454,6 +1454,12 @@
Justin Forbes 007e505
  *     code execution in kernel space should be permitted.
Justin Forbes 007e505
  *
Justin Forbes 007e505
  *     @what: kernel feature being accessed
Justin Forbes 007e505
+ *
Justin Forbes 007e505
+ * @lock_kernel_down
Justin Forbes 007e505
+ *     Put the kernel into lock-down mode.
Justin Forbes 007e505
+ *
Justin Forbes 007e505
+ *     @where: Where the lock-down is originating from (e.g. command line option)
Justin Forbes 007e505
+ *     @level: The lock-down level (can only increase)
Justin Forbes 007e505
  */
Justin Forbes 007e505
 union security_list_options {
Justin Forbes 007e505
 	int (*binder_set_context_mgr)(struct task_struct *mgr);
Justin Forbes 007e505
@@ -1818,6 +1824,7 @@ union security_list_options {
Justin Forbes 007e505
 	void (*bpf_prog_free_security)(struct bpf_prog_aux *aux);
Justin Forbes 007e505
 #endif /* CONFIG_BPF_SYSCALL */
Justin Forbes 007e505
 	int (*locked_down)(enum lockdown_reason what);
Justin Forbes 007e505
+	int (*lock_kernel_down)(const char *where, enum lockdown_reason level);
Justin Forbes 007e505
 };
Justin Forbes 007e505
 
Justin Forbes 007e505
 struct security_hook_heads {
Justin Forbes 007e505
@@ -2060,6 +2067,7 @@ struct security_hook_heads {
Justin Forbes 007e505
 	struct hlist_head bpf_prog_free_security;
Justin Forbes 007e505
 #endif /* CONFIG_BPF_SYSCALL */
Justin Forbes 007e505
 	struct hlist_head locked_down;
Justin Forbes 007e505
+	struct hlist_head lock_kernel_down;
Justin Forbes 007e505
 } __randomize_layout;
Justin Forbes 007e505
 
Justin Forbes 007e505
 /*
Justin Forbes 007e505
diff --git a/include/linux/security.h b/include/linux/security.h
Justin Forbes 007e505
index a8d59d612d27..467b9ccdf993 100644
Justin Forbes 007e505
--- a/include/linux/security.h
Justin Forbes 007e505
+++ b/include/linux/security.h
Justin Forbes 007e505
@@ -442,6 +442,7 @@ int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen);
Justin Forbes 007e505
 int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
Justin Forbes 007e505
 int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
Justin Forbes 007e505
 int security_locked_down(enum lockdown_reason what);
Justin Forbes 007e505
+int security_lock_kernel_down(const char *where, enum lockdown_reason level);
Justin Forbes 007e505
 #else /* CONFIG_SECURITY */
Justin Forbes 007e505
 
Justin Forbes 007e505
 static inline int call_blocking_lsm_notifier(enum lsm_event event, void *data)
Justin Forbes 007e505
@@ -1269,6 +1270,10 @@ static inline int security_locked_down(enum lockdown_reason what)
Justin Forbes 007e505
 {
Justin Forbes 007e505
 	return 0;
Justin Forbes 007e505
 }
Justin Forbes 007e505
+static inline int security_lock_kernel_down(const char *where, enum lockdown_reason level)
Justin Forbes 007e505
+{
Justin Forbes 007e505
+	return 0;
Justin Forbes 007e505
+}
Justin Forbes 007e505
 #endif	/* CONFIG_SECURITY */
Justin Forbes 007e505
 
Justin Forbes 007e505
 #ifdef CONFIG_SECURITY_NETWORK
Justin Forbes 007e505
diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c
Justin Forbes 007e505
index 8a10b43daf74..72a623075749 100644
Justin Forbes 007e505
--- a/security/lockdown/lockdown.c
Justin Forbes 007e505
+++ b/security/lockdown/lockdown.c
Justin Forbes 007e505
@@ -97,6 +97,7 @@ static int lockdown_is_locked_down(enum lockdown_reason what)
Justin Forbes 007e505
 
Justin Forbes 007e505
 static struct security_hook_list lockdown_hooks[] __lsm_ro_after_init = {
Justin Forbes 007e505
 	LSM_HOOK_INIT(locked_down, lockdown_is_locked_down),
Justin Forbes 007e505
+	LSM_HOOK_INIT(lock_kernel_down, lock_kernel_down),
Justin Forbes 007e505
 };
Justin Forbes 007e505
 
Justin Forbes 007e505
 static int __init lockdown_lsm_init(void)
Justin Forbes 007e505
diff --git a/security/security.c b/security/security.c
Justin Forbes 007e505
index 1bc000f834e2..1506b95427cf 100644
Justin Forbes 007e505
--- a/security/security.c
Justin Forbes 007e505
+++ b/security/security.c
Justin Forbes 007e505
@@ -2404,3 +2404,9 @@ int security_locked_down(enum lockdown_reason what)
Justin Forbes 007e505
 	return call_int_hook(locked_down, 0, what);
Justin Forbes 007e505
 }
Justin Forbes 007e505
 EXPORT_SYMBOL(security_locked_down);
Justin Forbes 007e505
+
Justin Forbes 007e505
+int security_lock_kernel_down(const char *where, enum lockdown_reason level)
Justin Forbes 007e505
+{
Justin Forbes 007e505
+	return call_int_hook(lock_kernel_down, 0, where, level);
Justin Forbes 007e505
+}
Justin Forbes 007e505
+EXPORT_SYMBOL(security_lock_kernel_down);
Justin Forbes 007e505
-- 
Justin Forbes 007e505
2.21.0
Justin Forbes 007e505
Justin Forbes 007e505
Jeremy Cline c8f9da6
From b5123d0553f4ed5e734f6457696cdd30228d1eee Mon Sep 17 00:00:00 2001
bbfe8b3
From: David Howells <dhowells@redhat.com>
bbfe8b3
Date: Tue, 27 Feb 2018 10:04:55 +0000
Justin Forbes 007e505
Subject: [PATCH 2/3] efi: Add an EFI_SECURE_BOOT flag to indicate secure
bbfe8b3
 boot mode
bbfe8b3
bbfe8b3
UEFI machines can be booted in Secure Boot mode.  Add an EFI_SECURE_BOOT
bbfe8b3
flag that can be passed to efi_enabled() to find out whether secure boot is
bbfe8b3
enabled.
bbfe8b3
bbfe8b3
Move the switch-statement in x86's setup_arch() that inteprets the
bbfe8b3
secure_boot boot parameter to generic code and set the bit there.
bbfe8b3
bbfe8b3
Suggested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
bbfe8b3
Signed-off-by: David Howells <dhowells@redhat.com>
bbfe8b3
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
bbfe8b3
cc: linux-efi@vger.kernel.org
Justin Forbes 007e505
[Rebased for context; efi_is_table_address was moved to arch/x86]
Jeremy Cline c8f9da6
Signed-off-by: Jeremy Cline <jcline@redhat.com>
bbfe8b3
---
Jeremy Cline c8f9da6
 arch/x86/kernel/setup.c           | 14 +-----------
bbfe8b3
 drivers/firmware/efi/Makefile     |  1 +
Jeremy Cline c8f9da6
 drivers/firmware/efi/secureboot.c | 38 +++++++++++++++++++++++++++++++
Jeremy Cline c8f9da6
 include/linux/efi.h               | 18 ++++++++++-----
Jeremy Cline c8f9da6
 4 files changed, 52 insertions(+), 19 deletions(-)
bbfe8b3
 create mode 100644 drivers/firmware/efi/secureboot.c
bbfe8b3
bbfe8b3
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
Justin Forbes 007e505
index bbe35bf879f5..7e528b6af86b 100644
bbfe8b3
--- a/arch/x86/kernel/setup.c
bbfe8b3
+++ b/arch/x86/kernel/setup.c
Justin Forbes 007e505
@@ -1179,19 +1179,7 @@ void __init setup_arch(char **cmdline_p)
bbfe8b3
 	/* Allocate bigger log buffer */
bbfe8b3
 	setup_log_buf(1);
Jeremy Cline c8f9da6
 
bbfe8b3
-	if (efi_enabled(EFI_BOOT)) {
bbfe8b3
-		switch (boot_params.secure_boot) {
bbfe8b3
-		case efi_secureboot_mode_disabled:
bbfe8b3
-			pr_info("Secure boot disabled\n");
bbfe8b3
-			break;
bbfe8b3
-		case efi_secureboot_mode_enabled:
bbfe8b3
-			pr_info("Secure boot enabled\n");
bbfe8b3
-			break;
bbfe8b3
-		default:
bbfe8b3
-			pr_info("Secure boot could not be determined\n");
bbfe8b3
-			break;
bbfe8b3
-		}
bbfe8b3
-	}
bbfe8b3
+	efi_set_secure_boot(boot_params.secure_boot);
Jeremy Cline c8f9da6
 
bbfe8b3
 	reserve_initrd();
Jeremy Cline c8f9da6
 
bbfe8b3
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
Justin Forbes 007e505
index 4ac2de4dfa72..195b078a423c 100644
bbfe8b3
--- a/drivers/firmware/efi/Makefile
bbfe8b3
+++ b/drivers/firmware/efi/Makefile
bbfe8b3
@@ -24,6 +24,7 @@ obj-$(CONFIG_EFI_FAKE_MEMMAP)		+= fake_mem.o
bbfe8b3
 obj-$(CONFIG_EFI_BOOTLOADER_CONTROL)	+= efibc.o
bbfe8b3
 obj-$(CONFIG_EFI_TEST)			+= test/
bbfe8b3
 obj-$(CONFIG_EFI_DEV_PATH_PARSER)	+= dev-path-parser.o
bbfe8b3
+obj-$(CONFIG_EFI)			+= secureboot.o
bbfe8b3
 obj-$(CONFIG_APPLE_PROPERTIES)		+= apple-properties.o
Justin Forbes 007e505
 obj-$(CONFIG_EFI_RCI2_TABLE)		+= rci2-table.o
Jeremy Cline c8f9da6
 
bbfe8b3
diff --git a/drivers/firmware/efi/secureboot.c b/drivers/firmware/efi/secureboot.c
bbfe8b3
new file mode 100644
bbfe8b3
index 000000000000..9070055de0a1
bbfe8b3
--- /dev/null
bbfe8b3
+++ b/drivers/firmware/efi/secureboot.c
bbfe8b3
@@ -0,0 +1,38 @@
bbfe8b3
+/* Core kernel secure boot support.
bbfe8b3
+ *
bbfe8b3
+ * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved.
bbfe8b3
+ * Written by David Howells (dhowells@redhat.com)
bbfe8b3
+ *
bbfe8b3
+ * This program is free software; you can redistribute it and/or
bbfe8b3
+ * modify it under the terms of the GNU General Public Licence
bbfe8b3
+ * as published by the Free Software Foundation; either version
bbfe8b3
+ * 2 of the Licence, or (at your option) any later version.
bbfe8b3
+ */
bbfe8b3
+
bbfe8b3
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
bbfe8b3
+
bbfe8b3
+#include <linux/efi.h>
bbfe8b3
+#include <linux/kernel.h>
bbfe8b3
+#include <linux/printk.h>
bbfe8b3
+
bbfe8b3
+/*
bbfe8b3
+ * Decide what to do when UEFI secure boot mode is enabled.
bbfe8b3
+ */
bbfe8b3
+void __init efi_set_secure_boot(enum efi_secureboot_mode mode)
bbfe8b3
+{
bbfe8b3
+	if (efi_enabled(EFI_BOOT)) {
bbfe8b3
+		switch (mode) {
bbfe8b3
+		case efi_secureboot_mode_disabled:
bbfe8b3
+			pr_info("Secure boot disabled\n");
bbfe8b3
+			break;
bbfe8b3
+		case efi_secureboot_mode_enabled:
bbfe8b3
+			set_bit(EFI_SECURE_BOOT, &efi.flags);
bbfe8b3
+			pr_info("Secure boot enabled\n");
bbfe8b3
+			break;
bbfe8b3
+		default:
bbfe8b3
+			pr_warning("Secure boot could not be determined (mode %u)\n",
bbfe8b3
+				   mode);
bbfe8b3
+			break;
bbfe8b3
+		}
bbfe8b3
+	}
bbfe8b3
+}
bbfe8b3
diff --git a/include/linux/efi.h b/include/linux/efi.h
Justin Forbes 007e505
index 21d81021c1f4..758ec061d03b 100644
bbfe8b3
--- a/include/linux/efi.h
bbfe8b3
+++ b/include/linux/efi.h
Justin Forbes 007e505
@@ -1204,6 +1204,14 @@ extern int __init efi_setup_pcdp_console(char *);
bbfe8b3
 #define EFI_DBG			8	/* Print additional debug info at runtime */
bbfe8b3
 #define EFI_NX_PE_DATA		9	/* Can runtime data regions be mapped non-executable? */
bbfe8b3
 #define EFI_MEM_ATTR		10	/* Did firmware publish an EFI_MEMORY_ATTRIBUTES table? */
bbfe8b3
+#define EFI_SECURE_BOOT		11	/* Are we in Secure Boot mode? */
bbfe8b3
+
bbfe8b3
+enum efi_secureboot_mode {
bbfe8b3
+	efi_secureboot_mode_unset,
bbfe8b3
+	efi_secureboot_mode_unknown,
bbfe8b3
+	efi_secureboot_mode_disabled,
bbfe8b3
+	efi_secureboot_mode_enabled,
bbfe8b3
+};
Jeremy Cline c8f9da6
 
bbfe8b3
 #ifdef CONFIG_EFI
bbfe8b3
 /*
Justin Forbes 007e505
@@ -1214,6 +1222,8 @@ static inline bool efi_enabled(int feature)
Justin Forbes 007e505
 	return test_bit(feature, &efi.flags) != 0;
Justin Forbes 007e505
 }
16332ac
 extern void efi_reboot(enum reboot_mode reboot_mode, const char *__unused);
Jeremy Cline c8f9da6
+
bbfe8b3
+extern void __init efi_set_secure_boot(enum efi_secureboot_mode mode);
bbfe8b3
 #else
bbfe8b3
 static inline bool efi_enabled(int feature)
bbfe8b3
 {
Justin Forbes 007e505
@@ -1227,6 +1237,8 @@ efi_capsule_pending(int *reset_type)
bbfe8b3
 {
16332ac
 	return false;
bbfe8b3
 }
Jeremy Cline c8f9da6
+
bbfe8b3
+static inline void efi_set_secure_boot(enum efi_secureboot_mode mode) {}
bbfe8b3
 #endif
Jeremy Cline c8f9da6
 
bbfe8b3
 extern int efi_status_to_err(efi_status_t status);
Justin Forbes 007e505
@@ -1619,12 +1631,6 @@ static inline bool efi_runtime_disabled(void) { return true; }
bbfe8b3
 extern void efi_call_virt_check_flags(unsigned long flags, const char *call);
Jeremy Cline 10301b4
 extern unsigned long efi_call_virt_save_flags(void);
Jeremy Cline c8f9da6
 
bbfe8b3
-enum efi_secureboot_mode {
bbfe8b3
-	efi_secureboot_mode_unset,
bbfe8b3
-	efi_secureboot_mode_unknown,
bbfe8b3
-	efi_secureboot_mode_disabled,
bbfe8b3
-	efi_secureboot_mode_enabled,
bbfe8b3
-};
bbfe8b3
 enum efi_secureboot_mode efi_get_secureboot(efi_system_table_t *sys_table);
Jeremy Cline c8f9da6
 
bbfe8b3
 #ifdef CONFIG_RESET_ATTACK_MITIGATION
bbfe8b3
-- 
Justin Forbes 007e505
2.21.0
Justin Forbes 007e505
bbfe8b3
Justin Forbes 007e505
From 15368f76d4997912318d35c52bfeb9041d85098e Mon Sep 17 00:00:00 2001
bbfe8b3
From: David Howells <dhowells@redhat.com>
Justin Forbes 007e505
Date: Mon, 30 Sep 2019 21:28:16 +0000
Justin Forbes 007e505
Subject: [PATCH 3/3] efi: Lock down the kernel if booted in secure boot mode
bbfe8b3
Justin Forbes 007e505
UEFI Secure Boot provides a mechanism for ensuring that the firmware
Justin Forbes 007e505
will only load signed bootloaders and kernels.  Certain use cases may
Justin Forbes 007e505
also require that all kernel modules also be signed.  Add a
Justin Forbes 007e505
configuration option that to lock down the kernel - which includes
Justin Forbes 007e505
requiring validly signed modules - if the kernel is secure-booted.
bbfe8b3
bbfe8b3
Signed-off-by: David Howells <dhowells@redhat.com>
Justin Forbes 007e505
Signed-off-by: Jeremy Cline <jcline@redhat.com>
bbfe8b3
---
Justin Forbes 007e505
 arch/x86/kernel/setup.c   |  8 ++++++++
Justin Forbes 007e505
 security/lockdown/Kconfig | 13 +++++++++++++
Justin Forbes 007e505
 2 files changed, 21 insertions(+)
bbfe8b3
bbfe8b3
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
Justin Forbes 007e505
index 77ea96b794bd..a119e1bc9623 100644
bbfe8b3
--- a/arch/x86/kernel/setup.c
bbfe8b3
+++ b/arch/x86/kernel/setup.c
Justin Forbes 007e505
@@ -73,6 +73,7 @@
Justin Forbes 007e505
 #include <linux/jiffies.h>
Justin Forbes 007e505
 #include <linux/mem_encrypt.h>
Justin Forbes 007e505
 #include <linux/sizes.h>
bbfe8b3
+#include <linux/security.h>
Jeremy Cline 10301b4
 
Justin Forbes 007e505
 #include <linux/usb/xhci-dbgp.h>
Justin Forbes 007e505
 #include <video/edid.h>
Justin Forbes 007e505
@@ -1027,6 +1028,13 @@ void __init setup_arch(char **cmdline_p)
bbfe8b3
 	if (efi_enabled(EFI_BOOT))
bbfe8b3
 		efi_init();
Jeremy Cline 10301b4
 
bbfe8b3
+	efi_set_secure_boot(boot_params.secure_boot);
bbfe8b3
+
Justin Forbes 007e505
+#ifdef CONFIG_LOCK_DOWN_IN_EFI_SECURE_BOOT
Justin Forbes 007e505
+	if (efi_enabled(EFI_SECURE_BOOT))
Justin Forbes 007e505
+		security_lock_kernel_down("EFI Secure Boot mode", LOCKDOWN_CONFIDENTIALITY_MAX);
Justin Forbes 007e505
+#endif
Jeremy Cline 10301b4
+
324e598
 	dmi_setup();
324e598
 
324e598
 	/*
Justin Forbes 007e505
diff --git a/security/lockdown/Kconfig b/security/lockdown/Kconfig
Justin Forbes 007e505
index e84ddf484010..d0501353a4b9 100644
Justin Forbes 007e505
--- a/security/lockdown/Kconfig
Justin Forbes 007e505
+++ b/security/lockdown/Kconfig
Justin Forbes 007e505
@@ -16,6 +16,19 @@ config SECURITY_LOCKDOWN_LSM_EARLY
Justin Forbes 007e505
 	  subsystem is fully initialised. If enabled, lockdown will
Justin Forbes 007e505
 	  unconditionally be called before any other LSMs.
Jeremy Cline 10301b4
 
bbfe8b3
+config LOCK_DOWN_IN_EFI_SECURE_BOOT
bbfe8b3
+	bool "Lock down the kernel in EFI Secure Boot mode"
bbfe8b3
+	default n
Justin Forbes 007e505
+	depends on EFI && SECURITY_LOCKDOWN_LSM_EARLY
bbfe8b3
+	help
bbfe8b3
+	  UEFI Secure Boot provides a mechanism for ensuring that the firmware
bbfe8b3
+	  will only load signed bootloaders and kernels.  Secure boot mode may
bbfe8b3
+	  be determined from EFI variables provided by the system firmware if
bbfe8b3
+	  not indicated by the boot parameters.
bbfe8b3
+
Justin Forbes 007e505
+	  Enabling this option results in kernel lockdown being triggered if
Justin Forbes 007e505
+	  EFI Secure Boot is set.
bbfe8b3
+
Justin Forbes 007e505
 choice
Justin Forbes 007e505
 	prompt "Kernel default lockdown mode"
Justin Forbes 007e505
 	default LOCK_DOWN_KERNEL_FORCE_NONE
bbfe8b3
-- 
Justin Forbes 007e505
2.21.0