linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Kees Cook <keescook@chromium.org>
To: Matthew Garrett <matthewgarrett@google.com>
Cc: jmorris@namei.org, linux-security-module@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-api@vger.kernel.org,
	Matthew Garrett <mjg59@google.com>,
	David Howells <dhowells@redhat.com>
Subject: Re: [PATCH V34 03/29] security: Add a static lockdown policy LSM
Date: Sat, 22 Jun 2019 16:37:42 -0700	[thread overview]
Message-ID: <201906221637.C57BBFA87C@keescook> (raw)
In-Reply-To: <20190622000358.19895-4-matthewgarrett@google.com>

On Fri, Jun 21, 2019 at 05:03:32PM -0700, Matthew Garrett wrote:
> While existing LSMs can be extended to handle lockdown policy,
> distributions generally want to be able to apply a straightforward
> static policy. This patch adds a simple LSM that can be configured to
> reject either integrity or all lockdown queries, and can be configured
> at runtime (through securityfs), boot time (via a kernel parameter) or
> build time (via a kconfig option). Based on initial code by David
> Howells.
> 
> Signed-off-by: Matthew Garrett <mjg59@google.com>

Reviewed-by: Kees Cook <keescook@chromium.org>

-Kees

> Cc: David Howells <dhowells@redhat.com>
> ---
>  .../admin-guide/kernel-parameters.txt         |   9 +
>  include/linux/security.h                      |   4 +
>  security/Kconfig                              |   3 +-
>  security/Makefile                             |   2 +
>  security/lockdown/Kconfig                     |  47 +++++
>  security/lockdown/Makefile                    |   1 +
>  security/lockdown/lockdown.c                  | 172 ++++++++++++++++++
>  7 files changed, 237 insertions(+), 1 deletion(-)
>  create mode 100644 security/lockdown/Kconfig
>  create mode 100644 security/lockdown/Makefile
>  create mode 100644 security/lockdown/lockdown.c
> 
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index 2b8ee90bb644..fa336f6cd5bc 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -2239,6 +2239,15 @@
>  	lockd.nlm_udpport=M	[NFS] Assign UDP port.
>  			Format: <integer>
>  
> +	lockdown=	[SECURITY]
> +			{ integrity | confidentiality }
> +			Enable the kernel lockdown feature. If set to
> +			integrity, kernel features that allow userland to
> +			modify the running kernel are disabled. If set to
> +			confidentiality, kernel features that allow userland
> +			to extract confidential information from the kernel
> +			are also disabled.
> +
>  	locktorture.nreaders_stress= [KNL]
>  			Set the number of locking read-acquisition kthreads.
>  			Defaults to being automatically set based on the
> diff --git a/include/linux/security.h b/include/linux/security.h
> index 9eaf02e70707..c808d344ec75 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -76,6 +76,10 @@ enum lsm_event {
>  	LSM_POLICY_CHANGE,
>  };
>  
> +/*
> + *  If you add to this, remember to extend lockdown_reasons in
> + *  security/lockdown/lockdown.c.
> + */
>  enum lockdown_reason {
>  	LOCKDOWN_NONE,
>  	LOCKDOWN_INTEGRITY_MAX,
> diff --git a/security/Kconfig b/security/Kconfig
> index 1d6463fb1450..c35aa72103df 100644
> --- a/security/Kconfig
> +++ b/security/Kconfig
> @@ -236,12 +236,13 @@ source "security/apparmor/Kconfig"
>  source "security/loadpin/Kconfig"
>  source "security/yama/Kconfig"
>  source "security/safesetid/Kconfig"
> +source "security/lockdown/Kconfig"
>  
>  source "security/integrity/Kconfig"
>  
>  config LSM
>  	string "Ordered list of enabled LSMs"
> -	default "yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor"
> +	default "lockdown,yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor"
>  	help
>  	  A comma-separated list of LSMs, in initialization order.
>  	  Any LSMs left off this list will be ignored. This can be
> diff --git a/security/Makefile b/security/Makefile
> index c598b904938f..be1dd9d2cb2f 100644
> --- a/security/Makefile
> +++ b/security/Makefile
> @@ -11,6 +11,7 @@ subdir-$(CONFIG_SECURITY_APPARMOR)	+= apparmor
>  subdir-$(CONFIG_SECURITY_YAMA)		+= yama
>  subdir-$(CONFIG_SECURITY_LOADPIN)	+= loadpin
>  subdir-$(CONFIG_SECURITY_SAFESETID)    += safesetid
> +subdir-$(CONFIG_SECURITY_LOCKDOWN_LSM)	+= lockdown
>  
>  # always enable default capabilities
>  obj-y					+= commoncap.o
> @@ -27,6 +28,7 @@ obj-$(CONFIG_SECURITY_APPARMOR)		+= apparmor/
>  obj-$(CONFIG_SECURITY_YAMA)		+= yama/
>  obj-$(CONFIG_SECURITY_LOADPIN)		+= loadpin/
>  obj-$(CONFIG_SECURITY_SAFESETID)       += safesetid/
> +obj-$(CONFIG_SECURITY_LOCKDOWN_LSM)	+= lockdown/
>  obj-$(CONFIG_CGROUP_DEVICE)		+= device_cgroup.o
>  
>  # Object integrity file lists
> diff --git a/security/lockdown/Kconfig b/security/lockdown/Kconfig
> new file mode 100644
> index 000000000000..7374ba76d8eb
> --- /dev/null
> +++ b/security/lockdown/Kconfig
> @@ -0,0 +1,47 @@
> +config SECURITY_LOCKDOWN_LSM
> +	bool "Basic module for enforcing kernel lockdown"
> +	depends on SECURITY
> +	help
> +	  Build support for an LSM that enforces a coarse kernel lockdown
> +	  behaviour.
> +
> +config SECURITY_LOCKDOWN_LSM_EARLY
> +	bool "Enable lockdown LSM early in init"
> +	depends on SECURITY_LOCKDOWN_LSM
> +	help
> +	  Enable the lockdown LSM early in boot. This is necessary in order
> +	  to ensure that lockdown enforcement can be carried out on kernel
> +	  boot parameters that are otherwise parsed before the security
> +	  subsystem is fully initialised. If enabled, lockdown will
> +	  unconditionally be called before any other LSMs.
> +
> +choice
> +	prompt "Kernel default lockdown mode"
> +	default LOCK_DOWN_KERNEL_FORCE_NONE
> +	depends on SECURITY_LOCKDOWN_LSM
> +	help
> +	  The kernel can be configured to default to differing levels of
> +	  lockdown.
> +
> +config LOCK_DOWN_KERNEL_FORCE_NONE
> +	bool "None"
> +	help
> +	  No lockdown functionality is enabled by default. Lockdown may be
> +	  enabled via the kernel commandline or /sys/kernel/security/lockdown.
> +
> +config LOCK_DOWN_KERNEL_FORCE_INTEGRITY
> +	bool "Integrity"
> +	help
> +	 The kernel runs in integrity mode by default. Features that allow
> +	 the kernel to be modified at runtime are disabled.
> +
> +config LOCK_DOWN_KERNEL_FORCE_CONFIDENTIALITY
> +	bool "Confidentiality"
> +	help
> +	 The kernel runs in confidentiality mode by default. Features that
> +	 allow the kernel to be modified at runtime or that permit userland
> +	 code to read confidential material held inside the kernel are
> +	 disabled.
> +
> +endchoice
> +
> diff --git a/security/lockdown/Makefile b/security/lockdown/Makefile
> new file mode 100644
> index 000000000000..e3634b9017e7
> --- /dev/null
> +++ b/security/lockdown/Makefile
> @@ -0,0 +1 @@
> +obj-$(CONFIG_SECURITY_LOCKDOWN_LSM) += lockdown.o
> diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c
> new file mode 100644
> index 000000000000..8e39b36b8f33
> --- /dev/null
> +++ b/security/lockdown/lockdown.c
> @@ -0,0 +1,172 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Lock down the kernel
> + *
> + * Copyright (C) 2016 Red Hat, Inc. All Rights Reserved.
> + * Written by David Howells (dhowells@redhat.com)
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public Licence
> + * as published by the Free Software Foundation; either version
> + * 2 of the Licence, or (at your option) any later version.
> + */
> +
> +#include <linux/security.h>
> +#include <linux/export.h>
> +#include <linux/lsm_hooks.h>
> +
> +static enum lockdown_reason kernel_locked_down;
> +
> +static char *lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {
> +	[LOCKDOWN_NONE] = "none",
> +	[LOCKDOWN_INTEGRITY_MAX] = "integrity",
> +	[LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality",
> +};
> +
> +static enum lockdown_reason lockdown_levels[] = {LOCKDOWN_NONE,
> +						 LOCKDOWN_INTEGRITY_MAX,
> +						 LOCKDOWN_CONFIDENTIALITY_MAX};
> +
> +/*
> + * Put the kernel into lock-down mode.
> + */
> +static int lock_kernel_down(const char *where, enum lockdown_reason level)
> +{
> +	if (kernel_locked_down >= level)
> +		return -EPERM;
> +
> +	kernel_locked_down = level;
> +	pr_notice("Kernel is locked down from %s; see man kernel_lockdown.7\n",
> +		  where);
> +	return 0;
> +}
> +
> +static int __init lockdown_param(char *level)
> +{
> +	if (!level)
> +		return -EINVAL;
> +
> +	if (strcmp(level, "integrity") == 0)
> +		lock_kernel_down("command line", LOCKDOWN_INTEGRITY_MAX);
> +	else if (strcmp(level, "confidentiality") == 0)
> +		lock_kernel_down("command line", LOCKDOWN_CONFIDENTIALITY_MAX);
> +	else
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +early_param("lockdown", lockdown_param);
> +
> +/**
> + * lockdown_is_locked_down - Find out if the kernel is locked down
> + * @what: Tag to use in notice generated if lockdown is in effect
> + */
> +static int lockdown_is_locked_down(enum lockdown_reason what)
> +{	
> +	if ((kernel_locked_down >= what)) {
> +		if (lockdown_reasons[what])
> +			pr_notice("Lockdown: %s is restricted; see man kernel_lockdown.7\n",
> +				  lockdown_reasons[what]);
> +		return -EPERM;
> +	}
> +
> +	return 0;
> +}
> +
> +static struct security_hook_list lockdown_hooks[] __lsm_ro_after_init = {
> +	LSM_HOOK_INIT(locked_down, lockdown_is_locked_down),
> +};
> +
> +static int __init lockdown_lsm_init(void)
> +{
> +#if defined(CONFIG_LOCK_DOWN_KERNEL_FORCE_INTEGRITY)
> +	lock_kernel_down("Kernel configuration", LOCKDOWN_INTEGRITY_MAX);
> +#elif defined(CONFIG_LOCK_DOWN_KERNEL_FORCE_CONFIDENTIALITY)
> +	lock_kernel_down("Kernel configuration", LOCKDOWN_CONFIDENTIALITY_MAX);
> +#endif
> +	security_add_hooks(lockdown_hooks, ARRAY_SIZE(lockdown_hooks),
> +			   "lockdown");
> +	return 0;
> +}
> +
> +static ssize_t lockdown_read(struct file *filp, char __user *buf, size_t count,
> +			     loff_t *ppos)
> +{
> +	char temp[80];
> +	int i, offset=0;
> +
> +	for (i = 0; i < ARRAY_SIZE(lockdown_levels); i++) {
> +		enum lockdown_reason level = lockdown_levels[i];
> +
> +		if (lockdown_reasons[level]) {
> +			const char *label = lockdown_reasons[level];
> +
> +			if (kernel_locked_down == level)
> +				offset += sprintf(temp+offset, "[%s] ", label);
> +			else
> +				offset += sprintf(temp+offset, "%s ", label);
> +		}
> +	}
> +
> +	/* Convert the last space to a newline if needed. */
> +	if (offset > 0)
> +		temp[offset-1] = '\n';
> +
> +	return simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
> +}
> +
> +static ssize_t lockdown_write(struct file *file, const char __user *buf,
> +			      size_t n, loff_t *ppos)
> +{
> +	char *state;
> +	int i, len, err = -EINVAL;
> +
> +	state = memdup_user_nul(buf, n);
> +	if (IS_ERR(state))
> +		return PTR_ERR(state);
> +
> +	len = strlen(state);
> +	if (len && state[len-1] == '\n') {
> +		state[len-1] = '\0';
> +		len--;
> +	}
> +
> +	for (i = 0; i < ARRAY_SIZE(lockdown_levels); i++) {
> +		enum lockdown_reason level = lockdown_levels[i];
> +		const char *label = lockdown_reasons[level];
> +
> +		if (label && !strcmp(state, label))
> +			err = lock_kernel_down("securityfs", level);
> +	}
> +
> +	kfree(state);
> +	return err ? err : n;
> +}
> +
> +static const struct file_operations lockdown_ops = {
> +	.read  = lockdown_read,
> +	.write = lockdown_write,
> +};
> +
> +static int __init lockdown_secfs_init(void)
> +{
> +	struct dentry *dentry;
> +
> +	dentry = securityfs_create_file("lockdown", 0600, NULL, NULL,
> +					&lockdown_ops);
> +	if (IS_ERR(dentry))
> +		return PTR_ERR(dentry);
> +
> +	return 0;
> +}
> +
> +core_initcall(lockdown_secfs_init);
> +
> +#ifdef CONFIG_SECURITY_LOCKDOWN_LSM_EARLY
> +DEFINE_EARLY_LSM(lockdown) = {
> +#else
> +DEFINE_LSM(lockdown) = {
> +#endif
> +	.name = "lockdown",
> +	.init = lockdown_lsm_init,
> +};
> -- 
> 2.22.0.410.gd8fdbe21b5-goog
> 

-- 
Kees Cook

  reply	other threads:[~2019-06-22 23:37 UTC|newest]

Thread overview: 80+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-22  0:03 [PATCH V34 00/29] Lockdown as an LSM Matthew Garrett
2019-06-22  0:03 ` [PATCH V34 01/29] security: Support early LSMs Matthew Garrett
2019-06-22 23:36   ` Kees Cook
2019-06-22  0:03 ` [PATCH V34 02/29] security: Add a "locked down" LSM hook Matthew Garrett
2019-06-22 23:37   ` Kees Cook
2019-06-22  0:03 ` [PATCH V34 03/29] security: Add a static lockdown policy LSM Matthew Garrett
2019-06-22 23:37   ` Kees Cook [this message]
2019-06-22  0:03 ` [PATCH V34 04/29] Enforce module signatures if the kernel is locked down Matthew Garrett
2019-06-22 23:48   ` Kees Cook
2019-06-22  0:03 ` [PATCH V34 05/29] Restrict /dev/{mem,kmem,port} when " Matthew Garrett
2019-06-22 23:52   ` Kees Cook
2019-06-22  0:03 ` [PATCH V34 06/29] kexec_load: Disable at runtime if " Matthew Garrett
2019-06-22 23:52   ` Kees Cook
2019-06-22  0:03 ` [PATCH V34 07/29] Copy secure_boot flag in boot params across kexec reboot Matthew Garrett
2019-06-22 23:53   ` Kees Cook
2019-06-22  0:03 ` [PATCH V34 08/29] kexec_file: split KEXEC_VERIFY_SIG into KEXEC_SIG and KEXEC_SIG_FORCE Matthew Garrett
2019-06-24  2:01   ` Dave Young
2019-06-25  2:35     ` Dave Young
2019-06-22  0:03 ` [PATCH V34 09/29] kexec_file: Restrict at runtime if the kernel is locked down Matthew Garrett
2019-06-22 23:54   ` Kees Cook
2019-06-27  4:59   ` James Morris
2019-06-27 15:28     ` Matthew Garrett
2019-06-27 18:14       ` James Morris
2019-06-27 23:17         ` Matthew Garrett
2019-06-22  0:03 ` [PATCH V34 10/29] hibernate: Disable when " Matthew Garrett
2019-06-22 17:52   ` Pavel Machek
2019-06-24 13:21     ` Jiri Kosina
2019-07-10 15:26       ` Joey Lee
2019-07-11  4:11       ` joeyli
2019-06-22 23:55   ` Kees Cook
2019-06-22  0:03 ` [PATCH V34 11/29] PCI: Lock down BAR access " Matthew Garrett
2019-06-22 23:55   ` Kees Cook
2019-06-22  0:03 ` [PATCH V34 12/29] x86: Lock down IO port " Matthew Garrett
2019-06-22 23:58   ` Kees Cook
2019-06-22  0:03 ` [PATCH V34 13/29] x86/msr: Restrict MSR " Matthew Garrett
2019-06-22  0:03 ` [PATCH V34 14/29] ACPI: Limit access to custom_method " Matthew Garrett
2019-06-22 23:59   ` Kees Cook
2019-06-22  0:03 ` [PATCH V34 15/29] acpi: Ignore acpi_rsdp kernel param when the kernel has been " Matthew Garrett
2019-06-22 23:59   ` Kees Cook
2019-06-22  0:03 ` [PATCH V34 16/29] acpi: Disable ACPI table override if the kernel is " Matthew Garrett
2019-06-23  0:00   ` Kees Cook
2019-06-22  0:03 ` [PATCH V34 17/29] Prohibit PCMCIA CIS storage when " Matthew Garrett
2019-06-23  0:00   ` Kees Cook
2019-06-22  0:03 ` [PATCH V34 18/29] Lock down TIOCSSERIAL Matthew Garrett
2019-06-23  0:01   ` Kees Cook
2019-06-22  0:03 ` [PATCH V34 19/29] Lock down module params that specify hardware parameters (eg. ioport) Matthew Garrett
2019-06-23  0:04   ` Kees Cook
2019-06-27  1:49   ` Daniel Axtens
2019-06-27 15:30     ` Matthew Garrett
2019-06-22  0:03 ` [PATCH V34 20/29] x86/mmiotrace: Lock down the testmmiotrace module Matthew Garrett
2019-06-23  0:04   ` Kees Cook
2019-06-23 11:08   ` Thomas Gleixner
2019-06-22  0:03 ` [PATCH V34 21/29] Lock down /proc/kcore Matthew Garrett
2019-06-23  0:05   ` Kees Cook
2019-06-22  0:03 ` [PATCH V34 22/29] Lock down tracing and perf kprobes when in confidentiality mode Matthew Garrett
2019-06-23  0:09   ` Kees Cook
2019-06-23  1:57   ` Masami Hiramatsu
2019-06-22  0:03 ` [PATCH V34 23/29] bpf: Restrict bpf when kernel lockdown is " Matthew Garrett
2019-06-23  0:09   ` Kees Cook
2019-06-24 15:15   ` Daniel Borkmann
2019-06-24 19:54     ` Matthew Garrett
2019-06-24 20:08       ` Andy Lutomirski
2019-06-24 20:15         ` Matthew Garrett
2019-06-24 20:59         ` Daniel Borkmann
2019-06-24 21:30           ` Matthew Garrett
2019-06-22  0:03 ` [PATCH V34 24/29] Lock down perf when " Matthew Garrett
2019-06-23  0:12   ` Kees Cook
2019-06-22  0:03 ` [PATCH V34 25/29] kexec: Allow kexec_file() with appropriate IMA policy when locked down Matthew Garrett
2019-06-22  0:03 ` [PATCH V34 26/29] debugfs: Restrict debugfs when the kernel is " Matthew Garrett
2019-06-22  0:03 ` [PATCH V34 27/29] tracefs: Restrict tracefs " Matthew Garrett
2019-06-22  0:03 ` [PATCH V34 28/29] efi: Restrict efivar_ssdt_load " Matthew Garrett
2019-06-23  0:14   ` Kees Cook
2019-06-25 15:00   ` Ard Biesheuvel
2019-06-22  0:03 ` [PATCH V34 29/29] lockdown: Print current->comm in restriction messages Matthew Garrett
2019-06-23  0:25   ` Kees Cook
2019-06-24 23:01 ` [PATCH V34 00/29] Lockdown as an LSM James Morris
2019-06-24 23:47   ` Casey Schaufler
2019-06-24 23:56   ` Matthew Garrett
2019-06-25  6:04     ` James Morris
2019-06-25  8:16   ` John Johansen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=201906221637.C57BBFA87C@keescook \
    --to=keescook@chromium.org \
    --cc=dhowells@redhat.com \
    --cc=jmorris@namei.org \
    --cc=linux-api@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=matthewgarrett@google.com \
    --cc=mjg59@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).