16e13c60ff
This change adds generic support for Clang's Shadow Call Stack, which uses a shadow stack to protect return addresses from being overwritten by an attacker. Details are available here: https://clang.llvm.org/docs/ShadowCallStack.html Note that security guarantees in the kernel differ from the ones documented for user space. The kernel must store addresses of shadow stacks used by other tasks and interrupt handlers in memory, which means an attacker capable reading and writing arbitrary memory may be able to locate them and hijack control flow by modifying shadow stacks that are not currently in use. Bug: 145210207 Change-Id: Ia5f1650593fa95da4efcf86f84830a20989f161c (am from https://lore.kernel.org/patchwork/patch/1149054/) Reviewed-by: Kees Cook <keescook@chromium.org> Reviewed-by: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com> Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
57 lines
1.6 KiB
C
57 lines
1.6 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Shadow Call Stack support.
|
|
*
|
|
* Copyright (C) 2019 Google LLC
|
|
*/
|
|
|
|
#ifndef _LINUX_SCS_H
|
|
#define _LINUX_SCS_H
|
|
|
|
#include <linux/gfp.h>
|
|
#include <linux/sched.h>
|
|
#include <asm/page.h>
|
|
|
|
#ifdef CONFIG_SHADOW_CALL_STACK
|
|
|
|
/*
|
|
* In testing, 1 KiB shadow stack size (i.e. 128 stack frames on a 64-bit
|
|
* architecture) provided ~40% safety margin on stack usage while keeping
|
|
* memory allocation overhead reasonable.
|
|
*/
|
|
#define SCS_SIZE 1024UL
|
|
#define GFP_SCS (GFP_KERNEL | __GFP_ZERO)
|
|
|
|
/*
|
|
* A random number outside the kernel's virtual address space to mark the
|
|
* end of the shadow stack.
|
|
*/
|
|
#define SCS_END_MAGIC 0xaf0194819b1635f6UL
|
|
|
|
#define task_scs(tsk) (task_thread_info(tsk)->shadow_call_stack)
|
|
|
|
static inline void task_set_scs(struct task_struct *tsk, void *s)
|
|
{
|
|
task_scs(tsk) = s;
|
|
}
|
|
|
|
extern void scs_init(void);
|
|
extern void scs_task_reset(struct task_struct *tsk);
|
|
extern int scs_prepare(struct task_struct *tsk, int node);
|
|
extern bool scs_corrupted(struct task_struct *tsk);
|
|
extern void scs_release(struct task_struct *tsk);
|
|
|
|
#else /* CONFIG_SHADOW_CALL_STACK */
|
|
|
|
#define task_scs(tsk) NULL
|
|
|
|
static inline void task_set_scs(struct task_struct *tsk, void *s) {}
|
|
static inline void scs_init(void) {}
|
|
static inline void scs_task_reset(struct task_struct *tsk) {}
|
|
static inline int scs_prepare(struct task_struct *tsk, int node) { return 0; }
|
|
static inline bool scs_corrupted(struct task_struct *tsk) { return false; }
|
|
static inline void scs_release(struct task_struct *tsk) {}
|
|
|
|
#endif /* CONFIG_SHADOW_CALL_STACK */
|
|
|
|
#endif /* _LINUX_SCS_H */
|