[RFC][PATCH 07/24] kernel/fork: Clear shadow stacks alongside normal stacks
From: Dave Hansen
Date: Wed Oct 21 2026 - 15:52:43 EST
The old stack clear does not work for shadow stacks work because the
shadow stack page is not writeable via the vmalloc() mapping. It has
shadow stack permissions after all.
Use the 'vm_struct' for the vmap'ing to find the struct page for
the shadow stack and clear it via the direct map alias.
This should all compile back to the old clear_pages() if shadow
stacks are not supported.
This also only supports a single shadow stack page for now. It's
obviously not rocket science to add a loop, but leave it as simple
as possible for now since x86 has a single shadow stack page.
---
b/kernel/fork.c | 25 +++++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff -puN kernel/fork.c~generic-clear-stack-area kernel/fork.c
--- a/kernel/fork.c~generic-clear-stack-area 2026-10-21 12:36:35.657876714 -0700
+++ b/kernel/fork.c 2026-10-21 12:36:35.660876720 -0700
@@ -345,6 +345,28 @@ static void *__vmalloc_thread_stack_node
return tu;
}
+static inline void clear_stack_area(struct vm_struct *vm_area)
+{
+ union thread_union *tu = vm_area->addr;
+
+ int nr_stack_pages = sizeof(tu->stacks.stack) / PAGE_SIZE;
+ int nr_shstk_pages = sizeof(tu->stacks.shadow_stack) / PAGE_SIZE;
+
+ /* Clear stale pointers from reused stack. */
+ clear_pages(&tu->stacks.stack, nr_stack_pages);
+
+ if (!nr_shstk_pages || !arch_kernel_shstk_enabled())
+ return;
+ /*
+ * Clear the shadow stack page too, but via its direct map
+ * alias. Note that the shadow stack is right after the
+ * regular stack, so the nr_stack_pages'th page is the
+ * first shadow stack page.
+ */
+ BUILD_BUG_ON(nr_shstk_pages && nr_shstk_pages > 1);
+ clear_highpage(vm_area->pages[nr_stack_pages]);
+}
+
static int alloc_thread_stack_node(struct task_struct *tsk, int node)
{
struct vm_struct *vm_area;
@@ -363,8 +385,7 @@ static int alloc_thread_stack_node(struc
stack = kasan_reset_tag(vm_area->addr);
- /* Clear stale pointers from reused stack. */
- clear_pages(vm_area->addr, vm_area->nr_pages);
+ clear_stack_area(vm_area);
tsk->stack_vm_area = vm_area;
tsk->stack = stack;
_