Re: [PATCH 2/3] sched/core: Add sched_stack_end_check= boot parameter

From: Peter Zijlstra

Date: Tue Oct 27 2026 - 06:18:04 EST


On Tue, Oct 27, 2026 at 02:36:21PM +0800, Chris Down wrote:
> 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.
>
> So let's make this configurable at boot time. In benchmarking sched pipe
> and sched messaging performance is unaffected.
>
> Signed-off-by: Chris Down <chris@xxxxxxxxxxxxxx>
> ---
> .../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 fbee7b544903..95911d33c0fe 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -6811,6 +6811,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 fc269fd10192..c1fb86b813bb 100644
> --- a/kernel/sched/core.c
> +++ b/kernel/sched/core.c
> @@ -6143,18 +6143,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 0;
> + }
> +
> + 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 (scs_is_enabled() && task_scs_end_corrupted(prev))
> - panic("corrupted shadow stack detected inside scheduler\n");
> -#endif
> + if (scs_is_enabled() && task_scs_end_corrupted(prev))
> + panic("corrupted shadow stack detected inside scheduler\n");
> + }

I just noticed that there's a number of task_stack_end_corrupted()
checks that:

- do not also do task_scs_end_corrupted(); should
task_scs_end_corrupted() be put inside task_stack_end_corrupted() to
make sure they're always done in tandem and the shadow stack check
isn't lost?

- should these other sites also respect this switch? It seems weird to
only have this one site affected.