scs.h 1.8 KB

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