From: David Stevens <[email protected]>

In preparation for partially populated kernel stacks, don't assume
that vm_area->nr_pages matches THREAD_SIZE when clearing a stack
for reuse.
Note that the VA range is still THREAD_SIZE in that case but it
might not be fully allocated.

Signed-off-by: David Stevens <[email protected]>
[Resolve conflict and updated commit msg]
Signed-off-by: Mostafa Saleh <[email protected]>
---
 kernel/fork.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/kernel/fork.c b/kernel/fork.c
index 2065693e762c..ec4431bf309a 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -335,11 +335,16 @@ static int alloc_thread_stack_node(struct task_struct 
*tsk, int node)
 
        vm_area = alloc_thread_stack_node_from_cache(tsk, node);
        if (vm_area) {
+               unsigned long offset = 0;
+
                if (memcg_charge_kernel_stack(vm_area)) {
                        vfree(vm_area->addr);
                        return -ENOMEM;
                }
 
+               if (!IS_ENABLED(CONFIG_STACK_GROWSUP))
+                       offset = THREAD_SIZE - vm_area->nr_pages * PAGE_SIZE;
+
                /* Reset stack metadata. */
                if (!kasan_hw_tags_enabled())
                        kasan_unpoison_range(vm_area->addr, THREAD_SIZE);
@@ -347,7 +352,7 @@ static int alloc_thread_stack_node(struct task_struct *tsk, 
int node)
                stack = kasan_reset_tag(vm_area->addr);
 
                /* Clear stale pointers from reused stack. */
-               clear_pages(vm_area->addr, vm_area->nr_pages);
+               clear_pages(vm_area->addr + offset, vm_area->nr_pages);
 
                tsk->stack_vm_area = vm_area;
                tsk->stack = stack;
-- 
2.56.0.rc1.315.gc6ed9934b7-goog


Reply via email to