Subject: net: sysrq via icmp From: Carsten Emde <C.Emde@osadl.org> Date: Tue, 19 Jul 2011 13:51:17 +0100 There are (probably rare) situations when a system crashed and the system console becomes unresponsive but the network icmp layer still is alive. Wouldn't it be wonderful, if we then could submit a sysreq command via ping? This patch provides this facility. Please consult the updated documentation Documentation/sysrq.txt for details. Signed-off-by: Carsten Emde <C.Emde@osadl.org> --- Documentation/admin-guide/sysrq.rst | 12 ++++++++++++ include/net/netns/ipv4.h | 1 + net/ipv4/icmp.c | 28 ++++++++++++++++++++++++++++ net/ipv4/sysctl_net_ipv4.c | 7 +++++++ 4 files changed, 48 insertions(+) Index: linux-5.15.34-rt40/Documentation/admin-guide/sysrq.rst =================================================================== --- linux-5.15.34-rt40.orig/Documentation/admin-guide/sysrq.rst +++ linux-5.15.34-rt40/Documentation/admin-guide/sysrq.rst @@ -81,6 +81,18 @@ On all The :kbd:`<command key>` is case sensitive. +On all + Enable network SysRq by writing a cookie to icmp_echo_sysrq, e.g.:: + + echo 0x01020304 >/proc/sys/net/ipv4/icmp_echo_sysrq + + Send an ICMP echo request with this pattern plus the particular + SysRq command key. Example:: + + ping -c1 -s57 -p0102030468 + + will trigger the SysRq-H (help) command. + What are the 'command' keys? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Index: linux-5.15.34-rt40/include/net/netns/ipv4.h =================================================================== --- linux-5.15.34-rt40.orig/include/net/netns/ipv4.h +++ linux-5.15.34-rt40/include/net/netns/ipv4.h @@ -80,6 +80,7 @@ struct netns_ipv4 { u8 sysctl_icmp_echo_ignore_all; u8 sysctl_icmp_echo_enable_probe; u8 sysctl_icmp_echo_ignore_broadcasts; + int sysctl_icmp_echo_sysrq; u8 sysctl_icmp_ignore_bogus_error_responses; u8 sysctl_icmp_errors_use_inbound_ifaddr; int sysctl_icmp_ratelimit; Index: linux-5.15.34-rt40/net/ipv4/icmp.c =================================================================== --- linux-5.15.34-rt40.orig/net/ipv4/icmp.c +++ linux-5.15.34-rt40/net/ipv4/icmp.c @@ -64,6 +64,7 @@ #include <linux/jiffies.h> #include <linux/kernel.h> #include <linux/fcntl.h> +#include <linux/sysrq.h> #include <linux/socket.h> #include <linux/in.h> #include <linux/inet.h> @@ -977,6 +978,29 @@ static bool icmp_redirect(struct sk_buff return true; } + /* 32bit and 64bit have different timestamp length, so we check for + * the cookie at offset 20 and verify if it is repeated at offset 50 + */ +#define CO_POS0 20 +#define CO_POS1 50 +#define CO_SIZE sizeof(int) +#define ICMP_SYSRQ_SIZE 57 + +/* + * We got a ICMP_SYSRQ_SIZE sized ping request. Check for the cookie + * pattern and if it matches send the next byte as a trigger to sysrq. + */ +static void icmp_check_sysrq(struct net *net, struct sk_buff *skb) +{ + int cookie = htonl(net->ipv4.sysctl_icmp_echo_sysrq); + char *p = skb->data; + + if (!memcmp(&cookie, p + CO_POS0, CO_SIZE) && + !memcmp(&cookie, p + CO_POS1, CO_SIZE) && + p[CO_POS0 + CO_SIZE] == p[CO_POS1 + CO_SIZE]) + handle_sysrq(p[CO_POS0 + CO_SIZE]); +} + /* * Handle ICMP_ECHO ("ping") and ICMP_EXT_ECHO ("PROBE") requests. * @@ -1012,6 +1036,10 @@ static bool icmp_echo(struct sk_buff *sk else if (!icmp_build_probe(skb, &icmp_param.data.icmph)) return true; + if (skb->len == ICMP_SYSRQ_SIZE && + net->ipv4.sysctl_icmp_echo_sysrq) + icmp_check_sysrq(net, skb); + icmp_reply(&icmp_param, skb); return true; } Index: linux-5.15.34-rt40/net/ipv4/sysctl_net_ipv4.c =================================================================== --- linux-5.15.34-rt40.orig/net/ipv4/sysctl_net_ipv4.c +++ linux-5.15.34-rt40/net/ipv4/sysctl_net_ipv4.c @@ -634,6 +634,13 @@ static struct ctl_table ipv4_net_table[] .proc_handler = proc_dou8vec_minmax, }, { + .procname = "icmp_echo_sysrq", + .data = &init_net.ipv4.sysctl_icmp_echo_sysrq, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec + }, + { .procname = "icmp_ignore_bogus_error_responses", .data = &init_net.ipv4.sysctl_icmp_ignore_bogus_error_responses, .maxlen = sizeof(u8),