This commit introduces a new Kconfig option, CONFIG_MAGIC_SYSRQ_CRASH_ONLY,
which allows for a significant hardening of the system by restricting
the Magic SysRq functionality at compile time.
Security Impact:
- Reduces attack surface by disabling non-essential SysRq commands
- Maintains critical crash-dump capability required for debugging
- Eliminates runtime configuration vulnerabilities
When CONFIG_MAGIC_SYSRQ_CRASH_ONLY is enabled:
1. Restricted Commands: Only the 'c' (trigger a system crash/dump)
SysRq command remains operational. All other built-in SysRq commands
(e.g., reboot, sync, show-memory, SAK) are disabled.
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -584,7 +620,6 @@ void __handle_sysrq(u8 key, bool check_mask)
{
const struct sysrq_key_op *op_p;
int orig_suppress_printk;
- int i;
orig_suppress_printk = suppress_printk;
suppress_printk = 0;
@@ -599,7 +634,15 @@ void __handle_sysrq(u8 key, bool check_mask)
*/
printk_force_console_enter();
+#ifdef CONFIG_MAGIC_SYSRQ_CRASH_ONLY
+ if (key != 'c') { /* In CRASH_ONLY mode, only 'c' is considered */
+ op_p = NULL;
+ } else {
+ op_p = __sysrq_get_key_op(key);
+ }
+#else
op_p = __sysrq_get_key_op(key);
+#endif
if (op_p) {...
/*
* Should we check for enabled operations (/proc/sysrq-trigger
@@ -1104,6 +1157,10 @@ static inline void sysrq_unregister_handler(void)
int sysrq_toggle_support(int enable_mask)
{
+#ifdef CONFIG_MAGIC_SYSRQ_CRASH_ONLY
+ pr_warn("SysRq: CONFIG_MAGIC_SYSRQ_CRASH_ONLY is set. Runtime toggle is not allowed.\n");
+ return -EPERM;...
+#else
bool was_enabled = sysrq_on();
sysrq_enabled = enable_mask;
@@ -1145,12 +1203,30 @@ static int __sysrq_swap_key_ops(u8 key, const struct sysrq_key_op *insert_op_p,
int register_sysrq_key(u8 key, const struct sysrq_key_op *op_p)
{
+#ifdef CONFIG_MAGIC_SYSRQ_CRASH_ONLY
+ /*
+ * In CRASH_ONLY mode, do not allow registering new SysRq ops.
+ */
+ pr_warn("SysRq: CONFIG_MAGIC_SYSRQ_CRASH_ONLY is set. Cannot register new SysRq key '%c'.\n", key);
+ return -EPERM;
+#endif
return __sysrq_swap_key_ops(key, op_p, NULL);
}
EXPORT_SYMBOL(register_sysrq_key);
int unregister_sysrq_key(u8 key, const struct sysrq_key_op *op_p)
{
+#ifdef CONFIG_MAGIC_SYSRQ_CRASH_ONLY
+ /*
+ * In CRASH_ONLY mode, do not allow unregistering the crash op.
+ * Other ops should be NULL anyway due to sysrq_init_crash_only_table.
+ */
+ if (op_p == &sysrq_crash_op) {
+ pr_warn("SysRq: CONFIG_MAGIC_SYSRQ_CRASH_ONLY is set. Cannot unregister the crash SysRq key '%c'.\n", key);
+ return -EPERM;
+ }
+ return -EPERM; /* Attempt to unregister anything else is also an error */
+#endif
return __sysrq_swap_key_ops(key, NULL, op_p);
}
EXPORT_SYMBOL(unregister_sysrq_key);
@@ -1209,6 +1285,7 @@ static inline void sysrq_init_procfs(void)
static int __init sysrq_init(void)
{
sysrq_init_procfs();
+ sysrq_init_crash_only_table();
if (sysrq_on())
sysrq_register_handler();
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index ebe33181b6e6..c05b80cfb8aa 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -640,6 +640,19 @@ config MAGIC_SYSRQ_DEFAULT_ENABLE
This may be set to 1 or 0 to enable or disable them all, or
to a bitmask as described in Documentation/admin-guide/sysrq.rst.
+config MAGIC_SYSRQ_CRASH_ONLY
+ bool "Restrict Magic SysRq to crash command only"
+ depends on MAGIC_SYSRQ
+ default n
+ help
+ If you say Y here, the Magic SysRq key functionality will be
+ severely restricted at compile time. Only the 'c' command (trigger
+ a system crash) will be available. All other SysRq commands will be
+ disabled, and no new SysRq commands can be registered at runtime.
+ The /proc/sys/kernel/sysrq setting will be ineffective for
+ non-crash commands, and attempts to change it may be blocked.
+ This is a security hardening option.