Commit f5730d44 authored by Heiko Carstens's avatar Heiko Carstens
Browse files

s390: Add stackprotector support



Stackprotector support was previously unavailable on s390 because by
default compilers generate code which is not suitable for the kernel:
the canary value is accessed via thread local storage, where the address
of thread local storage is within access registers 0 and 1.

Using those registers also for the kernel would come with a significant
performance impact and more complicated kernel entry/exit code, since
access registers contents would have to be exchanged on every kernel entry
and exit.

With the upcoming gcc 16 release new compiler options will become available
which allow to generate code suitable for the kernel. [1]

Compiler option -mstack-protector-guard=global instructs gcc to generate
stackprotector code that refers to a global stackprotector canary value via
symbol __stack_chk_guard. Access to this value is guaranteed to occur via
larl and lgrl instructions.

Furthermore, compiler option -mstack-protector-guard-record generates a
section containing all code addresses that reference the canary value.

To allow for per task canary values the instructions which load the address
of __stack_chk_guard are patched so they access a lowcore field instead: a
per task canary value is available within the task_struct of each task, and
is written to the per-cpu lowcore location on each context switch.

Also add sanity checks and debugging option to be consistent with other
kernel code patching mechanisms.

Full debugging output can be enabled with the following kernel command line
options:

debug_stackprotector
bootdebug
ignore_loglevel
earlyprintk
dyndbg="file stackprotector.c +p"

Example debug output:

stackprot: 0000021e402d4eda: c010005a9ae3 -> c01f00070240

where "<insn address>: <old insn> -> <new insn>".

[1] gcc commit 0cd1f03939d5 ("s390: Support global stack protector")

Reviewed-by: default avatarSven Schnelle <svens@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parent 1d7764cf
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -69,6 +69,9 @@ config CC_HAS_ASM_AOR_FORMAT_FLAGS
	  Clang versions before 19.1.0 do not support A,
	  O, and R inline assembly format flags.

config CC_HAS_STACKPROTECTOR_GLOBAL
	def_bool $(cc-option, -mstack-protector-guard=global -mstack-protector-guard-record)

config S390
	def_bool y
	#
@@ -245,6 +248,7 @@ config S390
	select HAVE_SAMPLE_FTRACE_DIRECT_MULTI
	select HAVE_SETUP_PER_CPU_AREA
	select HAVE_SOFTIRQ_ON_OWN_STACK
	select HAVE_STACKPROTECTOR if CC_HAS_STACKPROTECTOR_GLOBAL
	select HAVE_SYSCALL_TRACEPOINTS
	select HAVE_VIRT_CPU_ACCOUNTING
	select HAVE_VIRT_CPU_ACCOUNTING_IDLE
+4 −0
Original line number Diff line number Diff line
@@ -89,6 +89,10 @@ ifdef CONFIG_EXPOLINE
  aflags-y += -DCC_USING_EXPOLINE
endif

ifeq ($(CONFIG_STACKPROTECTOR),y)
  KBUILD_CFLAGS += -mstack-protector-guard=global -mstack-protector-guard-record
endif

ifdef CONFIG_FUNCTION_TRACER
  ifeq ($(call cc-option,-mfentry -mnop-mcount),)
    # make use of hotpatch feature if the compiler supports it
+1 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o
obj-y	+= $(if $(CONFIG_KERNEL_UNCOMPRESSED),,decompressor.o) info.o
obj-$(CONFIG_KERNEL_ZSTD) += clz_ctz.o
obj-$(CONFIG_KMSAN) += kmsan.o
obj-$(CONFIG_STACKPROTECTOR) += stackprotector.o
obj-all := $(obj-y) piggy.o syms.o

targets	:= bzImage section_cmp.boot.data section_cmp.boot.preserved.data $(obj-y)
+4 −0
Original line number Diff line number Diff line
@@ -28,6 +28,10 @@ struct vmlinux_info {
	unsigned long invalid_pg_dir_off;
	unsigned long alt_instructions;
	unsigned long alt_instructions_end;
#ifdef CONFIG_STACKPROTECTOR
	unsigned long stack_prot_start;
	unsigned long stack_prot_end;
#endif
#ifdef CONFIG_KASAN
	unsigned long kasan_early_shadow_page_off;
	unsigned long kasan_early_shadow_pte_off;
+6 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
#include <linux/init.h>
#include <linux/ctype.h>
#include <linux/pgtable.h>
#include <asm/arch-stackprotector.h>
#include <asm/abs_lowcore.h>
#include <asm/page-states.h>
#include <asm/machine.h>
@@ -294,6 +295,11 @@ void parse_boot_command_line(void)
				cmma_flag = 0;
		}

#ifdef CONFIG_STACKPROTECTOR
		if (!strcmp(param, "debug_stackprotector"))
			stack_protector_debug = 1;
#endif

#if IS_ENABLED(CONFIG_KVM)
		if (!strcmp(param, "prot_virt")) {
			rc = kstrtobool(val, &enabled);
Loading