[PATCH] do_exit(): panic() when double fault detected

From: Vladimir Kondratiev
Date: Sun Dec 06 2020 - 08:12:32 EST


Double fault detected in do_exit() is symptom of integrity
compromised. For safety critical systems, it may be better to
panic() in this case to minimize risk.

Signed-off-by: Vladimir Kondratiev <vladimir.kondratiev@xxxxxxxxx>
---
Documentation/admin-guide/kernel-parameters.txt | 5 +++++
include/linux/kernel.h | 1 +
kernel/exit.c | 7 +++++++
kernel/sysctl.c | 9 +++++++++
4 files changed, 22 insertions(+)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 44fde25bb221..6cb2a63c47f3 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -3521,6 +3521,11 @@
extra details on the taint flags that users can pick
to compose the bitmask to assign to panic_on_taint.

+ panic_on_double_fault
+ panic() when double fault detected in do_exit().
+ Useful on safety critical systems; double fault is
+ a symptom of kernel integrity compromised.
+
panic_on_warn panic() instead of WARN(). Useful to cause kdump
on a WARN().

diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 2f05e9128201..0d8822259a36 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -539,6 +539,7 @@ extern int sysctl_panic_on_rcu_stall;
extern int sysctl_panic_on_stackoverflow;

extern bool crash_kexec_post_notifiers;
+extern int panic_on_double_fault;

/*
* panic_cpu is used for synchronizing panic() and crash_kexec() execution. It
diff --git a/kernel/exit.c b/kernel/exit.c
index 1f236ed375f8..e67ae43644f9 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -68,6 +68,9 @@
#include <asm/unistd.h>
#include <asm/mmu_context.h>

+int panic_on_double_fault __read_mostly;
+core_param(panic_on_double_fault, panic_on_double_fault, int, 0644);
+
static void __unhash_process(struct task_struct *p, bool group_dead)
{
nr_threads--;
@@ -757,6 +760,10 @@ void __noreturn do_exit(long code)
*/
if (unlikely(tsk->flags & PF_EXITING)) {
pr_alert("Fixing recursive fault but reboot is needed!\n");
+ if (panic_on_double_fault)
+ panic("Double fault detected in %s[%d]\n",
+ current->comm, task_pid_nr(current));
+
futex_exit_recursive(tsk);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule();
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index afad085960b8..869a2ca41e8e 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -2600,6 +2600,15 @@ static struct ctl_table kern_table[] = {
.extra2 = &one_thousand,
},
#endif
+ {
+ .procname = "panic_on_double_fault",
+ .data = &panic_on_double_fault,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = SYSCTL_ZERO,
+ .extra2 = SYSCTL_ONE,
+ },
{
.procname = "panic_on_warn",
.data = &panic_on_warn,
--
2.27.0

---------------------------------------------------------------------
Intel Israel (74) Limited

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.