| From 16d2ba5d5bc46e67e6aa7a3d113fbcc18c217388 Mon Sep 17 00:00:00 2001 |
| From: Kyle McMartin <kyle@redhat.com> |
| Date: Fri, 30 Aug 2013 09:28:51 -0400 |
| Subject: [PATCH 20/20] Add sysrq option to disable secure boot mode |
| |
| Bugzilla: N/A |
| Upstream-status: Fedora mustard |
| |
| arch/x86/kernel/setup.c | 36 ++++++++++++++++++++++++++++++++++++ |
| 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 +- |
| kernel/module.c | 2 +- |
| 7 files changed, 64 insertions(+), 9 deletions(-) |
| |
| diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c |
| index f93826b8522c..41679b1aca83 100644 |
| |
| |
| @@ -70,6 +70,11 @@ |
| #include <linux/tboot.h> |
| #include <linux/jiffies.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> |
| @@ -1261,6 +1266,37 @@ void __init i386_reserve_resources(void) |
| |
| #endif /* CONFIG_X86_32 */ |
| |
| +#ifdef CONFIG_MAGIC_SYSRQ |
| +#ifdef CONFIG_MODULE_SIG |
| +extern bool sig_enforce; |
| +#endif |
| + |
| +static void sysrq_handle_secure_boot(int key) |
| +{ |
| + if (!efi_enabled(EFI_SECURE_BOOT)) |
| + return; |
| + |
| + pr_info("Secure boot disabled\n"); |
| +#ifdef CONFIG_MODULE_SIG |
| + sig_enforce = fips_enabled; |
| +#endif |
| +} |
| +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_MAGIC_SYSRQ*/ |
| + |
| + |
| 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 345df9b03aed..dea6a6c4a39b 100644 |
| |
| |
| @@ -364,6 +364,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 95b330a9ea98..dfa3e154a719 100644 |
| |
| |
| @@ -472,6 +472,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 */ |
| @@ -515,7 +516,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, int from) |
| { |
| struct sysrq_key_op *op_p; |
| int orig_log_level; |
| @@ -535,11 +536,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); |
| @@ -571,7 +576,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); |
| |
| @@ -652,7 +657,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, |
| @@ -803,8 +808,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; |
| } |
| @@ -1084,7 +1091,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 82ce323b9986..9e534f228945 100644 |
| |
| |
| @@ -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..4b07e30b3279 100644 |
| |
| |
| @@ -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, 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 4121345498e0..0ff3cef5df96 100644 |
| |
| |
| @@ -1968,7 +1968,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); |
| kdb_trap_printk--; |
| |
| return 0; |
| diff --git a/kernel/module.c b/kernel/module.c |
| index 2b403ab0ef29..7818c110e95c 100644 |
| |
| |
| @@ -292,7 +292,7 @@ static void module_assert_mutex_or_preempt(void) |
| #endif |
| } |
| |
| -static bool sig_enforce = IS_ENABLED(CONFIG_MODULE_SIG_FORCE); |
| +bool sig_enforce = IS_ENABLED(CONFIG_MODULE_SIG_FORCE); |
| #ifndef CONFIG_MODULE_SIG_FORCE |
| module_param(sig_enforce, bool_enable_only, 0644); |
| #endif /* !CONFIG_MODULE_SIG_FORCE */ |
| -- |
| 2.4.3 |
| |