[PATCH]: Secure SysRQ for 2.1.108.

Myrdraal (myrdraal@jackalz.dyn.ml.org)
Thu, 9 Jul 1998 23:53:52 -0400


--82I3+IH0IqGh5yIs
Content-Type: text/plain; charset=us-ascii

Hi,
This is the (I believe) finished version of my secure SysRQ patch. It
allows you to password protect SysRQ commands or toggle SysRQ entirely.
Is there any chance of this making it into 2.1.x?
-Myrdraal

-- 
Linux jackalz 2.1.108 #103 Thu Jul 2 03:18:16 EDT 1998 i486
11:52pm  up 7 days, 20:34, 20 users,  load average: 0.00, 0.02, 0.00

--82I3+IH0IqGh5yIs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="secure_sysrq-2.1.108.diff"

diff -ur linpatch/Documentation/sysrq.txt linux/Documentation/sysrq.txt --- linpatch/Documentation/sysrq.txt Sat Jun 27 05:25:53 1998 +++ linux/Documentation/sysrq.txt Thu Jul 9 13:08:16 1998 @@ -1,6 +1,6 @@ - MAGIC SYSRQ KEY DOCUMENTATION v1.2 + MAGIC SYSRQ KEY DOCUMENTATION v1.4 ------------------------------------ - [Sat May 16 01:09:21 EDT 1998] + [Thu Jul 9 13:00:49 EDT 1998] * What is the magic SysRQ key? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -22,7 +22,11 @@ On SPARC - You press 'ALT-STOP-<command key>', I believe. On other - If you know of the key combos for other architectures, please - let me know so I can add them to this section. + let me know so I can add them to this section. + +NOTE: SysRQ currently ignores the keyboard mapping. This means if you + redefine your keyboard to some other map (Dvorak for example) + SysRQ will still use the default layout. * What are the 'command' keys? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -46,6 +50,11 @@ 'm' - Will dump current memory info to your console. +'n' - If in secure mode, this will allow you to type in your password + and make available commands that require authentication. See the + section on security for more information. If you are already + authenticated, this command will remove your authentication. + '0'-'9' - Sets the console log level, controlling which kernel messages will be printed to your console. ('0', for example would make it so that only emergency messages like PANICs or OOPSes would @@ -88,6 +97,17 @@ are unable to kill any other way, especially if it's spawning other processes. +* A graphics program crashed, can I use SysRQ to fix the trashed console? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +You probably can. What I generally do is this: + 1. SysRQ-r (unRaw) + 2. SysRQ-k (saK) + 3. Switch to another console, and get a prompt. Login if you have to. + 4. Run a program that resets the video mode. (For example, dosemu -V, or + svgatextmode.) +This may or may not work, depending on your video card. Keep in mind that +you will be working blind. + * Sometimes SysRQ seems to get 'stuck' after using it, what can I do? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ That happens to me, also. I've found that tapping shift, alt, and control @@ -104,6 +124,44 @@ '#define SYSRQ_KEY 0x54' in [/usr/src/linux/]include/asm/keyboard.h to the keycode of the key you wish to use, then recompile. Oh, and by the way, you exit 'showkey' by not typing anything for ten seconds. + +* Is SysRQ a security vulnerability? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The answer is no - not if you configure it correctly. It can be as secure as +you want it to be. SysRQ will create three files that you can use to control +it; + /proc/sys/debug/sysrq_enable: + This file controls whether the system will accept any SysRQ commands. + You can turn it on (default) with this command: + echo "1">/proc/sys/debug/sysrq_enable + You can turn it off with this command: + echo "0">/proc/sys/debug/sysrq_enable + If it is set to "0', then the system will completely ignore SysRQ + commands, regardless of the settings in the other two files. + + /proc/sys/debug/sysrq_secure: + This is a list of the SysRQ commands that are considered secure, this + is set with the command letter of each SysRQ combination. To use a secure + SysRQ command, you must first authenticate using SysRQ-n. Here is an + example of making 'unRaw', 'Boot', and 'killalL' secure: + echo "rbl" >/proc/sys/debug/sysrq_secure + This setting is ignored if /proc/sys/debug/sysrq_enable is set to "0". + The default setting for this is "0". + + /proc/sys/debug/sysrq_password: + This file contains the current SysRQ password. This file is only readable + by the superuser. Example of setting the password: + echo "mypassword" >/proc/sys/debug/sysrq_password + Note that if sysrq_secure is set to "1" and the password is not set, you + will not be able to authenticate. + +Authenticating when in secure mode; + 1. Press SysRQ-n. + 2. Hold the SysRQ combination as you type your password. + 3. Press SysRQ-ENTER. + 4. Perform your SysRQ command. Authentication will be reset. + +Note that passwords with an 'a' in them may cause problems on SPARC. * I have more questions, who can I ask? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff -ur linpatch/drivers/char/keyboard.c linux/drivers/char/keyboard.c --- linpatch/drivers/char/keyboard.c Sun Jun 28 11:41:37 1998 +++ linux/drivers/char/keyboard.c Thu Jul 9 12:10:56 1998 @@ -150,7 +150,7 @@ struct pt_regs * kbd_pt_regs; #ifdef CONFIG_MAGIC_SYSRQ -static int sysrq_pressed; +extern int sysrq_pressed; #endif /* diff -ur linpatch/drivers/char/sysrq.c linux/drivers/char/sysrq.c --- linpatch/drivers/char/sysrq.c Thu Jun 25 01:10:11 1998 +++ linux/drivers/char/sysrq.c Thu Jul 9 12:29:26 1998 @@ -6,6 +6,11 @@ * * (c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz> * based on ideas by Pavel Machek <pavel@atrey.karlin.mff.cuni.cz> + * + * [Sun Jun 28 14:53:44 EDT 1998]: Myrdraal <myrdraal@deathsdoor.com> + * Password authentication added. + * [Tue Jun 30 11:05:52 EDT 1998]: Myrdraal <myrdraal@deathsdoor.com> + * Refined sysrq_secure to make it more finely grained. */ #include <linux/config.h> @@ -22,6 +27,7 @@ #include <linux/quotaops.h> #include <asm/ptrace.h> #include <asm/smp_lock.h> +#include <linux/string.h> #ifdef CONFIG_APM #include <linux/apm_bios.h> @@ -32,6 +38,23 @@ extern int console_loglevel; extern struct vfsmount *vfsmntlist; +/* Is sysrq pressed? (moved out of keyboard.c) */ +int sysrq_pressed = 0; +/* Are we authenticated to use sysrq? */ +int sysrq_authenticated = 0; +/* Is sysrq enabled? */ +int sysctl_sysrq_enable = 1; +/* List of sysrq keys that you need to authenticate to use. */ +char sysctl_sysrq_secure[64] = ""; +/* The password we require to use sysrq if sysrq_secure is set. */ +char sysctl_sysrq_password[64] = ""; +/* Our current position reading the password. */ +int sysrq_passpos = 0; +/* They blew it. (Incorrect password.) */ +int sysrq_blewit = 0; +/* We're waiting for the user to type 'password<ENTER>'. */ +int sysrq_authenticating = 0; + /* Send a signal to all user processes */ static void send_sig_all(int sig, int even_init) @@ -47,6 +70,57 @@ } } +/* Are we authenticated to perform a sysrq command? */ +int is_authenticated(int key) { + if (!sysrq_authenticated && strchr(sysctl_sysrq_secure,key)) { + /* Obviously we must not have authentication. */ + printk("You are not authenticated to use that SysRQ command.\n"); + return 0; + } else { + /* Full speed ahead. */ + return 1; + } +} + +/* Now we reset the authentication if this key is secured. */ +inline void reset_authentication(int key) { + if (strchr(sysctl_sysrq_secure,key)) + sysrq_authenticated=0; +} + +/* Process in one character of the password. */ +void read_password_char(int key) { + if (key=='\r') { + /* They hit ENTER. */ + if (sysrq_blewit || sysrq_passpos<strlen(sysctl_sysrq_password)) { + /* They typed incorrect characters, or they typed in a different + * number of characters than the password contains. */ + sysrq_authenticated=0; + printk("SysRq: Incorrect password. You are not authenticated.\n"); + } else { + /* They typed in the correct password. */ + printk("SysRq: Close enough. You are authenticated.\n"); + sysrq_authenticated=1; + } + /* Now we reset everything (except sysrq_authenticated.) and return.*/ + sysrq_authenticating=0; + sysrq_blewit=0; + sysrq_passpos=0; + return; + } + if (sysctl_sysrq_password[sysrq_passpos]=='\0') { + /* It appears that they typed in too many characters. */ + sysrq_blewit=1; + return; + } + if (sysctl_sysrq_password[sysrq_passpos]!=key) { + /* They typed in character that wasn't in the password. */ + sysrq_blewit=1; + } + /* Onward to the next position. */ + sysrq_passpos++; +} + /* * This function is called by the keyboard handler when SysRq is pressed * and any other keycode arrives. @@ -57,77 +131,146 @@ { int orig_log_level = console_loglevel; - if (!key) + if (!key || !sysctl_sysrq_enable) return; - + + if (sysrq_authenticating) { + /* Since we're in authenticate mode, we process each character that the + * user types with the sysrq combination. */ + read_password_char(key); + /* We don't need to do any more now. */ + return; + } + console_loglevel = 7; printk(KERN_INFO "SysRq: "); switch (key) { case 'r': /* R -- Reset raw mode */ - if (kbd) { - kbd->kbdmode = VC_XLATE; - printk("Keyboard mode set to XLATE\n"); + if (is_authenticated(key)) { + if (kbd) { + kbd->kbdmode = VC_XLATE; + printk("Keyboard mode set to XLATE\n"); + } + reset_authentication(key); } break; case 'k': /* K -- SAK */ - printk("SAK\n"); - if (tty) - do_SAK(tty); - reset_vc(fg_console); + if (is_authenticated(key)) { + printk("SAK\n"); + if (tty) + do_SAK(tty); + reset_vc(fg_console); + reset_authentication(key); + } break; case 'b': /* B -- boot immediately */ - printk("Resetting\n"); - machine_restart(NULL); + if (is_authenticated(key)) { + printk("Resetting\n"); + machine_restart(NULL); + reset_authentication(key); + } break; #ifdef CONFIG_APM case 'o': /* O -- power off */ - printk("Power off\n"); - apm_set_power_state(APM_STATE_OFF); + if (is_authenticated(key)) { + printk("Power off\n"); + apm_set_power_state(APM_STATE_OFF); + reset_authentication(key); + } break; #endif case 's': /* S -- emergency sync */ - printk("Emergency Sync\n"); - emergency_sync_scheduled = EMERG_SYNC; - wakeup_bdflush(0); + if (is_authenticated(key)) { + printk("Emergency Sync\n"); + emergency_sync_scheduled = EMERG_SYNC; + wakeup_bdflush(0); + reset_authentication(key); + } break; case 'u': /* U -- emergency remount R/O */ - printk("Emergency Remount R/O\n"); - emergency_sync_scheduled = EMERG_REMOUNT; - wakeup_bdflush(0); + if (is_authenticated(key)) { + printk("Emergency Remount R/O\n"); + emergency_sync_scheduled = EMERG_REMOUNT; + wakeup_bdflush(0); + reset_authentication(key); + } break; case 'p': /* P -- show PC */ - printk("Show Regs\n"); - if (pt_regs) - show_regs(pt_regs); + if (is_authenticated(key)) { + printk("Show Regs\n"); + if (pt_regs) + show_regs(pt_regs); + reset_authentication(key); + } break; case 't': /* T -- show task info */ - printk("Show State\n"); - show_state(); + if (is_authenticated(key)) { + printk("Show State\n"); + show_state(); + reset_authentication(key); + } break; case 'm': /* M -- show memory info */ - printk("Show Memory\n"); - show_mem(); + if (is_authenticated(key)) { + printk("Show Memory\n"); + show_mem(); + reset_authentication(key); + } + break; + case 'n': + /* They hit the 'autheNticate' combo. */ + if (!sysctl_sysrq_secure[0]) { + printk("You do not need to authenticate, secure mode is not set.\n"); + break; + } + if (sysrq_authenticated) { + printk("Authentication removed.\n"); + sysrq_authenticated=0; + break; + } + printk("You need to enter your password now. Remember to hold\n"); + printk("SysRq: the sysrq sequence as you type it, including the ENTER.\n"); + /* We prepare to authenticate. */ + sysrq_authenticating=1; + sysrq_passpos=0; + sysrq_authenticated=0; + sysrq_blewit=0; + /* And we exit so they can start typing in the password. */ break; case '0' ... '9': /* 0-9 -- set console logging level */ - orig_log_level = key - '0'; - printk("Log level set to %d\n", orig_log_level); + if (is_authenticated(key)) { + orig_log_level = key - '0'; + printk("Log level set to %d\n", orig_log_level); + reset_authentication(key); + } break; case 'e': /* E -- terminate all user processes */ - printk("Terminate All Tasks\n"); - send_sig_all(SIGTERM, 0); - orig_log_level = 8; /* We probably have killed syslogd */ + if (is_authenticated(key)) { + printk("Terminate All Tasks\n"); + send_sig_all(SIGTERM, 0); + orig_log_level = 8; /* We probably have killed syslogd */ + reset_authentication(key); + } break; case 'i': /* I -- kill all user processes */ - printk("Kill All Tasks\n"); - send_sig_all(SIGKILL, 0); - orig_log_level = 8; + if (is_authenticated(key)) { + printk("Kill All Tasks\n"); + send_sig_all(SIGKILL, 0); + orig_log_level = 8; + reset_authentication(key); + } break; case 'l': /* L -- kill all processes including init */ - printk("Kill ALL Tasks (even init)\n"); - send_sig_all(SIGKILL, 1); - orig_log_level = 8; + if (is_authenticated(key)) { + printk("Kill ALL Tasks (even init)\n"); + send_sig_all(SIGKILL, 1); + orig_log_level = 8; + reset_authentication(key); + } break; default: /* Unknown: help */ + if (sysctl_sysrq_secure[0]) + printk("autheNticate "); if (kbd) printk("unRaw "); if (tty) diff -ur linpatch/include/linux/sysctl.h linux/include/linux/sysctl.h --- linpatch/include/linux/sysctl.h Thu Jun 25 01:09:30 1998 +++ linux/include/linux/sysctl.h Thu Jul 9 12:10:56 1998 @@ -369,6 +369,11 @@ }; /* CTL_DEBUG names: */ +enum { + DEBUG_SYSRQ_ENABLE = 1, + DEBUG_SYSRQ_PASSWORD, + DEBUG_SYSRQ_SECURE, +}; /* CTL_DEV names: */ enum { diff -ur linpatch/kernel/sysctl.c linux/kernel/sysctl.c --- linpatch/kernel/sysctl.c Thu Jun 25 01:10:37 1998 +++ linux/kernel/sysctl.c Thu Jul 9 12:10:56 1998 @@ -41,6 +41,11 @@ extern int bdf_prm[], bdflush_min[], bdflush_max[]; extern char binfmt_java_interpreter[], binfmt_java_appletviewer[]; extern int sysctl_overcommit_memory; +#ifdef CONFIG_MAGIC_SYSRQ +extern int sysctl_sysrq_enable; +extern char sysctl_sysrq_secure[]; +extern char sysctl_sysrq_password[]; +#endif #ifdef CONFIG_KMOD extern char modprobe_path[]; #endif @@ -236,6 +241,14 @@ }; static ctl_table debug_table[] = { +#ifdef CONFIG_MAGIC_SYSRQ + {DEBUG_SYSRQ_PASSWORD, "sysrq_password", &sysctl_sysrq_password, 64, + 0600, NULL, &proc_dostring, &sysctl_string}, + {DEBUG_SYSRQ_ENABLE, "sysrq_enable", &sysctl_sysrq_enable, sizeof(int), + 0644, NULL, &proc_dointvec}, + {DEBUG_SYSRQ_SECURE, "sysrq_secure", &sysctl_sysrq_secure, 64, + 0644, NULL, &proc_dostring, &sysctl_string}, +#endif {0} };

--82I3+IH0IqGh5yIs--

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu