Received: by 2002:a05:6a10:a0d1:0:0:0:0 with SMTP id j17csp457493pxa; Tue, 4 Aug 2020 09:28:50 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwIc/6fZHy1nHxLOySmYidHuSin3Y2OsTw+zaSLnf+odxcQdWTn1XzJ4LX2emJ18os19QSK X-Received: by 2002:a50:f396:: with SMTP id g22mr21412808edm.220.1596558530303; Tue, 04 Aug 2020 09:28:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1596558530; cv=none; d=google.com; s=arc-20160816; b=kn0G/aCSKNiQl4mah5hlpw7CsDr8jfZfaR649zd2DHQjbFe8Vr1mcJmByE3GySCar1 glZyhHo50oaoMmXGcmim1Mts0VkgP1rgIcxcY0UcZsDdm8N5LFZdBwEKHiy/FDJqgNRy 0t+DoMFJ2SfNfh02MrGhVo+QOX6dMAGe49J57lN/xj2OnmQ5WZA5+u1uiePmcTg+MKN6 FomLIN2Axd7vwpetnSFn1ASz2QDglzhaXcl5MyF6D1N0pE3JBgaRW611Zh1jB1IyC0De FVa4lIFyo3nV4Ojt3kRyHZXpaMoxPfNTKrul1Ygss2D3m1lFOMw8Xr3doPuvN+GCb5hd UXMA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=tyzZuC0UGZzoVs4WRWwuIZKpSRrOjiDgK25pKlWR/W0=; b=nYjXPTJPh6DqhQFxuBvot3Y0LKeFu+fE36owmjiAezpIxj1mrKzVGUb2XNrLc9xKTn +XSUKqy9Bu5GfO6ZZ63B1FoHHehC4aN1qlycxnhQY3p03+85Ji3T7sxio2oXdEDjd/Ny I9a1m7Ssrz8UZRnGVVJc3lsuEeaT27r2mB/PxlqE8obejmqkDG4Li3UxJmK91SujEhUM WNP+H2qQELssVxY5byHRYby/lwiTGpZ1zSVdcPhMGHQEKFPYIuBhNcPnA7/p19+HBu4D eVwqAgD4C599lnGe1r2uJJL0UyZbwAo6JkaKHGrTv5VIf6US2pMjxaNp0yOuaOir51kX XKQA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=collabora.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id t1si12167304ejc.207.2020.08.04.09.28.27; Tue, 04 Aug 2020 09:28:50 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=collabora.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729985AbgHDQZ2 (ORCPT + 99 others); Tue, 4 Aug 2020 12:25:28 -0400 Received: from bhuna.collabora.co.uk ([46.235.227.227]:34188 "EHLO bhuna.collabora.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729884AbgHDQYL (ORCPT ); Tue, 4 Aug 2020 12:24:11 -0400 Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: andrzej.p) with ESMTPSA id 51D2C2950FD From: Andrzej Pietrasiewicz To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , Jiri Slaby , Dmitry Torokhov , Andrzej Pietrasiewicz , linux-input@vger.kernel.org, kernel@collabora.com Subject: [PATCH 2/2] tty/sysrq: Add configurable handler to execute a compound action Date: Tue, 4 Aug 2020 18:24:02 +0200 Message-Id: <20200804162402.2087-3-andrzej.p@collabora.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200804162402.2087-1-andrzej.p@collabora.com> References: <20200804162402.2087-1-andrzej.p@collabora.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Userland might want to execute e.g. 'w' (show blocked tasks), followed by 's' (sync), followed by 1000 ms delay and then followed by 'c' (crash) upon a single magic SysRq. Or one might want to execute the famous "Raising Elephants Is So Utterly Boring" action. This patch adds a configurable handler, triggered with 'C', for this exact purpose. The user specifies the composition of the compound action using syntax similar to getopt, where each letter corresponds to an individual action and a colon followed by a number corresponds to a delay of that many milliseconds, e.g.: ws:1000c or r:100eis:1000ub Signed-off-by: Andrzej Pietrasiewicz --- Documentation/admin-guide/sysrq.rst | 9 ++++ drivers/tty/sysrq.c | 81 ++++++++++++++++++++++++++++- include/linux/sysrq.h | 1 + 3 files changed, 90 insertions(+), 1 deletion(-) diff --git a/Documentation/admin-guide/sysrq.rst b/Documentation/admin-guide/sysrq.rst index 67dfa4c29093..80bdd8bf9636 100644 --- a/Documentation/admin-guide/sysrq.rst +++ b/Documentation/admin-guide/sysrq.rst @@ -32,6 +32,7 @@ to 1. Here is the list of possible values in /proc/sys/kernel/sysrq: 64 = 0x40 - enable signalling of processes (term, kill, oom-kill) 128 = 0x80 - allow reboot/poweroff 256 = 0x100 - allow nicing of all RT tasks + 512 = 0x200 - allow compound action You can set the value in the file by the following command:: @@ -148,6 +149,14 @@ Command Function ``z`` Dump the ftrace buffer +``C`` Execute a predefined, compound action. The action is defined with + sysrq.sysrq_compound_action module parameter, whose value contains known + command keys (except ``C`` to prevent recursion). The command keys can + be optionally followed by a colon and a number of milliseconds to wait + after executing the last action. For example: + + sysrq.sysrq_compound_action=r:100eis:1000ub + ``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 diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index 52e344bfe8c0..ffcda1316675 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -439,6 +440,15 @@ static const struct sysrq_key_op sysrq_unrt_op = { .enable_mask = SYSRQ_ENABLE_RTNICE, }; +static void sysrq_action_compound(int key); + +static struct sysrq_key_op sysrq_action_compound_op = { + .handler = sysrq_action_compound, + .help_msg = "execute-compound-action(C)", + .action_msg = "Execute compound action", + .enable_mask = SYSRQ_ENABLE_COMPOUND, +}; + /* Key Operations table and lock */ static DEFINE_SPINLOCK(sysrq_key_table_lock); @@ -501,7 +511,7 @@ static const struct sysrq_key_op *sysrq_key_table[62] = { &sysrq_ftrace_dump_op, /* z */ NULL, /* A */ NULL, /* B */ - NULL, /* C */ + &sysrq_action_compound_op, /* C */ NULL, /* D */ NULL, /* E */ NULL, /* F */ @@ -634,6 +644,7 @@ EXPORT_SYMBOL(handle_sysrq); #ifdef CONFIG_INPUT static int sysrq_reset_downtime_ms; +static char *sysrq_compound_action; /* Simple translation table for the SysRq keys */ static const unsigned char sysrq_xlate[KEY_CNT] = @@ -787,6 +798,61 @@ static void sysrq_of_get_keyreset_config(void) { } #endif +#define SYSRQ_COMPOUND_ACTION_VALIDATE 0 +#define SYSRQ_COMPOUND_ACTION_RUN 1 + +static int sysrq_process_compound_action(int pass) +{ + const char *action = sysrq_compound_action; + const struct sysrq_key_op *op_p; + int ret, delay; + + while (*action) { + op_p = __sysrq_get_key_op(*action); + if (!op_p) + return -EINVAL; + + /* Don't allow calling ourselves recursively */ + if (op_p == &sysrq_action_compound_op) + return -EINVAL; + + if (pass == SYSRQ_COMPOUND_ACTION_RUN) + __handle_sysrq(*action, false); + + if (*++action == ':') { + ret = sscanf(action++, ":%d", &delay); + if (ret < 1) /* we want at least ":[0-9]" => 1 item */ + return -EINVAL; + + while (*action >= '0' && *action <= '9') + ++action; + if (pass == SYSRQ_COMPOUND_ACTION_RUN) + mdelay(delay); + } + } + + return 0; +} + +static void sysrq_action_compound(int key) +{ + if (!sysrq_compound_action) { + pr_err("Unconfigured compound action for %s", + sysrq_action_compound_op.help_msg); + + return; + } + + if (sysrq_process_compound_action(SYSRQ_COMPOUND_ACTION_VALIDATE)) { + pr_err("Incorrect compound action %s for %s", + sysrq_compound_action, + sysrq_action_compound_op.help_msg); + + return; + } + + sysrq_process_compound_action(SYSRQ_COMPOUND_ACTION_RUN); +} static void sysrq_reinject_alt_sysrq(struct work_struct *work) { @@ -1079,8 +1145,21 @@ module_param_array_named(reset_seq, sysrq_reset_seq, sysrq_reset_seq, module_param_named(sysrq_downtime_ms, sysrq_reset_downtime_ms, int, 0644); +module_param(sysrq_compound_action, charp, 0644); +MODULE_PARM_DESC(sysrq_compound_action, + "Compound sysrq action to be executed on Alt-Shift-SysRq-C\n" + "The compound action definition consists of known SysRq action letters except 'C',\n" + "each letter can be optionally followed by a colon and a number of milliseconds to wait\n" + "after executing the last action.\n" + "Example:\n" + "To unRaw, wait 100ms, tErminate, kIll, Sync, wait 1000ms, Unmount, Boot\n" + "sysrq.sysrq_compound_action=r:100eis:1000ub"); #else +{ +} + +static void sysrq_action_compound(int key) static inline void sysrq_register_handler(void) { } diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h index 3a582ec7a2f1..6df4442f12a9 100644 --- a/include/linux/sysrq.h +++ b/include/linux/sysrq.h @@ -28,6 +28,7 @@ #define SYSRQ_ENABLE_SIGNAL 0x0040 #define SYSRQ_ENABLE_BOOT 0x0080 #define SYSRQ_ENABLE_RTNICE 0x0100 +#define SYSRQ_ENABLE_COMPOUND 0x0200 struct sysrq_key_op { void (* const handler)(int); -- 2.17.1