Line data Source code
1 : /* SPDX-License-Identifier: GPL-2.0 */ 2 : #ifndef _LINUX_SCHED_TASK_STACK_H 3 : #define _LINUX_SCHED_TASK_STACK_H 4 : 5 : /* 6 : * task->stack (kernel stack) handling interfaces: 7 : */ 8 : 9 : #include <linux/sched.h> 10 : #include <linux/magic.h> 11 : 12 : #ifdef CONFIG_THREAD_INFO_IN_TASK 13 : 14 : /* 15 : * When accessing the stack of a non-current task that might exit, use 16 : * try_get_task_stack() instead. task_stack_page will return a pointer 17 : * that could get freed out from under you. 18 : */ 19 : static __always_inline void *task_stack_page(const struct task_struct *task) 20 : { 21 : return task->stack; 22 : } 23 : 24 : #define setup_thread_stack(new,old) do { } while(0) 25 : 26 : static __always_inline unsigned long *end_of_stack(const struct task_struct *task) 27 : { 28 : #ifdef CONFIG_STACK_GROWSUP 29 : return (unsigned long *)((unsigned long)task->stack + THREAD_SIZE) - 1; 30 : #else 31 : return task->stack; 32 : #endif 33 : } 34 : 35 : #elif !defined(__HAVE_THREAD_FUNCTIONS) 36 : 37 : #define task_stack_page(task) ((void *)(task)->stack) 38 : 39 : static inline void setup_thread_stack(struct task_struct *p, struct task_struct *org) 40 : { 41 175 : *task_thread_info(p) = *task_thread_info(org); 42 175 : task_thread_info(p)->task = p; 43 : } 44 : 45 : /* 46 : * Return the address of the last usable long on the stack. 47 : * 48 : * When the stack grows down, this is just above the thread 49 : * info struct. Going any lower will corrupt the threadinfo. 50 : * 51 : * When the stack grows up, this is the highest address. 52 : * Beyond that position, we corrupt data on the next page. 53 : */ 54 : static inline unsigned long *end_of_stack(struct task_struct *p) 55 : { 56 : #ifdef CONFIG_STACK_GROWSUP 57 : return (unsigned long *)((unsigned long)task_thread_info(p) + THREAD_SIZE) - 1; 58 : #else 59 : return (unsigned long *)(task_thread_info(p) + 1); 60 : #endif 61 : } 62 : 63 : #endif 64 : 65 : #ifdef CONFIG_THREAD_INFO_IN_TASK 66 : static inline void *try_get_task_stack(struct task_struct *tsk) 67 : { 68 : return refcount_inc_not_zero(&tsk->stack_refcount) ? 69 : task_stack_page(tsk) : NULL; 70 : } 71 : 72 : extern void put_task_stack(struct task_struct *tsk); 73 : #else 74 : static inline void *try_get_task_stack(struct task_struct *tsk) 75 : { 76 : return task_stack_page(tsk); 77 : } 78 : 79 : static inline void put_task_stack(struct task_struct *tsk) {} 80 : #endif 81 : 82 : void exit_task_stack_account(struct task_struct *tsk); 83 : 84 : #define task_stack_end_corrupted(task) \ 85 : (*(end_of_stack(task)) != STACK_END_MAGIC) 86 : 87 : static inline int object_is_on_stack(const void *obj) 88 : { 89 0 : void *stack = task_stack_page(current); 90 : 91 0 : return (obj >= stack) && (obj < (stack + THREAD_SIZE)); 92 : } 93 : 94 : extern void thread_stack_cache_init(void); 95 : 96 : #ifdef CONFIG_DEBUG_STACK_USAGE 97 : static inline unsigned long stack_not_used(struct task_struct *p) 98 : { 99 : unsigned long *n = end_of_stack(p); 100 : 101 : do { /* Skip over canary */ 102 : # ifdef CONFIG_STACK_GROWSUP 103 : n--; 104 : # else 105 : n++; 106 : # endif 107 : } while (!*n); 108 : 109 : # ifdef CONFIG_STACK_GROWSUP 110 : return (unsigned long)end_of_stack(p) - (unsigned long)n; 111 : # else 112 : return (unsigned long)n - (unsigned long)end_of_stack(p); 113 : # endif 114 : } 115 : #endif 116 : extern void set_task_stack_end_magic(struct task_struct *tsk); 117 : 118 : #ifndef __HAVE_ARCH_KSTACK_END 119 : static inline int kstack_end(void *addr) 120 : { 121 : /* Reliable end of stack detection: 122 : * Some APM bios versions misalign the stack 123 : */ 124 12 : return !(((unsigned long)addr+sizeof(void*)-1) & (THREAD_SIZE-sizeof(void*))); 125 : } 126 : #endif 127 : 128 : #endif /* _LINUX_SCHED_TASK_STACK_H */