1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
260a5317fSTejun Heo /*
360a5317fSTejun Heo  * GCC stack protector support.
460a5317fSTejun Heo  *
580d47defSBrian Gerst  * Stack protector works by putting a predefined pattern at the start of
660a5317fSTejun Heo  * the stack frame and verifying that it hasn't been overwritten when
780d47defSBrian Gerst  * returning from the function.  The pattern is called the stack canary
880d47defSBrian Gerst  * and is a unique value for each task.
960a5317fSTejun Heo  */
1060a5317fSTejun Heo 
11b2b062b8SIngo Molnar #ifndef _ASM_STACKPROTECTOR_H
12b2b062b8SIngo Molnar #define _ASM_STACKPROTECTOR_H 1
13b2b062b8SIngo Molnar 
14050e9baaSLinus Torvalds #ifdef CONFIG_STACKPROTECTOR
1576397f72STejun Heo 
16b2b062b8SIngo Molnar #include <asm/tsc.h>
17947e76cdSBrian Gerst #include <asm/processor.h>
1876397f72STejun Heo #include <asm/percpu.h>
1960a5317fSTejun Heo #include <asm/desc.h>
20952f07ecSIngo Molnar 
21952f07ecSIngo Molnar #include <linux/sched.h>
22b2b062b8SIngo Molnar 
23*f3856cd3SBrian Gerst DECLARE_PER_CPU_CACHE_HOT(unsigned long, __stack_chk_guard);
2480d47defSBrian Gerst 
25b2b062b8SIngo Molnar /*
26b2b062b8SIngo Molnar  * Initialize the stackprotector canary value.
27b2b062b8SIngo Molnar  *
28a9a3ed1eSBorislav Petkov  * NOTE: this must only be called from functions that never return
29b2b062b8SIngo Molnar  * and it must always be inlined.
30a9a3ed1eSBorislav Petkov  *
31a9a3ed1eSBorislav Petkov  * In addition, it should be called from a compilation unit for which
32a9a3ed1eSBorislav Petkov  * stack protector is disabled. Alternatively, the caller should not end
33a9a3ed1eSBorislav Petkov  * with a function call which gets tail-call optimized as that would
34a9a3ed1eSBorislav Petkov  * lead to checking a modified canary value.
35b2b062b8SIngo Molnar  */
boot_init_stack_canary(void)36b2b062b8SIngo Molnar static __always_inline void boot_init_stack_canary(void)
37b2b062b8SIngo Molnar {
38622754e8SJason A. Donenfeld 	unsigned long canary = get_random_canary();
39b2b062b8SIngo Molnar 
40b2b062b8SIngo Molnar 	current->stack_canary = canary;
413fb0fdb3SAndy Lutomirski 	this_cpu_write(__stack_chk_guard, canary);
4260a5317fSTejun Heo }
4360a5317fSTejun Heo 
cpu_init_stack_canary(int cpu,struct task_struct * idle)44c9a1ff31SBrian Gerst static inline void cpu_init_stack_canary(int cpu, struct task_struct *idle)
45c9a1ff31SBrian Gerst {
463fb0fdb3SAndy Lutomirski 	per_cpu(__stack_chk_guard, cpu) = idle->stack_canary;
4760a5317fSTejun Heo }
4860a5317fSTejun Heo 
49050e9baaSLinus Torvalds #else	/* STACKPROTECTOR */
5060a5317fSTejun Heo 
5160a5317fSTejun Heo /* dummy boot_init_stack_canary() is defined in linux/stackprotector.h */
5260a5317fSTejun Heo 
cpu_init_stack_canary(int cpu,struct task_struct * idle)53c9a1ff31SBrian Gerst static inline void cpu_init_stack_canary(int cpu, struct task_struct *idle)
54c9a1ff31SBrian Gerst { }
55c9a1ff31SBrian Gerst 
56050e9baaSLinus Torvalds #endif	/* STACKPROTECTOR */
5776397f72STejun Heo #endif	/* _ASM_STACKPROTECTOR_H */
58