diff --git a/docs/misra/safe.json b/docs/misra/safe.json index 3d68b59169..e3489dba8e 100644 --- a/docs/misra/safe.json +++ b/docs/misra/safe.json @@ -108,6 +108,14 @@ }, { "id": "SAF-13-safe", + "analyser": { + "eclair": "MC3A2.R8.4" + }, + "name": "Rule 8.4: compiler-called function", + "text": "A function, all invocations of which are compiler generated, does not need to have a visible declaration prior to its definition." + }, + { + "id": "SAF-14-safe", "analyser": {}, "name": "Sentinel", "text": "Next ID to be used" diff --git a/xen/Makefile b/xen/Makefile index 58fafab33d..8fc4e042ff 100644 --- a/xen/Makefile +++ b/xen/Makefile @@ -435,7 +435,11 @@ else CFLAGS_UBSAN := endif +ifeq ($(CONFIG_STACK_PROTECTOR),y) +CFLAGS += -fstack-protector +else CFLAGS += -fno-stack-protector +endif ifeq ($(CONFIG_LTO),y) CFLAGS += -flto diff --git a/xen/common/Kconfig b/xen/common/Kconfig index 06ae9751aa..42a2b6a03f 100644 --- a/xen/common/Kconfig +++ b/xen/common/Kconfig @@ -100,6 +100,9 @@ config HAS_PMAP config HAS_SCHED_GRANULARITY bool +config HAS_STACK_PROTECTOR + bool + config HAS_UBSAN bool @@ -233,6 +236,18 @@ config SPECULATIVE_HARDEN_LOCK endmenu +menu "Other hardening" + +config STACK_PROTECTOR + bool "Stack protector" + depends on HAS_STACK_PROTECTOR + help + Enable the Stack Protector compiler hardening option. This inserts a + canary value in the stack frame of functions, and performs an integrity + check on function exit. + +endmenu + config DIT_DEFAULT bool "Data Independent Timing default" depends on HAS_DIT diff --git a/xen/common/Makefile b/xen/common/Makefile index 9da8a7244d..f625031d16 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -46,6 +46,7 @@ obj-y += shutdown.o obj-y += softirq.o obj-y += smp.o obj-y += spinlock.o +obj-$(CONFIG_STACK_PROTECTOR) += stack-protector.o obj-y += stop_machine.o obj-y += symbols.o obj-y += tasklet.o diff --git a/xen/common/stack-protector.c b/xen/common/stack-protector.c new file mode 100644 index 0000000000..2115912c3b --- /dev/null +++ b/xen/common/stack-protector.c @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#include +#include +#include +#include + +/* + * Initial value is chosen by a fair dice roll. + * It will be updated during boot process. + */ +#if BITS_PER_LONG == 32 +unsigned long __ro_after_init __stack_chk_guard = 0xdd2cc927UL; +#else +unsigned long __ro_after_init __stack_chk_guard = 0x2d853605a4d9a09cUL; +#endif + +/* SAF-13-safe compiler-called function */ +void noreturn __stack_chk_fail(void) +{ + dump_execution_state(); + panic("Stack Protector integrity violation identified\n"); +} diff --git a/xen/include/xen/stack-protector.h b/xen/include/xen/stack-protector.h new file mode 100644 index 0000000000..931affd919 --- /dev/null +++ b/xen/include/xen/stack-protector.h @@ -0,0 +1,39 @@ +#ifndef __XEN_STACK_PROTECTOR_H__ +#define __XEN_STACK_PROTECTOR_H__ + +extern unsigned long __stack_chk_guard; + +/* + * This function should be called from a C function that escapes stack + * canary tracking (by calling reset_stack_and_jump() for example). + */ +static always_inline void boot_stack_chk_guard_setup(void) +{ +#ifdef CONFIG_STACK_PROTECTOR + + /* + * Linear congruent generator (X_n+1 = X_n * a + c). + * + * Constant is taken from "Tables Of Linear Congruential + * Generators Of Different Sizes And Good Lattice Structure" by + * Pierre L’Ecuyer. + */ +#if BITS_PER_LONG == 32 + const unsigned long a = 2891336453UL; +#else + const unsigned long a = 2862933555777941757UL; +#endif + const unsigned long c = 1; + + unsigned long cycles = get_cycles(); + + /* Use the initial value if we can't generate random one */ + if ( !cycles ) + return; + + __stack_chk_guard = cycles * a + c; + +#endif /* CONFIG_STACK_PROTECTOR */ +} + +#endif /* __XEN_STACK_PROTECTOR_H__ */