2014-02-26 20:11:45

by Matthew Garrett

[permalink] [raw]
Subject: Trusted kernel patchset for Secure Boot lockdown

The conclusion we came to at Plumbers was that this patchset was basically
fine but that Linus hated the name "securelevel" more than I hate pickled
herring, so after thinking about this for a few months I've come up with
"Trusted Kernel". This flag indicates that the kernel is, via some
external mechanism, trusted and should behave that way. If firmware has
some way to verify the kernel, it can pass that information on. If userspace
has some way to verify the kernel, it can set the flag itself. However,
userspace should not attempt to use the flag as a means to verify that the
kernel was trusted - untrusted userspace could have set it on an untrusted
kernel, but by the same metric an untrusted kernel could just set it itself.

If people object to this name then I swear to god that I will open a poll
on Phoronix to decide the next attempt and you will like that even less.


2014-02-26 20:11:47

by Matthew Garrett

[permalink] [raw]
Subject: [PATCH 09/12] uswsusp: Disable when trusted_kernel is true

uswsusp allows a user process to dump and then restore kernel state, which
makes it possible to modify the running kernel. Disable this if
trusted_kernel is true.

Signed-off-by: Matthew Garrett <[email protected]>
---
kernel/power/user.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/kernel/power/user.c b/kernel/power/user.c
index 98d3575..2d7a5d3 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>

@@ -49,6 +50,9 @@ static int snapshot_open(struct inode *inode, struct file *filp)
struct snapshot_data *data;
int error;

+ if (get_trusted_kernel())
+ return -EPERM;
+
lock_system_sleep();

if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
--
1.8.5.3

2014-02-26 20:12:17

by Matthew Garrett

[permalink] [raw]
Subject: [PATCH 08/12] kexec: Disable at runtime if trusted_kernel is true

kexec permits the loading and execution of arbitrary code in ring 0, which
permits the modification of the running kernel. Prevent this if
trusted_kernel is true.

Signed-off-by: Matthew Garrett <[email protected]>
---
kernel/kexec.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/kernel/kexec.c b/kernel/kexec.c
index 60bafbe..281ddd0 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -32,6 +32,7 @@
#include <linux/vmalloc.h>
#include <linux/swap.h>
#include <linux/syscore_ops.h>
+#include <linux/security.h>

#include <asm/page.h>
#include <asm/uaccess.h>
@@ -946,6 +947,9 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
if (!capable(CAP_SYS_BOOT) || kexec_load_disabled)
return -EPERM;

+ if (get_trusted_kernel())
+ return -EPERM;
+
/*
* Verify we have a legal set of flags
* This leaves us room for future extensions.
--
1.8.5.3

2014-02-26 20:11:44

by Matthew Garrett

[permalink] [raw]
Subject: [PATCH 03/12] PCI: Lock down BAR access when trusted_kernel is true

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 trusted_kernel has been
set. Default to paranoid - in future we can potentially relax this for
sufficiently IOMMU-isolated devices.

Signed-off-by: Matthew Garrett <[email protected]>
---
drivers/pci/pci-sysfs.c | 9 +++++++++
drivers/pci/proc.c | 9 ++++++++-
drivers/pci/syscall.c | 3 ++-
3 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 276ef9c..256f373 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -663,6 +663,9 @@ pci_write_config(struct file* filp, struct kobject *kobj,
loff_t init_off = off;
u8 *data = (u8*) buf;

+ if (get_trusted_kernel())
+ return -EPERM;
+
if (off > dev->cfg_size)
return 0;
if (off + count > dev->cfg_size) {
@@ -969,6 +972,9 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
resource_size_t start, end;
int i;

+ if (get_trusted_kernel())
+ return -EPERM;
+
for (i = 0; i < PCI_ROM_RESOURCE; i++)
if (res == &pdev->resource[i])
break;
@@ -1076,6 +1082,9 @@ pci_write_resource_io(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
+ if (get_trusted_kernel())
+ return -EPERM;
+
return pci_resource_io(filp, kobj, attr, buf, off, count, true);
}

diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 46d1378..990b24b 100644
--- 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"
@@ -117,6 +118,9 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
int size = dev->cfg_size;
int cnt;

+ if (get_trusted_kernel())
+ return -EPERM;
+
if (pos >= size)
return 0;
if (nbytes >= size)
@@ -196,6 +200,9 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
#endif /* HAVE_PCI_MMAP */
int ret = 0;

+ if (get_trusted_kernel())
+ return -EPERM;
+
switch (cmd) {
case PCIIOC_CONTROLLER:
ret = pci_domain_nr(dev->bus);
@@ -234,7 +241,7 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
struct pci_filp_private *fpriv = file->private_data;
int i, ret;

- if (!capable(CAP_SYS_RAWIO))
+ if (!capable(CAP_SYS_RAWIO) || (get_trusted_kernel()))
return -EPERM;

/* Make sure the caller is mapping a real resource for this device */
diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c
index 24750a1..d962710 100644
--- 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, unsigned long, bus, unsigned long, dfn,
u32 dword;
int err = 0;

- if (!capable(CAP_SYS_ADMIN))
+ if (!capable(CAP_SYS_ADMIN) || (get_trusted_kernel()))
return -EPERM;

dev = pci_get_bus_and_slot(bus, dfn);
--
1.8.5.3

2014-02-26 20:12:48

by Matthew Garrett

[permalink] [raw]
Subject: [PATCH 07/12] acpi: Ignore acpi_rsdp kernel parameter when trusted_kernel is true.

From: Josh Boyer <[email protected]>

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 trusted_kernel is true.

Signed-off-by: Josh Boyer <[email protected]>
---
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 fc1aa79..087a351 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -44,6 +44,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>
@@ -244,7 +245,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_trusted_kernel())
return acpi_rsdp;
#endif

--
1.8.5.3

2014-02-26 20:11:42

by Matthew Garrett

[permalink] [raw]
Subject: [PATCH 02/12] Enforce module signatures when trusted kernel is enabled

If trusted_kernel is true, require that all modules have valid signatures.

Signed-off-by: Matthew Garrett <[email protected]>
---
kernel/module.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/module.c b/kernel/module.c
index d24fcf2..e0220db 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2448,7 +2448,7 @@ static int module_sig_check(struct load_info *info)
if (err < 0 && fips_enabled)
panic("Module verification failed with error %d in FIPS mode\n",
err);
- if (err == -ENOKEY && !sig_enforce)
+ if ((err == -ENOKEY && !sig_enforce) && !get_trusted_kernel())
err = 0;

return err;
--
1.8.5.3

2014-02-26 20:13:15

by Matthew Garrett

[permalink] [raw]
Subject: [PATCH 06/12] acpi: Limit access to custom_method if trusted_kernel is true

custom_method effectively allows arbitrary access to system memory, making
it possible for an attacker to modify the kernel at runtime. Prevent this
if trusted_kernel is true.

Signed-off-by: Matthew Garrett <[email protected]>
---
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 c68e724..774bb7b 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_trusted_kernel())
+ return -EPERM;
+
if (!(*ppos)) {
/* parse the table header to get the table length */
if (count <= sizeof(struct acpi_table_header))
--
1.8.5.3

2014-02-26 20:14:13

by Matthew Garrett

[permalink] [raw]
Subject: [PATCH 05/12] Restrict /dev/mem and /dev/kmem when trusted_kernel is true

Allowing users to write to address space provides mechanisms that may permit
modification of the kernel at runtime. Prevent this if trusted_kernel is
true.

Signed-off-by: Matthew Garrett <[email protected]>
---
drivers/char/mem.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 15331a8..2cecab9 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -158,6 +158,9 @@ static ssize_t write_mem(struct file *file, const char __user *buf,
unsigned long copied;
void *ptr;

+ if (get_trusted_kernel())
+ return -EPERM;
+
if (!valid_phys_addr_range(p, count))
return -EFAULT;

@@ -496,6 +499,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_trusted_kernel())
+ return -EPERM;
+
if (p < (unsigned long) high_memory) {
unsigned long to_write = min_t(unsigned long, count,
(unsigned long)high_memory - p);
--
1.8.5.3

2014-02-26 20:14:12

by Matthew Garrett

[permalink] [raw]
Subject: [PATCH 04/12] x86: Lock down IO port access when trusted_kernel is true

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 trusted_kernel is true

Signed-off-by: Matthew Garrett <[email protected]>
---
arch/x86/kernel/ioport.c | 5 +++--
drivers/char/mem.c | 7 +++++++
2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c
index 4ddaf66..3121541 100644
--- 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 from, unsigned long num, int turn_on)

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_trusted_kernel())))
return -EPERM;

/*
@@ -103,7 +104,7 @@ SYSCALL_DEFINE1(iopl, unsigned int, level)
return -EINVAL;
/* Trying to gain more privileges? */
if (level > old) {
- if (!capable(CAP_SYS_RAWIO))
+ if (!capable(CAP_SYS_RAWIO) || (get_trusted_kernel()))
return -EPERM;
}
regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12);
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 92c5937..15331a8 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -27,6 +27,7 @@
#include <linux/export.h>
#include <linux/io.h>
#include <linux/aio.h>
+#include <linux/security.h>

#include <asm/uaccess.h>

@@ -544,6 +545,9 @@ static ssize_t read_port(struct file *file, char __user *buf,
unsigned long i = *ppos;
char __user *tmp = buf;

+ if (get_trusted_kernel())
+ return -EPERM;
+
if (!access_ok(VERIFY_WRITE, buf, count))
return -EFAULT;
while (count-- > 0 && i < 65536) {
@@ -562,6 +566,9 @@ static ssize_t write_port(struct file *file, const char __user *buf,
unsigned long i = *ppos;
const char __user *tmp = buf;

+ if (get_trusted_kernel())
+ return -EPERM;
+
if (!access_ok(VERIFY_READ, buf, count))
return -EFAULT;
while (count-- > 0 && i < 65536) {
--
1.8.5.3

2014-02-26 20:14:53

by Matthew Garrett

[permalink] [raw]
Subject: [PATCH 01/12] Add support for indicating that the booted kernel is externally trusted

Provide a boolean runtime configuration option for restricting userspace's
ability to modify the running kernel. This can be used when some external
validation of the kernel's state has been performed.

Signed-off-by: Matthew Garrett <[email protected]>
---
Documentation/kernel-parameters.txt | 6 ++
Documentation/security/trusted_kernel.txt | 35 ++++++++++
include/linux/security.h | 8 +++
security/Kconfig | 9 +++
security/Makefile | 1 +
security/trusted_kernel.c | 111 ++++++++++++++++++++++++++++++
6 files changed, 170 insertions(+)
create mode 100644 Documentation/security/trusted_kernel.txt
create mode 100644 security/trusted_kernel.c

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 7116fda..d82ba9e 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -3271,6 +3271,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
with respect to transparent hugepages.
See Documentation/vm/transhuge.txt for more details.

+ trusted_kernel Indicate that the booted kernel has been verified to
+ be trustworthy and that userspace should be forbidden
+ from modifying it at runtime.
+ See Documentation/security/trusted_kernel.txt for more
+ details.
+
tsc= Disable clocksource stability checks for TSC.
Format: <string>
[x86] reliable: mark tsc clocksource as reliable, this
diff --git a/Documentation/security/trusted_kernel.txt b/Documentation/security/trusted_kernel.txt
new file mode 100644
index 0000000..538d21d
--- /dev/null
+++ b/Documentation/security/trusted_kernel.txt
@@ -0,0 +1,35 @@
+Linux trusted kernel support
+----------------------------
+
+Various mechanisms exist to ensure that a booted kernel is trusted by the
+user or some external party (UEFI Secure Boot, Intel TXT, embedded platform
+bootloaders). If userspace is able to modify the running kernel then this
+trust can be subverted.
+
+The trusted kernel support modifies certain kernel interfaces such that
+userspace is restricted from performing acts that would allow it to inject
+untrusted code into the kernel. 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.
+
+The trusted kernel feature may be enabled in multiple ways:
+
+1) Platform-specific code may automatically enable it when it detects that
+the system has been booted appropriately
+
+2) The user or bootloader may pass the "trusted_kernel" kernel parameter
+
+3) Userspace may write "1" to the /sys/kernel/security/trusted_kernel
+node. This must be done sufficiently early in the boot process that
+untrusted userspace has no opportunity to modify the kernel.
+
+Once enabled. trusted kernel support may not be disabled without rebooting
+the system.
+
+Note that this is a mechanism for the kernel to determine whether or not
+it is externally trusted. Untrusted userspace can enable this option even
+if the kernel is not trusted, and therefore userspace should not use this
+value as an indication of whether or not the kernel is trustworthy.
diff --git a/include/linux/security.h b/include/linux/security.h
index 5623a7f..3415968 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -3091,6 +3091,14 @@ static inline void security_audit_rule_free(void *lsmrule)
#endif /* CONFIG_SECURITY */
#endif /* CONFIG_AUDIT */

+#ifdef CONFIG_SECURITY_TRUSTED_KERNEL
+extern bool get_trusted_kernel(void);
+extern int set_trusted_kernel(bool new_trusted_kernel);
+#else
+static inline bool get_trusted_kernel(void) { return 0; }
+static inline int set_trusted_kernel(bool new_trusted_kernel) { return 0; }
+#endif /* CONFIG_TRUSTED_KERNEL */
+
#ifdef CONFIG_SECURITYFS

extern struct dentry *securityfs_create_file(const char *name, umode_t mode,
diff --git a/security/Kconfig b/security/Kconfig
index beb86b5..c0462c9 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -70,6 +70,15 @@ config SECURITY_PATH
implement pathname based access controls.
If you are unsure how to answer this question, answer N.

+config SECURITY_TRUSTED_KERNEL
+ bool "Support for indicating that the kernel is trusted"
+ depends on SECURITY
+ help
+ This enables support for adding a set of additional kernel security
+ restrictions at runtime.
+ See Documentation/security/trusted_kernel.txt for further
+ information.
+
config INTEL_TXT
bool "Enable Intel(R) Trusted Execution Technology (Intel(R) TXT)"
depends on HAVE_INTEL_TXT
diff --git a/security/Makefile b/security/Makefile
index a5918e0..72af305 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_MMU) += min_addr.o
# Object file lists
obj-$(CONFIG_SECURITY) += security.o capability.o
obj-$(CONFIG_SECURITYFS) += inode.o
+obj-$(CONFIG_SECURITY_TRUSTED_KERNEL) += trusted_kernel.o
obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
obj-$(CONFIG_AUDIT) += lsm_audit.o
diff --git a/security/trusted_kernel.c b/security/trusted_kernel.c
new file mode 100644
index 0000000..2808113
--- /dev/null
+++ b/security/trusted_kernel.c
@@ -0,0 +1,111 @@
+/*
+ * trusted_kernel.c - support for generic kernel lockdown
+ *
+ * Copyright Nebula, Inc <[email protected]>
+ *
+ * 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 bool trusted_kernel;
+
+bool get_trusted_kernel(void)
+{
+ return trusted_kernel;
+}
+EXPORT_SYMBOL(get_trusted_kernel);
+
+int set_trusted_kernel(bool new_trusted_kernel)
+{
+ if (trusted_kernel == true && new_trusted_kernel == false)
+ return -EINVAL;
+
+ trusted_kernel = new_trusted_kernel;
+
+ return 0;
+}
+EXPORT_SYMBOL(set_trusted_kernel);
+
+static ssize_t trusted_kernel_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ char tmpbuf[2];
+ ssize_t length;
+
+ length = scnprintf(tmpbuf, sizeof(tmpbuf), "%d", trusted_kernel);
+ return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
+}
+
+static ssize_t trusted_kernel_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ char *page = NULL;
+ ssize_t length;
+ int new_trusted_kernel;
+
+ 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_trusted_kernel) != 1)
+ goto out;
+
+ length = set_trusted_kernel(!!new_trusted_kernel);
+ if (length)
+ goto out;
+
+ length = count;
+out:
+ free_page((unsigned long) page);
+ return length;
+}
+
+static const struct file_operations trusted_kernel_fops = {
+ .read = trusted_kernel_read,
+ .write = trusted_kernel_write,
+ .llseek = generic_file_llseek,
+};
+
+static __init int setup_trusted_kernel(void)
+{
+ struct dentry *trusted_kernel_file;
+
+ trusted_kernel_file = securityfs_create_file("trusted_kernel",
+ S_IWUSR | S_IRUGO,
+ NULL, NULL,
+ &trusted_kernel_fops);
+
+ if (IS_ERR(trusted_kernel_file))
+ return PTR_ERR(trusted_kernel_file);
+
+ return 0;
+}
+late_initcall(setup_trusted_kernel);
+
+static int __init enable_trusted_kernel(char *__str)
+{
+ trusted_kernel = true;
+ return 1;
+}
+__setup("trusted_kernel", enable_trusted_kernel);
--
1.8.5.3

2014-02-26 20:16:12

by Matthew Garrett

[permalink] [raw]
Subject: [PATCH 12/12] Add option to automatically set trusted_kernel when in Secure Boot mode

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 <[email protected]>
---
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 | 6 ++++++
5 files changed, 59 insertions(+), 1 deletion(-)

diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt
index 199f453..ec38acf 100644
--- a/Documentation/x86/zero-page.txt
+++ b/Documentation/x86/zero-page.txt
@@ -30,6 +30,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
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 0af5250..3856dfb 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1585,6 +1585,19 @@ config EFI_STUB

See Documentation/efi-stub.txt for more information.

+config EFI_SECURE_BOOT_TRUSTED_KERNEL
+ def_bool n
+ depends on SECURITY_TRUSTED_KERNEL
+ depends on EFI
+ prompt "Automatically set trusted_kernel with UEFI Secure Boot"
+ ---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 trusted_kernel enforcement
+ when a system boots with UEFI Secure Boot enabled.
+
config SECCOMP
def_bool y
prompt "Enable seccomp to safely compute untrusted bytecode"
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index a7677ba..4836551 100644
--- 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>

#undef memcpy /* Use memcpy from misc.c */

@@ -421,6 +422,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_call_phys5(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_call_phys5(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
@@ -760,6 +792,10 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
goto fail;

+ sanitize_boot_params(boot_params);
+
+ boot_params->secure_boot = get_secure_boot();
+
setup_graphics(boot_params);

setup_efi_pci(boot_params);
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
index 225b098..90dbfb7 100644
--- a/arch/x86/include/uapi/asm/bootparam.h
+++ b/arch/x86/include/uapi/asm/bootparam.h
@@ -133,7 +133,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.
*
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 06853e6..875258e 100644
--- 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>
@@ -1143,6 +1144,11 @@ void __init setup_arch(char **cmdline_p)

io_delay_init();

+#ifdef CONFIG_EFI_SECURE_BOOT_TRUSTED_KERNEL
+ if (boot_params.secure_boot)
+ set_trusted_kernel(true);
+#endif
+
/*
* Parse the ACPI tables for possible boot-time SMP configuration.
*/
--
1.8.5.3

2014-02-26 20:16:20

by Matthew Garrett

[permalink] [raw]
Subject: [PATCH 10/12] x86: Restrict MSR access when trusted_kernel is true

Permitting write access to MSRs allows userspace to modify the running
kernel. Prevent this if trusted_kernel is true. Based on a patch by Kees
Cook.

Cc: Kees Cook <[email protected]>
Signed-off-by: Matthew Garrett <[email protected]>
---
arch/x86/kernel/msr.c | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
index 05266b5..1bd5e92 100644
--- a/arch/x86/kernel/msr.c
+++ b/arch/x86/kernel/msr.c
@@ -37,6 +37,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>
@@ -103,6 +104,9 @@ static ssize_t msr_write(struct file *file, const char __user *buf,
int err = 0;
ssize_t bytes = 0;

+ if (get_trusted_kernel())
+ return -EPERM;
+
if (count % 8)
return -EINVAL; /* Invalid chunk size */

@@ -150,6 +154,10 @@ static long msr_ioctl(struct file *file, unsigned int ioc, unsigned long arg)
err = -EBADF;
break;
}
+ if (get_trusted_kernel()) {
+ err = -EPERM;
+ break;
+ }
if (copy_from_user(&regs, uregs, sizeof regs)) {
err = -EFAULT;
break;
--
1.8.5.3

2014-02-26 20:16:31

by Matthew Garrett

[permalink] [raw]
Subject: [PATCH 11/12] asus-wmi: Restrict debugfs interface when trusted_kernel is true

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 trusted_kernel is true.

Signed-off-by: Matthew Garrett <[email protected]>
---
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 c5e082f..4c1000b 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -46,6 +46,7 @@
#include <linux/platform_device.h>
#include <linux/thermal.h>
#include <linux/acpi.h>
+#include <linux/security.h>
#include <acpi/video.h>

#include "asus-wmi.h"
@@ -1595,6 +1596,9 @@ static int show_dsts(struct seq_file *m, void *data)
int err;
u32 retval = -1;

+ if (get_trusted_kernel())
+ return -EPERM;
+
err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval);

if (err < 0)
@@ -1611,6 +1615,9 @@ static int show_devs(struct seq_file *m, void *data)
int err;
u32 retval = -1;

+ if (get_trusted_kernel())
+ return -EPERM;
+
err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param,
&retval);

@@ -1635,6 +1642,9 @@ static int show_call(struct seq_file *m, void *data)
union acpi_object *obj;
acpi_status status;

+ if (get_trusted_kernel())
+ return -EPERM;
+
status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID,
1, asus->debug.method_id,
&input, &output);
--
1.8.5.3

2014-02-26 21:11:30

by Kees Cook

[permalink] [raw]
Subject: Re: Trusted kernel patchset for Secure Boot lockdown

On Wed, Feb 26, 2014 at 12:11 PM, Matthew Garrett
<[email protected]> wrote:
> The conclusion we came to at Plumbers was that this patchset was basically
> fine but that Linus hated the name "securelevel" more than I hate pickled
> herring, so after thinking about this for a few months I've come up with
> "Trusted Kernel". This flag indicates that the kernel is, via some
> external mechanism, trusted and should behave that way. If firmware has
> some way to verify the kernel, it can pass that information on. If userspace
> has some way to verify the kernel, it can set the flag itself. However,
> userspace should not attempt to use the flag as a means to verify that the
> kernel was trusted - untrusted userspace could have set it on an untrusted
> kernel, but by the same metric an untrusted kernel could just set it itself.
>
> If people object to this name then I swear to god that I will open a poll
> on Phoronix to decide the next attempt and you will like that even less.

For the Chrome OS use-case, it might be better described as "untrusted
userspace", but that seems unfriendly. :) The "trusted kernel" name
seems fine to me.

-Kees

--
Kees Cook
Chrome OS Security

2014-02-26 22:22:10

by Alan Cox

[permalink] [raw]
Subject: Re: Trusted kernel patchset for Secure Boot lockdown

> > kernel was trusted - untrusted userspace could have set it on an untrusted
> > kernel, but by the same metric an untrusted kernel could just set it itself.
> >
> > If people object to this name then I swear to god that I will open a poll
> > on Phoronix to decide the next attempt and you will like that even less.

Go on open the poll - I dare you. But don't be shocked if it ends up
being called "Eric" or "Icanhazsigs" 8)

> For the Chrome OS use-case, it might be better described as "untrusted
> userspace", but that seems unfriendly. :) The "trusted kernel" name
> seems fine to me.

Trusted is rather misleading. It's not trusted, it's *measured*.

It's the same bits you had when you made it, and when you booted it
before. Whether you trust them is a different and quite unrelated
question. You may have reasons to do either.

Alan

2014-02-26 22:41:56

by Alan Cox

[permalink] [raw]
Subject: Re: [PATCH 12/12] Add option to automatically set trusted_kernel when in Secure Boot mode

On Wed, 26 Feb 2014 15:11:13 -0500
Matthew Garrett <[email protected]> wrote:

> 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.

I think you have a load more cases to attempt to paper over before you
even pretend to achieve that goal. Firewire for example. Also it only
remotely begins to work if you also force CAP_SYS_RAWIO off globally as
you need to force off things like raw command issuing to various
controllers (especially as some of that code is written on the basis that
'its RAWIO, screw making it secure and doing all the checks we could
bother with'.

RAWIO also disables things like CPU msr access - which is also quite
adequate for subverting a kernel.

Another issue that needs addressing is firmware. Quite a few of our
request_firmware cases load device firmware which is not signed into DMA
capable hardware. Probably also worth checking what the
architectural guarantees on bogus microcode updates is. Maybe we need
firmware signing for such cases to match the mod signing ?

I'm trying to think what else. Possibly disabling it on Pentium-M with
the rep movs erratum (Y19) as it's quite possible to set up suitable
adjacent page sets in user space via the graphics.

Alan

2014-02-26 22:47:39

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH 12/12] Add option to automatically set trusted_kernel when in Secure Boot mode

On 02/26/2014 02:41 PM, One Thousand Gnomes wrote:
> On Wed, 26 Feb 2014 15:11:13 -0500
> Matthew Garrett <[email protected]> wrote:
>
>> 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.
>
> I think you have a load more cases to attempt to paper over before you
> even pretend to achieve that goal. Firewire for example. Also it only
> remotely begins to work if you also force CAP_SYS_RAWIO off globally as
> you need to force off things like raw command issuing to various
> controllers (especially as some of that code is written on the basis that
> 'its RAWIO, screw making it secure and doing all the checks we could
> bother with'.
>
> RAWIO also disables things like CPU msr access - which is also quite
> adequate for subverting a kernel.
>
> Another issue that needs addressing is firmware. Quite a few of our
> request_firmware cases load device firmware which is not signed into DMA
> capable hardware. Probably also worth checking what the
> architectural guarantees on bogus microcode updates is. Maybe we need
> firmware signing for such cases to match the mod signing ?
>
> I'm trying to think what else. Possibly disabling it on Pentium-M with
> the rep movs erratum (Y19) as it's quite possible to set up suitable
> adjacent page sets in user space via the graphics.
>

I have been arguing for a long time that this should disable RAWIO. The
argument was that apparently some SCSI controllers started requiring
RAWIO to do things like update firmware... which is arguably equally
problematic, but either way is (a) clearly wrong and (b) started a long,
never-ending discussion...

-hpa

2014-02-26 22:48:54

by Matthew Garrett

[permalink] [raw]
Subject: Re: [PATCH 12/12] Add option to automatically set trusted_kernel when in Secure Boot mode

On Wed, 2014-02-26 at 22:41 +0000, One Thousand Gnomes wrote:

> I think you have a load more cases to attempt to paper over before you
> even pretend to achieve that goal. Firewire for example. Also it only
> remotely begins to work if you also force CAP_SYS_RAWIO off globally as
> you need to force off things like raw command issuing to various
> controllers (especially as some of that code is written on the basis that
> 'its RAWIO, screw making it secure and doing all the checks we could
> bother with'.

Physical presence is required to do anything meaningful with firewire,
and UEFI secure boot isn't intended to protect against that. Which
controllers will trigger arbitrary DMA in response to raw commands?

> RAWIO also disables things like CPU msr access - which is also quite
> adequate for subverting a kernel.

Patch 7.

> Another issue that needs addressing is firmware. Quite a few of our
> request_firmware cases load device firmware which is not signed into DMA
> capable hardware. Probably also worth checking what the
> architectural guarantees on bogus microcode updates is. Maybe we need
> firmware signing for such cases to match the mod signing ?

Vendors keep telling me that they're validating firmware for new
hardware, and I keep tending not to believe them. Meh. The big problem
with firmware signatures is that we don't necessarily have the right to
distribute modified versions of the firmware, so we'd need detached
signature support. I'm certainly not against this.

> I'm trying to think what else. Possibly disabling it on Pentium-M with
> the rep movs erratum (Y19) as it's quite possible to set up suitable
> adjacent page sets in user space via the graphics.

Quirking this out when the hardware makes it impossible to provide any
guarantees seems reasonable.

--
Matthew Garrett <[email protected]>
????{.n?+???????+%?????ݶ??w??{.n?+????{??G?????{ay?ʇڙ?,j??f???h?????????z_??(?階?ݢj"???m??????G????????????&???~???iO???z??v?^?m???? ????????I?

2014-02-27 18:04:39

by Josh Boyer

[permalink] [raw]
Subject: Re: Trusted kernel patchset for Secure Boot lockdown

On Wed, Feb 26, 2014 at 3:11 PM, Matthew Garrett
<[email protected]> wrote:
> The conclusion we came to at Plumbers was that this patchset was basically
> fine but that Linus hated the name "securelevel" more than I hate pickled
> herring, so after thinking about this for a few months I've come up with
> "Trusted Kernel". This flag indicates that the kernel is, via some
> external mechanism, trusted and should behave that way. If firmware has
> some way to verify the kernel, it can pass that information on. If userspace
> has some way to verify the kernel, it can set the flag itself. However,
> userspace should not attempt to use the flag as a means to verify that the
> kernel was trusted - untrusted userspace could have set it on an untrusted
> kernel, but by the same metric an untrusted kernel could just set it itself.

FWIW, I've been running a kernel using this patchset in place of the
patchset Fedora typically carries for this purpose for a bit. Things
appear to be working as expected and the protections remain the same.

It would be really nice to get this set of patches in so some of the
other patches that depend on them can start being pushed as well.

josh

2014-02-27 18:48:54

by Kees Cook

[permalink] [raw]
Subject: Re: [PATCH 12/12] Add option to automatically set trusted_kernel when in Secure Boot mode

On Wed, Feb 26, 2014 at 2:48 PM, Matthew Garrett
<[email protected]> wrote:
> On Wed, 2014-02-26 at 22:41 +0000, One Thousand Gnomes wrote:
>> Another issue that needs addressing is firmware. Quite a few of our
>> request_firmware cases load device firmware which is not signed into DMA
>> capable hardware. Probably also worth checking what the
>> architectural guarantees on bogus microcode updates is. Maybe we need
>> firmware signing for such cases to match the mod signing ?
>
> Vendors keep telling me that they're validating firmware for new
> hardware, and I keep tending not to believe them. Meh. The big problem
> with firmware signatures is that we don't necessarily have the right to
> distribute modified versions of the firmware, so we'd need detached
> signature support. I'm certainly not against this.

I have been working on a patch series for this. It will have LSM hooks
for validating firmware origin (via fd) and contents (via blob),
similar to the changes I made for validating module origins. It just
need to finish testing, and I'll post the series. If you want to check
it out in its current state, it's here:

http://git.kernel.org/cgit/linux/kernel/git/kees/linux.git/log/?h=fw-restrict

-Kees

--
Kees Cook
Chrome OS Security

2014-02-27 19:02:14

by Kees Cook

[permalink] [raw]
Subject: Re: [PATCH 01/12] Add support for indicating that the booted kernel is externally trusted

On Wed, Feb 26, 2014 at 12:11 PM, Matthew Garrett
<[email protected]> wrote:
> Provide a boolean runtime configuration option for restricting userspace's
> ability to modify the running kernel. This can be used when some external
> validation of the kernel's state has been performed.
>
> Signed-off-by: Matthew Garrett <[email protected]>
> ---
> Documentation/kernel-parameters.txt | 6 ++
> Documentation/security/trusted_kernel.txt | 35 ++++++++++
> include/linux/security.h | 8 +++
> security/Kconfig | 9 +++
> security/Makefile | 1 +
> security/trusted_kernel.c | 111 ++++++++++++++++++++++++++++++
> 6 files changed, 170 insertions(+)
> create mode 100644 Documentation/security/trusted_kernel.txt
> create mode 100644 security/trusted_kernel.c
>
> diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
> index 7116fda..d82ba9e 100644
> --- a/Documentation/kernel-parameters.txt
> +++ b/Documentation/kernel-parameters.txt
> @@ -3271,6 +3271,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
> with respect to transparent hugepages.
> See Documentation/vm/transhuge.txt for more details.
>
> + trusted_kernel Indicate that the booted kernel has been verified to
> + be trustworthy and that userspace should be forbidden
> + from modifying it at runtime.
> + See Documentation/security/trusted_kernel.txt for more
> + details.
> +
> tsc= Disable clocksource stability checks for TSC.
> Format: <string>
> [x86] reliable: mark tsc clocksource as reliable, this
> diff --git a/Documentation/security/trusted_kernel.txt b/Documentation/security/trusted_kernel.txt
> new file mode 100644
> index 0000000..538d21d
> --- /dev/null
> +++ b/Documentation/security/trusted_kernel.txt
> @@ -0,0 +1,35 @@
> +Linux trusted kernel support
> +----------------------------
> +
> +Various mechanisms exist to ensure that a booted kernel is trusted by the
> +user or some external party (UEFI Secure Boot, Intel TXT, embedded platform
> +bootloaders). If userspace is able to modify the running kernel then this
> +trust can be subverted.
> +
> +The trusted kernel support modifies certain kernel interfaces such that
> +userspace is restricted from performing acts that would allow it to inject
> +untrusted code into the kernel. 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.
> +
> +The trusted kernel feature may be enabled in multiple ways:
> +
> +1) Platform-specific code may automatically enable it when it detects that
> +the system has been booted appropriately
> +
> +2) The user or bootloader may pass the "trusted_kernel" kernel parameter
> +
> +3) Userspace may write "1" to the /sys/kernel/security/trusted_kernel
> +node. This must be done sufficiently early in the boot process that
> +untrusted userspace has no opportunity to modify the kernel.
> +
> +Once enabled. trusted kernel support may not be disabled without rebooting
> +the system.
> +
> +Note that this is a mechanism for the kernel to determine whether or not
> +it is externally trusted. Untrusted userspace can enable this option even
> +if the kernel is not trusted, and therefore userspace should not use this
> +value as an indication of whether or not the kernel is trustworthy.
> diff --git a/include/linux/security.h b/include/linux/security.h
> index 5623a7f..3415968 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -3091,6 +3091,14 @@ static inline void security_audit_rule_free(void *lsmrule)
> #endif /* CONFIG_SECURITY */
> #endif /* CONFIG_AUDIT */
>
> +#ifdef CONFIG_SECURITY_TRUSTED_KERNEL
> +extern bool get_trusted_kernel(void);
> +extern int set_trusted_kernel(bool new_trusted_kernel);
> +#else
> +static inline bool get_trusted_kernel(void) { return 0; }
> +static inline int set_trusted_kernel(bool new_trusted_kernel) { return 0; }

Should set_trusted_kernel return -ENOTSUPP when the config is off?

> +#endif /* CONFIG_TRUSTED_KERNEL */
> +
> #ifdef CONFIG_SECURITYFS
>
> extern struct dentry *securityfs_create_file(const char *name, umode_t mode,
> diff --git a/security/Kconfig b/security/Kconfig
> index beb86b5..c0462c9 100644
> --- a/security/Kconfig
> +++ b/security/Kconfig
> @@ -70,6 +70,15 @@ config SECURITY_PATH
> implement pathname based access controls.
> If you are unsure how to answer this question, answer N.
>
> +config SECURITY_TRUSTED_KERNEL
> + bool "Support for indicating that the kernel is trusted"
> + depends on SECURITY
> + help
> + This enables support for adding a set of additional kernel security
> + restrictions at runtime.
> + See Documentation/security/trusted_kernel.txt for further
> + information.
> +
> config INTEL_TXT
> bool "Enable Intel(R) Trusted Execution Technology (Intel(R) TXT)"
> depends on HAVE_INTEL_TXT
> diff --git a/security/Makefile b/security/Makefile
> index a5918e0..72af305 100644
> --- a/security/Makefile
> +++ b/security/Makefile
> @@ -16,6 +16,7 @@ obj-$(CONFIG_MMU) += min_addr.o
> # Object file lists
> obj-$(CONFIG_SECURITY) += security.o capability.o
> obj-$(CONFIG_SECURITYFS) += inode.o
> +obj-$(CONFIG_SECURITY_TRUSTED_KERNEL) += trusted_kernel.o
> obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
> obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
> obj-$(CONFIG_AUDIT) += lsm_audit.o
> diff --git a/security/trusted_kernel.c b/security/trusted_kernel.c
> new file mode 100644
> index 0000000..2808113
> --- /dev/null
> +++ b/security/trusted_kernel.c
> @@ -0,0 +1,111 @@
> +/*
> + * trusted_kernel.c - support for generic kernel lockdown
> + *
> + * Copyright Nebula, Inc <[email protected]>
> + *
> + * 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 bool trusted_kernel;
> +
> +bool get_trusted_kernel(void)
> +{
> + return trusted_kernel;
> +}
> +EXPORT_SYMBOL(get_trusted_kernel);
> +
> +int set_trusted_kernel(bool new_trusted_kernel)
> +{
> + if (trusted_kernel == true && new_trusted_kernel == false)
> + return -EINVAL;
> +
> + trusted_kernel = new_trusted_kernel;
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(set_trusted_kernel);
> +
> +static ssize_t trusted_kernel_read(struct file *filp, char __user *buf,
> + size_t count, loff_t *ppos)
> +{
> + char tmpbuf[2];
> + ssize_t length;
> +
> + length = scnprintf(tmpbuf, sizeof(tmpbuf), "%d", trusted_kernel);
> + return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
> +}
> +
> +static ssize_t trusted_kernel_write(struct file *file, const char __user *buf,
> + size_t count, loff_t *ppos)
> +{
> + char *page = NULL;
> + ssize_t length;
> + int new_trusted_kernel;
> +
> + 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_trusted_kernel) != 1)
> + goto out;
> +
> + length = set_trusted_kernel(!!new_trusted_kernel);
> + if (length)
> + goto out;
> +
> + length = count;
> +out:
> + free_page((unsigned long) page);
> + return length;
> +}
> +
> +static const struct file_operations trusted_kernel_fops = {
> + .read = trusted_kernel_read,
> + .write = trusted_kernel_write,
> + .llseek = generic_file_llseek,
> +};
> +
> +static __init int setup_trusted_kernel(void)
> +{
> + struct dentry *trusted_kernel_file;
> +
> + trusted_kernel_file = securityfs_create_file("trusted_kernel",
> + S_IWUSR | S_IRUGO,
> + NULL, NULL,
> + &trusted_kernel_fops);
> +
> + if (IS_ERR(trusted_kernel_file))
> + return PTR_ERR(trusted_kernel_file);
> +
> + return 0;
> +}
> +late_initcall(setup_trusted_kernel);
> +
> +static int __init enable_trusted_kernel(char *__str)
> +{
> + trusted_kernel = true;
> + return 1;
> +}
> +__setup("trusted_kernel", enable_trusted_kernel);
> --
> 1.8.5.3
>

Thanks for reposting this. I'm looking forward to adding
"trusted_kernel" to the Chrome OS kernel cmdline. :)

Please consider the series:

Acked-by: Kees Cook <[email protected]>

-Kees

--
Kees Cook
Chrome OS Security

2014-02-27 19:05:36

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: Trusted kernel patchset for Secure Boot lockdown

On Thu, Feb 27, 2014 at 01:04:34PM -0500, Josh Boyer wrote:
> On Wed, Feb 26, 2014 at 3:11 PM, Matthew Garrett
> <[email protected]> wrote:
> > The conclusion we came to at Plumbers was that this patchset was basically
> > fine but that Linus hated the name "securelevel" more than I hate pickled
> > herring, so after thinking about this for a few months I've come up with
> > "Trusted Kernel". This flag indicates that the kernel is, via some
> > external mechanism, trusted and should behave that way. If firmware has
> > some way to verify the kernel, it can pass that information on. If userspace
> > has some way to verify the kernel, it can set the flag itself. However,
> > userspace should not attempt to use the flag as a means to verify that the
> > kernel was trusted - untrusted userspace could have set it on an untrusted
> > kernel, but by the same metric an untrusted kernel could just set it itself.
>
> FWIW, I've been running a kernel using this patchset in place of the
> patchset Fedora typically carries for this purpose for a bit. Things
> appear to be working as expected and the protections remain the same.
>
> It would be really nice to get this set of patches in so some of the
> other patches that depend on them can start being pushed as well.

What other patches depend on this series? Why aren't they also in this
series?

thanks,

greg k-h

2014-02-27 19:11:09

by Josh Boyer

[permalink] [raw]
Subject: Re: Trusted kernel patchset for Secure Boot lockdown

On Thu, Feb 27, 2014 at 2:07 PM, Greg KH <[email protected]> wrote:
> On Thu, Feb 27, 2014 at 01:04:34PM -0500, Josh Boyer wrote:
>> On Wed, Feb 26, 2014 at 3:11 PM, Matthew Garrett
>> <[email protected]> wrote:
>> > The conclusion we came to at Plumbers was that this patchset was basically
>> > fine but that Linus hated the name "securelevel" more than I hate pickled
>> > herring, so after thinking about this for a few months I've come up with
>> > "Trusted Kernel". This flag indicates that the kernel is, via some
>> > external mechanism, trusted and should behave that way. If firmware has
>> > some way to verify the kernel, it can pass that information on. If userspace
>> > has some way to verify the kernel, it can set the flag itself. However,
>> > userspace should not attempt to use the flag as a means to verify that the
>> > kernel was trusted - untrusted userspace could have set it on an untrusted
>> > kernel, but by the same metric an untrusted kernel could just set it itself.
>>
>> FWIW, I've been running a kernel using this patchset in place of the
>> patchset Fedora typically carries for this purpose for a bit. Things
>> appear to be working as expected and the protections remain the same.
>>
>> It would be really nice to get this set of patches in so some of the
>> other patches that depend on them can start being pushed as well.
>
> What other patches depend on this series? Why aren't they also in this
> series?

The patches we have to import certificates from the UEFI db and dbx
vars, and MokListRT and apply them to signed module verification.
Looking at them closely, there are pieces that could be sent now as
they are slightly orthogonal to what this patchset is doing, which is
probably why they aren't in this patchset to begin with. I'll have to
figure out which of those actually depend on anything in Matthew's
series.

josh

2014-02-28 02:54:51

by James Morris

[permalink] [raw]
Subject: Re: Trusted kernel patchset for Secure Boot lockdown

On Thu, 27 Feb 2014, Josh Boyer wrote:

> On Wed, Feb 26, 2014 at 3:11 PM, Matthew Garrett
> <[email protected]> wrote:
> > The conclusion we came to at Plumbers was that this patchset was basically
> > fine but that Linus hated the name "securelevel" more than I hate pickled
> > herring, so after thinking about this for a few months I've come up with
> > "Trusted Kernel". This flag indicates that the kernel is, via some
> > external mechanism, trusted and should behave that way. If firmware has
> > some way to verify the kernel, it can pass that information on. If userspace
> > has some way to verify the kernel, it can set the flag itself. However,
> > userspace should not attempt to use the flag as a means to verify that the
> > kernel was trusted - untrusted userspace could have set it on an untrusted
> > kernel, but by the same metric an untrusted kernel could just set it itself.
>
> FWIW, I've been running a kernel using this patchset in place of the
> patchset Fedora typically carries for this purpose for a bit. Things
> appear to be working as expected and the protections remain the same.
>
> It would be really nice to get this set of patches in so some of the
> other patches that depend on them can start being pushed as well.

Ok, which tree should take this? I'm happy to, although most of it is
outside security/ .



--
James Morris
<[email protected]>

2014-02-28 04:53:08

by Matthew Garrett

[permalink] [raw]
Subject: Re: Trusted kernel patchset for Secure Boot lockdown

On Fri, 2014-02-28 at 14:03 +1100, James Morris wrote:

> Ok, which tree should take this? I'm happy to, although most of it is
> outside security/ .

Security might make the most sense - I don't think any of the additional
restrictions (beyond kexec, and I think we've hashed that argument out
now) are terribly controversial.

--
Matthew Garrett <[email protected]>
????{.n?+???????+%?????ݶ??w??{.n?+????{??G?????{ay?ʇڙ?,j??f???h?????????z_??(?階?ݢj"???m??????G????????????&???~???iO???z??v?^?m???? ????????I?

2014-02-28 12:50:47

by Josh Boyer

[permalink] [raw]
Subject: Re: Trusted kernel patchset for Secure Boot lockdown

On Thu, Feb 27, 2014 at 2:11 PM, Josh Boyer <[email protected]> wrote:
> On Thu, Feb 27, 2014 at 2:07 PM, Greg KH <[email protected]> wrote:
>> On Thu, Feb 27, 2014 at 01:04:34PM -0500, Josh Boyer wrote:
>>> On Wed, Feb 26, 2014 at 3:11 PM, Matthew Garrett
>>> <[email protected]> wrote:
>>> > The conclusion we came to at Plumbers was that this patchset was basically
>>> > fine but that Linus hated the name "securelevel" more than I hate pickled
>>> > herring, so after thinking about this for a few months I've come up with
>>> > "Trusted Kernel". This flag indicates that the kernel is, via some
>>> > external mechanism, trusted and should behave that way. If firmware has
>>> > some way to verify the kernel, it can pass that information on. If userspace
>>> > has some way to verify the kernel, it can set the flag itself. However,
>>> > userspace should not attempt to use the flag as a means to verify that the
>>> > kernel was trusted - untrusted userspace could have set it on an untrusted
>>> > kernel, but by the same metric an untrusted kernel could just set it itself.
>>>
>>> FWIW, I've been running a kernel using this patchset in place of the
>>> patchset Fedora typically carries for this purpose for a bit. Things
>>> appear to be working as expected and the protections remain the same.
>>>
>>> It would be really nice to get this set of patches in so some of the
>>> other patches that depend on them can start being pushed as well.
>>
>> What other patches depend on this series? Why aren't they also in this
>> series?
>
> The patches we have to import certificates from the UEFI db and dbx
> vars, and MokListRT and apply them to signed module verification.
> Looking at them closely, there are pieces that could be sent now as
> they are slightly orthogonal to what this patchset is doing, which is
> probably why they aren't in this patchset to begin with. I'll have to
> figure out which of those actually depend on anything in Matthew's
> series.

OK, I figured it out. I have a patch that adds an EFI_SECURE_BOOT
x86_efi_facility bit, and that is used in the later patches where
applicable. The patch that adds it depends on patch 12 in Matthew's
series.

There are a few patches that are mostly stand-alone and I'll try and
get those sent out soon. They're a mix of things from David Howells
and myself, and should probably go through the security tree.

josh

2015-04-22 11:37:29

by Dan Carpenter

[permalink] [raw]
Subject: Re: [PATCH 12/12] Add option to automatically set trusted_kernel when in Secure Boot mode

On Fri, Mar 13, 2015 at 11:38:28AM -1000, Matthew Garrett wrote:
> 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 <[email protected]>
> ---
> Documentation/x86/zero-page.txt | 2 ++
> arch/x86/Kconfig | 13 +++++++++++++
> arch/x86/boot/compressed/eboot.c | 33 +++++++++++++++++++++++++++++++++
> arch/x86/include/uapi/asm/bootparam.h | 3 ++-
> arch/x86/kernel/setup.c | 6 ++++++
> 5 files changed, 56 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt
> index 82fbdbc..a811210 100644
> --- a/Documentation/x86/zero-page.txt
> +++ b/Documentation/x86/zero-page.txt
> @@ -30,6 +30,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

This line looks like it was included by mistake?

> +1EC/001 ALL secure_boot Secure boot is enabled in the firmware

regards,
dan carpenter