xen: common: add ability to enable stack protector

Both GCC and Clang support -fstack-protector feature, which add stack
canaries to functions where stack corruption is possible. This patch
makes general preparations to enable this feature on different
supported architectures:

 - Added CONFIG_HAS_STACK_PROTECTOR option so each architecture
   can enable this feature individually
 - Added user-selectable CONFIG_STACK_PROTECTOR option
 - Implemented code that sets up random stack canary and a basic
   handler for stack protector failures

Stack guard value is initialized in two phases:

1. Pre-defined randomly-selected value.

2. Own implementation of linear congruent random number generator. It
relies on get_cycles() being available very early. If get_cycles()
returns zero, it would leave pre-defined value from the previous step.

boot_stack_chk_guard_setup() is declared as always_inline to ensure
that it will not trigger stack protector by itself. And of course,
caller should ensure that stack protection code will not be reached
later. It is possible to call the same function from an ASM code by
introducing simple trampoline in stack-protector.c, but right now
there is no use case for such trampoline.

As __stack_chk_fail() is not called by Xen source code directly, and
only called by compiler-generated code, it does not needed to be
declared separately. So we need separate MISRA deviation for it.

Signed-off-by: Volodymyr Babchuk <volodymyr_babchuk@epam.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
Volodymyr Babchuk authored and Jan Beulich committed 2025-04-14 13:07:12 +02:00
1 parent 40bc520ca0
commit be2a6a1096
6 files changed
+89

No files matched your search

+8
View File
@@ -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"
+4
View File
@@ -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
+15
View File
@@ -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
+1
View File
@@ -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
+22
View File
@@ -0,0 +1,22 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <xen/init.h>
#include <xen/lib.h>
#include <xen/random.h>
#include <xen/time.h>
/*
* 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");
}
+39
View File
@@ -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__ */
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.