133 lines
4.3 KiB
Diff
133 lines
4.3 KiB
Diff
|
From 44dd1353575f9f1da93338d280e6765dc5e209cc Mon Sep 17 00:00:00 2001
|
||
|
From: Carsten Emde <C.Emde@osadl.org>
|
||
|
Date: Tue, 19 Jul 2011 13:51:17 +0100
|
||
|
Subject: [PATCH 241/365] net: sysrq via icmp
|
||
|
|
||
|
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/sysrq.txt | 11 +++++++++--
|
||
|
include/net/netns/ipv4.h | 1 +
|
||
|
net/ipv4/icmp.c | 30 ++++++++++++++++++++++++++++++
|
||
|
net/ipv4/sysctl_net_ipv4.c | 7 +++++++
|
||
|
4 files changed, 47 insertions(+), 2 deletions(-)
|
||
|
|
||
|
diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt
|
||
|
index 3a3b30ac2a75..9e0745cafbd8 100644
|
||
|
--- a/Documentation/sysrq.txt
|
||
|
+++ b/Documentation/sysrq.txt
|
||
|
@@ -59,10 +59,17 @@ On PowerPC - Press 'ALT - Print Screen (or F13) - <command key>,
|
||
|
On other - If you know of the key combos for other architectures, please
|
||
|
let me know so I can add them to this section.
|
||
|
|
||
|
-On all - write a character to /proc/sysrq-trigger. e.g.:
|
||
|
-
|
||
|
+On all - write a character to /proc/sysrq-trigger, e.g.:
|
||
|
echo t > /proc/sysrq-trigger
|
||
|
|
||
|
+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?
|
||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
'b' - Will immediately reboot the system without syncing or unmounting
|
||
|
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
|
||
|
index af1c5e7c7e94..faf4a8cd61e6 100644
|
||
|
--- a/include/net/netns/ipv4.h
|
||
|
+++ b/include/net/netns/ipv4.h
|
||
|
@@ -70,6 +70,7 @@ struct netns_ipv4 {
|
||
|
|
||
|
int sysctl_icmp_echo_ignore_all;
|
||
|
int sysctl_icmp_echo_ignore_broadcasts;
|
||
|
+ int sysctl_icmp_echo_sysrq;
|
||
|
int sysctl_icmp_ignore_bogus_error_responses;
|
||
|
int sysctl_icmp_ratelimit;
|
||
|
int sysctl_icmp_ratemask;
|
||
|
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
|
||
|
index bd6a58c725b5..c79ad4ba670a 100644
|
||
|
--- a/net/ipv4/icmp.c
|
||
|
+++ b/net/ipv4/icmp.c
|
||
|
@@ -69,6 +69,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>
|
||
|
@@ -914,6 +915,30 @@ static bool icmp_redirect(struct sk_buff *skb)
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
+/*
|
||
|
+ * 32bit and 64bit have different timestamp length, so we check for
|
||
|
+ * the cookie at offset 20 and verify 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") requests.
|
||
|
*
|
||
|
@@ -941,6 +966,11 @@ static bool icmp_echo(struct sk_buff *skb)
|
||
|
icmp_param.data_len = skb->len;
|
||
|
icmp_param.head_len = sizeof(struct icmphdr);
|
||
|
icmp_reply(&icmp_param, skb);
|
||
|
+
|
||
|
+ if (skb->len == ICMP_SYSRQ_SIZE &&
|
||
|
+ net->ipv4.sysctl_icmp_echo_sysrq) {
|
||
|
+ icmp_check_sysrq(net, skb);
|
||
|
+ }
|
||
|
}
|
||
|
/* should there be an ICMP stat for ignored echos? */
|
||
|
return true;
|
||
|
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
|
||
|
index 22436858b534..c29d8662e961 100644
|
||
|
--- a/net/ipv4/sysctl_net_ipv4.c
|
||
|
+++ b/net/ipv4/sysctl_net_ipv4.c
|
||
|
@@ -716,6 +716,13 @@ static struct ctl_table ipv4_net_table[] = {
|
||
|
.mode = 0644,
|
||
|
.proc_handler = proc_dointvec
|
||
|
},
|
||
|
+ {
|
||
|
+ .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,
|
||
|
--
|
||
|
2.28.0
|
||
|
|