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); From patchwork Thu Feb 28 22:44:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Garrett X-Patchwork-Id: 10834203 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 BC0211390 for ; Thu, 28 Feb 2019 22:45:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A8FD82FA84 for ; Thu, 28 Feb 2019 22:45:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9D5632FB81; Thu, 28 Feb 2019 22:45:34 +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 D4A8A2FA84 for ; Thu, 28 Feb 2019 22:45:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731854AbfB1Wp2 (ORCPT ); Thu, 28 Feb 2019 17:45:28 -0500 Received: from mail-it1-f202.google.com ([209.85.166.202]:42297 "EHLO mail-it1-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731833AbfB1Wp1 (ORCPT ); Thu, 28 Feb 2019 17:45:27 -0500 Received: by mail-it1-f202.google.com with SMTP id j127so9736359itj.7 for ; Thu, 28 Feb 2019 14:45:26 -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=u73jCkXFL2POTTvMCMv7ZqTMPf3k7bn3erx/FRu/gvg=; b=Ho8lwH0YxKGVNqvm0Jc1+0KjU9E8HBG83DZ88mkt7s+RcUpsxl5Dt1Kf/PJHbYqBE+ 3aJ8Fy0y5/XsvOvy+bsnO4Xg/M47lofri1LrCfL/z01+gecD7HrSbbwZl+5vPqtRMLFR t7W5W6FUeHYeJeJUuU2A/2YArKj2t0E2Qou4mrj905z9GhNT/iNEGNRoyBAGtXEfE2w6 Hx9sjpK33Rf/Y6gl4F/yZTsOgFI7a8FUQ11XiSEUNeCuR5lWx+E+8J0+TPJ1nkfnt/wY lh+X88Y1yHssjnxD9KefEB5Ghk/nSBNTp5OzIzigdllGkaa7Ytp6rlwK2xwemKvxwqt5 72sw== 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=u73jCkXFL2POTTvMCMv7ZqTMPf3k7bn3erx/FRu/gvg=; b=ZhW8taZ0SaLuNY6g//x+eeFzESJW/sCtAF7c8SoItMcXq3vaZGk86ogYKDz/FHmaUl JPP3DsXdW6bL0OmEViab51bPoGu9baH8i5eecFTqN6V6GlruqI7PE1aENA2ZOcgHKRMK HmmlNEsDtI0TBDVy1w1yS3sELmAwG/PaQrS+R6F/0AN1uih9h+XTsD2yHoksp15EDnoh /7KejUC8dEAUIr2cFLQE6i8g9VR5GdBI6dP+dqtPu7u7jZrewmhu+1BjtFJouOXBzgKy xykcbYvp9ZsUKkOGs3VZ6UImt0Hy+8M/iY3dYmkai2Br2fvhHxEN9EzGdd9utkHgPJfd uVIQ== X-Gm-Message-State: APjAAAVVaeQOBi3xOg22ejzh1H27h5dnhx37xWjrcGW5NB00V3IzgKr2 cZQYgvpcYB9r3/+XGF6bsHxXFmAZxZ23QgalGfG1ww== X-Google-Smtp-Source: APXvYqxQUufBGv+9yQHLXwUt7jCwll9cNotUOq6WihISWPeN2VIti0sBUHVAXLv+3PnXSszKrncSQVuzl2Y16WWYw+QE6A== X-Received: by 2002:a24:508e:: with SMTP id m136mr1396084itb.34.1551393926426; Thu, 28 Feb 2019 14:45:26 -0800 (PST) Date: Thu, 28 Feb 2019 14:44:42 -0800 In-Reply-To: <20190228224507.198833-1-matthewgarrett@google.com> Message-Id: <20190228224507.198833-2-matthewgarrett@google.com> Mime-Version: 1.0 References: <20190228224507.198833-1-matthewgarrett@google.com> X-Mailer: git-send-email 2.21.0.352.gf09ad66450-goog Subject: [PATCH 02/27] Add a SysRq option to lift kernel lockdown From: Matthew Garrett To: jmorris@namei.org Cc: linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, dhowells@redhat.com, Kyle McMartin , x86@kernel.org Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP From: Kyle McMartin Make an option to provide a sysrq key that will lift the kernel lockdown, thereby allowing the running kernel image to be accessed and modified. On x86 this is triggered with SysRq+x, but this key may not be available on all arches, so it is set by setting LOCKDOWN_LIFT_KEY in asm/setup.h. Since this macro must be defined in an arch to be able to use this facility for that arch, the Kconfig option is restricted to arches that support it. Signed-off-by: Kyle McMartin Signed-off-by: David Howells cc: x86@kernel.org --- arch/x86/include/asm/setup.h | 2 ++ drivers/input/misc/uinput.c | 1 + drivers/tty/sysrq.c | 19 ++++++++++----- include/linux/input.h | 5 ++++ include/linux/sysrq.h | 8 +++++- kernel/debug/kdb/kdb_main.c | 2 +- security/Kconfig | 9 +++++++ security/lock_down.c | 47 ++++++++++++++++++++++++++++++++++++ 8 files changed, 85 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h index ed8ec011a9fd..8daf633a5347 100644 --- a/arch/x86/include/asm/setup.h +++ b/arch/x86/include/asm/setup.h @@ -9,6 +9,8 @@ #include #include +#define LOCKDOWN_LIFT_KEY 'x' + #ifdef __i386__ #include diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 26ec603fe220..a73e92490286 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -366,6 +366,7 @@ static int uinput_create_device(struct uinput_device *udev) dev->flush = uinput_dev_flush; } + dev->flags |= INPUTDEV_FLAGS_SYNTHETIC; dev->event = uinput_dev_event; input_set_drvdata(udev->dev, udev); diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index 1f03078ec352..0a05d336008e 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -480,6 +480,7 @@ static struct sysrq_key_op *sysrq_key_table[36] = { /* x: May be registered on mips for TLB dump */ /* x: May be registered on ppc/powerpc for xmon */ /* x: May be registered on sparc64 for global PMU dump */ + /* x: May be registered on x86_64 for disabling secure boot */ NULL, /* x */ /* y: May be registered on sparc64 for global register dump */ NULL, /* y */ @@ -523,7 +524,7 @@ static void __sysrq_put_key_op(int key, struct sysrq_key_op *op_p) sysrq_key_table[i] = op_p; } -void __handle_sysrq(int key, bool check_mask) +void __handle_sysrq(int key, unsigned int from) { struct sysrq_key_op *op_p; int orig_log_level; @@ -543,11 +544,15 @@ void __handle_sysrq(int key, bool check_mask) op_p = __sysrq_get_key_op(key); if (op_p) { + /* Ban synthetic events from some sysrq functionality */ + if ((from == SYSRQ_FROM_PROC || from == SYSRQ_FROM_SYNTHETIC) && + op_p->enable_mask & SYSRQ_DISABLE_USERSPACE) + printk("This sysrq operation is disabled from userspace.\n"); /* * Should we check for enabled operations (/proc/sysrq-trigger * should not) and is the invoked operation enabled? */ - if (!check_mask || sysrq_on_mask(op_p->enable_mask)) { + if (from == SYSRQ_FROM_KERNEL || sysrq_on_mask(op_p->enable_mask)) { pr_cont("%s\n", op_p->action_msg); console_loglevel = orig_log_level; op_p->handler(key); @@ -579,7 +584,7 @@ void __handle_sysrq(int key, bool check_mask) void handle_sysrq(int key) { if (sysrq_on()) - __handle_sysrq(key, true); + __handle_sysrq(key, SYSRQ_FROM_KERNEL); } EXPORT_SYMBOL(handle_sysrq); @@ -659,7 +664,7 @@ static void sysrq_do_reset(struct timer_list *t) static void sysrq_handle_reset_request(struct sysrq_state *state) { if (state->reset_requested) - __handle_sysrq(sysrq_xlate[KEY_B], false); + __handle_sysrq(sysrq_xlate[KEY_B], SYSRQ_FROM_KERNEL); if (sysrq_reset_downtime_ms) mod_timer(&state->keyreset_timer, @@ -812,8 +817,10 @@ static bool sysrq_handle_keypress(struct sysrq_state *sysrq, default: if (sysrq->active && value && value != 2) { + int from = sysrq->handle.dev->flags & INPUTDEV_FLAGS_SYNTHETIC ? + SYSRQ_FROM_SYNTHETIC : 0; sysrq->need_reinject = false; - __handle_sysrq(sysrq_xlate[code], true); + __handle_sysrq(sysrq_xlate[code], from); } break; } @@ -1096,7 +1103,7 @@ static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf, if (get_user(c, buf)) return -EFAULT; - __handle_sysrq(c, false); + __handle_sysrq(c, SYSRQ_FROM_PROC); } return count; diff --git a/include/linux/input.h b/include/linux/input.h index 7c7516eb7d76..38cd0ea72c37 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -42,6 +42,7 @@ struct input_value { * @phys: physical path to the device in the system hierarchy * @uniq: unique identification code for the device (if device has it) * @id: id of the device (struct input_id) + * @flags: input device flags (SYNTHETIC, etc.) * @propbit: bitmap of device properties and quirks * @evbit: bitmap of types of events supported by the device (EV_KEY, * EV_REL, etc.) @@ -124,6 +125,8 @@ struct input_dev { const char *uniq; struct input_id id; + unsigned int flags; + unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)]; unsigned long evbit[BITS_TO_LONGS(EV_CNT)]; @@ -190,6 +193,8 @@ struct input_dev { }; #define to_input_dev(d) container_of(d, struct input_dev, dev) +#define INPUTDEV_FLAGS_SYNTHETIC 0x000000001 + /* * Verify that we are in sync with input_device_id mod_devicetable.h #defines */ diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h index 8c71874e8485..7de1f08b60a9 100644 --- a/include/linux/sysrq.h +++ b/include/linux/sysrq.h @@ -29,6 +29,8 @@ #define SYSRQ_ENABLE_BOOT 0x0080 #define SYSRQ_ENABLE_RTNICE 0x0100 +#define SYSRQ_DISABLE_USERSPACE 0x00010000 + struct sysrq_key_op { void (*handler)(int); char *help_msg; @@ -43,8 +45,12 @@ struct sysrq_key_op { * are available -- else NULL's). */ +#define SYSRQ_FROM_KERNEL 0x0001 +#define SYSRQ_FROM_PROC 0x0002 +#define SYSRQ_FROM_SYNTHETIC 0x0004 + void handle_sysrq(int key); -void __handle_sysrq(int key, bool check_mask); +void __handle_sysrq(int key, unsigned int from); int register_sysrq_key(int key, struct sysrq_key_op *op); int unregister_sysrq_key(int key, struct sysrq_key_op *op); struct sysrq_key_op *__sysrq_get_key_op(int key); diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index 82a3b32a7cfc..efee1abf5e8e 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c @@ -1981,7 +1981,7 @@ static int kdb_sr(int argc, const char **argv) return KDB_ARGCOUNT; kdb_trap_printk++; - __handle_sysrq(*argv[1], check_mask); + __handle_sysrq(*argv[1], check_mask ? SYSRQ_FROM_KERNEL : 0); kdb_trap_printk--; return 0; diff --git a/security/Kconfig b/security/Kconfig index c2aff0006de2..afaf6fa17c9a 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -245,6 +245,15 @@ config LOCK_DOWN_KERNEL_FORCE help Enable the kernel lock down functionality automatically at boot. +config ALLOW_LOCKDOWN_LIFT_BY_SYSRQ + bool "Allow the kernel lockdown to be lifted by SysRq" + depends on LOCK_DOWN_KERNEL + depends on MAGIC_SYSRQ + depends on X86 + help + Allow the lockdown on a kernel to be lifted, by pressing a SysRq key + combination on a wired keyboard. + source "security/selinux/Kconfig" source "security/smack/Kconfig" source "security/tomoyo/Kconfig" diff --git a/security/lock_down.c b/security/lock_down.c index 13a8228c1034..cfbc2c39712b 100644 --- a/security/lock_down.c +++ b/security/lock_down.c @@ -11,8 +11,14 @@ #include #include +#include +#include +#ifdef CONFIG_ALLOW_LOCKDOWN_LIFT_BY_SYSRQ +static __read_mostly bool kernel_locked_down; +#else static __ro_after_init bool kernel_locked_down; +#endif /* * Put the kernel into lock-down mode. @@ -57,3 +63,44 @@ bool __kernel_is_locked_down(const char *what, bool first) return kernel_locked_down; } EXPORT_SYMBOL(__kernel_is_locked_down); + +#ifdef CONFIG_ALLOW_LOCKDOWN_LIFT_BY_SYSRQ + +/* + * Take the kernel out of lockdown mode. + */ +static void lift_kernel_lockdown(void) +{ + pr_notice("Lifting lockdown\n"); + kernel_locked_down = false; +} + +/* + * Allow lockdown to be lifted by pressing something like SysRq+x (and not by + * echoing the appropriate letter into the sysrq-trigger file). + */ +static void sysrq_handle_lockdown_lift(int key) +{ + if (kernel_locked_down) + lift_kernel_lockdown(); +} + +static struct sysrq_key_op lockdown_lift_sysrq_op = { + .handler = sysrq_handle_lockdown_lift, + .help_msg = "unSB(x)", + .action_msg = "Disabling Secure Boot restrictions", + .enable_mask = SYSRQ_DISABLE_USERSPACE, +}; + +static int __init lockdown_lift_sysrq(void) +{ + if (kernel_locked_down) { + lockdown_lift_sysrq_op.help_msg[5] = LOCKDOWN_LIFT_KEY; + register_sysrq_key(LOCKDOWN_LIFT_KEY, &lockdown_lift_sysrq_op); + } + return 0; +} + +late_initcall(lockdown_lift_sysrq); + +#endif /* CONFIG_ALLOW_LOCKDOWN_LIFT_BY_SYSRQ */