From: Jan Kara <jack@suse.cz>

Attached patch fixes a regression introduced by my patch allowing separate
enabling of magic-sysrq functions.  The problem is that originally it was
always possible to use /proc/sysrq-trigger regardless the value of
/proc/sys/kernel/sysrq (which actually I didn't know ;) and my original
patch disallowed it.  As I think the original behaviour is more useful and
has no security problems (only root can access sysrq-trigger) the patch
implementing the old behaviour is attached.

Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/Documentation/sysrq.txt |    4 ++++
 25-akpm/drivers/char/sysrq.c    |    9 ++++++---
 25-akpm/fs/proc/proc_misc.c     |    2 +-
 25-akpm/include/linux/sysrq.h   |    2 +-
 4 files changed, 12 insertions(+), 5 deletions(-)

diff -puN Documentation/sysrq.txt~fix-partial-sysrq-setting Documentation/sysrq.txt
--- 25/Documentation/sysrq.txt~fix-partial-sysrq-setting	Wed Feb  9 14:42:56 2005
+++ 25-akpm/Documentation/sysrq.txt	Wed Feb  9 14:42:56 2005
@@ -33,6 +33,10 @@ in /proc/sys/kernel/sysrq:
 You can set the value in the file by the following command:
     echo "number" >/proc/sys/kernel/sysrq
 
+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?
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 On x86   - You press the key combo 'ALT-SysRq-<command key>'. Note - Some
diff -puN drivers/char/sysrq.c~fix-partial-sysrq-setting drivers/char/sysrq.c
--- 25/drivers/char/sysrq.c~fix-partial-sysrq-setting	Wed Feb  9 14:42:56 2005
+++ 25-akpm/drivers/char/sysrq.c	Wed Feb  9 14:43:59 2005
@@ -345,7 +345,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;
@@ -359,7 +359,10 @@ void __handle_sysrq(int key, struct pt_r
 
         op_p = __sysrq_get_key_op(key);
         if (op_p) {
-		if (sysrq_enabled == 1 || sysrq_enabled & op_p->enable_mask) {
+		/* 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);
@@ -390,7 +393,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 fs/proc/proc_misc.c~fix-partial-sysrq-setting fs/proc/proc_misc.c
--- 25/fs/proc/proc_misc.c~fix-partial-sysrq-setting	Wed Feb  9 14:42:56 2005
+++ 25-akpm/fs/proc/proc_misc.c	Wed Feb  9 14:42:56 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;
 }
diff -puN include/linux/sysrq.h~fix-partial-sysrq-setting include/linux/sysrq.h
--- 25/include/linux/sysrq.h~fix-partial-sysrq-setting	Wed Feb  9 14:42:56 2005
+++ 25-akpm/include/linux/sysrq.h	Wed Feb  9 14:42:56 2005
@@ -42,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);
_