mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	Input: implement SysRq as a separate input handler
Instead of keeping SysRq support inside of legacy keyboard driver split it out into a separate input handler (filter). This stops most SysRq input events from leaking into evdev clients (some events, such as first SysRq scancode - not keycode - event, are still leaked into both legacy keyboard and evdev). [martinez.javier@gmail.com: fix compile error when CONFIG_MAGIC_SYSRQ is not defined] Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
This commit is contained in:
		
							parent
							
								
									b91c4be730
								
							
						
					
					
						commit
						97f5f0cd8c
					
				
					 4 changed files with 249 additions and 86 deletions
				
			
		| 
						 | 
				
			
			@ -38,7 +38,6 @@
 | 
			
		|||
#include <linux/kbd_kern.h>
 | 
			
		||||
#include <linux/kbd_diacr.h>
 | 
			
		||||
#include <linux/vt_kern.h>
 | 
			
		||||
#include <linux/sysrq.h>
 | 
			
		||||
#include <linux/input.h>
 | 
			
		||||
#include <linux/reboot.h>
 | 
			
		||||
#include <linux/notifier.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -82,8 +81,7 @@ void compute_shiftstate(void);
 | 
			
		|||
typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
 | 
			
		||||
			    char up_flag);
 | 
			
		||||
static k_handler_fn K_HANDLERS;
 | 
			
		||||
k_handler_fn *k_handler[16] = { K_HANDLERS };
 | 
			
		||||
EXPORT_SYMBOL_GPL(k_handler);
 | 
			
		||||
static k_handler_fn *k_handler[16] = { K_HANDLERS };
 | 
			
		||||
 | 
			
		||||
#define FN_HANDLERS\
 | 
			
		||||
	fn_null,	fn_enter,	fn_show_ptregs,	fn_show_mem,\
 | 
			
		||||
| 
						 | 
				
			
			@ -147,22 +145,6 @@ static struct ledptr {
 | 
			
		|||
	unsigned char valid:1;
 | 
			
		||||
} ledptrs[3];
 | 
			
		||||
 | 
			
		||||
/* Simple translation table for the SysRq keys */
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_MAGIC_SYSRQ
 | 
			
		||||
unsigned char kbd_sysrq_xlate[KEY_MAX + 1] =
 | 
			
		||||
        "\000\0331234567890-=\177\t"                    /* 0x00 - 0x0f */
 | 
			
		||||
        "qwertyuiop[]\r\000as"                          /* 0x10 - 0x1f */
 | 
			
		||||
        "dfghjkl;'`\000\\zxcv"                          /* 0x20 - 0x2f */
 | 
			
		||||
        "bnm,./\000*\000 \000\201\202\203\204\205"      /* 0x30 - 0x3f */
 | 
			
		||||
        "\206\207\210\211\212\000\000789-456+1"         /* 0x40 - 0x4f */
 | 
			
		||||
        "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
 | 
			
		||||
        "\r\000/";                                      /* 0x60 - 0x6f */
 | 
			
		||||
static int sysrq_down;
 | 
			
		||||
static int sysrq_alt_use;
 | 
			
		||||
#endif
 | 
			
		||||
static int sysrq_alt;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Notifier list for console keyboard events
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -1108,7 +1090,8 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode,
 | 
			
		|||
			 * pressing PrtSc/SysRq alone, but simply 0x54
 | 
			
		||||
			 * when pressing Alt+PrtSc/SysRq.
 | 
			
		||||
			 */
 | 
			
		||||
			if (sysrq_alt) {
 | 
			
		||||
			if (test_bit(KEY_LEFTALT, key_down) ||
 | 
			
		||||
			    test_bit(KEY_RIGHTALT, key_down)) {
 | 
			
		||||
				put_queue(vc, 0x54 | up_flag);
 | 
			
		||||
			} else {
 | 
			
		||||
				put_queue(vc, 0xe0);
 | 
			
		||||
| 
						 | 
				
			
			@ -1176,8 +1159,6 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
 | 
			
		|||
 | 
			
		||||
	kbd = kbd_table + vc->vc_num;
 | 
			
		||||
 | 
			
		||||
	if (keycode == KEY_LEFTALT || keycode == KEY_RIGHTALT)
 | 
			
		||||
		sysrq_alt = down ? keycode : 0;
 | 
			
		||||
#ifdef CONFIG_SPARC
 | 
			
		||||
	if (keycode == KEY_STOP)
 | 
			
		||||
		sparc_l1_a_state = down;
 | 
			
		||||
| 
						 | 
				
			
			@ -1190,21 +1171,6 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
 | 
			
		|||
			if (keycode < BTN_MISC && printk_ratelimit())
 | 
			
		||||
				printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode);
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_MAGIC_SYSRQ	       /* Handle the SysRq Hack */
 | 
			
		||||
	if (keycode == KEY_SYSRQ && (sysrq_down || (down == 1 && sysrq_alt))) {
 | 
			
		||||
		if (!sysrq_down) {
 | 
			
		||||
			sysrq_down = down;
 | 
			
		||||
			sysrq_alt_use = sysrq_alt;
 | 
			
		||||
		}
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if (sysrq_down && !down && keycode == sysrq_alt_use)
 | 
			
		||||
		sysrq_down = 0;
 | 
			
		||||
	if (sysrq_down && down && !rep) {
 | 
			
		||||
		handle_sysrq(kbd_sysrq_xlate[keycode], tty);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef CONFIG_SPARC
 | 
			
		||||
	if (keycode == KEY_A && sparc_l1_a_state) {
 | 
			
		||||
		sparc_l1_a_state = 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,4 @@
 | 
			
		|||
/* -*- linux-c -*-
 | 
			
		||||
 *
 | 
			
		||||
 *	$Id: sysrq.c,v 1.15 1998/08/23 14:56:41 mj Exp $
 | 
			
		||||
 *
 | 
			
		||||
/*
 | 
			
		||||
 *	Linux Magic System Request Key Hacks
 | 
			
		||||
 *
 | 
			
		||||
 *	(c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
 | 
			
		||||
| 
						 | 
				
			
			@ -10,8 +7,13 @@
 | 
			
		|||
 *	(c) 2000 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
 | 
			
		||||
 *	overhauled to use key registration
 | 
			
		||||
 *	based upon discusions in irc://irc.openprojects.net/#kernelnewbies
 | 
			
		||||
 *
 | 
			
		||||
 *	Copyright (c) 2010 Dmitry Torokhov
 | 
			
		||||
 *	Input handler conversion
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 | 
			
		||||
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/interrupt.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -39,33 +41,34 @@
 | 
			
		|||
#include <linux/hrtimer.h>
 | 
			
		||||
#include <linux/oom.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/input.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/ptrace.h>
 | 
			
		||||
#include <asm/irq_regs.h>
 | 
			
		||||
 | 
			
		||||
/* Whether we react on sysrq keys or just ignore them */
 | 
			
		||||
int __read_mostly __sysrq_enabled = 1;
 | 
			
		||||
static int __read_mostly sysrq_enabled = 1;
 | 
			
		||||
static bool __read_mostly sysrq_always_enabled;
 | 
			
		||||
 | 
			
		||||
static int __read_mostly sysrq_always_enabled;
 | 
			
		||||
 | 
			
		||||
int sysrq_on(void)
 | 
			
		||||
static bool sysrq_on(void)
 | 
			
		||||
{
 | 
			
		||||
	return __sysrq_enabled || sysrq_always_enabled;
 | 
			
		||||
	return sysrq_enabled || sysrq_always_enabled;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * A value of 1 means 'all', other nonzero values are an op mask:
 | 
			
		||||
 */
 | 
			
		||||
static inline int sysrq_on_mask(int mask)
 | 
			
		||||
static bool sysrq_on_mask(int mask)
 | 
			
		||||
{
 | 
			
		||||
	return sysrq_always_enabled || __sysrq_enabled == 1 ||
 | 
			
		||||
						(__sysrq_enabled & mask);
 | 
			
		||||
	return sysrq_always_enabled ||
 | 
			
		||||
	       sysrq_enabled == 1 ||
 | 
			
		||||
	       (sysrq_enabled & mask);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int __init sysrq_always_enabled_setup(char *str)
 | 
			
		||||
{
 | 
			
		||||
	sysrq_always_enabled = 1;
 | 
			
		||||
	printk(KERN_INFO "debug: sysrq always enabled.\n");
 | 
			
		||||
	sysrq_always_enabled = true;
 | 
			
		||||
	pr_info("sysrq always enabled.\n");
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -76,6 +79,7 @@ __setup("sysrq_always_enabled", sysrq_always_enabled_setup);
 | 
			
		|||
static void sysrq_handle_loglevel(int key, struct tty_struct *tty)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	i = key - '0';
 | 
			
		||||
	console_loglevel = 7;
 | 
			
		||||
	printk("Loglevel set to %d\n", i);
 | 
			
		||||
| 
						 | 
				
			
			@ -101,7 +105,7 @@ static struct sysrq_key_op sysrq_SAK_op = {
 | 
			
		|||
	.enable_mask	= SYSRQ_ENABLE_KEYBOARD,
 | 
			
		||||
};
 | 
			
		||||
#else
 | 
			
		||||
#define sysrq_SAK_op (*(struct sysrq_key_op *)0)
 | 
			
		||||
#define sysrq_SAK_op (*(struct sysrq_key_op *)NULL)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_VT
 | 
			
		||||
| 
						 | 
				
			
			@ -119,7 +123,7 @@ static struct sysrq_key_op sysrq_unraw_op = {
 | 
			
		|||
	.enable_mask	= SYSRQ_ENABLE_KEYBOARD,
 | 
			
		||||
};
 | 
			
		||||
#else
 | 
			
		||||
#define sysrq_unraw_op (*(struct sysrq_key_op *)0)
 | 
			
		||||
#define sysrq_unraw_op (*(struct sysrq_key_op *)NULL)
 | 
			
		||||
#endif /* CONFIG_VT */
 | 
			
		||||
 | 
			
		||||
static void sysrq_handle_crash(int key, struct tty_struct *tty)
 | 
			
		||||
| 
						 | 
				
			
			@ -195,7 +199,7 @@ static struct sysrq_key_op sysrq_showlocks_op = {
 | 
			
		|||
	.action_msg	= "Show Locks Held",
 | 
			
		||||
};
 | 
			
		||||
#else
 | 
			
		||||
#define sysrq_showlocks_op (*(struct sysrq_key_op *)0)
 | 
			
		||||
#define sysrq_showlocks_op (*(struct sysrq_key_op *)NULL)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_SMP
 | 
			
		||||
| 
						 | 
				
			
			@ -298,7 +302,7 @@ static struct sysrq_key_op sysrq_ftrace_dump_op = {
 | 
			
		|||
	.enable_mask	= SYSRQ_ENABLE_DUMP,
 | 
			
		||||
};
 | 
			
		||||
#else
 | 
			
		||||
#define sysrq_ftrace_dump_op (*(struct sysrq_key_op *)0)
 | 
			
		||||
#define sysrq_ftrace_dump_op (*(struct sysrq_key_op *)NULL)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void sysrq_handle_showmem(int key, struct tty_struct *tty)
 | 
			
		||||
| 
						 | 
				
			
			@ -477,6 +481,7 @@ struct sysrq_key_op *__sysrq_get_key_op(int key)
 | 
			
		|||
	i = sysrq_key_table_key2index(key);
 | 
			
		||||
	if (i != -1)
 | 
			
		||||
	        op_p = sysrq_key_table[i];
 | 
			
		||||
 | 
			
		||||
        return op_p;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -488,11 +493,7 @@ static void __sysrq_put_key_op(int key, struct sysrq_key_op *op_p)
 | 
			
		|||
                sysrq_key_table[i] = op_p;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This is the non-locking version of handle_sysrq.  It must/can only be called
 | 
			
		||||
 * by sysrq key handlers, as they are inside of the lock
 | 
			
		||||
 */
 | 
			
		||||
void __handle_sysrq(int key, struct tty_struct *tty, int check_mask)
 | 
			
		||||
static void __handle_sysrq(int key, struct tty_struct *tty, int check_mask)
 | 
			
		||||
{
 | 
			
		||||
	struct sysrq_key_op *op_p;
 | 
			
		||||
	int orig_log_level;
 | 
			
		||||
| 
						 | 
				
			
			@ -544,10 +545,6 @@ void __handle_sysrq(int key, struct tty_struct *tty, int check_mask)
 | 
			
		|||
	spin_unlock_irqrestore(&sysrq_key_table_lock, flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This function is called by the keyboard handler when SysRq is pressed
 | 
			
		||||
 * and any other keycode arrives.
 | 
			
		||||
 */
 | 
			
		||||
void handle_sysrq(int key, struct tty_struct *tty)
 | 
			
		||||
{
 | 
			
		||||
	if (sysrq_on())
 | 
			
		||||
| 
						 | 
				
			
			@ -555,10 +552,177 @@ void handle_sysrq(int key, struct tty_struct *tty)
 | 
			
		|||
}
 | 
			
		||||
EXPORT_SYMBOL(handle_sysrq);
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_INPUT
 | 
			
		||||
 | 
			
		||||
/* Simple translation table for the SysRq keys */
 | 
			
		||||
static const unsigned char sysrq_xlate[KEY_MAX + 1] =
 | 
			
		||||
        "\000\0331234567890-=\177\t"                    /* 0x00 - 0x0f */
 | 
			
		||||
        "qwertyuiop[]\r\000as"                          /* 0x10 - 0x1f */
 | 
			
		||||
        "dfghjkl;'`\000\\zxcv"                          /* 0x20 - 0x2f */
 | 
			
		||||
        "bnm,./\000*\000 \000\201\202\203\204\205"      /* 0x30 - 0x3f */
 | 
			
		||||
        "\206\207\210\211\212\000\000789-456+1"         /* 0x40 - 0x4f */
 | 
			
		||||
        "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
 | 
			
		||||
        "\r\000/";                                      /* 0x60 - 0x6f */
 | 
			
		||||
 | 
			
		||||
static bool sysrq_down;
 | 
			
		||||
static int sysrq_alt_use;
 | 
			
		||||
static int sysrq_alt;
 | 
			
		||||
 | 
			
		||||
static bool sysrq_filter(struct input_handle *handle, unsigned int type,
 | 
			
		||||
		         unsigned int code, int value)
 | 
			
		||||
{
 | 
			
		||||
	if (type != EV_KEY)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	switch (code) {
 | 
			
		||||
 | 
			
		||||
	case KEY_LEFTALT:
 | 
			
		||||
	case KEY_RIGHTALT:
 | 
			
		||||
		if (value)
 | 
			
		||||
			sysrq_alt = code;
 | 
			
		||||
		else if (sysrq_down && code == sysrq_alt_use)
 | 
			
		||||
			sysrq_down = false;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case KEY_SYSRQ:
 | 
			
		||||
		if (value == 1 && sysrq_alt) {
 | 
			
		||||
			sysrq_down = true;
 | 
			
		||||
			sysrq_alt_use = sysrq_alt;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		if (sysrq_down && value && value != 2)
 | 
			
		||||
			__handle_sysrq(sysrq_xlate[code], NULL, 1);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	return sysrq_down;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int sysrq_connect(struct input_handler *handler,
 | 
			
		||||
			 struct input_dev *dev,
 | 
			
		||||
			 const struct input_device_id *id)
 | 
			
		||||
{
 | 
			
		||||
	struct input_handle *handle;
 | 
			
		||||
	int error;
 | 
			
		||||
 | 
			
		||||
	sysrq_down = false;
 | 
			
		||||
	sysrq_alt = 0;
 | 
			
		||||
 | 
			
		||||
	handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
 | 
			
		||||
	if (!handle)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
	handle->dev = dev;
 | 
			
		||||
	handle->handler = handler;
 | 
			
		||||
	handle->name = "sysrq";
 | 
			
		||||
 | 
			
		||||
	error = input_register_handle(handle);
 | 
			
		||||
	if (error) {
 | 
			
		||||
		pr_err("Failed to register input sysrq handler, error %d\n",
 | 
			
		||||
			error);
 | 
			
		||||
		goto err_free;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	error = input_open_device(handle);
 | 
			
		||||
	if (error) {
 | 
			
		||||
		pr_err("Failed to open input device, error %d\n", error);
 | 
			
		||||
		goto err_unregister;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
 err_unregister:
 | 
			
		||||
	input_unregister_handle(handle);
 | 
			
		||||
 err_free:
 | 
			
		||||
	kfree(handle);
 | 
			
		||||
	return error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void sysrq_disconnect(struct input_handle *handle)
 | 
			
		||||
{
 | 
			
		||||
	input_close_device(handle);
 | 
			
		||||
	input_unregister_handle(handle);
 | 
			
		||||
	kfree(handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * We are matching on KEY_LEFTALT insteard of KEY_SYSRQ because not all
 | 
			
		||||
 * keyboards have SysRq ikey predefined and so user may add it to keymap
 | 
			
		||||
 * later, but we expect all such keyboards to have left alt.
 | 
			
		||||
 */
 | 
			
		||||
static const struct input_device_id sysrq_ids[] = {
 | 
			
		||||
	{
 | 
			
		||||
		.flags = INPUT_DEVICE_ID_MATCH_EVBIT |
 | 
			
		||||
				INPUT_DEVICE_ID_MATCH_KEYBIT,
 | 
			
		||||
		.evbit = { BIT_MASK(EV_KEY) },
 | 
			
		||||
		.keybit = { BIT_MASK(KEY_LEFTALT) },
 | 
			
		||||
	},
 | 
			
		||||
	{ },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct input_handler sysrq_handler = {
 | 
			
		||||
	.filter		= sysrq_filter,
 | 
			
		||||
	.connect	= sysrq_connect,
 | 
			
		||||
	.disconnect	= sysrq_disconnect,
 | 
			
		||||
	.name		= "sysrq",
 | 
			
		||||
	.id_table	= sysrq_ids,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static bool sysrq_handler_registered;
 | 
			
		||||
 | 
			
		||||
static inline void sysrq_register_handler(void)
 | 
			
		||||
{
 | 
			
		||||
	int error;
 | 
			
		||||
 | 
			
		||||
	error = input_register_handler(&sysrq_handler);
 | 
			
		||||
	if (error)
 | 
			
		||||
		pr_err("Failed to register input handler, error %d", error);
 | 
			
		||||
	else
 | 
			
		||||
		sysrq_handler_registered = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void sysrq_unregister_handler(void)
 | 
			
		||||
{
 | 
			
		||||
	if (sysrq_handler_registered) {
 | 
			
		||||
		input_unregister_handler(&sysrq_handler);
 | 
			
		||||
		sysrq_handler_registered = false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
static inline void sysrq_register_handler(void)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void sysrq_unregister_handler(void)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* CONFIG_INPUT */
 | 
			
		||||
 | 
			
		||||
int sysrq_toggle_support(int enable_mask)
 | 
			
		||||
{
 | 
			
		||||
	bool was_enabled = sysrq_on();
 | 
			
		||||
 | 
			
		||||
	sysrq_enabled = enable_mask;
 | 
			
		||||
 | 
			
		||||
	if (was_enabled != sysrq_on()) {
 | 
			
		||||
		if (sysrq_on())
 | 
			
		||||
			sysrq_register_handler();
 | 
			
		||||
		else
 | 
			
		||||
			sysrq_unregister_handler();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,
 | 
			
		||||
                                struct sysrq_key_op *remove_op_p)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	int retval;
 | 
			
		||||
	unsigned long flags;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -599,6 +763,7 @@ static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf,
 | 
			
		|||
			return -EFAULT;
 | 
			
		||||
		__handle_sysrq(c, NULL, 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -606,10 +771,28 @@ static const struct file_operations proc_sysrq_trigger_operations = {
 | 
			
		|||
	.write		= write_sysrq_trigger,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void sysrq_init_procfs(void)
 | 
			
		||||
{
 | 
			
		||||
	if (!proc_create("sysrq-trigger", S_IWUSR, NULL,
 | 
			
		||||
			 &proc_sysrq_trigger_operations))
 | 
			
		||||
		pr_err("Failed to register proc interface\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
static inline void sysrq_init_procfs(void)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* CONFIG_PROC_FS */
 | 
			
		||||
 | 
			
		||||
static int __init sysrq_init(void)
 | 
			
		||||
{
 | 
			
		||||
	proc_create("sysrq-trigger", S_IWUSR, NULL, &proc_sysrq_trigger_operations);
 | 
			
		||||
	sysrq_init_procfs();
 | 
			
		||||
 | 
			
		||||
	if (sysrq_on())
 | 
			
		||||
		sysrq_register_handler();
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
module_init(sysrq_init);
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,40 +39,33 @@ struct sysrq_key_op {
 | 
			
		|||
 | 
			
		||||
#ifdef CONFIG_MAGIC_SYSRQ
 | 
			
		||||
 | 
			
		||||
extern int sysrq_on(void);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Do not use this one directly:
 | 
			
		||||
 */
 | 
			
		||||
extern int __sysrq_enabled;
 | 
			
		||||
 | 
			
		||||
/* Generic SysRq interface -- you may call it from any device driver, supplying
 | 
			
		||||
 * ASCII code of the key, pointer to registers and kbd/tty structs (if they
 | 
			
		||||
 * are available -- else NULL's).
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
void handle_sysrq(int key, struct tty_struct *tty);
 | 
			
		||||
void __handle_sysrq(int key, struct tty_struct *tty, int check_mask);
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
int sysrq_toggle_support(int enable_mask);
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
static inline int sysrq_on(void)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
static inline int __reterr(void)
 | 
			
		||||
{
 | 
			
		||||
	return -EINVAL;
 | 
			
		||||
}
 | 
			
		||||
static inline void handle_sysrq(int key, struct tty_struct *tty)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define register_sysrq_key(ig,nore) __reterr()
 | 
			
		||||
#define unregister_sysrq_key(ig,nore) __reterr()
 | 
			
		||||
static inline int register_sysrq_key(int key, struct sysrq_key_op *op)
 | 
			
		||||
{
 | 
			
		||||
	return -EINVAL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int unregister_sysrq_key(int key, struct sysrq_key_op *op)
 | 
			
		||||
{
 | 
			
		||||
	return -EINVAL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -163,6 +163,27 @@ static int proc_taint(struct ctl_table *table, int write,
 | 
			
		|||
			       void __user *buffer, size_t *lenp, loff_t *ppos);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_MAGIC_SYSRQ
 | 
			
		||||
static int __sysrq_enabled; /* Note: sysrq code ises it's own private copy */
 | 
			
		||||
 | 
			
		||||
static int sysrq_sysctl_handler(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_support(__sysrq_enabled);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static struct ctl_table root_table[];
 | 
			
		||||
static struct ctl_table_root sysctl_table_root;
 | 
			
		||||
static struct ctl_table_header root_table_header = {
 | 
			
		||||
| 
						 | 
				
			
			@ -567,7 +588,7 @@ static struct ctl_table kern_table[] = {
 | 
			
		|||
		.data		= &__sysrq_enabled,
 | 
			
		||||
		.maxlen		= sizeof (int),
 | 
			
		||||
		.mode		= 0644,
 | 
			
		||||
		.proc_handler	= proc_dointvec,
 | 
			
		||||
		.proc_handler	= sysrq_sysctl_handler,
 | 
			
		||||
	},
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef CONFIG_PROC_SYSCTL
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue