diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index 6b4a28bcf2f5..d064743d9ded 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -58,6 +58,7 @@ /* Whether we react on sysrq keys or just ignore them */ static int __read_mostly sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE; static bool __read_mostly sysrq_always_enabled; +static bool __read_mostly sysrq_use_leftctrl = true; static bool sysrq_on(void) { @@ -796,6 +797,7 @@ static void sysrq_reinject_alt_sysrq(struct work_struct *work) container_of(work, struct sysrq_state, reinject_work); struct input_handle *handle = &sysrq->handle; unsigned int alt_code = sysrq->alt_use; + unsigned int sysrq_code = sysrq_use_leftctrl ? KEY_LEFTCTRL : KEY_SYSRQ; if (sysrq->need_reinject) { /* we do not want the assignment to be reordered */ @@ -804,10 +806,10 @@ static void sysrq_reinject_alt_sysrq(struct work_struct *work) /* Simulate press and release of Alt + SysRq */ input_inject_event(handle, EV_KEY, alt_code, 1); - input_inject_event(handle, EV_KEY, KEY_SYSRQ, 1); + input_inject_event(handle, EV_KEY, sysrq_code, 1); input_inject_event(handle, EV_SYN, SYN_REPORT, 1); - input_inject_event(handle, EV_KEY, KEY_SYSRQ, 0); + input_inject_event(handle, EV_KEY, sysrq_code, 0); input_inject_event(handle, EV_KEY, alt_code, 0); input_inject_event(handle, EV_SYN, SYN_REPORT, 1); @@ -849,6 +851,10 @@ static bool sysrq_handle_keypress(struct sysrq_state *sysrq, sysrq->shift_use = sysrq->shift; break; + case KEY_LEFTCTRL: + if (!sysrq_use_leftctrl || sysrq->active) + break; + fallthrough; case KEY_SYSRQ: if (value == 1 && sysrq->alt != KEY_RESERVED) { sysrq->active = true; @@ -874,7 +880,6 @@ static bool sysrq_handle_keypress(struct sysrq_state *sysrq, clear_bit(KEY_SYSRQ, sysrq->handle.dev->key); break; - default: if (sysrq->active && value && value != 2) { unsigned char c = sysrq_xlate[code]; @@ -1111,6 +1116,12 @@ int sysrq_toggle_support(int enable_mask) } EXPORT_SYMBOL_GPL(sysrq_toggle_support); +int sysrq_toggle_sysrq_key(int __sysrq_use_leftctrl) +{ + sysrq_use_leftctrl = !!__sysrq_use_leftctrl; + return 0; +} + static int __sysrq_swap_key_ops(u8 key, const struct sysrq_key_op *insert_op_p, const struct sysrq_key_op *remove_op_p) { diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h index bdca467ebb77..bf3052c1ac6e 100644 --- a/include/linux/sysrq.h +++ b/include/linux/sysrq.h @@ -50,6 +50,7 @@ int unregister_sysrq_key(u8 key, const struct sysrq_key_op *op); extern const struct sysrq_key_op *__sysrq_reboot_op; int sysrq_toggle_support(int enable_mask); +int sysrq_toggle_sysrq_key(int __sysrq_use_leftctrl); int sysrq_mask(void); #else diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 354a2d294f52..35c58b04d83e 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1004,6 +1004,8 @@ int proc_dou8vec_minmax(struct ctl_table *table, int write, EXPORT_SYMBOL_GPL(proc_dou8vec_minmax); #ifdef CONFIG_MAGIC_SYSRQ +static int __sysrq_use_leftctrl = 1; + static int sysrq_sysctl_handler(struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) { @@ -1021,6 +1023,22 @@ static int sysrq_sysctl_handler(struct ctl_table *table, int write, return 0; } + +static int sysrq_use_leftctrl_sysctl_handler(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) +{ + int error; + + error = proc_dointvec(table, write, buffer, lenp, ppos); + if (error) + return error; + + if (write) + sysrq_toggle_sysrq_key(__sysrq_use_leftctrl); + + return 0; +} #endif static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, @@ -1765,6 +1783,14 @@ static struct ctl_table kern_table[] = { .mode = 0644, .proc_handler = sysrq_sysctl_handler, }, + { + .procname = "sysrq_use_leftctrl", + .data = &__sysrq_use_leftctrl, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = sysrq_use_leftctrl_sysctl_handler, + + }, #endif #ifdef CONFIG_PROC_SYSCTL {