Commit 154b7a489a5b1d808323b933b04864958c2f1056

Authored by Mathieu Poirier
Committed by Dmitry Torokhov
1 parent 0799a924bc

Input: sysrq - allow specifying alternate reset sequence

This patch adds keyreset functionality to the sysrq driver. It allows
certain button/key combinations to be used in order to trigger emergency
reboots.

Redefining the '__weak platform_sysrq_reset_seq' variable is required
to trigger the feature.  Alternatively keys can be passed to the driver
via a module parameter.

This functionality comes from the keyreset driver submitted by
Arve Hjønnevåg in the Android kernel.

Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

Showing 1 changed file with 202 additions and 74 deletions Side-by-side Diff

... ... @@ -41,6 +41,7 @@
41 41 #include <linux/slab.h>
42 42 #include <linux/input.h>
43 43 #include <linux/uaccess.h>
  44 +#include <linux/moduleparam.h>
44 45  
45 46 #include <asm/ptrace.h>
46 47 #include <asm/irq_regs.h>
47 48  
... ... @@ -576,8 +577,71 @@
576 577 bool active;
577 578 bool need_reinject;
578 579 bool reinjecting;
  580 +
  581 + /* reset sequence handling */
  582 + bool reset_canceled;
  583 + unsigned long reset_keybit[BITS_TO_LONGS(KEY_CNT)];
  584 + int reset_seq_len;
  585 + int reset_seq_cnt;
  586 + int reset_seq_version;
579 587 };
580 588  
  589 +#define SYSRQ_KEY_RESET_MAX 20 /* Should be plenty */
  590 +static unsigned short sysrq_reset_seq[SYSRQ_KEY_RESET_MAX];
  591 +static unsigned int sysrq_reset_seq_len;
  592 +static unsigned int sysrq_reset_seq_version = 1;
  593 +
  594 +static void sysrq_parse_reset_sequence(struct sysrq_state *state)
  595 +{
  596 + int i;
  597 + unsigned short key;
  598 +
  599 + state->reset_seq_cnt = 0;
  600 +
  601 + for (i = 0; i < sysrq_reset_seq_len; i++) {
  602 + key = sysrq_reset_seq[i];
  603 +
  604 + if (key == KEY_RESERVED || key > KEY_MAX)
  605 + break;
  606 +
  607 + __set_bit(key, state->reset_keybit);
  608 + state->reset_seq_len++;
  609 +
  610 + if (test_bit(key, state->key_down))
  611 + state->reset_seq_cnt++;
  612 + }
  613 +
  614 + /* Disable reset until old keys are not released */
  615 + state->reset_canceled = state->reset_seq_cnt != 0;
  616 +
  617 + state->reset_seq_version = sysrq_reset_seq_version;
  618 +}
  619 +
  620 +static bool sysrq_detect_reset_sequence(struct sysrq_state *state,
  621 + unsigned int code, int value)
  622 +{
  623 + if (!test_bit(code, state->reset_keybit)) {
  624 + /*
  625 + * Pressing any key _not_ in reset sequence cancels
  626 + * the reset sequence.
  627 + */
  628 + if (value && state->reset_seq_cnt)
  629 + state->reset_canceled = true;
  630 + } else if (value == 0) {
  631 + /* key release */
  632 + if (--state->reset_seq_cnt == 0)
  633 + state->reset_canceled = false;
  634 + } else if (value == 1) {
  635 + /* key press, not autorepeat */
  636 + if (++state->reset_seq_cnt == state->reset_seq_len &&
  637 + !state->reset_canceled) {
  638 + return true;
  639 + }
  640 + }
  641 +
  642 + return false;
  643 +}
  644 +
581 645 static void sysrq_reinject_alt_sysrq(struct work_struct *work)
582 646 {
583 647 struct sysrq_state *sysrq =
584 648  
585 649  
586 650  
587 651  
588 652  
589 653  
590 654  
591 655  
592 656  
593 657  
594 658  
595 659  
596 660  
597 661  
598 662  
599 663  
600 664  
... ... @@ -604,102 +668,123 @@
604 668 }
605 669 }
606 670  
607   -static bool sysrq_filter(struct input_handle *handle,
608   - unsigned int type, unsigned int code, int value)
  671 +static bool sysrq_handle_keypress(struct sysrq_state *sysrq,
  672 + unsigned int code, int value)
609 673 {
610   - struct sysrq_state *sysrq = handle->private;
611 674 bool was_active = sysrq->active;
612 675 bool suppress;
613 676  
614   - /*
615   - * Do not filter anything if we are in the process of re-injecting
616   - * Alt+SysRq combination.
617   - */
618   - if (sysrq->reinjecting)
619   - return false;
  677 + switch (code) {
620 678  
621   - switch (type) {
  679 + case KEY_LEFTALT:
  680 + case KEY_RIGHTALT:
  681 + if (!value) {
  682 + /* One of ALTs is being released */
  683 + if (sysrq->active && code == sysrq->alt_use)
  684 + sysrq->active = false;
622 685  
623   - case EV_SYN:
624   - suppress = false;
  686 + sysrq->alt = KEY_RESERVED;
  687 +
  688 + } else if (value != 2) {
  689 + sysrq->alt = code;
  690 + sysrq->need_reinject = false;
  691 + }
625 692 break;
626 693  
627   - case EV_KEY:
628   - switch (code) {
  694 + case KEY_SYSRQ:
  695 + if (value == 1 && sysrq->alt != KEY_RESERVED) {
  696 + sysrq->active = true;
  697 + sysrq->alt_use = sysrq->alt;
  698 + /*
  699 + * If nothing else will be pressed we'll need
  700 + * to re-inject Alt-SysRq keysroke.
  701 + */
  702 + sysrq->need_reinject = true;
  703 + }
629 704  
630   - case KEY_LEFTALT:
631   - case KEY_RIGHTALT:
632   - if (!value) {
633   - /* One of ALTs is being released */
634   - if (sysrq->active && code == sysrq->alt_use)
635   - sysrq->active = false;
  705 + /*
  706 + * Pretend that sysrq was never pressed at all. This
  707 + * is needed to properly handle KGDB which will try
  708 + * to release all keys after exiting debugger. If we
  709 + * do not clear key bit it KGDB will end up sending
  710 + * release events for Alt and SysRq, potentially
  711 + * triggering print screen function.
  712 + */
  713 + if (sysrq->active)
  714 + clear_bit(KEY_SYSRQ, sysrq->handle.dev->key);
636 715  
637   - sysrq->alt = KEY_RESERVED;
  716 + break;
638 717  
639   - } else if (value != 2) {
640   - sysrq->alt = code;
641   - sysrq->need_reinject = false;
642   - }
643   - break;
  718 + default:
  719 + if (sysrq->active && value && value != 2) {
  720 + sysrq->need_reinject = false;
  721 + __handle_sysrq(sysrq_xlate[code], true);
  722 + }
  723 + break;
  724 + }
644 725  
645   - case KEY_SYSRQ:
646   - if (value == 1 && sysrq->alt != KEY_RESERVED) {
647   - sysrq->active = true;
648   - sysrq->alt_use = sysrq->alt;
649   - /*
650   - * If nothing else will be pressed we'll need
651   - * to re-inject Alt-SysRq keysroke.
652   - */
653   - sysrq->need_reinject = true;
654   - }
  726 + suppress = sysrq->active;
655 727  
656   - /*
657   - * Pretend that sysrq was never pressed at all. This
658   - * is needed to properly handle KGDB which will try
659   - * to release all keys after exiting debugger. If we
660   - * do not clear key bit it KGDB will end up sending
661   - * release events for Alt and SysRq, potentially
662   - * triggering print screen function.
663   - */
664   - if (sysrq->active)
665   - clear_bit(KEY_SYSRQ, handle->dev->key);
  728 + if (!sysrq->active) {
666 729  
667   - break;
  730 + /*
  731 + * See if reset sequence has changed since the last time.
  732 + */
  733 + if (sysrq->reset_seq_version != sysrq_reset_seq_version)
  734 + sysrq_parse_reset_sequence(sysrq);
668 735  
669   - default:
670   - if (sysrq->active && value && value != 2) {
671   - sysrq->need_reinject = false;
672   - __handle_sysrq(sysrq_xlate[code], true);
673   - }
674   - break;
  736 + /*
  737 + * If we are not suppressing key presses keep track of
  738 + * keyboard state so we can release keys that have been
  739 + * pressed before entering SysRq mode.
  740 + */
  741 + if (value)
  742 + set_bit(code, sysrq->key_down);
  743 + else
  744 + clear_bit(code, sysrq->key_down);
  745 +
  746 + if (was_active)
  747 + schedule_work(&sysrq->reinject_work);
  748 +
  749 + if (sysrq_detect_reset_sequence(sysrq, code, value)) {
  750 + /* Force emergency reboot */
  751 + __handle_sysrq(sysrq_xlate[KEY_B], false);
675 752 }
676 753  
677   - suppress = sysrq->active;
  754 + } else if (value == 0 && test_and_clear_bit(code, sysrq->key_down)) {
  755 + /*
  756 + * Pass on release events for keys that was pressed before
  757 + * entering SysRq mode.
  758 + */
  759 + suppress = false;
  760 + }
678 761  
679   - if (!sysrq->active) {
680   - /*
681   - * If we are not suppressing key presses keep track of
682   - * keyboard state so we can release keys that have been
683   - * pressed before entering SysRq mode.
684   - */
685   - if (value)
686   - set_bit(code, sysrq->key_down);
687   - else
688   - clear_bit(code, sysrq->key_down);
  762 + return suppress;
  763 +}
689 764  
690   - if (was_active)
691   - schedule_work(&sysrq->reinject_work);
  765 +static bool sysrq_filter(struct input_handle *handle,
  766 + unsigned int type, unsigned int code, int value)
  767 +{
  768 + struct sysrq_state *sysrq = handle->private;
  769 + bool suppress;
692 770  
693   - } else if (value == 0 &&
694   - test_and_clear_bit(code, sysrq->key_down)) {
695   - /*
696   - * Pass on release events for keys that was pressed before
697   - * entering SysRq mode.
698   - */
699   - suppress = false;
700   - }
  771 + /*
  772 + * Do not filter anything if we are in the process of re-injecting
  773 + * Alt+SysRq combination.
  774 + */
  775 + if (sysrq->reinjecting)
  776 + return false;
  777 +
  778 + switch (type) {
  779 +
  780 + case EV_SYN:
  781 + suppress = false;
701 782 break;
702 783  
  784 + case EV_KEY:
  785 + suppress = sysrq_handle_keypress(sysrq, code, value);
  786 + break;
  787 +
703 788 default:
704 789 suppress = sysrq->active;
705 790 break;
706 791  
707 792  
... ... @@ -785,8 +870,21 @@
785 870  
786 871 static inline void sysrq_register_handler(void)
787 872 {
  873 + extern unsigned short platform_sysrq_reset_seq[] __weak;
  874 + unsigned short key;
788 875 int error;
  876 + int i;
789 877  
  878 + if (platform_sysrq_reset_seq) {
  879 + for (i = 0; i < ARRAY_SIZE(sysrq_reset_seq); i++) {
  880 + key = platform_sysrq_reset_seq[i];
  881 + if (key == KEY_RESERVED || key > KEY_MAX)
  882 + break;
  883 +
  884 + sysrq_reset_seq[sysrq_reset_seq_len++] = key;
  885 + }
  886 + }
  887 +
790 888 error = input_register_handler(&sysrq_handler);
791 889 if (error)
792 890 pr_err("Failed to register input handler, error %d", error);
... ... @@ -801,6 +899,36 @@
801 899 sysrq_handler_registered = false;
802 900 }
803 901 }
  902 +
  903 +static int sysrq_reset_seq_param_set(const char *buffer,
  904 + const struct kernel_param *kp)
  905 +{
  906 + unsigned long val;
  907 + int error;
  908 +
  909 + error = strict_strtoul(buffer, 0, &val);
  910 + if (error < 0)
  911 + return error;
  912 +
  913 + if (val > KEY_MAX)
  914 + return -EINVAL;
  915 +
  916 + *((unsigned short *)kp->arg) = val;
  917 + sysrq_reset_seq_version++;
  918 +
  919 + return 0;
  920 +}
  921 +
  922 +static struct kernel_param_ops param_ops_sysrq_reset_seq = {
  923 + .get = param_get_ushort,
  924 + .set = sysrq_reset_seq_param_set,
  925 +};
  926 +
  927 +#define param_check_sysrq_reset_seq(name, p) \
  928 + __param_check(name, p, unsigned short)
  929 +
  930 +module_param_array_named(reset_seq, sysrq_reset_seq, sysrq_reset_seq,
  931 + &sysrq_reset_seq_len, 0644);
804 932  
805 933 #else
806 934