* [PATCH v2 0/3] Make the scheduler stack end check selectable at boot
@ 2026-11-13 8:37 ` Chris Down
0 siblings, 0 replies; 8+ messages in thread
From: Chris Down @ 2026-11-13 8:37 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Kees Cook
Cc: Juri Lelli, Vincent Guittot, Dietmar Eggemann, Steven Rostedt,
Ben Segall, Mel Gorman, Valentin Schneider, K Prateek Nayak,
Ard Biesheuvel, Will Deacon, Sami Tolvanen, Jonathan Corbet,
Shuah Khan, Randy Dunlap, Arnd Bergmann, Greg Kroah-Hartman,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
linux-arm-kernel, linux-riscv, linux-doc, linux-kselftest,
linux-kernel, kernel-team
At Meta, some of our host types enable CONFIG_SCHED_STACK_END_CHECK, but
we don't want it generally on because of the extra work on every context
switch.
Right now this is only configurable by setting the Kconfig option at
build time. Let's make it so we can also select it at boot with
sched_stack_end_check=, so that those hosts can share one kernel image.
(Patch 1 is a cleanup I happened upon while working on this, it can
also be taken independently.)
v2:
- Check scs_is_enabled() inside task_scs_end_corrupted() rather than in
schedule_debug() (Peter)
- Return 1 when sched_stack_end_check= can't be parsed (Randy)
- Say in the changelog why the other task_stack_end_corrupted() callers
are left alone (Peter)
- Rebase onto tip/sched/core
v1: https://lore.kernel.org/r/cover.1793082868.git.chris@chrisdown.name
Chris Down (3):
scs: Skip the shadow stack end check when SCS is disabled
sched/core: Add sched_stack_end_check= boot parameter
lkdtm/bugs: Add CORRUPT_STACK_END to test the scheduler stack end
check
.../admin-guide/kernel-parameters.txt | 8 +++++
drivers/misc/lkdtm/bugs.c | 21 ++++++++++++
include/linux/scs.h | 19 ++++++-----
kernel/sched/core.c | 33 +++++++++++++++----
tools/testing/selftests/lkdtm/tests.txt | 1 +
5 files changed, 68 insertions(+), 14 deletions(-)
base-commit: d7e670601af6c564ccf6d3b2ddf70ee4f41a6d1c
--
2.56.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 0/3] Make the scheduler stack end check selectable at boot
@ 2026-11-13 8:37 ` Chris Down
0 siblings, 0 replies; 8+ messages in thread
From: Chris Down @ 2026-11-13 8:37 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Kees Cook
Cc: Juri Lelli, Vincent Guittot, Dietmar Eggemann, Steven Rostedt,
Ben Segall, Mel Gorman, Valentin Schneider, K Prateek Nayak,
Ard Biesheuvel, Will Deacon, Sami Tolvanen, Jonathan Corbet,
Shuah Khan, Randy Dunlap, Arnd Bergmann, Greg Kroah-Hartman,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
linux-arm-kernel, linux-riscv, linux-doc, linux-kselftest,
linux-kernel, kernel-team
At Meta, some of our host types enable CONFIG_SCHED_STACK_END_CHECK, but
we don't want it generally on because of the extra work on every context
switch.
Right now this is only configurable by setting the Kconfig option at
build time. Let's make it so we can also select it at boot with
sched_stack_end_check=, so that those hosts can share one kernel image.
(Patch 1 is a cleanup I happened upon while working on this, it can
also be taken independently.)
v2:
- Check scs_is_enabled() inside task_scs_end_corrupted() rather than in
schedule_debug() (Peter)
- Return 1 when sched_stack_end_check= can't be parsed (Randy)
- Say in the changelog why the other task_stack_end_corrupted() callers
are left alone (Peter)
- Rebase onto tip/sched/core
v1: https://lore.kernel.org/r/cover.1793082868.git.chris@chrisdown.name
Chris Down (3):
scs: Skip the shadow stack end check when SCS is disabled
sched/core: Add sched_stack_end_check= boot parameter
lkdtm/bugs: Add CORRUPT_STACK_END to test the scheduler stack end
check
.../admin-guide/kernel-parameters.txt | 8 +++++
drivers/misc/lkdtm/bugs.c | 21 ++++++++++++
include/linux/scs.h | 19 ++++++-----
kernel/sched/core.c | 33 +++++++++++++++----
tools/testing/selftests/lkdtm/tests.txt | 1 +
5 files changed, 68 insertions(+), 14 deletions(-)
base-commit: d7e670601af6c564ccf6d3b2ddf70ee4f41a6d1c
--
2.56.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 1/3] scs: Skip the shadow stack end check when SCS is disabled
2026-11-13 8:37 ` Chris Down
@ 2026-11-13 8:37 ` Chris Down
-1 siblings, 0 replies; 8+ messages in thread
From: Chris Down @ 2026-11-13 8:37 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Kees Cook
Cc: Juri Lelli, Vincent Guittot, Dietmar Eggemann, Steven Rostedt,
Ben Segall, Mel Gorman, Valentin Schneider, K Prateek Nayak,
Ard Biesheuvel, Will Deacon, Sami Tolvanen, Jonathan Corbet,
Shuah Khan, Randy Dunlap, Arnd Bergmann, Greg Kroah-Hartman,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
linux-arm-kernel, linux-riscv, linux-doc, linux-kselftest,
linux-kernel, kernel-team
With CONFIG_DYNAMIC_SCS, shadow call stacks are only used when the boot
CPU lacks pointer authentication. scs_release() already checks
scs_is_enabled() before it looks at the shadow stack since commit
9beccca09840 ("scs: add support for dynamic shadow call stacks"), but
schedule_debug() does not.
With CONFIG_SCHED_STACK_END_CHECK=y it therefore checks init_task's
unused shadow stack on every context switch. That is harmless right now,
but the check is redundant and costs a load from an unrelated cache line
in __schedule().
Make task_scs_end_corrupted() check scs_is_enabled() itself. It is a
static branch, and it folds to true when CONFIG_DYNAMIC_SCS is not set.
Signed-off-by: Chris Down <chris@chrisdown.name>
---
include/linux/scs.h | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/include/linux/scs.h b/include/linux/scs.h
index 4ab5bdc898cf..29ec2b8cf7bf 100644
--- a/include/linux/scs.h
+++ b/include/linux/scs.h
@@ -45,14 +45,6 @@ static inline unsigned long *__scs_magic(void *s)
return (unsigned long *)(s + SCS_SIZE) - 1;
}
-static inline bool task_scs_end_corrupted(struct task_struct *tsk)
-{
- unsigned long *magic = __scs_magic(task_scs(tsk));
- unsigned long sz = task_scs_sp(tsk) - task_scs(tsk);
-
- return sz >= SCS_SIZE - 1 || READ_ONCE_NOCHECK(*magic) != SCS_END_MAGIC;
-}
-
DECLARE_STATIC_KEY_FALSE(dynamic_scs_enabled);
static inline bool scs_is_dynamic(void)
@@ -69,6 +61,17 @@ static inline bool scs_is_enabled(void)
return scs_is_dynamic();
}
+static inline bool task_scs_end_corrupted(struct task_struct *tsk)
+{
+ unsigned long *magic = __scs_magic(task_scs(tsk));
+ unsigned long sz = task_scs_sp(tsk) - task_scs(tsk);
+
+ if (!scs_is_enabled())
+ return false;
+
+ return sz >= SCS_SIZE - 1 || READ_ONCE_NOCHECK(*magic) != SCS_END_MAGIC;
+}
+
#else /* CONFIG_SHADOW_CALL_STACK */
static inline void *scs_alloc(int node) { return NULL; }
--
2.56.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 1/3] scs: Skip the shadow stack end check when SCS is disabled
@ 2026-11-13 8:37 ` Chris Down
0 siblings, 0 replies; 8+ messages in thread
From: Chris Down @ 2026-11-13 8:37 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Kees Cook
Cc: Juri Lelli, Vincent Guittot, Dietmar Eggemann, Steven Rostedt,
Ben Segall, Mel Gorman, Valentin Schneider, K Prateek Nayak,
Ard Biesheuvel, Will Deacon, Sami Tolvanen, Jonathan Corbet,
Shuah Khan, Randy Dunlap, Arnd Bergmann, Greg Kroah-Hartman,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
linux-arm-kernel, linux-riscv, linux-doc, linux-kselftest,
linux-kernel, kernel-team
With CONFIG_DYNAMIC_SCS, shadow call stacks are only used when the boot
CPU lacks pointer authentication. scs_release() already checks
scs_is_enabled() before it looks at the shadow stack since commit
9beccca09840 ("scs: add support for dynamic shadow call stacks"), but
schedule_debug() does not.
With CONFIG_SCHED_STACK_END_CHECK=y it therefore checks init_task's
unused shadow stack on every context switch. That is harmless right now,
but the check is redundant and costs a load from an unrelated cache line
in __schedule().
Make task_scs_end_corrupted() check scs_is_enabled() itself. It is a
static branch, and it folds to true when CONFIG_DYNAMIC_SCS is not set.
Signed-off-by: Chris Down <chris@chrisdown.name>
---
include/linux/scs.h | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/include/linux/scs.h b/include/linux/scs.h
index 4ab5bdc898cf..29ec2b8cf7bf 100644
--- a/include/linux/scs.h
+++ b/include/linux/scs.h
@@ -45,14 +45,6 @@ static inline unsigned long *__scs_magic(void *s)
return (unsigned long *)(s + SCS_SIZE) - 1;
}
-static inline bool task_scs_end_corrupted(struct task_struct *tsk)
-{
- unsigned long *magic = __scs_magic(task_scs(tsk));
- unsigned long sz = task_scs_sp(tsk) - task_scs(tsk);
-
- return sz >= SCS_SIZE - 1 || READ_ONCE_NOCHECK(*magic) != SCS_END_MAGIC;
-}
-
DECLARE_STATIC_KEY_FALSE(dynamic_scs_enabled);
static inline bool scs_is_dynamic(void)
@@ -69,6 +61,17 @@ static inline bool scs_is_enabled(void)
return scs_is_dynamic();
}
+static inline bool task_scs_end_corrupted(struct task_struct *tsk)
+{
+ unsigned long *magic = __scs_magic(task_scs(tsk));
+ unsigned long sz = task_scs_sp(tsk) - task_scs(tsk);
+
+ if (!scs_is_enabled())
+ return false;
+
+ return sz >= SCS_SIZE - 1 || READ_ONCE_NOCHECK(*magic) != SCS_END_MAGIC;
+}
+
#else /* CONFIG_SHADOW_CALL_STACK */
static inline void *scs_alloc(int node) { return NULL; }
--
2.56.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 2/3] sched/core: Add sched_stack_end_check= boot parameter
2026-11-13 8:37 ` Chris Down
@ 2026-11-13 8:37 ` Chris Down
-1 siblings, 0 replies; 8+ messages in thread
From: Chris Down @ 2026-11-13 8:37 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Kees Cook
Cc: Juri Lelli, Vincent Guittot, Dietmar Eggemann, Steven Rostedt,
Ben Segall, Mel Gorman, Valentin Schneider, K Prateek Nayak,
Ard Biesheuvel, Will Deacon, Sami Tolvanen, Jonathan Corbet,
Shuah Khan, Randy Dunlap, Arnd Bergmann, Greg Kroah-Hartman,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
linux-arm-kernel, linux-riscv, linux-doc, linux-kselftest,
linux-kernel, kernel-team
CONFIG_SCHED_STACK_END_CHECK makes schedule_debug() check the magic at
the end of the outgoing task's stack and panic if it has been
overwritten.
Right now this can only be configured by setting the Kconfig option at
build time. At Meta we have it on for some hosts and off for others,
since it is helpful but adds cost on context switching. That means today
we have to build separate kernels for each, which is less than ideal.
Make this configurable at boot time with sched_stack_end_check=, and
keep the Kconfig option as its default. In benchmarking sched pipe and
sched messaging performance is unaffected.
The other callers of task_stack_end_corrupted() are left as they are.
They have never depended on CONFIG_SCHED_STACK_END_CHECK, and they only
look at the magic once an oops or a might_sleep() report is already
being printed, or when the stack tracer records a new maximum.
Signed-off-by: Chris Down <chris@chrisdown.name>
---
.../admin-guide/kernel-parameters.txt | 8 +++++
kernel/sched/core.c | 33 +++++++++++++++----
2 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 0b3c140babd9..c106f744b5a4 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -6825,6 +6825,14 @@ Kernel parameters
core priority to both SMT siblings, so this option
does not favor either sibling.
+ sched_stack_end_check= [KNL]
+ Format: <bool>
+ Check the magic value at the end of the outgoing
+ task's stack (and its shadow call stack, if any) on
+ every call to schedule(), and panic if it has been
+ overwritten.
+ Default set by CONFIG_SCHED_STACK_END_CHECK.
+
sched_verbose [KNL,EARLY] Enables verbose scheduler debug messages.
schedstats= [KNL,X86] Enable or disable scheduled statistics.
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 175b52a7ea79..9e5b3c62c697 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -6144,18 +6144,39 @@ static noinline void __schedule_bug(struct task_struct *prev)
add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
}
+static DEFINE_STATIC_KEY_MAYBE_RO(CONFIG_SCHED_STACK_END_CHECK, sched_stack_end_check);
+
+static int __init setup_sched_stack_end_check(char *str)
+{
+ bool enable;
+
+ if (kstrtobool(str, &enable)) {
+ pr_warn("Unable to parse sched_stack_end_check=\n");
+ return 1;
+ }
+
+ if (enable)
+ static_branch_enable(&sched_stack_end_check);
+ else
+ static_branch_disable(&sched_stack_end_check);
+
+ return 1;
+}
+__setup("sched_stack_end_check=", setup_sched_stack_end_check);
+
/*
* Various schedule()-time debugging checks and statistics:
*/
static inline void schedule_debug(struct task_struct *prev, bool preempt)
{
-#ifdef CONFIG_SCHED_STACK_END_CHECK
- if (task_stack_end_corrupted(prev))
- panic("corrupted stack end detected inside scheduler\n");
+ if (static_branch_maybe(CONFIG_SCHED_STACK_END_CHECK,
+ &sched_stack_end_check)) {
+ if (task_stack_end_corrupted(prev))
+ panic("corrupted stack end detected inside scheduler\n");
- if (task_scs_end_corrupted(prev))
- panic("corrupted shadow stack detected inside scheduler\n");
-#endif
+ if (task_scs_end_corrupted(prev))
+ panic("corrupted shadow stack detected inside scheduler\n");
+ }
#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
if (!preempt && READ_ONCE(prev->__state) && prev->non_block_count) {
--
2.56.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 2/3] sched/core: Add sched_stack_end_check= boot parameter
@ 2026-11-13 8:37 ` Chris Down
0 siblings, 0 replies; 8+ messages in thread
From: Chris Down @ 2026-11-13 8:37 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Kees Cook
Cc: Juri Lelli, Vincent Guittot, Dietmar Eggemann, Steven Rostedt,
Ben Segall, Mel Gorman, Valentin Schneider, K Prateek Nayak,
Ard Biesheuvel, Will Deacon, Sami Tolvanen, Jonathan Corbet,
Shuah Khan, Randy Dunlap, Arnd Bergmann, Greg Kroah-Hartman,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
linux-arm-kernel, linux-riscv, linux-doc, linux-kselftest,
linux-kernel, kernel-team
CONFIG_SCHED_STACK_END_CHECK makes schedule_debug() check the magic at
the end of the outgoing task's stack and panic if it has been
overwritten.
Right now this can only be configured by setting the Kconfig option at
build time. At Meta we have it on for some hosts and off for others,
since it is helpful but adds cost on context switching. That means today
we have to build separate kernels for each, which is less than ideal.
Make this configurable at boot time with sched_stack_end_check=, and
keep the Kconfig option as its default. In benchmarking sched pipe and
sched messaging performance is unaffected.
The other callers of task_stack_end_corrupted() are left as they are.
They have never depended on CONFIG_SCHED_STACK_END_CHECK, and they only
look at the magic once an oops or a might_sleep() report is already
being printed, or when the stack tracer records a new maximum.
Signed-off-by: Chris Down <chris@chrisdown.name>
---
.../admin-guide/kernel-parameters.txt | 8 +++++
kernel/sched/core.c | 33 +++++++++++++++----
2 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 0b3c140babd9..c106f744b5a4 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -6825,6 +6825,14 @@ Kernel parameters
core priority to both SMT siblings, so this option
does not favor either sibling.
+ sched_stack_end_check= [KNL]
+ Format: <bool>
+ Check the magic value at the end of the outgoing
+ task's stack (and its shadow call stack, if any) on
+ every call to schedule(), and panic if it has been
+ overwritten.
+ Default set by CONFIG_SCHED_STACK_END_CHECK.
+
sched_verbose [KNL,EARLY] Enables verbose scheduler debug messages.
schedstats= [KNL,X86] Enable or disable scheduled statistics.
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 175b52a7ea79..9e5b3c62c697 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -6144,18 +6144,39 @@ static noinline void __schedule_bug(struct task_struct *prev)
add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
}
+static DEFINE_STATIC_KEY_MAYBE_RO(CONFIG_SCHED_STACK_END_CHECK, sched_stack_end_check);
+
+static int __init setup_sched_stack_end_check(char *str)
+{
+ bool enable;
+
+ if (kstrtobool(str, &enable)) {
+ pr_warn("Unable to parse sched_stack_end_check=\n");
+ return 1;
+ }
+
+ if (enable)
+ static_branch_enable(&sched_stack_end_check);
+ else
+ static_branch_disable(&sched_stack_end_check);
+
+ return 1;
+}
+__setup("sched_stack_end_check=", setup_sched_stack_end_check);
+
/*
* Various schedule()-time debugging checks and statistics:
*/
static inline void schedule_debug(struct task_struct *prev, bool preempt)
{
-#ifdef CONFIG_SCHED_STACK_END_CHECK
- if (task_stack_end_corrupted(prev))
- panic("corrupted stack end detected inside scheduler\n");
+ if (static_branch_maybe(CONFIG_SCHED_STACK_END_CHECK,
+ &sched_stack_end_check)) {
+ if (task_stack_end_corrupted(prev))
+ panic("corrupted stack end detected inside scheduler\n");
- if (task_scs_end_corrupted(prev))
- panic("corrupted shadow stack detected inside scheduler\n");
-#endif
+ if (task_scs_end_corrupted(prev))
+ panic("corrupted shadow stack detected inside scheduler\n");
+ }
#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
if (!preempt && READ_ONCE(prev->__state) && prev->non_block_count) {
--
2.56.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 3/3] lkdtm/bugs: Add CORRUPT_STACK_END to test the scheduler stack end check
2026-11-13 8:37 ` Chris Down
@ 2026-11-13 8:37 ` Chris Down
-1 siblings, 0 replies; 8+ messages in thread
From: Chris Down @ 2026-11-13 8:37 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Kees Cook
Cc: Juri Lelli, Vincent Guittot, Dietmar Eggemann, Steven Rostedt,
Ben Segall, Mel Gorman, Valentin Schneider, K Prateek Nayak,
Ard Biesheuvel, Will Deacon, Sami Tolvanen, Jonathan Corbet,
Shuah Khan, Randy Dunlap, Arnd Bergmann, Greg Kroah-Hartman,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
linux-arm-kernel, linux-riscv, linux-doc, linux-kselftest,
linux-kernel, kernel-team
There's no existing test for the stack end check in schedule(), so add
one.
CORRUPT_STACK_END overwrites the magic at the end of the current task's
stack and then calls schedule(). That should panic when the check is
enabled. When it isn't, the test restores the magic and uses
pr_expected_config_param() to say whether that was expected.
Signed-off-by: Chris Down <chris@chrisdown.name>
---
drivers/misc/lkdtm/bugs.c | 21 +++++++++++++++++++++
tools/testing/selftests/lkdtm/tests.txt | 1 +
2 files changed, 22 insertions(+)
diff --git a/drivers/misc/lkdtm/bugs.c b/drivers/misc/lkdtm/bugs.c
index 2761685cf4f8..a39cde7495d3 100644
--- a/drivers/misc/lkdtm/bugs.c
+++ b/drivers/misc/lkdtm/bugs.c
@@ -215,6 +215,26 @@ static noinline void lkdtm_CORRUPT_STACK_STRONG(void)
__lkdtm_CORRUPT_STACK((void *)&data);
}
+static void lkdtm_CORRUPT_STACK_END(void)
+{
+ unsigned long *stack_end = end_of_stack(current);
+
+ if (READ_ONCE(*stack_end) != STACK_END_MAGIC) {
+ pr_err("FAIL: stack end magic is already corrupted\n");
+ return;
+ }
+
+ pr_info("Corrupting stack end magic and calling schedule() ...\n");
+ WRITE_ONCE(*stack_end, ~STACK_END_MAGIC);
+ schedule_timeout_uninterruptible(1);
+
+ /* Still alive, so let's restore the magic so nothing else trips over it. */
+ WRITE_ONCE(*stack_end, STACK_END_MAGIC);
+ pr_err("FAIL: corrupted stack end was not detected by the scheduler\n");
+ pr_expected_config_param(CONFIG_SCHED_STACK_END_CHECK,
+ "sched_stack_end_check");
+}
+
static pid_t stack_pid;
static unsigned long stack_addr;
@@ -885,6 +905,7 @@ static struct crashtype crashtypes[] = {
CRASHTYPE(EXHAUST_STACK),
CRASHTYPE(CORRUPT_STACK),
CRASHTYPE(CORRUPT_STACK_STRONG),
+ CRASHTYPE(CORRUPT_STACK_END),
CRASHTYPE(REPORT_STACK),
CRASHTYPE(REPORT_STACK_CANARY),
CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE),
diff --git a/tools/testing/selftests/lkdtm/tests.txt b/tools/testing/selftests/lkdtm/tests.txt
index bec57a02913a..2d856ed77a64 100644
--- a/tools/testing/selftests/lkdtm/tests.txt
+++ b/tools/testing/selftests/lkdtm/tests.txt
@@ -10,6 +10,7 @@ EXCEPTION
#EXHAUST_STACK Corrupts memory on failure
#CORRUPT_STACK Crashes entire system on success
#CORRUPT_STACK_STRONG Crashes entire system on success
+#CORRUPT_STACK_END Crashes entire system on success
ARRAY_BOUNDS call trace:|UBSAN: array-index-out-of-bounds
FAM_BOUNDS call trace:|UBSAN: array-index-out-of-bounds
PTR_BOUNDS call trace:|UBSAN: array-index-out-of-bounds
--
2.56.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 3/3] lkdtm/bugs: Add CORRUPT_STACK_END to test the scheduler stack end check
@ 2026-11-13 8:37 ` Chris Down
0 siblings, 0 replies; 8+ messages in thread
From: Chris Down @ 2026-11-13 8:37 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Kees Cook
Cc: Juri Lelli, Vincent Guittot, Dietmar Eggemann, Steven Rostedt,
Ben Segall, Mel Gorman, Valentin Schneider, K Prateek Nayak,
Ard Biesheuvel, Will Deacon, Sami Tolvanen, Jonathan Corbet,
Shuah Khan, Randy Dunlap, Arnd Bergmann, Greg Kroah-Hartman,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
linux-arm-kernel, linux-riscv, linux-doc, linux-kselftest,
linux-kernel, kernel-team
There's no existing test for the stack end check in schedule(), so add
one.
CORRUPT_STACK_END overwrites the magic at the end of the current task's
stack and then calls schedule(). That should panic when the check is
enabled. When it isn't, the test restores the magic and uses
pr_expected_config_param() to say whether that was expected.
Signed-off-by: Chris Down <chris@chrisdown.name>
---
drivers/misc/lkdtm/bugs.c | 21 +++++++++++++++++++++
tools/testing/selftests/lkdtm/tests.txt | 1 +
2 files changed, 22 insertions(+)
diff --git a/drivers/misc/lkdtm/bugs.c b/drivers/misc/lkdtm/bugs.c
index 2761685cf4f8..a39cde7495d3 100644
--- a/drivers/misc/lkdtm/bugs.c
+++ b/drivers/misc/lkdtm/bugs.c
@@ -215,6 +215,26 @@ static noinline void lkdtm_CORRUPT_STACK_STRONG(void)
__lkdtm_CORRUPT_STACK((void *)&data);
}
+static void lkdtm_CORRUPT_STACK_END(void)
+{
+ unsigned long *stack_end = end_of_stack(current);
+
+ if (READ_ONCE(*stack_end) != STACK_END_MAGIC) {
+ pr_err("FAIL: stack end magic is already corrupted\n");
+ return;
+ }
+
+ pr_info("Corrupting stack end magic and calling schedule() ...\n");
+ WRITE_ONCE(*stack_end, ~STACK_END_MAGIC);
+ schedule_timeout_uninterruptible(1);
+
+ /* Still alive, so let's restore the magic so nothing else trips over it. */
+ WRITE_ONCE(*stack_end, STACK_END_MAGIC);
+ pr_err("FAIL: corrupted stack end was not detected by the scheduler\n");
+ pr_expected_config_param(CONFIG_SCHED_STACK_END_CHECK,
+ "sched_stack_end_check");
+}
+
static pid_t stack_pid;
static unsigned long stack_addr;
@@ -885,6 +905,7 @@ static struct crashtype crashtypes[] = {
CRASHTYPE(EXHAUST_STACK),
CRASHTYPE(CORRUPT_STACK),
CRASHTYPE(CORRUPT_STACK_STRONG),
+ CRASHTYPE(CORRUPT_STACK_END),
CRASHTYPE(REPORT_STACK),
CRASHTYPE(REPORT_STACK_CANARY),
CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE),
diff --git a/tools/testing/selftests/lkdtm/tests.txt b/tools/testing/selftests/lkdtm/tests.txt
index bec57a02913a..2d856ed77a64 100644
--- a/tools/testing/selftests/lkdtm/tests.txt
+++ b/tools/testing/selftests/lkdtm/tests.txt
@@ -10,6 +10,7 @@ EXCEPTION
#EXHAUST_STACK Corrupts memory on failure
#CORRUPT_STACK Crashes entire system on success
#CORRUPT_STACK_STRONG Crashes entire system on success
+#CORRUPT_STACK_END Crashes entire system on success
ARRAY_BOUNDS call trace:|UBSAN: array-index-out-of-bounds
FAM_BOUNDS call trace:|UBSAN: array-index-out-of-bounds
PTR_BOUNDS call trace:|UBSAN: array-index-out-of-bounds
--
2.56.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-11-13 8:38 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-13 8:37 [PATCH v2 0/3] Make the scheduler stack end check selectable at boot Chris Down
2026-11-13 8:37 ` Chris Down
2026-11-13 8:37 ` [PATCH v2 1/3] scs: Skip the shadow stack end check when SCS is disabled Chris Down
2026-11-13 8:37 ` Chris Down
2026-11-13 8:37 ` [PATCH v2 2/3] sched/core: Add sched_stack_end_check= boot parameter Chris Down
2026-11-13 8:37 ` Chris Down
2026-11-13 8:37 ` [PATCH v2 3/3] lkdtm/bugs: Add CORRUPT_STACK_END to test the scheduler stack end check Chris Down
2026-11-13 8:37 ` Chris Down
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.