From a2b06232caa794788896393311f5681e27ca632b Mon Sep 17 00:00:00 2001 From: Cheng Lingfei Date: Sat, 30 May 2026 22:22:30 +0800 Subject: [PATCH] lkl: make object_is_on_stack() check host thread stacks object_is_on_stack() assumes that task_stack_page(current) describes the stack currently used for execution. That is not true for lkl: task->stack contains the LKL thread_info allocation, while kernel code actually runs on the host thread stack. As a result, stack-allocated kernel buffers on LKL are not detected as being on-stack. Callers such as blk_rq_map_kern() can then take the direct mapping path and eventually call virt_to_page() on a host stack address, which is not part of the kernel linear map. Allow architectures to override the stack range check by providing arch_object_is_on_stack() via __HAVE_ARCH_OBJECT_IS_ON_STACK, while keeping the KASAN tag reset in the generic object_is_on_stack() helper. Implement the LKL override using lkl_ops->thread_stack(), which returns the current host thread stack base and size when the host provides it. This lets all object_is_on_stack() callers handle LKL host-stack buffers correctly, without adding a block-layer-specific workaround. Signed-off-by: Cheng Lingfei --- arch/lkl/include/asm/thread_info.h | 17 +++++++++++++++++ include/linux/sched/task_stack.h | 7 +++++++ 2 files changed, 24 insertions(+) diff --git a/arch/lkl/include/asm/thread_info.h b/arch/lkl/include/asm/thread_info.h index ae6df8f77f5e2e..1b23d96c741a39 100644 --- a/arch/lkl/include/asm/thread_info.h +++ b/arch/lkl/include/asm/thread_info.h @@ -8,6 +8,23 @@ #include #include +#define __HAVE_ARCH_OBJECT_IS_ON_STACK +static inline int arch_object_is_on_stack(const void *obj) +{ + unsigned long addr = (unsigned long)obj; + unsigned long stack_size; + unsigned long stack; + + if (!lkl_ops || !lkl_ops->thread_stack) + return 0; + + stack = (unsigned long)lkl_ops->thread_stack(&stack_size); + if (!stack) + return 0; + + return addr >= stack && addr - stack < stack_size; +} + struct thread_info { struct task_struct *task; unsigned long flags; diff --git a/include/linux/sched/task_stack.h b/include/linux/sched/task_stack.h index 6c2fef89a4fdb5..ab25a50affe0a8 100644 --- a/include/linux/sched/task_stack.h +++ b/include/linux/sched/task_stack.h @@ -88,10 +88,17 @@ void exit_task_stack_account(struct task_struct *tsk); static inline int object_is_on_stack(const void *obj) { +#ifndef __HAVE_ARCH_OBJECT_IS_ON_STACK void *stack = task_stack_page(current); +#endif obj = kasan_reset_tag(obj); + +#ifdef __HAVE_ARCH_OBJECT_IS_ON_STACK + return arch_object_is_on_stack(obj); +#else return (obj >= stack) && (obj < (stack + THREAD_SIZE)); +#endif } extern void thread_stack_cache_init(void);