sysrq-j: emergency shell
RFC PATCH 1/1 sysrq-j: emergency shell
Quoted 1 line
From
57adfe62983db316fceba1b64258fd3d8830bcd8Mon Sep 17 00:00:00 2001
From: Vegard Nossum <[email protected]>
Date: Sat, 22 Nov 2008 00:25:57 +0100
Subject: [PATCH] sysrq-j: emergency shell
This patch adds support for "SysRq-j", which invokes an emergency root shell in the current console.
Please don't bite my head off for abusing the file API; documentation was rather sparse! (Corrections are welcome, though.)
It seems that keyboard input will go to the shell only half of the time; the other half goes to whatever program was running there in the first place. I tried to kill the other users of the TTY using TIOCSCTTY, but it seems not to have worked. Any ideas?
--- init/main.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 104 insertions(+), 0 deletions(-)
init/main.c +104 -0
@@ -63,6 +63,8 @@#include <linux/signal.h> #include <linux/idr.h> #include <linux/ftrace.h> +#include <linux/sysrq.h> +#include <linux/file.h> #include <asm/io.h> #include <asm/bugs.h>
@@ -833,6 +835,106 @@ static int noinline init_post(void)panic ("No init found. Try passing init= option to kernel." ); } +static int sysrq_sh_thread (void *unused) +{ +static char *const argv[] = {"sh" ,NULL }; +static char *const envp[] = {"HOME=/" ,"TERM=linux" ,NULL }; + +struct file *console; +int i; +int ret; + +for (i =0 ; i <3 ; ++i) { + ret =get_unused_fd (); +if (ret <0 ) + goto put_fds; +if (ret != i) { +put_unused_fd (ret); + ret = -EBADF ; + goto put_fds; + } + } + + console =filp_open ("/dev/console" ,O_RDWR |O_NOCTTY ,0 ); +if (IS_ERR (console)) { + ret =PTR_ERR (console); + goto put_fds; + } + +get_file (console); +get_file (console); +get_file (console); +fd_install (0 , console); +fd_install (1 , console); +fd_install (2 , console); + +/* Become session leader */ + ret =sys_setsid (); +if (ret <0 ) + goto put_filp; + +/* Exclusive mode; no others are allowed to open() this tty */ + ret =sys_ioctl (0 ,TIOCEXCL ,0 ); +if (ret <0 ) + goto put_filp; + +/* Steal the tty from whoever */ + ret =sys_ioctl (0 ,TIOCSCTTY ,1 ); +if (ret <0 ) + goto put_filp; + +/* Flush pending input */ + ret =sys_ioctl (0 ,TCFLSH ,TCIFLUSH ); +if (ret <0 ) + goto put_filp; + +/* If execve() returns, something went wrong. */ + ret =kernel_execve ("/bin/sh" , argv, envp); + +put_filp: +fput (console); + +put_fds: +while (--i >=0 ) +put_unused_fd (i); + +printk (KERN_ERR "Couldn't start shell: %d\n" , ret); +return ret; +} + +static void sysrq_sh_work_func (struct work_struct *work) +{ +int err; + + err =kernel_thread (sysrq_sh_thread,NULL ,CLONE_FS |CLONE_SIGHAND ); +if (err <0 ) +printk (KERN_ERR "Couldn't start kernel thread (%d)\n" , err); +} + +static DECLARE_WORK(sysrq_sh_work, &sysrq_sh_work_func); + +static void sysrq_sh_handle (int key,struct tty_struct *tty) +{ +schedule_work (&sysrq_sh_work); +} + +static struct sysrq_key_op sysrq_sh_op = { + .handler = sysrq_sh_handle, + .help_msg ="shell(j)" , + .action_msg ="Emergency shell" , +}; + +static void sysrq_sh_init (void ) +{ +int err; + + err =register_sysrq_key ('j' , &sysrq_sh_op); +if (err <0 ) { +printk (KERN_ERR "Couldn't register SysRq-j (emergency shell) " +"handler. (%d)\n" , err); + } +} +static int __init kernel_init (void * unused) {lock_kernel ();
@@ -877,6 +979,8 @@ static int __init kernel_init(void * unused)prepare_namespace (); } +sysrq_sh_init (); +/* * Ok, we have completed the initial bootup, and * we're essentially up and running. Get rid of the
Signature · 1 line
1.5.6.5
Quoted 8 lines · Vegard Nossum
Quoted 1 line
From
57adfe62983db316fceba1b64258fd3d8830bcd8Mon Sep 17 00:00:00 2001From: Vegard Nossum <[email protected]>
Date: Sat, 22 Nov 2008 00:25:57 +0100
Subject: [PATCH] sysrq-j: emergency shellThis patch adds support for "SysRq-j", which invokes an emergency root shell in the current console.
Quoted 8 lines
Please don't bite my head off for abusing the file API; documentation was rather sparse! (Corrections are welcome, though.)
It seems that keyboard input will go to the shell only half of the time; the other half goes to whatever program was running there in the first place. I tried to kill the other users of the TTY using TIOCSCTTY, but it seems not to have worked. Any ideas?
Have you considered SIGTSTP?
Matt
Quoted 2 lines · Vegard Nossum
This patch adds support for "SysRq-j", which invokes an emergency root shell in the current console.
I like this idea. I like it a lot.
Quoted 10 lines · Vegard Nossum
This patch adds support for "SysRq-j", which invokes an emergency root shell in the current console.
Please don't bite my head off for abusing the file API; documentation was rather sparse! (Corrections are welcome, though.)
It seems that keyboard input will go to the shell only half of the time; the other half goes to whatever program was running there in the first place. I tried to kill the other users of the TTY using TIOCSCTTY, but it seems not to have worked. Any ideas?
This should go in together with CVE number attached.
Quoted 6 lines
Quoted 4 lines
It seems that keyboard input will go to the shell only half of the time; the other half goes to whatever program was running there in the first place. I tried to kill the other users of the TTY using TIOCSCTTY, but it seems not to have worked. Any ideas?
This should go in together with CVE number attached.
TIOCSTTY isn't supposed to kill anything.
Alan
Quoted 8 lines · Alan Cox
Quoted 6 lines
Quoted 4 lines
It seems that keyboard input will go to the shell only half of the time; the other half goes to whatever program was running there in the first place. I tried to kill the other users of the TTY using TIOCSCTTY, but it seems not to have worked. Any ideas?
This should go in together with CVE number attached.
TIOCSTTY isn't supposed to kill anything.
Oops, by killing, I meant simply to take it exclusively:
EPERM, unless the caller is root and arg equals 1, in which case the tty is stolen, and all processes that had it as controlling tty lose it.
But I realize that this does not necessarily mean that the other processes cannot read from or write to the tty anymore. Do you know how to do that? :-)
Vegard
Signature · 4 lines
"The animistic metaphor of the bug that maliciously sneaked in while the programmer was not looking is intellectually dishonest as it disguises that the error is the programmer's own creation." -- E. W. Dijkstra, EWD1036
Quoted 3 lines
But I realize that this does not necessarily mean that the other processes cannot read from or write to the tty anymore. Do you know how to do that? :-)
When you have control vhangup()
That just leaves the small matter of keymaps. I'm really not sure of the point of this sysrq-j hack, it seems to me we have a perfectly good vt switch mechanism
Quoted 5 lines · Alan Cox
Quoted 3 lines
But I realize that this does not necessarily mean that the other processes cannot read from or write to the tty anymore. Do you know how to do that? :-)
When you have control
vhangup()
It also means more people have to disable sysrq than before.
AFAIK currently it's not possible to actually change anything with sysrq (just reboot/kill/show information). That would be the first one who could be actually used to change data, enable network login etc.
I bet this unexpected change of security policy would surprise a lot of existing users and suddenly give a new attack vector.
So if this is added it should at least have a separate enable switch with default off. But as Alan says, we have vt-switch anyways so ...
-Andi
Signature · 1 line
[email protected]