Add Matthew Garrett's securelevel patchset in preparation for Secure Boot support

This commit is contained in:
Ben Hutchings 2016-04-03 04:04:45 +01:00
parent ea7af96b4d
commit 7321950826
22 changed files with 1163 additions and 0 deletions

2
debian/changelog vendored
View File

@ -8,6 +8,8 @@ linux (4.5-1~exp2) UNRELEASED; urgency=medium
write support
* Merge linux-tools source package into linux
(Closes: #550379, #573483, #816500)
* Add Matthew Garrett's securelevel patchset in preparation for Secure Boot
support (see Documentation/security/securelevel.txt)
-- Ben Hutchings <ben@decadent.org.uk> Fri, 25 Mar 2016 13:43:57 +0000

View File

@ -6655,6 +6655,7 @@ CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_NETWORK_XFRM=y
# CONFIG_SECURITY_PATH is not set
CONFIG_SECURITY_SECURELEVEL=y
# CONFIG_INTEL_TXT is not set
CONFIG_LSM_MMAP_MIN_ADDR=32768
## choice: Default security module

View File

@ -54,6 +54,7 @@ CONFIG_X86_SMAP=y
CONFIG_X86_INTEL_MPX=y
CONFIG_EFI=y
CONFIG_EFI_STUB=y
CONFIG_EFI_SECURE_BOOT_SECURELEVEL=y
CONFIG_SECCOMP=y
CONFIG_KEXEC=y
CONFIG_CRASH_DUMP=y

View File

@ -0,0 +1,64 @@
From: Linn Crosetto <linn@hpe.com>
Date: Fri, 4 Mar 2016 16:08:24 -0700
Subject: [16/18] acpi: Disable ACPI table override if securelevel is set
Origin: https://github.com/mjg59/linux/commit/a4a5ed2835e8ea042868b7401dced3f517cafa76
From the kernel documentation (initrd_table_override.txt):
If the ACPI_INITRD_TABLE_OVERRIDE compile option is true, it is possible
to override nearly any ACPI table provided by the BIOS with an
instrumented, modified one.
When securelevel is set, the kernel should disallow any unauthenticated
changes to kernel space. ACPI tables contain code invoked by the kernel, so
do not allow ACPI tables to be overridden if securelevel is set.
Signed-off-by: Linn Crosetto <linn@hpe.com>
---
arch/x86/kernel/setup.c | 12 ++++++------
drivers/acpi/osl.c | 6 ++++++
2 files changed, 12 insertions(+), 6 deletions(-)
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1136,6 +1136,12 @@ void __init setup_arch(char **cmdline_p)
/* Allocate bigger log buffer */
setup_log_buf(1);
+#ifdef CONFIG_EFI_SECURE_BOOT_SECURELEVEL
+ if (boot_params.secure_boot) {
+ set_securelevel(1);
+ }
+#endif
+
reserve_initrd();
#if defined(CONFIG_ACPI) && defined(CONFIG_BLK_DEV_INITRD)
@@ -1146,12 +1152,6 @@ 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.
*/
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -698,6 +698,12 @@ void __init acpi_initrd_override(void *d
if (table_nr == 0)
return;
+ if (get_securelevel() > 0) {
+ pr_notice(PREFIX
+ "securelevel enabled, ignoring table override\n");
+ return;
+ }
+
acpi_tables_addr =
memblock_find_in_range(0, max_low_pfn_mapped << PAGE_SHIFT,
all_tables_size, PAGE_SIZE);

View File

@ -0,0 +1,45 @@
From: Linn Crosetto <linn@hpe.com>
Date: Wed, 16 Mar 2016 14:43:33 -0600
Subject: [17/18] acpi: Disable APEI error injection if securelevel is set
Origin: https://github.com/mjg59/linux/commit/d7a6be58edc01b1c66ecd8fcc91236bfbce0a420
ACPI provides an error injection mechanism, EINJ, for debugging and testing
the ACPI Platform Error Interface (APEI) and other RAS features. If
supported by the firmware, ACPI specification 5.0 and later provide for a
way to specify a physical memory address to which to inject the error.
Injecting errors through EINJ can produce errors which to the platform are
indistinguishable from real hardware errors. This can have undesirable
side-effects, such as causing the platform to mark hardware as needing
replacement.
While it does not provide a method to load unauthenticated privileged code,
the effect of these errors may persist across reboots and affect trust in
the underlying hardware, so disable error injection through EINJ if
securelevel is set.
Signed-off-by: Linn Crosetto <linn@hpe.com>
---
drivers/acpi/apei/einj.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/drivers/acpi/apei/einj.c
+++ b/drivers/acpi/apei/einj.c
@@ -29,6 +29,7 @@
#include <linux/nmi.h>
#include <linux/delay.h>
#include <linux/mm.h>
+#include <linux/security.h>
#include <asm/unaligned.h>
#include "apei-internal.h"
@@ -521,6 +522,9 @@ static int einj_error_inject(u32 type, u
int rc;
unsigned long pfn;
+ if (get_securelevel() > 0)
+ return -EPERM;
+
/* If user manually set "flags", make sure it is legal */
if (flags && (flags &
~(SETWA_FLAGS_APICID|SETWA_FLAGS_MEM|SETWA_FLAGS_PCIE_SBDF)))

View File

@ -0,0 +1,36 @@
From: Josh Boyer <jwboyer@redhat.com>
Date: Mon, 25 Jun 2012 19:57:30 -0400
Subject: [07/18] acpi: Ignore acpi_rsdp kernel parameter when securelevel is
set
Origin: https://github.com/mjg59/linux/commit/9524fadac774fbe85e2ac6abe7b957b1750c7e36
This option allows userspace to pass the RSDP address to the kernel, which
makes it possible for a user to execute arbitrary code in the kernel.
Disable this when securelevel is set.
Signed-off-by: Josh Boyer <jwboyer@redhat.com>
---
drivers/acpi/osl.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 814d5f83b75e..242ca81bb606 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -40,6 +40,7 @@
#include <linux/list.h>
#include <linux/jiffies.h>
#include <linux/semaphore.h>
+#include <linux/security.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -254,7 +255,7 @@ early_param("acpi_rsdp", setup_acpi_rsdp);
acpi_physical_address __init acpi_os_get_root_pointer(void)
{
#ifdef CONFIG_KEXEC
- if (acpi_rsdp)
+ if (acpi_rsdp && (get_securelevel() <= 0))
return acpi_rsdp;
#endif

View File

@ -0,0 +1,36 @@
From: Matthew Garrett <mjg59@srcf.ucam.org>
Date: Fri, 9 Mar 2012 08:39:37 -0500
Subject: [06/18] acpi: Limit access to custom_method if securelevel is set
Origin: https://github.com/mjg59/linux/commit/3cdc48db6b6d1b3cc1412d428389889f74cafe83
custom_method effectively allows arbitrary access to system memory, making
it possible for an attacker to modify the kernel at runtime. Prevent this
if securelevel has been set.
Signed-off-by: Matthew Garrett <mjg59@srcf.ucam.org>
---
drivers/acpi/custom_method.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/acpi/custom_method.c b/drivers/acpi/custom_method.c
index c68e72414a67..359f45d54543 100644
--- a/drivers/acpi/custom_method.c
+++ b/drivers/acpi/custom_method.c
@@ -8,6 +8,7 @@
#include <linux/uaccess.h>
#include <linux/debugfs.h>
#include <linux/acpi.h>
+#include <linux/security.h>
#include "internal.h"
@@ -29,6 +30,9 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf,
struct acpi_table_header table;
acpi_status status;
+ if (get_securelevel() > 0)
+ return -EPERM;
+
if (!(*ppos)) {
/* parse the table header to get the table length */
if (count <= sizeof(struct acpi_table_header))

View File

@ -0,0 +1,208 @@
From: Matthew Garrett <mjg59@srcf.ucam.org>
Date: Fri, 9 Aug 2013 17:58:15 -0400
Subject: [01/18] Add BSD-style securelevel support
Origin: https://github.com/mjg59/linux/commit/058b8ddfe86dc90268f6dbe0ffed29ec46f1fafa
Provide a coarse-grained runtime configuration option for restricting
userspace's ability to modify the running kernel.
Signed-off-by: Matthew Garrett <mjg59@srcf.ucam.org>
---
Documentation/security/securelevel.txt | 23 +++++++
include/linux/security.h | 8 +++
security/Kconfig | 8 +++
security/Makefile | 1 +
security/securelevel.c | 116 +++++++++++++++++++++++++++++++++
5 files changed, 156 insertions(+)
create mode 100644 Documentation/security/securelevel.txt
create mode 100644 security/securelevel.c
--- /dev/null
+++ b/Documentation/security/securelevel.txt
@@ -0,0 +1,23 @@
+Linux securelevel interface
+---------------------------
+
+The Linux securelevel interface (inspired by the BSD securelevel interface)
+is a runtime mechanism for configuring coarse-grained kernel-level security
+restrictions. It provides a runtime configuration variable at
+/sys/kernel/security/securelevel which can be written to by root. The
+following values are supported:
+
+-1: Permanently insecure mode. This level is equivalent to level 0, but once
+ set cannot be changed.
+
+0: Insecure mode (default). This level imposes no additional kernel
+ restrictions.
+
+1: Secure mode. If set, userspace will be unable to perform direct access
+ to PCI devices, port IO access, access system memory directly via
+ /dev/mem and /dev/kmem, perform kexec_load(), use the userspace
+ software suspend mechanism, insert new ACPI code at runtime via the
+ custom_method interface or modify CPU MSRs (on x86). Certain drivers
+ may also limit additional interfaces.
+
+Once the securelevel value is increased, it may not be decreased.
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1589,6 +1589,14 @@ static inline void security_audit_rule_f
#endif /* CONFIG_SECURITY */
#endif /* CONFIG_AUDIT */
+#ifdef CONFIG_SECURITY_SECURELEVEL
+extern int get_securelevel(void);
+extern int set_securelevel(int new_securelevel);
+#else
+static inline int get_securelevel(void) { return 0; }
+static inline int set_securelevel(int new_securelevel) { return 0; }
+#endif /* CONFIG_SECURELEVEL */
+
#ifdef CONFIG_SECURITYFS
extern struct dentry *securityfs_create_file(const char *name, umode_t mode,
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -93,6 +93,14 @@ config SECURITY_PATH
implement pathname based access controls.
If you are unsure how to answer this question, answer N.
+config SECURITY_SECURELEVEL
+ bool "Securelevel kernel restriction interface"
+ depends on SECURITY
+ help
+ This enables support for adding a set of additional kernel security
+ restrictions at runtime. See Documentation/security/securelevel.txt
+ for further information.
+
config INTEL_TXT
bool "Enable Intel(R) Trusted Execution Technology (Intel(R) TXT)"
depends on HAVE_INTEL_TXT
--- a/security/Makefile
+++ b/security/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_MMU) += min_addr.o
# Object file lists
obj-$(CONFIG_SECURITY) += security.o
obj-$(CONFIG_SECURITYFS) += inode.o
+obj-$(CONFIG_SECURITY_SECURELEVEL) += securelevel.o
obj-$(CONFIG_SECURITY_SELINUX) += selinux/
obj-$(CONFIG_SECURITY_SMACK) += smack/
obj-$(CONFIG_AUDIT) += lsm_audit.o
--- /dev/null
+++ b/security/securelevel.c
@@ -0,0 +1,116 @@
+/*
+ * securelevel.c - support for generic kernel lockdown
+ *
+ * Copyright Nebula, Inc <mjg59@srcf.ucam.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/security.h>
+#include <linux/uaccess.h>
+
+static int securelevel;
+
+static DEFINE_SPINLOCK(securelevel_lock);
+
+#define MAX_SECURELEVEL 1
+
+int get_securelevel(void)
+{
+ return securelevel;
+}
+EXPORT_SYMBOL(get_securelevel);
+
+int set_securelevel(int new_securelevel)
+{
+ int ret = 0;
+
+ spin_lock(&securelevel_lock);
+
+ if ((securelevel == -1) || (new_securelevel < securelevel) ||
+ (new_securelevel > MAX_SECURELEVEL)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ securelevel = new_securelevel;
+out:
+ spin_unlock(&securelevel_lock);
+ return ret;
+}
+EXPORT_SYMBOL(set_securelevel);
+
+static ssize_t securelevel_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ char tmpbuf[12];
+ ssize_t length;
+
+ length = scnprintf(tmpbuf, sizeof(tmpbuf), "%d", securelevel);
+ return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
+}
+
+static ssize_t securelevel_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ char *page = NULL;
+ ssize_t length;
+ int new_securelevel;
+
+ length = -ENOMEM;
+ if (count >= PAGE_SIZE)
+ goto out;
+
+ length = -EINVAL;
+ if (*ppos != 0)
+ goto out;
+
+ length = -ENOMEM;
+ page = (char *)get_zeroed_page(GFP_KERNEL);
+ if (!page)
+ goto out;
+
+ length = -EFAULT;
+ if (copy_from_user(page, buf, count))
+ goto out;
+
+ length = -EINVAL;
+ if (sscanf(page, "%d", &new_securelevel) != 1)
+ goto out;
+
+ length = set_securelevel(new_securelevel);
+ if (length)
+ goto out;
+
+ length = count;
+out:
+ free_page((unsigned long) page);
+ return length;
+}
+
+static const struct file_operations securelevel_fops = {
+ .read = securelevel_read,
+ .write = securelevel_write,
+ .llseek = generic_file_llseek,
+};
+
+static __init int setup_securelevel(void)
+{
+ struct dentry *securelevel_file;
+
+ securelevel_file = securityfs_create_file("securelevel",
+ S_IWUSR | S_IRUGO,
+ NULL, NULL,
+ &securelevel_fops);
+
+ if (IS_ERR(securelevel_file))
+ return PTR_ERR(securelevel_file);
+
+ return 0;
+}
+late_initcall(setup_securelevel);

View File

@ -0,0 +1,148 @@
From: Matthew Garrett <mjg59@srcf.ucam.org>
Date: Fri, 9 Aug 2013 18:36:30 -0400
Subject: [12/18] Add option to automatically set securelevel when in Secure
Boot mode
Origin: https://github.com/mjg59/linux/commit/e324de2d053295670f3ba8ef67289835d663aae5
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>
---
Documentation/x86/zero-page.txt | 2 ++
arch/x86/Kconfig | 13 +++++++++++++
arch/x86/boot/compressed/eboot.c | 36 +++++++++++++++++++++++++++++++++++
arch/x86/include/uapi/asm/bootparam.h | 3 ++-
arch/x86/kernel/setup.c | 7 +++++++
5 files changed, 60 insertions(+), 1 deletion(-)
--- a/Documentation/x86/zero-page.txt
+++ b/Documentation/x86/zero-page.txt
@@ -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
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1754,6 +1754,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"
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -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"
@@ -1050,6 +1051,37 @@ void setup_graphics(struct 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
@@ -1432,6 +1464,10 @@ struct boot_params *efi_main(struct efi_
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);
--- a/arch/x86/include/uapi/asm/bootparam.h
+++ b/arch/x86/include/uapi/asm/bootparam.h
@@ -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.
*
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -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>
@@ -1145,6 +1146,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.
*/

View File

@ -0,0 +1,57 @@
From: Matthew Garrett <mjg59@srcf.ucam.org>
Date: Fri, 9 Mar 2012 08:46:50 -0500
Subject: [11/18] asus-wmi: Restrict debugfs interface when securelevel is set
Origin: https://github.com/mjg59/linux/commit/f6e21827205ffcbfcce4b13d3a233427c3e742e0
We have no way of validating what all of the Asus WMI methods do on a
given machine, and there's a risk that some will allow hardware state to
be manipulated in such a way that arbitrary code can be executed in the
kernel. Prevent that if securelevel is set.
Signed-off-by: Matthew Garrett <mjg59@srcf.ucam.org>
---
drivers/platform/x86/asus-wmi.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index a96630d52346..93943e480a67 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -45,6 +45,7 @@
#include <linux/seq_file.h>
#include <linux/platform_device.h>
#include <linux/thermal.h>
+#include <linux/security.h>
#include <linux/acpi.h>
#include <linux/dmi.h>
#include <acpi/video.h>
@@ -1867,6 +1868,9 @@ static int show_dsts(struct seq_file *m, void *data)
int err;
u32 retval = -1;
+ if (get_securelevel() > 0)
+ return -EPERM;
+
err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval);
if (err < 0)
@@ -1883,6 +1887,9 @@ static int show_devs(struct seq_file *m, void *data)
int err;
u32 retval = -1;
+ if (get_securelevel() > 0)
+ return -EPERM;
+
err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param,
&retval);
@@ -1907,6 +1914,9 @@ static int show_call(struct seq_file *m, void *data)
union acpi_object *obj;
acpi_status status;
+ if (get_securelevel() > 0)
+ return -EPERM;
+
status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID,
1, asus->debug.method_id,
&input, &output);

View File

@ -0,0 +1,66 @@
From: Josh Boyer <jwboyer@fedoraproject.org>
Date: Tue, 5 Feb 2013 19:25:05 -0500
Subject: [13/18] efi: Disable secure boot if shim is in insecure mode
Origin: https://github.com/mjg59/linux/commit/f444a5ecb0ab09d6cf661b4520dd8e6fffacb8be
A user can manually tell the shim boot loader to disable validation of
images it loads. When a user does this, it creates a UEFI variable called
MokSBState that does not have the runtime attribute set. Given that the
user explicitly disabled validation, we can honor that and not enable
secure boot mode if that variable is set.
Signed-off-by: Josh Boyer <jwboyer@fedoraproject.org>
---
arch/x86/boot/compressed/eboot.c | 20 +++++++++++++++++++-
include/linux/efi.h | 3 +++
2 files changed, 22 insertions(+), 1 deletion(-)
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -1053,8 +1053,9 @@ void setup_graphics(struct boot_params *
static int get_secure_boot(void)
{
- u8 sb, setup;
+ u8 sb, setup, moksbstate;
unsigned long datasize = sizeof(sb);
+ u32 attr;
efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID;
efi_status_t status;
@@ -1078,6 +1079,23 @@ static int get_secure_boot(void)
if (setup == 1)
return 0;
+ /* See if a user has put shim into insecure_mode. If so, and the variable
+ * doesn't have the runtime attribute set, we might as well honor that.
+ */
+ var_guid = EFI_SHIM_LOCK_GUID;
+ status = efi_early->call((unsigned long)sys_table->runtime->get_variable,
+ L"MokSBState", &var_guid, &attr, &datasize,
+ &moksbstate);
+
+ /* If it fails, we don't care why. Default to secure */
+ if (status != EFI_SUCCESS)
+ return 1;
+
+ if (!(attr & EFI_VARIABLE_RUNTIME_ACCESS)) {
+ if (moksbstate == 1)
+ return 0;
+ }
+
return 1;
}
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -629,6 +629,9 @@ typedef struct {
#define EFI_1_10_SYSTEM_TABLE_REVISION ((1 << 16) | (10))
#define EFI_1_02_SYSTEM_TABLE_REVISION ((1 << 16) | (02))
+#define EFI_SHIM_LOCK_GUID \
+ EFI_GUID( 0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 )
+
typedef struct {
efi_table_hdr_t hdr;
u64 fw_vendor; /* physical addr of CHAR16 vendor string */

View File

@ -0,0 +1,49 @@
From: Matthew Garrett <mjg59@coreos.com>
Date: Tue, 12 Jan 2016 12:51:27 -0800
Subject: [18/18] Enable cold boot attack mitigation
Origin: https://github.com/mjg59/linux/commit/02d999574936dd234a508c0112a0200c135a5c34
---
arch/x86/boot/compressed/eboot.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 28c24d80d0a0..b0413ba639af 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -1051,6 +1051,22 @@ void setup_graphics(struct boot_params *boot_params)
}
}
+#define MEMORY_ONLY_RESET_CONTROL_GUID \
+ EFI_GUID (0xe20939be, 0x32d4, 0x41be, 0xa1, 0x50, 0x89, 0x7f, 0x85, 0xd4, 0x98, 0x29)
+
+static void enable_reset_attack_mitigation(void)
+{
+ u8 val = 1;
+ efi_guid_t var_guid = MEMORY_ONLY_RESET_CONTROL_GUID;
+
+ /* Ignore the return value here - there's not really a lot we can do */
+ efi_early->call((unsigned long)sys_table->runtime->set_variable,
+ L"MemoryOverwriteRequestControl", &var_guid,
+ EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS, sizeof(val), val);
+}
+
static int get_secure_boot(void)
{
u8 sb, setup, moksbstate;
@@ -1482,6 +1498,12 @@ struct boot_params *efi_main(struct efi_config *c,
else
setup_boot_services32(efi_early);
+ /*
+ * Ask the firmware to clear memory if we don't have a clean
+ * shutdown
+ */
+ enable_reset_attack_mitigation();
+
sanitize_boot_params(boot_params);
boot_params->secure_boot = get_secure_boot();

View File

@ -0,0 +1,24 @@
From: Matthew Garrett <mjg59@srcf.ucam.org>
Date: Mon, 9 Sep 2013 08:46:52 -0400
Subject: [02/18] Enforce module signatures when securelevel is greater than 0
Origin: https://github.com/mjg59/linux/commit/90e0fa532b145d1bb76c368277a3a3e3b3eb5c94
If securelevel has been set to 1 or greater, require that all modules have
valid signatures.
Signed-off-by: Matthew Garrett <mjg59@srcf.ucam.org>
---
kernel/module.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2616,7 +2616,7 @@ static int module_sig_check(struct load_
}
/* Not having a signature is only an error if we're strict. */
- if (err == -ENOKEY && !sig_enforce)
+ if ((err == -ENOKEY && !sig_enforce) && (get_securelevel() <= 0))
err = 0;
return err;

View File

@ -0,0 +1,36 @@
From: Josh Boyer <jwboyer@fedoraproject.org>
Date: Fri, 20 Jun 2014 08:53:24 -0400
Subject: [14/18] hibernate: Disable when securelevel is set
Origin: https://github.com/mjg59/linux/commit/500a87278c5c0608ba88ed8af7a35fcfa955c492
There is currently no way to verify the resume image when returning
from hibernate. This might compromise the securelevel trust model,
so until we can work with signed hibernate images we disable it in
a secure modules environment.
Signed-off-by: Josh Boyer <jwboyer@fedoraproject.org>
---
kernel/power/hibernate.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index fca9254280ee..7bf7f723a27f 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -29,6 +29,7 @@
#include <linux/ctype.h>
#include <linux/genhd.h>
#include <linux/ktime.h>
+#include <linux/security.h>
#include <trace/events/power.h>
#include "power.h"
@@ -66,7 +67,7 @@ static const struct platform_hibernation_ops *hibernation_ops;
bool hibernation_available(void)
{
- return (nohibernate == 0);
+ return ((nohibernate == 0) && (get_securelevel() <= 0));
}
/**

View File

@ -0,0 +1,36 @@
From: Matthew Garrett <mjg59@srcf.ucam.org>
Date: Fri, 9 Aug 2013 03:33:56 -0400
Subject: [08/18] kexec: Disable at runtime if securelevel has been set.
Origin: https://github.com/mjg59/linux/commit/ec87b6aac76fd553578cec2c05674e22b79afe3e
kexec permits the loading and execution of arbitrary code in ring 0, which
permits the modification of the running kernel. Prevent this if securelevel
has been set.
Signed-off-by: Matthew Garrett <mjg59@srcf.ucam.org>
---
kernel/kexec.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/kernel/kexec.c b/kernel/kexec.c
index ee70aef5cd81..542655ea297c 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -17,6 +17,7 @@
#include <linux/syscalls.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
+#include <linux/security.h>
#include "kexec_internal.h"
@@ -134,6 +135,9 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
if (!capable(CAP_SYS_BOOT) || kexec_load_disabled)
return -EPERM;
+ if (get_securelevel() > 0)
+ return -EPERM;
+
/*
* Verify we have a legal set of flags
* This leaves us room for future extensions.

View File

@ -0,0 +1,32 @@
From: Dave Young <dyoung@redhat.com>
Date: Tue, 6 Oct 2015 13:31:31 +0100
Subject: [15/18] kexec/uefi: copy secure_boot flag in boot params across kexec
reboot
Origin: https://github.com/mjg59/linux/commit/4b2b64d5a6ebc84214755ebccd599baef7c1b798
Kexec reboot in case secure boot being enabled does not keep the secure
boot mode in new kernel, so later one can load unsigned kernel via legacy
kexec_load. In this state, the system is missing the protections provided
by secure boot. Adding a patch to fix this by retain the secure_boot flag
in original kernel.
secure_boot flag in boot_params is set in EFI stub, but kexec bypasses the
stub. Fixing this issue by copying secure_boot flag across kexec reboot.
Signed-off-by: Dave Young <dyoung@redhat.com>
---
arch/x86/kernel/kexec-bzimage64.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c
index 2af478e3fd4e..61827eeb6881 100644
--- a/arch/x86/kernel/kexec-bzimage64.c
+++ b/arch/x86/kernel/kexec-bzimage64.c
@@ -180,6 +180,7 @@ setup_efi_state(struct boot_params *params, unsigned long params_load_addr,
if (efi_enabled(EFI_OLD_MEMMAP))
return 0;
+ params->secure_boot = boot_params.secure_boot;
ei->efi_loader_signature = current_ei->efi_loader_signature;
ei->efi_systab = current_ei->efi_systab;
ei->efi_systab_hi = current_ei->efi_systab_hi;

View File

@ -0,0 +1,108 @@
From: Matthew Garrett <mjg59@srcf.ucam.org>
Date: Thu, 8 Mar 2012 10:10:38 -0500
Subject: [03/18] PCI: Lock down BAR access when securelevel is enabled
Origin: https://github.com/mjg59/linux/commit/2533a3844cf8c43bf58b653334f8925cd1e7d405
Any hardware that can potentially generate DMA has to be locked down from
userspace in order to avoid it being possible for an attacker to modify
kernel code. This should be prevented if securelevel has been set. Default
to paranoid - in future we can potentially relax this for sufficiently
IOMMU-isolated devices.
Signed-off-by: Matthew Garrett <mjg59@srcf.ucam.org>
---
drivers/pci/pci-sysfs.c | 9 +++++++++
drivers/pci/proc.c | 9 ++++++++-
drivers/pci/syscall.c | 3 ++-
3 files changed, 19 insertions(+), 2 deletions(-)
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -711,6 +711,9 @@ static ssize_t pci_write_config(struct f
loff_t init_off = off;
u8 *data = (u8 *) buf;
+ if (get_securelevel() > 0)
+ return -EPERM;
+
if (off > dev->cfg_size)
return 0;
if (off + count > dev->cfg_size) {
@@ -998,6 +1001,9 @@ static int pci_mmap_resource(struct kobj
resource_size_t start, end;
int i;
+ if (get_securelevel() > 0)
+ return -EPERM;
+
for (i = 0; i < PCI_ROM_RESOURCE; i++)
if (res == &pdev->resource[i])
break;
@@ -1098,6 +1104,9 @@ static ssize_t pci_write_resource_io(str
struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
+ if (get_securelevel() > 0)
+ return -EPERM;
+
return pci_resource_io(filp, kobj, attr, buf, off, count, true);
}
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -11,6 +11,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/capability.h>
+#include <linux/security.h>
#include <asm/uaccess.h>
#include <asm/byteorder.h>
#include "pci.h"
@@ -116,6 +117,9 @@ static ssize_t proc_bus_pci_write(struct
int size = dev->cfg_size;
int cnt;
+ if (get_securelevel() > 0)
+ return -EPERM;
+
if (pos >= size)
return 0;
if (nbytes >= size)
@@ -195,6 +199,9 @@ static long proc_bus_pci_ioctl(struct fi
#endif /* HAVE_PCI_MMAP */
int ret = 0;
+ if (get_securelevel() > 0)
+ return -EPERM;
+
switch (cmd) {
case PCIIOC_CONTROLLER:
ret = pci_domain_nr(dev->bus);
@@ -233,7 +240,7 @@ static int proc_bus_pci_mmap(struct file
struct pci_filp_private *fpriv = file->private_data;
int i, ret;
- if (!capable(CAP_SYS_RAWIO))
+ if (!capable(CAP_SYS_RAWIO) || (get_securelevel() > 0))
return -EPERM;
/* Make sure the caller is mapping a real resource for this device */
--- a/drivers/pci/syscall.c
+++ b/drivers/pci/syscall.c
@@ -10,6 +10,7 @@
#include <linux/errno.h>
#include <linux/pci.h>
#include <linux/syscalls.h>
+#include <linux/security.h>
#include <asm/uaccess.h>
#include "pci.h"
@@ -92,7 +93,7 @@ SYSCALL_DEFINE5(pciconfig_write, unsigne
u32 dword;
int err = 0;
- if (!capable(CAP_SYS_ADMIN))
+ if (!capable(CAP_SYS_ADMIN) || (get_securelevel() > 0))
return -EPERM;
dev = pci_get_bus_and_slot(bus, dfn);

View File

@ -0,0 +1,38 @@
From: Matthew Garrett <mjg59@srcf.ucam.org>
Date: Fri, 9 Mar 2012 09:28:15 -0500
Subject: [05/18] Restrict /dev/mem and /dev/kmem when securelevel is set.
Origin: https://github.com/mjg59/linux/commit/401996625d478c814fe9e736ca9e6c5c5f055f06
Allowing users to write to address space provides mechanisms that may permit
modification of the kernel at runtime. Prevent this if securelevel has been
set.
Signed-off-by: Matthew Garrett <mjg59@srcf.ucam.org>
---
drivers/char/mem.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index cef0d40a3d74..c810f1e15c73 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -167,6 +167,9 @@ static ssize_t write_mem(struct file *file, const char __user *buf,
if (p != *ppos)
return -EFBIG;
+ if (get_securelevel() > 0)
+ return -EPERM;
+
if (!valid_phys_addr_range(p, count))
return -EFAULT;
@@ -513,6 +516,9 @@ static ssize_t write_kmem(struct file *file, const char __user *buf,
char *kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
int err = 0;
+ if (get_securelevel() > 0)
+ return -EPERM;
+
if (p < (unsigned long) high_memory) {
unsigned long to_write = min_t(unsigned long, count,
(unsigned long)high_memory - p);

View File

@ -0,0 +1,36 @@
From: Matthew Garrett <mjg59@srcf.ucam.org>
Date: Tue, 3 Sep 2013 11:23:29 -0400
Subject: [09/18] uswsusp: Disable when securelevel is set
Origin: https://github.com/mjg59/linux/commit/504f45f7cc9b4265a4d89728c4f8254295e81977
uswsusp allows a user process to dump and then restore kernel state, which
makes it possible to modify the running kernel. Disable this if securelevel
has been set.
Signed-off-by: Matthew Garrett <mjg59@srcf.ucam.org>
---
kernel/power/user.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 526e8911460a..40618bf41620 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -24,6 +24,7 @@
#include <linux/console.h>
#include <linux/cpu.h>
#include <linux/freezer.h>
+#include <linux/security.h>
#include <asm/uaccess.h>
@@ -52,6 +53,9 @@ static int snapshot_open(struct inode *inode, struct file *filp)
if (!hibernation_available())
return -EPERM;
+ if (get_securelevel() > 0)
+ return -EPERM;
+
lock_system_sleep();
if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {

View File

@ -0,0 +1,74 @@
From: Matthew Garrett <mjg59@srcf.ucam.org>
Date: Thu, 8 Mar 2012 10:35:59 -0500
Subject: [04/18] x86: Lock down IO port access when securelevel is enabled
Origin: https://github.com/mjg59/linux/commit/2ad64f6ea1f1164c8b552860faa27392d9da9928
IO port access would permit users to gain access to PCI configuration
registers, which in turn (on a lot of hardware) give access to MMIO register
space. This would potentially permit root to trigger arbitrary DMA, so lock
it down when securelevel is set.
Signed-off-by: Matthew Garrett <mjg59@srcf.ucam.org>
---
arch/x86/kernel/ioport.c | 5 +++--
drivers/char/mem.c | 7 +++++++
2 files changed, 10 insertions(+), 2 deletions(-)
--- a/arch/x86/kernel/ioport.c
+++ b/arch/x86/kernel/ioport.c
@@ -15,6 +15,7 @@
#include <linux/thread_info.h>
#include <linux/syscalls.h>
#include <linux/bitmap.h>
+#include <linux/security.h>
#include <asm/syscalls.h>
/*
@@ -28,7 +29,7 @@ asmlinkage long sys_ioperm(unsigned long
if ((from + num <= from) || (from + num > IO_BITMAP_BITS))
return -EINVAL;
- if (turn_on && !capable(CAP_SYS_RAWIO))
+ if (turn_on && (!capable(CAP_SYS_RAWIO) || (get_securelevel() > 0)))
return -EPERM;
/*
@@ -103,7 +104,7 @@ SYSCALL_DEFINE1(iopl, unsigned int, leve
return -EINVAL;
/* Trying to gain more privileges? */
if (level > old) {
- if (!capable(CAP_SYS_RAWIO))
+ if (!capable(CAP_SYS_RAWIO) || (get_securelevel() > 0))
return -EPERM;
}
regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12);
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -27,6 +27,7 @@
#include <linux/export.h>
#include <linux/io.h>
#include <linux/uio.h>
+#include <linux/security.h>
#include <linux/uaccess.h>
@@ -559,6 +560,9 @@ static ssize_t read_port(struct file *fi
unsigned long i = *ppos;
char __user *tmp = buf;
+ if (get_securelevel() > 0)
+ return -EPERM;
+
if (!access_ok(VERIFY_WRITE, buf, count))
return -EFAULT;
while (count-- > 0 && i < 65536) {
@@ -577,6 +581,9 @@ static ssize_t write_port(struct file *f
unsigned long i = *ppos;
const char __user *tmp = buf;
+ if (get_securelevel() > 0)
+ return -EPERM;
+
if (!access_ok(VERIFY_READ, buf, count))
return -EFAULT;
while (count-- > 0 && i < 65536) {

View File

@ -0,0 +1,46 @@
From: Matthew Garrett <mjg59@srcf.ucam.org>
Date: Fri, 8 Feb 2013 11:12:13 -0800
Subject: [10/18] x86: Restrict MSR access when securelevel is set
Origin: https://github.com/mjg59/linux/commit/c6ad37822699967e60fae57a64ae89676f543182
Permitting write access to MSRs allows userspace to modify the running
kernel. Prevent this if securelevel has been set. Based on a patch by Kees
Cook.
Cc: Kees Cook <keescook@chromium.org>
Signed-off-by: Matthew Garrett <mjg59@srcf.ucam.org>
---
arch/x86/kernel/msr.c | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/arch/x86/kernel/msr.c
+++ b/arch/x86/kernel/msr.c
@@ -39,6 +39,7 @@
#include <linux/notifier.h>
#include <linux/uaccess.h>
#include <linux/gfp.h>
+#include <linux/security.h>
#include <asm/processor.h>
#include <asm/msr.h>
@@ -83,6 +84,9 @@ static ssize_t msr_write(struct file *fi
int err = 0;
ssize_t bytes = 0;
+ if (get_securelevel() > 0)
+ return -EPERM;
+
if (count % 8)
return -EINVAL; /* Invalid chunk size */
@@ -130,6 +134,10 @@ static long msr_ioctl(struct file *file,
err = -EBADF;
break;
}
+ if (get_securelevel() > 0) {
+ err = -EPERM;
+ break;
+ }
if (copy_from_user(&regs, uregs, sizeof regs)) {
err = -EFAULT;
break;

20
debian/patches/series vendored
View File

@ -75,6 +75,26 @@ features/all/grsecurity/grsecurity-kconfig.patch
#features/all/grsecurity/grsecurity-kbuild.patch
features/all/grsecurity/grkernsec_perf_harden.patch
# Securelevel patchset from mjg59
features/all/securelevel/add-bsd-style-securelevel-support.patch
features/all/securelevel/enforce-module-signatures-when-securelevel-is-greate.patch
features/all/securelevel/pci-lock-down-bar-access-when-securelevel-is-enabled.patch
features/all/securelevel/x86-lock-down-io-port-access-when-securelevel-is-ena.patch
features/all/securelevel/restrict-dev-mem-and-dev-kmem-when-securelevel-is-se.patch
features/all/securelevel/acpi-limit-access-to-custom_method-if-securelevel-is.patch
features/all/securelevel/acpi-ignore-acpi_rsdp-kernel-parameter-when-securele.patch
features/all/securelevel/kexec-disable-at-runtime-if-securelevel-has-been-set.patch
features/all/securelevel/uswsusp-disable-when-securelevel-is-set.patch
features/all/securelevel/x86-restrict-msr-access-when-securelevel-is-set.patch
features/all/securelevel/asus-wmi-restrict-debugfs-interface-when-securelevel.patch
features/all/securelevel/add-option-to-automatically-set-securelevel-when-in-.patch
features/all/securelevel/efi-disable-secure-boot-if-shim-is-in-insecure-mode.patch
features/all/securelevel/hibernate-disable-when-securelevel-is-set.patch
features/all/securelevel/kexec-uefi-copy-secure_boot-flag-in-boot-params-acro.patch
features/all/securelevel/acpi-disable-acpi-table-override-if-securelevel-is-s.patch
features/all/securelevel/acpi-disable-apei-error-injection-if-securelevel-is-.patch
features/all/securelevel/enable-cold-boot-attack-mitigation.patch
# Security fixes
bugfix/all/ptrace-being-capable-wrt-a-process-requires-mapped-uids-gids.patch
bugfix/x86/x86-mm-page-align-the-_end-symbol-to-avoid-pfn-conve.patch