Commit 5287569a authored by Sami Tolvanen's avatar Sami Tolvanen Committed by Will Deacon
Browse files

arm64: Implement Shadow Call Stack



This change implements shadow stack switching, initial SCS set-up,
and interrupt shadow stacks for arm64.

Signed-off-by: default avatarSami Tolvanen <samitolvanen@google.com>
Reviewed-by: default avatarKees Cook <keescook@chromium.org>
Signed-off-by: default avatarWill Deacon <will@kernel.org>
parent 96547368
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ config ARM64
	select ARCH_USE_QUEUED_RWLOCKS
	select ARCH_USE_QUEUED_SPINLOCKS
	select ARCH_SUPPORTS_MEMORY_FAILURE
	select ARCH_SUPPORTS_SHADOW_CALL_STACK if CC_HAVE_SHADOW_CALL_STACK
	select ARCH_SUPPORTS_ATOMIC_RMW
	select ARCH_SUPPORTS_INT128 if CC_HAS_INT128 && (GCC_VERSION >= 50000 || CC_IS_CLANG)
	select ARCH_SUPPORTS_NUMA_BALANCING
@@ -1025,6 +1026,10 @@ config ARCH_HAS_CACHE_LINE_SIZE
config ARCH_ENABLE_SPLIT_PMD_PTLOCK
	def_bool y if PGTABLE_LEVELS > 2

# Supported by clang >= 7.0
config CC_HAVE_SHADOW_CALL_STACK
	def_bool $(cc-option, -fsanitize=shadow-call-stack -ffixed-x18)

config SECCOMP
	bool "Enable seccomp to safely compute untrusted bytecode"
	---help---
+46 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_SCS_H
#define _ASM_SCS_H

#ifdef __ASSEMBLY__

#ifdef CONFIG_SHADOW_CALL_STACK
	.macro scs_load tsk, tmp
	ldp	x18, \tmp, [\tsk, #TSK_TI_SCS_BASE]
	add	x18, x18, \tmp
	.endm

	.macro scs_save tsk, tmp
	ldr	\tmp, [\tsk, #TSK_TI_SCS_BASE]
	sub	\tmp, x18, \tmp
	str	\tmp, [\tsk, #TSK_TI_SCS_OFFSET]
	.endm
#else
	.macro scs_load tsk, tmp
	.endm

	.macro scs_save tsk, tmp
	.endm
#endif /* CONFIG_SHADOW_CALL_STACK */

#else /* __ASSEMBLY__ */

#include <linux/scs.h>

#ifdef CONFIG_SHADOW_CALL_STACK

static inline void scs_overflow_check(struct task_struct *tsk)
{
	if (unlikely(scs_corrupted(tsk)))
		panic("corrupted shadow stack detected inside scheduler\n");
}

#else /* CONFIG_SHADOW_CALL_STACK */

static inline void scs_overflow_check(struct task_struct *tsk) {}

#endif /* CONFIG_SHADOW_CALL_STACK */

#endif /* __ASSEMBLY __ */

#endif /* _ASM_SCS_H */
+13 −0
Original line number Diff line number Diff line
@@ -41,6 +41,10 @@ struct thread_info {
#endif
		} preempt;
	};
#ifdef CONFIG_SHADOW_CALL_STACK
	void			*scs_base;
	unsigned long		scs_offset;
#endif
};

#define thread_saved_pc(tsk)	\
@@ -100,11 +104,20 @@ void arch_release_task_struct(struct task_struct *tsk);
				 _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \
				 _TIF_SYSCALL_EMU)

#ifdef CONFIG_SHADOW_CALL_STACK
#define INIT_SCS							\
	.scs_base	= init_shadow_call_stack,			\
	.scs_offset	= 0,
#else
#define INIT_SCS
#endif

#define INIT_THREAD_INFO(tsk)						\
{									\
	.flags		= _TIF_FOREIGN_FPSTATE,				\
	.preempt_count	= INIT_PREEMPT_COUNT,				\
	.addr_limit	= KERNEL_DS,					\
	INIT_SCS							\
}

#endif /* __ASM_THREAD_INFO_H */
+1 −0
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ obj-$(CONFIG_CRASH_CORE) += crash_core.o
obj-$(CONFIG_ARM_SDE_INTERFACE)		+= sdei.o
obj-$(CONFIG_ARM64_SSBD)		+= ssbd.o
obj-$(CONFIG_ARM64_PTR_AUTH)		+= pointer_auth.o
obj-$(CONFIG_SHADOW_CALL_STACK)		+= scs.o

obj-y					+= vdso/ probes/
obj-$(CONFIG_COMPAT_VDSO)		+= vdso32/
+4 −0
Original line number Diff line number Diff line
@@ -33,6 +33,10 @@ int main(void)
  DEFINE(TSK_TI_ADDR_LIMIT,	offsetof(struct task_struct, thread_info.addr_limit));
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
  DEFINE(TSK_TI_TTBR0,		offsetof(struct task_struct, thread_info.ttbr0));
#endif
#ifdef CONFIG_SHADOW_CALL_STACK
  DEFINE(TSK_TI_SCS_BASE,	offsetof(struct task_struct, thread_info.scs_base));
  DEFINE(TSK_TI_SCS_OFFSET,	offsetof(struct task_struct, thread_info.scs_offset));
#endif
  DEFINE(TSK_STACK,		offsetof(struct task_struct, stack));
#ifdef CONFIG_STACKPROTECTOR
Loading