[5/6] tty/sysrq: Add configurable handler to signal a process
diff mbox series

Message ID 20200511135918.8203-6-andrzej.p@collabora.com
State New
Headers show
Series
  • Magic SysRq extensions
Related show

Commit Message

Andrzej Pietrasiewicz May 11, 2020, 1:59 p.m. UTC
Some userland might want to implement a policy to signal a configured
process with a configured signal. This patch adds necessary kernel-side
infrastructure and the newly added handler is triggered with
Alt-Shift-SysRq-s. Optionally the userland can also specify the expected
name of parent process of the victim.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
---
 drivers/tty/sysrq.c | 123 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 122 insertions(+), 1 deletion(-)

Comments

Greg Kroah-Hartman May 11, 2020, 4:20 p.m. UTC | #1
On Mon, May 11, 2020 at 03:59:17PM +0200, Andrzej Pietrasiewicz wrote:
> Some userland might want to implement a policy to signal a configured
> process with a configured signal. This patch adds necessary kernel-side
> infrastructure and the newly added handler is triggered with
> Alt-Shift-SysRq-s. Optionally the userland can also specify the expected
> name of parent process of the victim.

THat's crazy, what "userspace" wants to do something like this that
can't just do it by running a program?  Why force the kernel to do it
for them?

And you don't document any of this :(

greg k-h
kernel test robot May 14, 2020, 9:06 a.m. UTC | #2
Hi Andrzej,

I love your patch! Yet something to improve:

[auto build test ERROR on 2ef96a5bb12be62ef75b5828c0aab838ebb29cb8]

url:    https://github.com/0day-ci/linux/commits/Andrzej-Pietrasiewicz/Magic-SysRq-extensions/20200514-151142
base:    2ef96a5bb12be62ef75b5828c0aab838ebb29cb8
config: alpha-defconfig (attached as .config)
compiler: alpha-linux-gcc (GCC) 9.3.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day GCC_VERSION=9.3.0 make.cross ARCH=alpha 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kbuild test robot <lkp@intel.com>

All errors (new ones prefixed by >>, old ones prefixed by <<):

drivers/tty/sysrq.c: In function 'sysrq_str_to_signal':
>> drivers/tty/sysrq.c:791:17: error: 'SIGSTKFLT' undeclared (first use in this function); did you mean 'SIGSTKSZ'?
791 |   {"SIGSTKFLT", SIGSTKFLT},
|                 ^~~~~~~~~
|                 SIGSTKSZ
drivers/tty/sysrq.c:791:17: note: each undeclared identifier is reported only once for each function it appears in

vim +791 drivers/tty/sysrq.c

   771	
   772	static void sysrq_str_to_signal(void)
   773	{
   774		static const struct signal_search signals[] = {
   775			{"SIGHUP", SIGHUP},
   776			{"SIGINT", SIGINT},
   777			{"SIGQUIT", SIGQUIT},
   778			{"SIGILL", SIGILL},
   779			{"SIGTRAP", SIGTRAP},
   780			{"SIGABRT", SIGABRT},
   781			{"SIGIOT", SIGIOT},
   782			{"SIGBUS", SIGBUS},
   783			{"SIGFPE", SIGFPE},
   784			{"SIGKILL", SIGKILL},
   785			{"SIGUSR1", SIGUSR1},
   786			{"SIGSEGV", SIGSEGV},
   787			{"SIGUSR2", SIGUSR2},
   788			{"SIGPIPE", SIGPIPE},
   789			{"SIGALRM", SIGALRM},
   790			{"SIGTERM", SIGTERM},
 > 791			{"SIGSTKFLT", SIGSTKFLT},
   792			{"SIGCHLD", SIGCHLD},
   793			{"SIGCONT", SIGCONT},
   794			{"SIGSTOP", SIGSTOP},
   795			{"SIGTSTP", SIGTSTP},
   796			{"SIGTTIN", SIGTTIN},
   797			{"SIGTTOU", SIGTTOU},
   798			{"SIGURG", SIGURG},
   799			{"SIGXCPU", SIGXCPU},
   800			{"SIGXFSZ", SIGXFSZ},
   801			{"SIGVTALRM", SIGVTALRM},
   802			{"SIGPROF", SIGPROF},
   803			{"SIGWINCH", SIGWINCH},
   804			{"SIGIO", SIGIO},
   805			{"SIGPOLL", SIGPOLL},
   806			{"SIGPWR", SIGPWR},
   807			{"SIGSYS", SIGSYS},
   808		};
   809		int i;
   810	
   811		if (!sysrq_signal)
   812			return;
   813	
   814		for (i = 0; i < ARRAY_SIZE(signals); ++i)
   815			if (!strcmp(signals[i].name, sysrq_signal))
   816				break;
   817	
   818		if (i >= ARRAY_SIZE(signals)) {
   819			pr_err("Unknown signal name %s", sysrq_signal);
   820	
   821			return;
   822		}
   823	
   824		sysrq_signal_code = signals[i].code;
   825	}
   826	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

Patch
diff mbox series

diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index ab4121a446b4..a6e91e4ae304 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -437,6 +437,15 @@  static struct sysrq_key_op sysrq_unrt_op = {
 	.enable_mask	= SYSRQ_ENABLE_RTNICE,
 };
 
+static void sysrq_signal_configured(int key);
+
+static struct sysrq_key_op sysrq_signal_configured_op = {
+	.handler	= sysrq_signal_configured,
+	.help_msg	= "signal-configured-process(S)",
+	.action_msg	= "Signal configured process",
+	.enable_mask	= SYSRQ_ENABLE_SIGNAL,
+};
+
 /* Key Operations table and lock */
 static DEFINE_SPINLOCK(sysrq_key_table_lock);
 
@@ -515,7 +524,7 @@  static struct sysrq_key_op *sysrq_key_table[62] = {
 	NULL,				/* P */
 	NULL,				/* Q */
 	NULL,				/* R */
-	NULL,				/* S */
+	&sysrq_signal_configured_op,	/* S */
 	NULL,				/* T */
 	NULL,				/* U */
 	NULL,				/* V */
@@ -633,6 +642,10 @@  EXPORT_SYMBOL(handle_sysrq);
 #ifdef CONFIG_INPUT
 static int sysrq_reset_downtime_ms;
 static unsigned short sysrq_key = KEY_SYSRQ;
+static char *sysrq_signalled;
+static char *sysrq_signalled_parent;
+static char *sysrq_signal;
+static int sysrq_signal_code;
 
 /* Simple translation table for the SysRq keys */
 static const unsigned char sysrq_xlate[KEY_CNT] =
@@ -751,6 +764,106 @@  static void sysrq_detect_reset_sequence(struct sysrq_state *state,
 	}
 }
 
+struct signal_search {
+	const char *name;
+	int code;
+};
+
+static void sysrq_str_to_signal(void)
+{
+	static const struct signal_search signals[] = {
+		{"SIGHUP", SIGHUP},
+		{"SIGINT", SIGINT},
+		{"SIGQUIT", SIGQUIT},
+		{"SIGILL", SIGILL},
+		{"SIGTRAP", SIGTRAP},
+		{"SIGABRT", SIGABRT},
+		{"SIGIOT", SIGIOT},
+		{"SIGBUS", SIGBUS},
+		{"SIGFPE", SIGFPE},
+		{"SIGKILL", SIGKILL},
+		{"SIGUSR1", SIGUSR1},
+		{"SIGSEGV", SIGSEGV},
+		{"SIGUSR2", SIGUSR2},
+		{"SIGPIPE", SIGPIPE},
+		{"SIGALRM", SIGALRM},
+		{"SIGTERM", SIGTERM},
+		{"SIGSTKFLT", SIGSTKFLT},
+		{"SIGCHLD", SIGCHLD},
+		{"SIGCONT", SIGCONT},
+		{"SIGSTOP", SIGSTOP},
+		{"SIGTSTP", SIGTSTP},
+		{"SIGTTIN", SIGTTIN},
+		{"SIGTTOU", SIGTTOU},
+		{"SIGURG", SIGURG},
+		{"SIGXCPU", SIGXCPU},
+		{"SIGXFSZ", SIGXFSZ},
+		{"SIGVTALRM", SIGVTALRM},
+		{"SIGPROF", SIGPROF},
+		{"SIGWINCH", SIGWINCH},
+		{"SIGIO", SIGIO},
+		{"SIGPOLL", SIGPOLL},
+		{"SIGPWR", SIGPWR},
+		{"SIGSYS", SIGSYS},
+	};
+	int i;
+
+	if (!sysrq_signal)
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(signals); ++i)
+		if (!strcmp(signals[i].name, sysrq_signal))
+			break;
+
+	if (i >= ARRAY_SIZE(signals)) {
+		pr_err("Unknown signal name %s", sysrq_signal);
+
+		return;
+	}
+
+	sysrq_signal_code = signals[i].code;
+}
+
+static void sysrq_signal_configured(int key)
+{
+	struct task_struct *p;
+
+	sysrq_str_to_signal();
+
+	if (!sysrq_signalled) {
+		pr_err("Unconfigured process name for %s",
+		       sysrq_signal_configured_op.help_msg);
+
+		return;
+	}
+
+	if (!sysrq_signal_code) {
+		pr_err("Unconfigured signal for %s",
+		       sysrq_signal_configured_op.help_msg);
+
+		return;
+	}
+
+	read_lock(&tasklist_lock);
+	for_each_process(p) {
+		if (p->flags & (PF_KTHREAD | PF_EXITING))
+			continue;
+		if (is_global_init(p))
+			continue;
+		if (strncmp(p->comm, sysrq_signalled, TASK_COMM_LEN))
+			continue;
+		if (sysrq_signalled_parent
+		    && strncmp(p->parent->comm, sysrq_signalled_parent,
+			       TASK_COMM_LEN))
+			continue;
+
+		pr_err("%s: signal %d %s pid %u tgid %u\n", __func__,
+		       sysrq_signal_code, sysrq_signalled, p->pid, p->tgid);
+		do_send_sig_info(sysrq_signal_code, SEND_SIG_PRIV, p, true);
+	}
+	read_unlock(&tasklist_lock);
+}
+
 
 static void sysrq_reinject_alt_sysrq(struct work_struct *work)
 {
@@ -1048,8 +1161,16 @@  module_param_named(sysrq_downtime_ms, sysrq_reset_downtime_ms, int, 0644);
 
 module_param(sysrq_key, ushort, 0644);
 
+module_param(sysrq_signalled, charp, 0644);
+module_param(sysrq_signalled_parent, charp, 0644);
+module_param(sysrq_signal, charp, 0644);
+
 #else
 
+static void sysrq_signal_configured(int key)
+{
+}
+
 static inline void sysrq_register_handler(void)
 {
 }