From patchwork Thu Feb 28 22:44:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Garrett X-Patchwork-Id: 10834201 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 995A51515 for ; Thu, 28 Feb 2019 22:45:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 86D6A2FA84 for ; Thu, 28 Feb 2019 22:45:26 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7ACA92FB81; Thu, 28 Feb 2019 22:45:26 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-14.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,RCVD_IN_DNSWL_HI,USER_IN_DEF_DKIM_WL autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EE0402FA84 for ; Thu, 28 Feb 2019 22:45:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729193AbfB1WpZ (ORCPT ); Thu, 28 Feb 2019 17:45:25 -0500 Received: from mail-yw1-f74.google.com ([209.85.161.74]:54081 "EHLO mail-yw1-f74.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728183AbfB1WpZ (ORCPT ); Thu, 28 Feb 2019 17:45:25 -0500 Received: by mail-yw1-f74.google.com with SMTP id g123so19297363ywb.20 for ; Thu, 28 Feb 2019 14:45:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=JgzwmpXUZt6KNQDOAKfrLdx7UP057Xc3K0KJM8I4IMs=; b=Lt47Wg1APFp2M6To1egyx29fj4coXryui4+x2KR9LMj46Bwc7h45gQTZl7/4sbwUOJ 0u2Fr1XwdFwXclIYZRd3ECzWh0xNNCWcEJc/8aRYqWaCNJ/ddZrE5ULTXmYkLEVt6b3U UExjSxlWaIrdg+UCPTObr4QfLj8xKnDovtX9Mioe2er82t7IImTEBZ8QwY9v/b2z+Qei a0Nxa+hqBPAXEGAdJj/SPPTKjLdDcwsuY8qyyUlAlyeVCMS00iyIlkqZ7O9uEXW98E7l hsbDcaFWho2t6UpD1kVDudL8ixrvCWnRQKUMC/ZF+p7/JJkHgHMPV+H1srBgmWiNT/qF XyMw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=JgzwmpXUZt6KNQDOAKfrLdx7UP057Xc3K0KJM8I4IMs=; b=f12DK7g7UORkW0Zp5rp4LCXsliQRF1p/G1V4K4xIaL4SKHYRs/Az3pQTPFBfmeGQfT MdDoU3qN6m1pBh9xOXMvzkAwOVQnCro7yrnFecCx+aAMqh0Pc0FdablIgZPUaJ3vo5sq fpciTnVe5jaxmtwcnEpje/4D0r6YH0+dvqOzgtBs9vZrCjg8nqK+kawawGgFNNNIi6qY y4M/Vj3KXcVkZ8Z3nHe45GNpD3zhqiKQDinDj3C8pjGJvB7qqLkZ4z2sCUHpoAuUwHVU Q6921wwstUcy27hOvTGHCCLHWC83KJIoj6MffMoaNH0VuGOoihFdT+181nVTGVeFMOuv MmtQ== X-Gm-Message-State: APjAAAUF3Ke47EUj3eMAe1ChYgTfZz7efqIDn/tflKDMHBFwGQBuybcw gjnna8VRGu+l0Ldv8m+2k3KxouQTYRQvruGRquD5RA== X-Google-Smtp-Source: APXvYqzOUdvDsOdnZaHwv63FfSC01OGwpYFnVmcI7CiQKML/BAMqg5jKrtUds28QdA8OJfIlEUvx8XxI7R+kV2IqR0ocQQ== X-Received: by 2002:a25:41c2:: with SMTP id o185mr967551yba.96.1551393923889; Thu, 28 Feb 2019 14:45:23 -0800 (PST) Date: Thu, 28 Feb 2019 14:44:41 -0800 In-Reply-To: Message-Id: <20190228224507.198833-1-matthewgarrett@google.com> Mime-Version: 1.0 References: X-Mailer: git-send-email 2.21.0.352.gf09ad66450-goog Subject: [PATCH 01/27] Add the ability to lock down access to the running kernel image From: Matthew Garrett To: jmorris@namei.org Cc: linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, dhowells@redhat.com, James Morris Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP From: David Howells 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 the loading of modules that aren't validly signed with a key we recognise, fiddling with MSR registers and disallowing hibernation. Signed-off-by: David Howells Acked-by: James Morris --- include/linux/kernel.h | 17 ++++++++++++ include/linux/security.h | 9 +++++- security/Kconfig | 15 ++++++++++ security/Makefile | 3 ++ security/lock_down.c | 59 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 security/lock_down.c diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 8f0e68e250a7..833bf32ce4e6 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -340,6 +340,23 @@ static inline void refcount_error_report(struct pt_regs *regs, const char *err) { } #endif +#ifdef CONFIG_LOCK_DOWN_KERNEL +extern bool __kernel_is_locked_down(const char *what, bool first); +#else +static inline bool __kernel_is_locked_down(const char *what, bool first) +{ + return false; +} +#endif + +#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; \ + }) + /* 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/include/linux/security.h b/include/linux/security.h index dbfb5a66babb..35f0be540e0b 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1793,5 +1793,12 @@ static inline void security_bpf_prog_free(struct bpf_prog_aux *aux) #endif /* CONFIG_SECURITY */ #endif /* CONFIG_BPF_SYSCALL */ -#endif /* ! __LINUX_SECURITY_H */ +#ifdef CONFIG_LOCK_DOWN_KERNEL +extern void __init init_lockdown(void); +#else +static inline void __init init_lockdown(void) +{ +} +#endif +#endif /* ! __LINUX_SECURITY_H */ diff --git a/security/Kconfig b/security/Kconfig index e4fe2f3c2c65..c2aff0006de2 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -230,6 +230,21 @@ 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. If lockdown support is enabled + and activated, the kernel will impose additional restrictions + intended to prevent uid 0 from being able to modify the running + kernel. This may break userland applications that rely on low-level + access to hardware. + +config LOCK_DOWN_KERNEL_FORCE + bool "Enable kernel lockdown mode automatically" + depends on LOCK_DOWN_KERNEL + help + Enable the kernel lock down functionality automatically at boot. + source "security/selinux/Kconfig" source "security/smack/Kconfig" source "security/tomoyo/Kconfig" 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..13a8228c1034 --- /dev/null +++ b/security/lock_down.c @@ -0,0 +1,59 @@ +/* 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 + +static __ro_after_init bool kernel_locked_down; + +/* + * Put the kernel into lock-down mode. + */ +static void __init lock_kernel_down(const char *where) +{ + if (!kernel_locked_down) { + kernel_locked_down = true; + pr_notice("Kernel is locked down from %s; see man kernel_lockdown.7\n", + where); + } +} + +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_FORCE + lock_kernel_down("Kernel configuration"); +#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 is restricted; see man kernel_lockdown.7\n", + what); + return kernel_locked_down; +} +EXPORT_SYMBOL(__kernel_is_locked_down);