Messages in this thread Patch in this message | | | Subject | twist: allow disabling reboot request | From | Tetsuo Handa <> | Date | Wed, 3 Jun 2020 20:03:28 +0900 |
| |
On 2020/05/29 22:26, Tetsuo Handa wrote: > By the way, I do worry that people forget to perform these steps when they do > their tests without asking syzbot...
Here is a draft of boot-time switching. Since kconfig can handle string variable up to 2048 characters, we could hold the content of the "your-config" file inside .config file in order to avoid relying on external file in "syzkaller tree". But since only one kconfig option is used, basically the way to temporarily include/exclude specific options (under automated testing by syzbot) seems to remain directly patching apply_twist_flags(), for https://github.com/google/syzkaller/blob/master/dashboard/config/util.sh will automatically overwrite CONFIG_DEFAULT_TWIST_FLAGS settings. If each twist flag were using independent kconfig option, the way to temporarily include/exclude specific options will become directly patching Kconfig file.
drivers/tty/vt/keyboard.c | 2 ++ include/linux/kernel.h | 8 ++++++++ init/main.c | 30 ++++++++++++++++++++++++++++++ kernel/reboot.c | 36 ++++++++++++++++++++++++++++++++++++ lib/Kconfig.debug | 5 +++++ 5 files changed, 81 insertions(+)
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index 568b2171f335..ae0b7cd69249 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -637,6 +637,8 @@ static void k_spec(struct vc_data *vc, unsigned char value, char up_flag) kbd->kbdmode == VC_OFF) && value != KVAL(K_SAK)) return; /* SAK is allowed even in raw mode */ + if (twist_flags.disable_kbd_k_spec_handler) + return; fn_handler[value](vc); } diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 82d91547d122..78fdbb4f17b1 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -1038,4 +1038,12 @@ static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { } /* OTHER_WRITABLE? Generally considered a bad idea. */ \ BUILD_BUG_ON_ZERO((perms) & 2) + \ (perms)) + +/* Flags for twisting kernel behavior. */ +struct twist_flags { + bool disable_kbd_k_spec_handler; + bool disable_reboot_request; +}; +extern struct twist_flags twist_flags; + #endif diff --git a/init/main.c b/init/main.c index 0ead83e86b5a..15eecd253b61 100644 --- a/init/main.c +++ b/init/main.c @@ -1531,3 +1531,33 @@ static noinline void __init kernel_init_freeable(void) integrity_load_keys(); } + +/* Flags for twisting kernel behavior. */ +struct twist_flags twist_flags __ro_after_init; +EXPORT_SYMBOL(twist_flags); +static __initdata char default_twist_flags[] __initdata = CONFIG_DEFAULT_TWIST_FLAGS; +static __initdata char *chosen_twist_flags = default_twist_flags; + +static int __init overwrite_twist_flags(char *str) +{ + chosen_twist_flags = str; + return 1; +} +__setup("twist_flags=", overwrite_twist_flags); + +static int __init apply_twist_flags(void) +{ + char *flags = chosen_twist_flags; + char *name; + + while ((name = strsep(&flags, ",")) != NULL) { + if (!strcmp(name, "kbd-disable-hotkeys")) + twist_flags.disable_kbd_k_spec_handler = true; + else if (!strcmp(name, "disable-reboot-request")) + twist_flags.disable_reboot_request = true; + else + printk(KERN_INFO "Ignoring unknown twist option '%s'.\n", name); + } + return 0; +} +late_initcall(apply_twist_flags); diff --git a/kernel/reboot.c b/kernel/reboot.c index 491f1347bf43..63cec97a9e59 100644 --- a/kernel/reboot.c +++ b/kernel/reboot.c @@ -63,6 +63,8 @@ EXPORT_SYMBOL_GPL(pm_power_off_prepare); */ void emergency_restart(void) { + if (twist_flags.disable_reboot_request) + panic("reboot request is disabled"); kmsg_dump(KMSG_DUMP_EMERG); machine_emergency_restart(); } @@ -243,6 +245,8 @@ void migrate_to_reboot_cpu(void) */ void kernel_restart(char *cmd) { + if (twist_flags.disable_reboot_request) + panic("reboot request is disabled"); kernel_restart_prepare(cmd); migrate_to_reboot_cpu(); syscore_shutdown(); @@ -270,6 +274,8 @@ static void kernel_shutdown_prepare(enum system_states state) */ void kernel_halt(void) { + if (twist_flags.disable_reboot_request) + panic("reboot request is disabled"); kernel_shutdown_prepare(SYSTEM_HALT); migrate_to_reboot_cpu(); syscore_shutdown(); @@ -286,6 +292,8 @@ EXPORT_SYMBOL_GPL(kernel_halt); */ void kernel_power_off(void) { + if (twist_flags.disable_reboot_request) + panic("reboot request is disabled"); kernel_shutdown_prepare(SYSTEM_POWER_OFF); if (pm_power_off_prepare) pm_power_off_prepare(); @@ -344,6 +352,10 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, mutex_lock(&system_transition_mutex); switch (cmd) { case LINUX_REBOOT_CMD_RESTART: + if (twist_flags.disable_reboot_request) { + ret = -EPERM; + break; + } kernel_restart(NULL); break; @@ -356,11 +368,19 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, break; case LINUX_REBOOT_CMD_HALT: + if (twist_flags.disable_reboot_request) { + ret = -EPERM; + break; + } kernel_halt(); do_exit(0); panic("cannot halt"); case LINUX_REBOOT_CMD_POWER_OFF: + if (twist_flags.disable_reboot_request) { + ret = -EPERM; + break; + } kernel_power_off(); do_exit(0); break; @@ -373,17 +393,29 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, } buffer[sizeof(buffer) - 1] = '\0'; + if (twist_flags.disable_reboot_request) { + ret = -EPERM; + break; + } kernel_restart(buffer); break; #ifdef CONFIG_KEXEC_CORE case LINUX_REBOOT_CMD_KEXEC: + if (twist_flags.disable_reboot_request) { + ret = -EPERM; + break; + } ret = kernel_kexec(); break; #endif #ifdef CONFIG_HIBERNATION case LINUX_REBOOT_CMD_SW_SUSPEND: + if (twist_flags.disable_reboot_request) { + ret = -EPERM; + break; + } ret = hibernate(); break; #endif @@ -493,6 +525,8 @@ static DECLARE_WORK(poweroff_work, poweroff_work_func); */ void orderly_poweroff(bool force) { + if (twist_flags.disable_reboot_request) + panic("reboot request is disabled"); if (force) /* do not override the pending "true" */ poweroff_force = true; schedule_work(&poweroff_work); @@ -514,6 +548,8 @@ static DECLARE_WORK(reboot_work, reboot_work_func); */ void orderly_reboot(void) { + if (twist_flags.disable_reboot_request) + panic("reboot request is disabled"); schedule_work(&reboot_work); } EXPORT_SYMBOL_GPL(orderly_reboot); diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 498d344ea53a..41cfabc74ad7 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2338,4 +2338,9 @@ config HYPERV_TESTING endmenu # "Kernel Testing and Coverage" +menuconfig DEFAULT_TWIST_FLAGS + string "Default twist options (DANGEROUS)" + help + Don't specify anything unless you know what you are doing. + endmenu # Kernel hacking
| |