162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * GCC stack protector support. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Stack protector works by putting predefined pattern at the start of 662306a36Sopenharmony_ci * the stack frame and verifying that it hasn't been overwritten when 762306a36Sopenharmony_ci * returning from the function. The pattern is called stack canary 862306a36Sopenharmony_ci * and unfortunately gcc historically required it to be at a fixed offset 962306a36Sopenharmony_ci * from the percpu segment base. On x86_64, the offset is 40 bytes. 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * The same segment is shared by percpu area and stack canary. On 1262306a36Sopenharmony_ci * x86_64, percpu symbols are zero based and %gs (64-bit) points to the 1362306a36Sopenharmony_ci * base of percpu area. The first occupant of the percpu area is always 1462306a36Sopenharmony_ci * fixed_percpu_data which contains stack_canary at the appropriate 1562306a36Sopenharmony_ci * offset. On x86_32, the stack canary is just a regular percpu 1662306a36Sopenharmony_ci * variable. 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * Putting percpu data in %fs on 32-bit is a minor optimization compared to 1962306a36Sopenharmony_ci * using %gs. Since 32-bit userspace normally has %fs == 0, we are likely 2062306a36Sopenharmony_ci * to load 0 into %fs on exit to usermode, whereas with percpu data in 2162306a36Sopenharmony_ci * %gs, we are likely to load a non-null %gs on return to user mode. 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * Once we are willing to require GCC 8.1 or better for 64-bit stackprotector 2462306a36Sopenharmony_ci * support, we can remove some of this complexity. 2562306a36Sopenharmony_ci */ 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#ifndef _ASM_STACKPROTECTOR_H 2862306a36Sopenharmony_ci#define _ASM_STACKPROTECTOR_H 1 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#ifdef CONFIG_STACKPROTECTOR 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci#include <asm/tsc.h> 3362306a36Sopenharmony_ci#include <asm/processor.h> 3462306a36Sopenharmony_ci#include <asm/percpu.h> 3562306a36Sopenharmony_ci#include <asm/desc.h> 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#include <linux/sched.h> 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/* 4062306a36Sopenharmony_ci * Initialize the stackprotector canary value. 4162306a36Sopenharmony_ci * 4262306a36Sopenharmony_ci * NOTE: this must only be called from functions that never return 4362306a36Sopenharmony_ci * and it must always be inlined. 4462306a36Sopenharmony_ci * 4562306a36Sopenharmony_ci * In addition, it should be called from a compilation unit for which 4662306a36Sopenharmony_ci * stack protector is disabled. Alternatively, the caller should not end 4762306a36Sopenharmony_ci * with a function call which gets tail-call optimized as that would 4862306a36Sopenharmony_ci * lead to checking a modified canary value. 4962306a36Sopenharmony_ci */ 5062306a36Sopenharmony_cistatic __always_inline void boot_init_stack_canary(void) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci unsigned long canary = get_random_canary(); 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci#ifdef CONFIG_X86_64 5562306a36Sopenharmony_ci BUILD_BUG_ON(offsetof(struct fixed_percpu_data, stack_canary) != 40); 5662306a36Sopenharmony_ci#endif 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci current->stack_canary = canary; 5962306a36Sopenharmony_ci#ifdef CONFIG_X86_64 6062306a36Sopenharmony_ci this_cpu_write(fixed_percpu_data.stack_canary, canary); 6162306a36Sopenharmony_ci#else 6262306a36Sopenharmony_ci this_cpu_write(__stack_chk_guard, canary); 6362306a36Sopenharmony_ci#endif 6462306a36Sopenharmony_ci} 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistatic inline void cpu_init_stack_canary(int cpu, struct task_struct *idle) 6762306a36Sopenharmony_ci{ 6862306a36Sopenharmony_ci#ifdef CONFIG_X86_64 6962306a36Sopenharmony_ci per_cpu(fixed_percpu_data.stack_canary, cpu) = idle->stack_canary; 7062306a36Sopenharmony_ci#else 7162306a36Sopenharmony_ci per_cpu(__stack_chk_guard, cpu) = idle->stack_canary; 7262306a36Sopenharmony_ci#endif 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci#else /* STACKPROTECTOR */ 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci/* dummy boot_init_stack_canary() is defined in linux/stackprotector.h */ 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_cistatic inline void cpu_init_stack_canary(int cpu, struct task_struct *idle) 8062306a36Sopenharmony_ci{ } 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci#endif /* STACKPROTECTOR */ 8362306a36Sopenharmony_ci#endif /* _ASM_STACKPROTECTOR_H */ 84