On Wed, Feb 26, 2014 at 12:11 PM, Matthew Garrett
<matthew.garr...@nebula.com> 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 <matthew.garr...@nebula.com>
> ---
>  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 <matthew.garr...@nebula.com>
> + *
> + *  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 <keesc...@chromium.org>

-Kees

-- 
Kees Cook
Chrome OS Security
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to