Line data Source code
1 : /* SPDX-License-Identifier: GPL-2.0 */ 2 : /* 3 : * Shadow Call Stack support. 4 : * 5 : * Copyright (C) 2019 Google LLC 6 : */ 7 : 8 : #ifndef _LINUX_SCS_H 9 : #define _LINUX_SCS_H 10 : 11 : #include <linux/gfp.h> 12 : #include <linux/poison.h> 13 : #include <linux/sched.h> 14 : #include <linux/sizes.h> 15 : 16 : #ifdef CONFIG_SHADOW_CALL_STACK 17 : 18 : #define SCS_ORDER 0 19 : #define SCS_SIZE (PAGE_SIZE << SCS_ORDER) 20 : #define GFP_SCS (GFP_KERNEL | __GFP_ZERO) 21 : 22 : /* An illegal pointer value to mark the end of the shadow stack. */ 23 : #define SCS_END_MAGIC (0x5f6UL + POISON_POINTER_DELTA) 24 : 25 : #define task_scs(tsk) (task_thread_info(tsk)->scs_base) 26 : #define task_scs_sp(tsk) (task_thread_info(tsk)->scs_sp) 27 : 28 : void *scs_alloc(int node); 29 : void scs_free(void *s); 30 : void scs_init(void); 31 : int scs_prepare(struct task_struct *tsk, int node); 32 : void scs_release(struct task_struct *tsk); 33 : 34 : static inline void scs_task_reset(struct task_struct *tsk) 35 : { 36 : /* 37 : * Reset the shadow stack to the base address in case the task 38 : * is reused. 39 : */ 40 : task_scs_sp(tsk) = task_scs(tsk); 41 : } 42 : 43 : static inline unsigned long *__scs_magic(void *s) 44 : { 45 : return (unsigned long *)(s + SCS_SIZE) - 1; 46 : } 47 : 48 : static inline bool task_scs_end_corrupted(struct task_struct *tsk) 49 : { 50 : unsigned long *magic = __scs_magic(task_scs(tsk)); 51 : unsigned long sz = task_scs_sp(tsk) - task_scs(tsk); 52 : 53 : return sz >= SCS_SIZE - 1 || READ_ONCE_NOCHECK(*magic) != SCS_END_MAGIC; 54 : } 55 : 56 : #else /* CONFIG_SHADOW_CALL_STACK */ 57 : 58 : static inline void *scs_alloc(int node) { return NULL; } 59 : static inline void scs_free(void *s) {} 60 1 : static inline void scs_init(void) {} 61 10 : static inline void scs_task_reset(struct task_struct *tsk) {} 62 916 : static inline int scs_prepare(struct task_struct *tsk, int node) { return 0; } 63 834 : static inline void scs_release(struct task_struct *tsk) {} 64 : static inline bool task_scs_end_corrupted(struct task_struct *tsk) { return false; } 65 : 66 : #endif /* CONFIG_SHADOW_CALL_STACK */ 67 : 68 : #endif /* _LINUX_SCS_H */