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