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 <matthew.garrett@xxxxxxxxxx> --- 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 <matthew.garrett@xxxxxxxxxx> + * + * 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 -- To unsubscribe from this list: send the line "unsubscribe linux-efi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html