From: Jan Kara Allow admin to enable only some of the Magic-Sysrq functions. This allows admin to disable sysrq functions he considers dangerous (e.g. sending kill signal, remounting fs RO) while keeping the possibility to use the others (e.g. debug deadlocks by dumps of processes etc.). Signed-off-by: Jan Kara Signed-off-by: Andrew Morton --- 25-akpm/Documentation/sysrq.txt | 29 ++++++++++++++++++++++++----- 25-akpm/drivers/char/sysrq.c | 31 +++++++++++++++++++++++++------ 25-akpm/fs/proc/proc_misc.c | 2 +- 25-akpm/include/linux/sysrq.h | 14 +++++++++++++- 25-akpm/kernel/power/poweroff.c | 3 ++- 5 files changed, 65 insertions(+), 14 deletions(-) diff -puN Documentation/sysrq.txt~allow-admin-to-enable-only-some-of-the-magic-sysrq-functions Documentation/sysrq.txt --- 25/Documentation/sysrq.txt~allow-admin-to-enable-only-some-of-the-magic-sysrq-functions Thu Mar 10 15:27:59 2005 +++ 25-akpm/Documentation/sysrq.txt Thu Mar 10 15:32:13 2005 @@ -10,13 +10,32 @@ regardless of whatever else it is doing, * How do I enable the magic SysRq key? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You need to say "yes" to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when -configuring the kernel. When running on a kernel with SysRq compiled in, it -may be DISABLED at run-time using following command: +configuring the kernel. When running a kernel with SysRq compiled in, +/proc/sys/kernel/sysrq controls the functions allowed to be invoked via +the SysRq key. By default the file contains 1 which means that every +possible SysRq request is allowed (in older versions SysRq was disabled +by default, and you were required to specifically enable it at run-time +but this is not the case any more). Here is the list of possible values +in /proc/sys/kernel/sysrq: + 0 - disable sysrq completely + 1 - enable all functions of sysrq + >1 - bitmask of allowed sysrq functions (see below for detailed function + description): + 2 - enable control of console logging level + 4 - enable control of keyboard (SAK, unraw) + 8 - enable debugging dumps of processes etc. + 16 - enable sync command + 32 - enable remount read-only + 64 - enable signalling of processes (term, kill, oom-kill) + 128 - allow reboot/poweroff + 256 - allow nicing of all RT tasks - echo "0" > /proc/sys/kernel/sysrq +You can set the value in the file by the following command: + echo "number" >/proc/sys/kernel/sysrq -Note that previous versions disabled sysrq by default, and you were required -to specifically enable it at run-time. That is not the case any longer. +Note that the value of /proc/sys/kernel/sysrq influences only the invocation +via a keyboard. Invocation of any operation via /proc/sysrq-trigger is always +allowed. * How do I use the magic SysRq key? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff -puN drivers/char/sysrq.c~allow-admin-to-enable-only-some-of-the-magic-sysrq-functions drivers/char/sysrq.c --- 25/drivers/char/sysrq.c~allow-admin-to-enable-only-some-of-the-magic-sysrq-functions Thu Mar 10 15:27:59 2005 +++ 25-akpm/drivers/char/sysrq.c Thu Mar 10 15:32:13 2005 @@ -57,6 +57,7 @@ static struct sysrq_key_op sysrq_logleve .handler = sysrq_handle_loglevel, .help_msg = "loglevel0-8", .action_msg = "Changing Loglevel", + .enable_mask = SYSRQ_ENABLE_LOG, }; @@ -73,6 +74,7 @@ static struct sysrq_key_op sysrq_SAK_op .handler = sysrq_handle_SAK, .help_msg = "saK", .action_msg = "SAK", + .enable_mask = SYSRQ_ENABLE_KEYBOARD, }; #endif @@ -90,6 +92,7 @@ static struct sysrq_key_op sysrq_unraw_o .handler = sysrq_handle_unraw, .help_msg = "unRaw", .action_msg = "Keyboard mode set to XLATE", + .enable_mask = SYSRQ_ENABLE_KEYBOARD, }; #endif /* CONFIG_VT */ @@ -105,6 +108,7 @@ static struct sysrq_key_op sysrq_reboot_ .handler = sysrq_handle_reboot, .help_msg = "reBoot", .action_msg = "Resetting", + .enable_mask = SYSRQ_ENABLE_BOOT, }; static void sysrq_handle_sync(int key, struct pt_regs *pt_regs, @@ -117,6 +121,7 @@ static struct sysrq_key_op sysrq_sync_op .handler = sysrq_handle_sync, .help_msg = "Sync", .action_msg = "Emergency Sync", + .enable_mask = SYSRQ_ENABLE_SYNC, }; static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs, @@ -129,6 +134,7 @@ static struct sysrq_key_op sysrq_mountro .handler = sysrq_handle_mountro, .help_msg = "Unmount", .action_msg = "Emergency Remount R/O", + .enable_mask = SYSRQ_ENABLE_REMOUNT, }; /* END SYNC SYSRQ HANDLERS BLOCK */ @@ -146,6 +152,7 @@ static struct sysrq_key_op sysrq_showreg .handler = sysrq_handle_showregs, .help_msg = "showPc", .action_msg = "Show Regs", + .enable_mask = SYSRQ_ENABLE_DUMP, }; @@ -158,6 +165,7 @@ static struct sysrq_key_op sysrq_showsta .handler = sysrq_handle_showstate, .help_msg = "showTasks", .action_msg = "Show State", + .enable_mask = SYSRQ_ENABLE_DUMP, }; @@ -170,6 +178,7 @@ static struct sysrq_key_op sysrq_showmem .handler = sysrq_handle_showmem, .help_msg = "showMem", .action_msg = "Show Memory", + .enable_mask = SYSRQ_ENABLE_DUMP, }; /* SHOW SYSRQ HANDLERS BLOCK */ @@ -200,6 +209,7 @@ static struct sysrq_key_op sysrq_term_op .handler = sysrq_handle_term, .help_msg = "tErm", .action_msg = "Terminate All Tasks", + .enable_mask = SYSRQ_ENABLE_SIGNAL, }; static void sysrq_handle_kill(int key, struct pt_regs *pt_regs, @@ -212,6 +222,7 @@ static struct sysrq_key_op sysrq_kill_op .handler = sysrq_handle_kill, .help_msg = "kIll", .action_msg = "Kill All Tasks", + .enable_mask = SYSRQ_ENABLE_SIGNAL, }; /* END SIGNAL SYSRQ HANDLERS BLOCK */ @@ -224,7 +235,8 @@ static void sysrq_handle_unrt(int key, s static struct sysrq_key_op sysrq_unrt_op = { .handler = sysrq_handle_unrt, .help_msg = "Nice", - .action_msg = "Nice All RT Tasks" + .action_msg = "Nice All RT Tasks", + .enable_mask = SYSRQ_ENABLE_RTNICE, }; /* Key Operations table and lock */ @@ -320,7 +332,7 @@ void __sysrq_put_key_op (int key, struct * as they are inside of the lock */ -void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty) +void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty, int check_mask) { struct sysrq_key_op *op_p; int orig_log_level; @@ -334,9 +346,16 @@ void __handle_sysrq(int key, struct pt_r op_p = __sysrq_get_key_op(key); if (op_p) { - printk ("%s\n", op_p->action_msg); - console_loglevel = orig_log_level; - op_p->handler(key, pt_regs, tty); + /* Should we check for enabled operations (/proc/sysrq-trigger should not) + * and is the invoked operation enabled? */ + if (!check_mask || sysrq_enabled == 1 || + (sysrq_enabled & op_p->enable_mask)) { + printk ("%s\n", op_p->action_msg); + console_loglevel = orig_log_level; + op_p->handler(key, pt_regs, tty); + } + else + printk("This sysrq operation is disabled.\n"); } else { printk("HELP : "); /* Only print the help msg once per handler */ @@ -361,7 +380,7 @@ void handle_sysrq(int key, struct pt_reg { if (!sysrq_enabled) return; - __handle_sysrq(key, pt_regs, tty); + __handle_sysrq(key, pt_regs, tty, 1); } int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p, diff -puN include/linux/sysrq.h~allow-admin-to-enable-only-some-of-the-magic-sysrq-functions include/linux/sysrq.h --- 25/include/linux/sysrq.h~allow-admin-to-enable-only-some-of-the-magic-sysrq-functions Thu Mar 10 15:27:59 2005 +++ 25-akpm/include/linux/sysrq.h Thu Mar 10 15:32:13 2005 @@ -16,10 +16,22 @@ struct pt_regs; struct tty_struct; +/* Possible values of bitmask for enabling sysrq functions */ +/* 0x0001 is reserved for enable everything */ +#define SYSRQ_ENABLE_LOG 0x0002 +#define SYSRQ_ENABLE_KEYBOARD 0x0004 +#define SYSRQ_ENABLE_DUMP 0x0008 +#define SYSRQ_ENABLE_SYNC 0x0010 +#define SYSRQ_ENABLE_REMOUNT 0x0020 +#define SYSRQ_ENABLE_SIGNAL 0x0040 +#define SYSRQ_ENABLE_BOOT 0x0080 +#define SYSRQ_ENABLE_RTNICE 0x0100 + struct sysrq_key_op { void (*handler)(int, struct pt_regs *, struct tty_struct *); char *help_msg; char *action_msg; + int enable_mask; }; #ifdef CONFIG_MAGIC_SYSRQ @@ -30,7 +42,7 @@ struct sysrq_key_op { */ void handle_sysrq(int, struct pt_regs *, struct tty_struct *); -void __handle_sysrq(int, struct pt_regs *, struct tty_struct *); +void __handle_sysrq(int, struct pt_regs *, struct tty_struct *, int check_mask); int register_sysrq_key(int, struct sysrq_key_op *); int unregister_sysrq_key(int, struct sysrq_key_op *); struct sysrq_key_op *__sysrq_get_key_op(int key); diff -puN kernel/power/poweroff.c~allow-admin-to-enable-only-some-of-the-magic-sysrq-functions kernel/power/poweroff.c --- 25/kernel/power/poweroff.c~allow-admin-to-enable-only-some-of-the-magic-sysrq-functions Thu Mar 10 15:27:59 2005 +++ 25-akpm/kernel/power/poweroff.c Thu Mar 10 15:27:59 2005 @@ -32,7 +32,8 @@ static void handle_poweroff(int key, str static struct sysrq_key_op sysrq_poweroff_op = { .handler = handle_poweroff, .help_msg = "powerOff", - .action_msg = "Power Off" + .action_msg = "Power Off", + .enable_mask = SYSRQ_ENABLE_BOOT, }; static int pm_sysrq_init(void) diff -puN fs/proc/proc_misc.c~allow-admin-to-enable-only-some-of-the-magic-sysrq-functions fs/proc/proc_misc.c --- 25/fs/proc/proc_misc.c~allow-admin-to-enable-only-some-of-the-magic-sysrq-functions Thu Mar 10 15:32:13 2005 +++ 25-akpm/fs/proc/proc_misc.c Thu Mar 10 15:32:13 2005 @@ -524,7 +524,7 @@ static ssize_t write_sysrq_trigger(struc if (get_user(c, buf)) return -EFAULT; - __handle_sysrq(c, NULL, NULL); + __handle_sysrq(c, NULL, NULL, 0); } return count; } _