1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 268db0cf1SIngo Molnar #ifndef _LINUX_SCHED_TASK_STACK_H 368db0cf1SIngo Molnar #define _LINUX_SCHED_TASK_STACK_H 468db0cf1SIngo Molnar 5f3ac6067SIngo Molnar /* 6f3ac6067SIngo Molnar * task->stack (kernel stack) handling interfaces: 7f3ac6067SIngo Molnar */ 8f3ac6067SIngo Molnar 968db0cf1SIngo Molnar #include <linux/sched.h> 1050d34394SIngo Molnar #include <linux/magic.h> 11f6120d52SKent Overstreet #include <linux/refcount.h> 12*fd7b4f9fSQun-Wei Lin #include <linux/kasan.h> 1368db0cf1SIngo Molnar 14f3ac6067SIngo Molnar #ifdef CONFIG_THREAD_INFO_IN_TASK 15f3ac6067SIngo Molnar 16f3ac6067SIngo Molnar /* 17f3ac6067SIngo Molnar * When accessing the stack of a non-current task that might exit, use 18f3ac6067SIngo Molnar * try_get_task_stack() instead. task_stack_page will return a pointer 19f3ac6067SIngo Molnar * that could get freed out from under you. 20f3ac6067SIngo Molnar */ task_stack_page(const struct task_struct * task)21e87f4152SBorislav Petkovstatic __always_inline void *task_stack_page(const struct task_struct *task) 22f3ac6067SIngo Molnar { 23f3ac6067SIngo Molnar return task->stack; 24f3ac6067SIngo Molnar } 25f3ac6067SIngo Molnar 26f3ac6067SIngo Molnar #define setup_thread_stack(new,old) do { } while(0) 27f3ac6067SIngo Molnar end_of_stack(const struct task_struct * task)28e0b081d1SJosh Poimboeufstatic __always_inline unsigned long *end_of_stack(const struct task_struct *task) 29f3ac6067SIngo Molnar { 309cc2fa4fSHelge Deller #ifdef CONFIG_STACK_GROWSUP 319cc2fa4fSHelge Deller return (unsigned long *)((unsigned long)task->stack + THREAD_SIZE) - 1; 329cc2fa4fSHelge Deller #else 33f3ac6067SIngo Molnar return task->stack; 349cc2fa4fSHelge Deller #endif 35f3ac6067SIngo Molnar } 36f3ac6067SIngo Molnar 37f3ac6067SIngo Molnar #else 38f3ac6067SIngo Molnar 39f3ac6067SIngo Molnar #define task_stack_page(task) ((void *)(task)->stack) 40f3ac6067SIngo Molnar setup_thread_stack(struct task_struct * p,struct task_struct * org)41f3ac6067SIngo Molnarstatic inline void setup_thread_stack(struct task_struct *p, struct task_struct *org) 42f3ac6067SIngo Molnar { 43f3ac6067SIngo Molnar *task_thread_info(p) = *task_thread_info(org); 44f3ac6067SIngo Molnar task_thread_info(p)->task = p; 45f3ac6067SIngo Molnar } 46f3ac6067SIngo Molnar 47f3ac6067SIngo Molnar /* 48f3ac6067SIngo Molnar * Return the address of the last usable long on the stack. 49f3ac6067SIngo Molnar * 50f3ac6067SIngo Molnar * When the stack grows down, this is just above the thread 51f3ac6067SIngo Molnar * info struct. Going any lower will corrupt the threadinfo. 52f3ac6067SIngo Molnar * 53f3ac6067SIngo Molnar * When the stack grows up, this is the highest address. 54f3ac6067SIngo Molnar * Beyond that position, we corrupt data on the next page. 55f3ac6067SIngo Molnar */ end_of_stack(struct task_struct * p)56f3ac6067SIngo Molnarstatic inline unsigned long *end_of_stack(struct task_struct *p) 57f3ac6067SIngo Molnar { 58f3ac6067SIngo Molnar #ifdef CONFIG_STACK_GROWSUP 59f3ac6067SIngo Molnar return (unsigned long *)((unsigned long)task_thread_info(p) + THREAD_SIZE) - 1; 60f3ac6067SIngo Molnar #else 61f3ac6067SIngo Molnar return (unsigned long *)(task_thread_info(p) + 1); 62f3ac6067SIngo Molnar #endif 63f3ac6067SIngo Molnar } 64f3ac6067SIngo Molnar 65f3ac6067SIngo Molnar #endif 66f3ac6067SIngo Molnar 67f3ac6067SIngo Molnar #ifdef CONFIG_THREAD_INFO_IN_TASK try_get_task_stack(struct task_struct * tsk)68f3ac6067SIngo Molnarstatic inline void *try_get_task_stack(struct task_struct *tsk) 69f3ac6067SIngo Molnar { 70f0b89d39SElena Reshetova return refcount_inc_not_zero(&tsk->stack_refcount) ? 71f3ac6067SIngo Molnar task_stack_page(tsk) : NULL; 72f3ac6067SIngo Molnar } 73f3ac6067SIngo Molnar 74f3ac6067SIngo Molnar extern void put_task_stack(struct task_struct *tsk); 75f3ac6067SIngo Molnar #else try_get_task_stack(struct task_struct * tsk)76f3ac6067SIngo Molnarstatic inline void *try_get_task_stack(struct task_struct *tsk) 77f3ac6067SIngo Molnar { 78f3ac6067SIngo Molnar return task_stack_page(tsk); 79f3ac6067SIngo Molnar } 80f3ac6067SIngo Molnar put_task_stack(struct task_struct * tsk)81f3ac6067SIngo Molnarstatic inline void put_task_stack(struct task_struct *tsk) {} 82f3ac6067SIngo Molnar #endif 83f3ac6067SIngo Molnar 841a03d3f1SSebastian Andrzej Siewior void exit_task_stack_account(struct task_struct *tsk); 851a03d3f1SSebastian Andrzej Siewior 86f3ac6067SIngo Molnar #define task_stack_end_corrupted(task) \ 87f3ac6067SIngo Molnar (*(end_of_stack(task)) != STACK_END_MAGIC) 88f3ac6067SIngo Molnar object_is_on_stack(const void * obj)8900ef0ef2SSascha Hauerstatic inline int object_is_on_stack(const void *obj) 90f3ac6067SIngo Molnar { 91f3ac6067SIngo Molnar void *stack = task_stack_page(current); 92f3ac6067SIngo Molnar 93*fd7b4f9fSQun-Wei Lin obj = kasan_reset_tag(obj); 94f3ac6067SIngo Molnar return (obj >= stack) && (obj < (stack + THREAD_SIZE)); 95f3ac6067SIngo Molnar } 96f3ac6067SIngo Molnar 97f3ac6067SIngo Molnar extern void thread_stack_cache_init(void); 98f3ac6067SIngo Molnar 99f3ac6067SIngo Molnar #ifdef CONFIG_DEBUG_STACK_USAGE 100fbe76a65SPasha Tatashin unsigned long stack_not_used(struct task_struct *p); 101fbe76a65SPasha Tatashin #else stack_not_used(struct task_struct * p)102f3ac6067SIngo Molnarstatic inline unsigned long stack_not_used(struct task_struct *p) 103f3ac6067SIngo Molnar { 104fbe76a65SPasha Tatashin return 0; 105f3ac6067SIngo Molnar } 106f3ac6067SIngo Molnar #endif 107f3ac6067SIngo Molnar extern void set_task_stack_end_magic(struct task_struct *tsk); 108f3ac6067SIngo Molnar 1099049863aSIngo Molnar #ifndef __HAVE_ARCH_KSTACK_END kstack_end(void * addr)1109049863aSIngo Molnarstatic inline int kstack_end(void *addr) 1119049863aSIngo Molnar { 1129049863aSIngo Molnar /* Reliable end of stack detection: 1139049863aSIngo Molnar * Some APM bios versions misalign the stack 1149049863aSIngo Molnar */ 1159049863aSIngo Molnar return !(((unsigned long)addr+sizeof(void*)-1) & (THREAD_SIZE-sizeof(void*))); 1169049863aSIngo Molnar } 1179049863aSIngo Molnar #endif 1189049863aSIngo Molnar 11968db0cf1SIngo Molnar #endif /* _LINUX_SCHED_TASK_STACK_H */ 120