Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b609eb65 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Greg Kroah-Hartman
Browse files

s390: introduce execute-trampolines for branches



[ Upstream commit f19fbd5ed642dc31c809596412dab1ed56f2f156 ]

Add CONFIG_EXPOLINE to enable the use of the new -mindirect-branch= and
-mfunction_return= compiler options to create a kernel fortified against
the specte v2 attack.

With CONFIG_EXPOLINE=y all indirect branches will be issued with an
execute type instruction. For z10 or newer the EXRL instruction will
be used, for older machines the EX instruction. The typical indirect
call

	basr	%r14,%r1

is replaced with a PC relative call to a new thunk

	brasl	%r14,__s390x_indirect_jump_r1

The thunk contains the EXRL/EX instruction to the indirect branch

__s390x_indirect_jump_r1:
	exrl	0,0f
	j	.
0:	br	%r1

The detour via the execute type instruction has a performance impact.
To get rid of the detour the new kernel parameter "nospectre_v2" and
"spectre_v2=[on,off,auto]" can be used. If the parameter is specified
the kernel and module code will be patched at runtime.

Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 0bd4c47c
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -555,6 +555,34 @@ config KERNEL_NOBP

	  If unsure, say N.

config EXPOLINE
	def_bool n
	prompt "Avoid speculative indirect branches in the kernel"
	help
	  Compile the kernel with the expoline compiler options to guard
	  against kernel-to-user data leaks by avoiding speculative indirect
	  branches.
	  Requires a compiler with -mindirect-branch=thunk support for full
	  protection. The kernel may run slower.

	  If unsure, say N.

choice
	prompt "Expoline default"
	depends on EXPOLINE
	default EXPOLINE_FULL

config EXPOLINE_OFF
	bool "spectre_v2=off"

config EXPOLINE_MEDIUM
	bool "spectre_v2=auto"

config EXPOLINE_FULL
	bool "spectre_v2=on"

endchoice

endmenu

menu "Memory setup"
+10 −0
Original line number Diff line number Diff line
@@ -81,6 +81,16 @@ ifeq ($(call cc-option-yn,-mwarn-dynamicstack),y)
cflags-$(CONFIG_WARN_DYNAMIC_STACK) += -mwarn-dynamicstack
endif

ifdef CONFIG_EXPOLINE
  ifeq ($(call cc-option-yn,$(CC_FLAGS_MARCH) -mindirect-branch=thunk),y)
    CC_FLAGS_EXPOLINE := -mindirect-branch=thunk
    CC_FLAGS_EXPOLINE += -mfunction-return=thunk
    CC_FLAGS_EXPOLINE += -mindirect-branch-table
    export CC_FLAGS_EXPOLINE
    cflags-y += $(CC_FLAGS_EXPOLINE)
  endif
endif

ifdef CONFIG_FUNCTION_TRACER
# make use of hotpatch feature if the compiler supports it
cc_hotpatch	:= -mhotpatch=0,3
+3 −1
Original line number Diff line number Diff line
@@ -140,7 +140,9 @@ struct lowcore {
	/* Per cpu primary space access list */
	__u32	paste[16];			/* 0x0400 */

	__u8	pad_0x04c0[0x0e00-0x0440];	/* 0x0440 */
	/* br %r1 trampoline */
	__u16	br_r1_trampoline;		/* 0x0440 */
	__u8	pad_0x0442[0x0e00-0x0442];	/* 0x0442 */

	/*
	 * 0xe00 contains the address of the IPL Parameter Information
+18 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_S390_EXPOLINE_H
#define _ASM_S390_EXPOLINE_H

#ifndef __ASSEMBLY__

#include <linux/types.h>

extern int nospec_call_disable;
extern int nospec_return_disable;

void nospec_init_branches(void);
void nospec_call_revert(s32 *start, s32 *end);
void nospec_return_revert(s32 *start, s32 *end);

#endif /* __ASSEMBLY__ */

#endif /* _ASM_S390_EXPOLINE_H */
+4 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ UBSAN_SANITIZE_early.o := n
#
ifneq ($(CC_FLAGS_MARCH),-march=z900)
CFLAGS_REMOVE_als.o	+= $(CC_FLAGS_MARCH)
CFLAGS_REMOVE_als.o	+= $(CC_FLAGS_EXPOLINE)
CFLAGS_als.o		+= -march=z900
AFLAGS_REMOVE_head.o	+= $(CC_FLAGS_MARCH)
AFLAGS_head.o		+= -march=z900
@@ -61,6 +62,9 @@ obj-y += entry.o reipl.o relocate_kernel.o kdebugfs.o alternative.o

extra-y				+= head.o head64.o vmlinux.lds

obj-$(CONFIG_EXPOLINE)		+= nospec-branch.o
CFLAGS_REMOVE_expoline.o	+= $(CC_FLAGS_EXPOLINE)

obj-$(CONFIG_MODULES)		+= module.o
obj-$(CONFIG_SMP)		+= smp.o
obj-$(CONFIG_SCHED_TOPOLOGY)	+= topology.o
Loading