2017-04-05 17:09:53

by David Howells

[permalink] [raw]
Subject: [PATCH 00/24] Kernel lockdown


These patches provide a facility by which a variety of avenues by which
userspace can feasibly modify the running kernel image can be locked down.
These include:

(*) No unsigned modules and no modules for which can't validate the
signature.

(*) No use of ioperm(), iopl() and no writing to /dev/port.

(*) No writing to /dev/mem or /dev/kmem.

(*) No hibernation.

(*) Restrict PCI BAR access.

(*) Restrict MSR access.

(*) No kexec_load().

(*) Certain ACPI restrictions.

(*) Restrict debugfs interface to ASUS WMI.

The lock-down can be configured to be triggered by the EFI secure boot
status, provided the shim isn't insecure. The lock-down can be lifted by
typing SysRq+x on a keyboard attached to the system.


The patches can be found here also:

http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=efi-lockdown

They are dependent on the hwparam branch, which I posted separately.

David
---
Dave Young (1):
Copy secure_boot flag in boot params across kexec reboot

David Howells (7):
Add the ability to lock down access to the running kernel image
efi: Lock down the kernel if booted in secure boot mode
Enforce module signatures if the kernel is locked down
scsi: Lock down the eata driver
Prohibit PCMCIA CIS storage when the kernel is locked down
Lock down TIOCSSERIAL
Lock down module params that specify hardware parameters (eg. ioport)

Josh Boyer (3):
efi: Add EFI_SECURE_BOOT bit
hibernate: Disable when the kernel is locked down
acpi: Ignore acpi_rsdp kernel param when the kernel has been locked down

Kyle McMartin (1):
Add a sysrq option to exit secure boot mode

Lee, Chun-Yi (2):
kexec_file: Disable at runtime if securelevel has been set
bpf: Restrict kernel image access functions when the kernel is locked down

Linn Crosetto (2):
acpi: Disable ACPI table override if the kernel is locked down
acpi: Disable APEI error injection if the kernel is locked down

Matthew Garrett (8):
Restrict /dev/mem and /dev/kmem when the kernel is locked down
kexec: Disable at runtime if the kernel is locked down
uswsusp: Disable when the kernel is locked down
PCI: Lock down BAR access when the kernel is locked down
x86: Lock down IO port access when the kernel is locked down
x86: Restrict MSR access when the kernel is locked down
asus-wmi: Restrict debugfs interface when the kernel is locked down
ACPI: Limit access to custom_method when the kernel is locked down


arch/x86/Kconfig | 22 ++++++++++++++++++++
arch/x86/kernel/ioport.c | 4 ++--
arch/x86/kernel/kexec-bzimage64.c | 1 +
arch/x86/kernel/msr.c | 7 ++++++
arch/x86/kernel/setup.c | 40 ++++++++++++++++++++++++++++++++++++-
drivers/acpi/apei/einj.c | 3 +++
drivers/acpi/custom_method.c | 3 +++
drivers/acpi/osl.c | 2 +-
drivers/acpi/tables.c | 5 +++++
drivers/char/mem.c | 8 +++++++
drivers/input/misc/uinput.c | 1 +
drivers/pci/pci-sysfs.c | 9 ++++++++
drivers/pci/proc.c | 8 ++++++-
drivers/pci/syscall.c | 2 +-
drivers/pcmcia/cistpl.c | 5 +++++
drivers/platform/x86/asus-wmi.c | 9 ++++++++
drivers/scsi/eata.c | 7 ++++++
drivers/tty/serial/serial_core.c | 6 ++++++
drivers/tty/sysrq.c | 19 ++++++++++++------
include/linux/efi.h | 1 +
include/linux/input.h | 5 +++++
include/linux/kernel.h | 9 ++++++++
include/linux/security.h | 11 ++++++++++
include/linux/sysrq.h | 8 ++++++-
kernel/debug/kdb/kdb_main.c | 2 +-
kernel/kexec.c | 7 ++++++
kernel/kexec_file.c | 6 ++++++
kernel/module.c | 2 +-
kernel/params.c | 27 ++++++++++++++++++++-----
kernel/power/hibernate.c | 2 +-
kernel/power/user.c | 3 +++
kernel/trace/bpf_trace.c | 11 ++++++++++
security/Kconfig | 15 ++++++++++++++
security/Makefile | 3 +++
security/lock_down.c | 40 +++++++++++++++++++++++++++++++++++++
35 files changed, 291 insertions(+), 22 deletions(-)
create mode 100644 security/lock_down.c


2017-04-05 17:07:27

by David Howells

[permalink] [raw]
Subject: [PATCH 01/24] efi: Add EFI_SECURE_BOOT bit

From: Josh Boyer <[email protected]>

UEFI machines can be booted in Secure Boot mode. Add a EFI_SECURE_BOOT bit
that can be passed to efi_enabled() to find out whether secure boot is
enabled.

This will be used by the SysRq+x handler, registered by the x86 arch, to find
out whether secure boot mode is enabled so that it can be disabled.

Signed-off-by: Josh Boyer <[email protected]>
Signed-off-by: David Howells <[email protected]>
---

arch/x86/kernel/setup.c | 1 +
include/linux/efi.h | 1 +
2 files changed, 2 insertions(+)

diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 4bf0c8926a1c..396285bddb93 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1184,6 +1184,7 @@ void __init setup_arch(char **cmdline_p)
pr_info("Secure boot disabled\n");
break;
case efi_secureboot_mode_enabled:
+ set_bit(EFI_SECURE_BOOT, &efi.flags);
pr_info("Secure boot enabled\n");
break;
default:
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 94d34e0be24f..6049600e5475 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1069,6 +1069,7 @@ extern int __init efi_setup_pcdp_console(char *);
#define EFI_DBG 8 /* Print additional debug info at runtime */
#define EFI_NX_PE_DATA 9 /* Can runtime data regions be mapped non-executable? */
#define EFI_MEM_ATTR 10 /* Did firmware publish an EFI_MEMORY_ATTRIBUTES table? */
+#define EFI_SECURE_BOOT 11 /* Are we in Secure Boot mode? */

#ifdef CONFIG_EFI
/*

2017-04-05 17:07:45

by David Howells

[permalink] [raw]
Subject: [PATCH 02/24] Add the ability to lock down access to the running kernel image

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 <[email protected]>
---

include/linux/kernel.h | 9 +++++++++
include/linux/security.h | 11 +++++++++++
security/Kconfig | 15 +++++++++++++++
security/Makefile | 3 +++
security/lock_down.c | 40 ++++++++++++++++++++++++++++++++++++++++
5 files changed, 78 insertions(+)
create mode 100644 security/lock_down.c

diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 4c26dc3a8295..b820a80dc949 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -275,6 +275,15 @@ extern int oops_may_print(void);
void do_exit(long error_code) __noreturn;
void complete_and_exit(struct completion *, long) __noreturn;

+#ifdef CONFIG_LOCK_DOWN_KERNEL
+extern bool kernel_is_locked_down(void);
+#else
+static inline bool kernel_is_locked_down(void)
+{
+ return 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/include/linux/security.h b/include/linux/security.h
index af675b576645..68bab18ddd57 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1698,5 +1698,16 @@ static inline void free_secdata(void *secdata)
{ }
#endif /* CONFIG_SECURITY */

+#ifdef CONFIG_LOCK_DOWN_KERNEL
+extern void lock_kernel_down(void);
+#ifdef CONFIG_ALLOW_LOCKDOWN_LIFT
+extern void lift_kernel_lockdown(void);
+#endif
+#else
+static inline void lock_kernel_down(void)
+{
+}
+#endif
+
#endif /* ! __LINUX_SECURITY_H */

diff --git a/security/Kconfig b/security/Kconfig
index 3ff1bf91080e..e3830171bdcb 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -198,6 +198,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 under certain circumstances, for
+ instance if UEFI secure boot is enabled. Locking down the kernel
+ turns off various features that might otherwise allow access to the
+ kernel image (eg. setting MSR registers).
+
+config ALLOW_LOCKDOWN_LIFT
+ bool
+ help
+ Allow the lockdown on a kernel to be lifted, thereby restoring the
+ ability of userspace to access the kernel image (eg. by SysRq+x under
+ x86).
+
source security/selinux/Kconfig
source security/smack/Kconfig
source security/tomoyo/Kconfig
diff --git a/security/Makefile b/security/Makefile
index f2d71cdb8e19..8c4a43e3d4e0 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -29,3 +29,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..5788c60ff4e1
--- /dev/null
+++ b/security/lock_down.c
@@ -0,0 +1,40 @@
+/* Lock down the kernel
+ *
+ * Copyright (C) 2016 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells ([email protected])
+ *
+ * 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>
+
+static __read_mostly bool kernel_locked_down;
+
+/*
+ * Put the kernel into lock-down mode.
+ */
+void lock_kernel_down(void)
+{
+ kernel_locked_down = true;
+}
+
+/*
+ * Take the kernel out of lockdown mode.
+ */
+void lift_kernel_lockdown(void)
+{
+ kernel_locked_down = false;
+}
+
+/**
+ * kernel_is_locked_down - Find out if the kernel is locked down
+ */
+bool kernel_is_locked_down(void)
+{
+ return kernel_locked_down;
+}
+EXPORT_SYMBOL(kernel_is_locked_down);

2017-04-05 17:08:07

by David Howells

[permalink] [raw]
Subject: [PATCH 05/24] Restrict /dev/mem and /dev/kmem when the kernel is locked down

From: Matthew Garrett <[email protected]>

Allowing users to write to address space makes it possible for the kernel to
be subverted, avoiding module loading restrictions. Prevent this when the
kernel has been locked down.

Signed-off-by: Matthew Garrett <[email protected]>
Signed-off-by: David Howells <[email protected]>
---

drivers/char/mem.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 6d9cc2d39d22..f8144049bda3 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -163,6 +163,9 @@ static ssize_t write_mem(struct file *file, const char __user *buf,
if (p != *ppos)
return -EFBIG;

+ if (kernel_is_locked_down())
+ return -EPERM;
+
if (!valid_phys_addr_range(p, count))
return -EFAULT;

@@ -513,6 +516,9 @@ static ssize_t write_kmem(struct file *file, const char __user *buf,
char *kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
int err = 0;

+ if (kernel_is_locked_down())
+ return -EPERM;
+
if (p < (unsigned long) high_memory) {
unsigned long to_write = min_t(unsigned long, count,
(unsigned long)high_memory - p);

2017-04-05 17:07:58

by David Howells

[permalink] [raw]
Subject: [PATCH 03/24] efi: Lock down the kernel if booted in secure boot mode

UEFI Secure Boot provides a mechanism for ensuring that the firmware will
only load signed bootloaders and kernels. Certain use cases may also
require that all kernel modules also be signed. Add a configuration option
that to lock down the kernel - which includes requiring validly signed
modules - if the kernel is secure-booted.

Signed-off-by: David Howells <[email protected]>
---

arch/x86/Kconfig | 12 ++++++++++++
arch/x86/kernel/setup.c | 8 +++++++-
2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index cc98d5a294ee..21f39855661d 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1817,6 +1817,18 @@ config EFI_MIXED

If unsure, say N.

+config EFI_SECURE_BOOT_LOCK_DOWN
+ def_bool n
+ depends on EFI
+ prompt "Lock down the kernel when UEFI Secure Boot is enabled"
+ ---help---
+ UEFI Secure Boot provides a mechanism for ensuring that the firmware
+ will only load signed bootloaders and kernels. Certain use cases may
+ also require that all kernel modules also be signed and that
+ userspace is prevented from directly changing the running kernel
+ image. Say Y here to automatically lock down the kernel when a
+ system boots with UEFI Secure Boot enabled.
+
config SECCOMP
def_bool y
prompt "Enable seccomp to safely compute untrusted bytecode"
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 396285bddb93..85dfa745c442 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -69,6 +69,7 @@
#include <linux/crash_dump.h>
#include <linux/tboot.h>
#include <linux/jiffies.h>
+#include <linux/security.h>

#include <video/edid.h>

@@ -1185,7 +1186,12 @@ void __init setup_arch(char **cmdline_p)
break;
case efi_secureboot_mode_enabled:
set_bit(EFI_SECURE_BOOT, &efi.flags);
- pr_info("Secure boot enabled\n");
+ if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT_LOCK_DOWN)) {
+ lock_kernel_down();
+ pr_info("Secure boot enabled and kernel locked down\n");
+ } else {
+ pr_info("Secure boot enabled\n");
+ }
break;
default:
pr_info("Secure boot could not be determined\n");

2017-04-05 17:08:20

by David Howells

[permalink] [raw]
Subject: [PATCH 04/24] Enforce module signatures if the kernel is locked down

If the kernel is locked down, require that all modules have valid
signatures that we can verify.

Signed-off-by: David Howells <[email protected]>
---

kernel/module.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/module.c b/kernel/module.c
index 7eba6dea4f41..3331f2eb9b93 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2756,7 +2756,7 @@ static int module_sig_check(struct load_info *info, int flags)
}

/* Not having a signature is only an error if we're strict. */
- if (err == -ENOKEY && !sig_enforce)
+ if (err == -ENOKEY && !sig_enforce && !kernel_is_locked_down())
err = 0;

return err;

2017-04-05 17:08:38

by David Howells

[permalink] [raw]
Subject: [PATCH 08/24] Copy secure_boot flag in boot params across kexec reboot

From: Dave Young <[email protected]>

Kexec reboot in case secure boot being enabled does not keep the secure
boot mode in new kernel, so later one can load unsigned kernel via legacy
kexec_load. In this state, the system is missing the protections provided
by secure boot.

Adding a patch to fix this by retain the secure_boot flag in original
kernel.

secure_boot flag in boot_params is set in EFI stub, but kexec bypasses the
stub. Fixing this issue by copying secure_boot flag across kexec reboot.

Signed-off-by: Dave Young <[email protected]>
Signed-off-by: David Howells <[email protected]>
---

arch/x86/kernel/kexec-bzimage64.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c
index d0a814a9d96a..3551bcaa1eaf 100644
--- a/arch/x86/kernel/kexec-bzimage64.c
+++ b/arch/x86/kernel/kexec-bzimage64.c
@@ -179,6 +179,7 @@ setup_efi_state(struct boot_params *params, unsigned long params_load_addr,
if (efi_enabled(EFI_OLD_MEMMAP))
return 0;

+ params->secure_boot = boot_params.secure_boot;
ei->efi_loader_signature = current_ei->efi_loader_signature;
ei->efi_systab = current_ei->efi_systab;
ei->efi_systab_hi = current_ei->efi_systab_hi;

2017-04-05 17:08:44

by David Howells

[permalink] [raw]
Subject: [PATCH 06/24] Add a sysrq option to exit secure boot mode

From: Kyle McMartin <[email protected]>

Make sysrq+x exit secure boot mode on x86_64, thereby allowing the running
kernel image to be modified. This lifts the lockdown.

Signed-off-by: Kyle McMartin <[email protected]>
Signed-off-by: David Howells <[email protected]>
---

arch/x86/Kconfig | 10 ++++++++++
arch/x86/kernel/setup.c | 31 +++++++++++++++++++++++++++++++
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 +-
7 files changed, 68 insertions(+), 8 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 21f39855661d..457c04971849 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1829,6 +1829,16 @@ config EFI_SECURE_BOOT_LOCK_DOWN
image. Say Y here to automatically lock down the kernel when a
system boots with UEFI Secure Boot enabled.

+config EFI_ALLOW_SECURE_BOOT_EXIT
+ def_bool n
+ depends on EFI_SECURE_BOOT_LOCK_DOWN && MAGIC_SYSRQ
+ select ALLOW_LOCKDOWN_LIFT
+ prompt "Allow secure boot mode to be exited with SysRq+x on a keyboard"
+ ---help---
+ Allow secure boot mode to be exited and the kernel lockdown lifted by
+ typing SysRq+x on a keyboard attached to the system (not permitted
+ through procfs).
+
config SECCOMP
def_bool y
prompt "Enable seccomp to safely compute untrusted bytecode"
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 85dfa745c442..a415a4817684 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -71,6 +71,11 @@
#include <linux/jiffies.h>
#include <linux/security.h>

+#include <linux/fips.h>
+#include <linux/cred.h>
+#include <linux/sysrq.h>
+#include <linux/init_task.h>
+
#include <video/edid.h>

#include <asm/mtrr.h>
@@ -1330,6 +1335,32 @@ void __init i386_reserve_resources(void)

#endif /* CONFIG_X86_32 */

+#ifdef CONFIG_EFI_ALLOW_SECURE_BOOT_EXIT
+
+static void sysrq_handle_secure_boot(int key)
+{
+ if (!efi_enabled(EFI_SECURE_BOOT))
+ return;
+
+ pr_info("Secure boot disabled\n");
+ lift_kernel_lockdown();
+}
+static struct sysrq_key_op secure_boot_sysrq_op = {
+ .handler = sysrq_handle_secure_boot,
+ .help_msg = "unSB(x)",
+ .action_msg = "Disabling Secure Boot restrictions",
+ .enable_mask = SYSRQ_DISABLE_USERSPACE,
+};
+static int __init secure_boot_sysrq(void)
+{
+ if (efi_enabled(EFI_SECURE_BOOT))
+ register_sysrq_key('x', &secure_boot_sysrq_op);
+ return 0;
+}
+late_initcall(secure_boot_sysrq);
+#endif /*CONFIG_EFI_ALLOW_SECURE_BOOT_EXIT*/
+
+
static struct notifier_block kernel_offset_notifier = {
.notifier_call = dump_kernel_offset
};
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 022be0e22eba..4a054a564636 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -387,6 +387,7 @@ static int uinput_allocate_device(struct uinput_device *udev)
if (!udev->dev)
return -ENOMEM;

+ udev->dev->flags |= INPUTDEV_FLAGS_SYNTHETIC;
udev->dev->event = uinput_dev_event;
input_set_drvdata(udev->dev, udev);

diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index c6fc7141d7b2..0c96cf60f1a6 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -481,6 +481,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 */
@@ -524,7 +525,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;
@@ -544,11 +545,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);
@@ -580,7 +585,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);

@@ -661,7 +666,7 @@ static void sysrq_do_reset(unsigned long _state)
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;
}
@@ -1097,7 +1104,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 a65e3b24fb18..8b0357175049 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 387fa7d05c98..f7c52a9ea394 100644
--- a/include/linux/sysrq.h
+++ b/include/linux/sysrq.h
@@ -28,6 +28,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;
@@ -42,8 +44,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 c8146d53ca67..b480cadf9272 100644
--- a/kernel/debug/kdb/kdb_main.c
+++ b/kernel/debug/kdb/kdb_main.c
@@ -1970,7 +1970,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;

2017-04-05 17:08:42

by David Howells

[permalink] [raw]
Subject: [PATCH 07/24] kexec: Disable at runtime if the kernel is locked down

From: Matthew Garrett <[email protected]>

kexec permits the loading and execution of arbitrary code in ring 0, which
is something that lock-down is meant to prevent. It makes sense to disable
kexec in this situation.

This does not affect kexec_file_load() which can check for a signature on the
image to be booted.

Signed-off-by: Matthew Garrett <[email protected]>
Signed-off-by: David Howells <[email protected]>
---

kernel/kexec.c | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/kernel/kexec.c b/kernel/kexec.c
index 980936a90ee6..46de8e6b42f4 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -194,6 +194,13 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
return -EPERM;

/*
+ * kexec can be used to circumvent module loading restrictions, so
+ * prevent loading in that case
+ */
+ if (kernel_is_locked_down())
+ return -EPERM;
+
+ /*
* Verify we have a legal set of flags
* This leaves us room for future extensions.
*/

2017-04-07 16:33:01

by Justin Forbes

[permalink] [raw]
Subject: Re: [PATCH 00/24] Kernel lockdown

On Wed, Apr 5, 2017 at 12:07 PM, David Howells <[email protected]> wrote:
>
> These patches provide a facility by which a variety of avenues by which
> userspace can feasibly modify the running kernel image can be locked down.
> These include:
>
> (*) No unsigned modules and no modules for which can't validate the
> signature.
>
> (*) No use of ioperm(), iopl() and no writing to /dev/port.
>
> (*) No writing to /dev/mem or /dev/kmem.
>
> (*) No hibernation.
>
> (*) Restrict PCI BAR access.
>
> (*) Restrict MSR access.
>
> (*) No kexec_load().
>
> (*) Certain ACPI restrictions.
>
> (*) Restrict debugfs interface to ASUS WMI.
>
> The lock-down can be configured to be triggered by the EFI secure boot
> status, provided the shim isn't insecure. The lock-down can be lifted by
> typing SysRq+x on a keyboard attached to the system.
>
>
> The patches can be found here also:
>
> http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=efi-lockdown
>
> They are dependent on the hwparam branch, which I posted separately.
>
> David
> ---
> Dave Young (1):
> Copy secure_boot flag in boot params across kexec reboot
>
> David Howells (7):
> Add the ability to lock down access to the running kernel image
> efi: Lock down the kernel if booted in secure boot mode
> Enforce module signatures if the kernel is locked down
> scsi: Lock down the eata driver
> Prohibit PCMCIA CIS storage when the kernel is locked down
> Lock down TIOCSSERIAL
> Lock down module params that specify hardware parameters (eg. ioport)
>
> Josh Boyer (3):
> efi: Add EFI_SECURE_BOOT bit
> hibernate: Disable when the kernel is locked down
> acpi: Ignore acpi_rsdp kernel param when the kernel has been locked down
>
> Kyle McMartin (1):
> Add a sysrq option to exit secure boot mode
>
> Lee, Chun-Yi (2):
> kexec_file: Disable at runtime if securelevel has been set
> bpf: Restrict kernel image access functions when the kernel is locked down
>
> Linn Crosetto (2):
> acpi: Disable ACPI table override if the kernel is locked down
> acpi: Disable APEI error injection if the kernel is locked down
>
> Matthew Garrett (8):
> Restrict /dev/mem and /dev/kmem when the kernel is locked down
> kexec: Disable at runtime if the kernel is locked down
> uswsusp: Disable when the kernel is locked down
> PCI: Lock down BAR access when the kernel is locked down
> x86: Lock down IO port access when the kernel is locked down
> x86: Restrict MSR access when the kernel is locked down
> asus-wmi: Restrict debugfs interface when the kernel is locked down
> ACPI: Limit access to custom_method when the kernel is locked down
>
>
> arch/x86/Kconfig | 22 ++++++++++++++++++++
> arch/x86/kernel/ioport.c | 4 ++--
> arch/x86/kernel/kexec-bzimage64.c | 1 +
> arch/x86/kernel/msr.c | 7 ++++++
> arch/x86/kernel/setup.c | 40 ++++++++++++++++++++++++++++++++++++-
> drivers/acpi/apei/einj.c | 3 +++
> drivers/acpi/custom_method.c | 3 +++
> drivers/acpi/osl.c | 2 +-
> drivers/acpi/tables.c | 5 +++++
> drivers/char/mem.c | 8 +++++++
> drivers/input/misc/uinput.c | 1 +
> drivers/pci/pci-sysfs.c | 9 ++++++++
> drivers/pci/proc.c | 8 ++++++-
> drivers/pci/syscall.c | 2 +-
> drivers/pcmcia/cistpl.c | 5 +++++
> drivers/platform/x86/asus-wmi.c | 9 ++++++++
> drivers/scsi/eata.c | 7 ++++++
> drivers/tty/serial/serial_core.c | 6 ++++++
> drivers/tty/sysrq.c | 19 ++++++++++++------
> include/linux/efi.h | 1 +
> include/linux/input.h | 5 +++++
> include/linux/kernel.h | 9 ++++++++
> include/linux/security.h | 11 ++++++++++
> include/linux/sysrq.h | 8 ++++++-
> kernel/debug/kdb/kdb_main.c | 2 +-
> kernel/kexec.c | 7 ++++++
> kernel/kexec_file.c | 6 ++++++
> kernel/module.c | 2 +-
> kernel/params.c | 27 ++++++++++++++++++++-----
> kernel/power/hibernate.c | 2 +-
> kernel/power/user.c | 3 +++
> kernel/trace/bpf_trace.c | 11 ++++++++++
> security/Kconfig | 15 ++++++++++++++
> security/Makefile | 3 +++
> security/lock_down.c | 40 +++++++++++++++++++++++++++++++++++++
> 35 files changed, 291 insertions(+), 22 deletions(-)
> create mode 100644 security/lock_down.c
>

Tested-by: Justin Forbes <[email protected]>