Received: by 10.192.165.156 with SMTP id m28csp933347imm; Wed, 11 Apr 2018 09:29:19 -0700 (PDT) X-Google-Smtp-Source: AIpwx49yXj8onGVJsNhuv82eu1txY9jVw9SYpTZYqU8fsvxy7hn69xj7PL3kNN/Adm9qwsmq+DiM X-Received: by 10.99.117.12 with SMTP id q12mr3861589pgc.395.1523464158986; Wed, 11 Apr 2018 09:29:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1523464158; cv=none; d=google.com; s=arc-20160816; b=Cq8fV0sKTiYJlmyJNlEpTzxhP7wddmBhHFtIpwlqJFfCO3HVHdDIWZlm994A/w84/f /AV1X70uQhoU78Z5Nyd0bCc0w+rttqyN5AloxMt9Si1H5XKeuGjBapPoah4pJqXNqKTD KWUmMZoE34kII5Tgx6i+T7xEkE2Oz8QcgdEXEHPwLffXyLWbc6qsOaeWSAfR2me02RHJ 2gcCF0pExZlobUBuGdyuBRrWras2+fn9JG1uoCxB3LGRwk6P+EuVyDJHoepZ83Tr/P0b /v90bbd/wys3Si7UXoNpVOxvXuwT/VagscYSBUA0XrSEuo5Sn5TqqdTzK3U3/OlLDYR9 z7oQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:cc:to:from :subject:organization:arc-authentication-results; bh=5pXqBvETTMrlMVSkz9t5DNRDZBtvjRCvVoLln+I8t4Q=; b=YD2wjc4rBLnzaaGg/yZv3EKElpVg01nx7wY+sMPeyn1Gq4Hv1NtKmNIGCHjN7fgHGC QURz+wOrHAJjvYa3nuS3j5LvpZ7Ux85QwzhMxKcOLW5mibxFaG2i/EwiRMtdd7bNFO+i 0dShzcdtxm4wEwvRhjMoh3YXuHFe+Gh8PuXA+6EJxwh2BJx2ImJek46y4DUEF1uv027X CjSSJPpIyfOBkMqLTTqhIUePv91szzvQiS2Z7kgSXdsXWCVo5ONwLykCW91JrqChoOGf RwniNWMFkWw/NpgKXnaNYuJ4wQOigXFNgmU7HK7jm+EL5/8luS2Y1c4ZwN/ZBktkaHcp Br4w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e4si957528pgs.526.2018.04.11.09.28.31; Wed, 11 Apr 2018 09:29:18 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753840AbeDKQYv (ORCPT + 99 others); Wed, 11 Apr 2018 12:24:51 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:59352 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753707AbeDKQYs (ORCPT ); Wed, 11 Apr 2018 12:24:48 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 41F30722C7; Wed, 11 Apr 2018 16:24:47 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-120-8.rdu2.redhat.com [10.10.120.8]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5281A10AF9E0; Wed, 11 Apr 2018 16:24:46 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [PATCH 01/24] Add the ability to lock down access to the running kernel image From: David Howells To: torvalds@linux-foundation.org Cc: linux-man@vger.kernel.org, linux-api@vger.kernel.org, jmorris@namei.org, linux-kernel@vger.kernel.org, dhowells@redhat.com, linux-security-module@vger.kernel.org Date: Wed, 11 Apr 2018 17:24:45 +0100 Message-ID: <152346388583.4030.15146667041427303547.stgit@warthog.procyon.org.uk> In-Reply-To: <152346387861.4030.4408662483445703127.stgit@warthog.procyon.org.uk> References: <152346387861.4030.4408662483445703127.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Wed, 11 Apr 2018 16:24:47 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Wed, 11 Apr 2018 16:24:47 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'dhowells@redhat.com' RCPT:'' Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Provide a single call to allow kernel code to determine whether the system should be locked down, thereby disallowing various accesses that might allow the running kernel image to be changed, including: - /dev/mem and similar - Loading of unauthorised modules - Fiddling with MSR registers - Suspend to disk managed by the kernel - Use of device DMA Two kernel configuration options are provided: (*) CONFIG_LOCK_DOWN_KERNEL This makes lockdown available and applies it to all the points that need to be locked down if the mode is set. Lockdown mode can be enabled by providing: lockdown=1 on the command line. (*) CONFIG_LOCK_DOWN_MANDATORY This forces lockdown on at compile time, overriding the command line option. init_lockdown() is used as a hook from which lockdown can be managed in future. It has to be called from arch setup code before things like ACPI are enabled. Note that, with the other changes in this series, if lockdown mode is enabled, the kernel will not be able to use certain drivers as the ability to manually configure hardware parameters would then be prohibited. This primarily applies to ISA hardware devices. Signed-off-by: David Howells --- arch/x86/kernel/setup.c | 2 + include/linux/kernel.h | 32 +++++++++++++++++++++++ security/Kconfig | 23 ++++++++++++++++- security/Makefile | 3 ++ security/lock_down.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 security/lock_down.c diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 6285697b6e56..566f0f447053 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -996,6 +996,8 @@ void __init setup_arch(char **cmdline_p) if (efi_enabled(EFI_BOOT)) efi_init(); + init_lockdown(); + dmi_scan_machine(); dmi_memdev_walk(); dmi_set_dump_stack_arch_desc(); diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 4ae1dfd9bf05..7d085cca9cee 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -306,6 +306,38 @@ static inline void refcount_error_report(struct pt_regs *regs, const char *err) { } #endif +#ifdef CONFIG_LOCK_DOWN_KERNEL +extern void __init init_lockdown(void); +extern bool __kernel_is_locked_down(const char *what, bool first); + +#ifndef CONFIG_LOCK_DOWN_MANDATORY +#define kernel_is_locked_down(what) \ + ({ \ + static bool message_given; \ + bool locked_down = __kernel_is_locked_down(what, !message_given); \ + message_given = true; \ + locked_down; \ + }) +#else +#define kernel_is_locked_down(what) \ + ({ \ + static bool message_given; \ + __kernel_is_locked_down(what, !message_given); \ + message_given = true; \ + true; \ + }) +#endif +#else +static inline void __init init_lockdown(void) +{ +} +static inline bool __kernel_is_locked_down(const char *what, bool first) +{ + return false; +} +#define kernel_is_locked_down(what) ({ false; }) +#endif + /* Internal, do not use. */ int __must_check _kstrtoul(const char *s, unsigned int base, unsigned long *res); int __must_check _kstrtol(const char *s, unsigned int base, long *res); diff --git a/security/Kconfig b/security/Kconfig index c4302067a3ad..a68e5bdebad5 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -231,6 +231,28 @@ config STATIC_USERMODEHELPER_PATH If you wish for all usermode helper programs to be disabled, specify an empty string here (i.e. ""). +config LOCK_DOWN_KERNEL + bool "Allow the kernel to be 'locked down'" + help + Allow the kernel to be locked down. Locking down the kernel turns + off various features that might otherwise allow access to the kernel + image (eg. setting MSR registers). + + Note, however, that locking down your kernel will prevent some + drivers from functioning because allowing manual configuration of + hardware parameters is forbidden, lest a device be used to access the + kernel by DMA. This mostly applies to ISA devices. + + The kernel lockdown can be triggered by adding lockdown=1 to the + kernel command line. + +config LOCK_DOWN_MANDATORY + bool "Make kernel lockdown mandatory" + depends on LOCK_DOWN_KERNEL + help + Makes the lockdown non-negotiable. It is always on and cannot be + disabled. + source security/selinux/Kconfig source security/smack/Kconfig source security/tomoyo/Kconfig @@ -278,4 +300,3 @@ config DEFAULT_SECURITY default "" if DEFAULT_SECURITY_DAC endmenu - diff --git a/security/Makefile b/security/Makefile index 4d2d3782ddef..507ac8c520ce 100644 --- a/security/Makefile +++ b/security/Makefile @@ -30,3 +30,6 @@ obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o # Object integrity file lists subdir-$(CONFIG_INTEGRITY) += integrity obj-$(CONFIG_INTEGRITY) += integrity/ + +# Allow the kernel to be locked down +obj-$(CONFIG_LOCK_DOWN_KERNEL) += lock_down.o diff --git a/security/lock_down.c b/security/lock_down.c new file mode 100644 index 000000000000..f35ffdd096ad --- /dev/null +++ b/security/lock_down.c @@ -0,0 +1,65 @@ +/* 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 +#include + +#ifndef CONFIG_LOCK_DOWN_MANDATORY +static __ro_after_init bool kernel_locked_down; +#else +#define kernel_locked_down true +#endif + +/* + * Put the kernel into lock-down mode. + */ +static void __init lock_kernel_down(const char *where) +{ +#ifndef CONFIG_LOCK_DOWN_MANDATORY + if (!kernel_locked_down) { + kernel_locked_down = true; + pr_notice("Kernel is locked down from %s; see man kernel_lockdown.7\n", + where); + } +#endif +} + +static int __init lockdown_param(char *ignored) +{ + lock_kernel_down("command line"); + return 0; +} + +early_param("lockdown", lockdown_param); + +/* + * Lock the kernel down from very early in the arch setup. This must happen + * prior to things like ACPI being initialised. + */ +void __init init_lockdown(void) +{ +#ifdef CONFIG_LOCK_DOWN_MANDATORY + pr_notice("Kernel is locked down from config; see man kernel_lockdown.7\n"); +#endif +} + +/** + * kernel_is_locked_down - Find out if the kernel is locked down + * @what: Tag to use in notice generated if lockdown is in effect + */ +bool __kernel_is_locked_down(const char *what, bool first) +{ + if (what && first && kernel_locked_down) + pr_notice("Lockdown: %s: %s is restricted; see man kernel_lockdown.7\n", + current->comm, what); + return kernel_locked_down; +} +EXPORT_SYMBOL(__kernel_is_locked_down);