
From: Jan Kara <jack@ucw.cz>

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 <jack@suse.cz>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/Documentation/sysrq.txt |   27 +++++++++++++++++++++------
 25-akpm/drivers/char/sysrq.c    |   24 ++++++++++++++++++++----
 25-akpm/include/linux/sysrq.h   |   12 ++++++++++++
 25-akpm/kernel/power/poweroff.c |    3 ++-
 4 files changed, 55 insertions(+), 11 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	2005-01-10 21:14:34.654306712 -0800
+++ 25-akpm/Documentation/sysrq.txt	2005-01-10 21:14:34.662305496 -0800
@@ -10,13 +10,28 @@ 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
-
-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.
+You can set the value in the file by the following command:
+    echo "number" >/proc/sys/kernel/sysrq
 
 *  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	2005-01-10 21:14:34.655306560 -0800
+++ 25-akpm/drivers/char/sysrq.c	2005-01-10 21:14:34.663305344 -0800
@@ -58,6 +58,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,
 };
 
 
@@ -74,6 +75,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
 
@@ -91,6 +93,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 */
 
@@ -106,6 +109,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,
@@ -118,6 +122,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,
@@ -130,6 +135,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 */
@@ -147,6 +153,7 @@ static struct sysrq_key_op sysrq_showreg
 	.handler	= sysrq_handle_showregs,
 	.help_msg	= "showPc",
 	.action_msg	= "Show Regs",
+	.enable_mask	= SYSRQ_ENABLE_DUMP,
 };
 
 
@@ -159,6 +166,7 @@ static struct sysrq_key_op sysrq_showsta
 	.handler	= sysrq_handle_showstate,
 	.help_msg	= "showTasks",
 	.action_msg	= "Show State",
+	.enable_mask	= SYSRQ_ENABLE_DUMP,
 };
 
 
@@ -171,6 +179,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 */
@@ -201,6 +210,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_moom(int key, struct pt_regs *pt_regs,
@@ -225,6 +235,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 */
@@ -237,7 +248,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 */
@@ -347,9 +359,13 @@ 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);
+		if (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 */
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	2005-01-10 21:14:34.657306256 -0800
+++ 25-akpm/include/linux/sysrq.h	2005-01-10 21:14:34.663305344 -0800
@@ -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
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	2005-01-10 21:14:34.658306104 -0800
+++ 25-akpm/kernel/power/poweroff.c	2005-01-10 21:14:34.664305192 -0800
@@ -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)
_
