S/390: Disable prediction of indirect branches
authorAndreas Krebbel <krebbel@linux.vnet.ibm.com>
Thu, 8 Feb 2018 14:45:53 +0000 (14:45 +0000)
committerAndreas Krebbel <krebbel@gcc.gnu.org>
Thu, 8 Feb 2018 14:45:53 +0000 (14:45 +0000)
commit84b4c7b593cd4ebb475a08aa4b816c722f716ce6
tree8788aae4fe5effe49577ad31730b775e75869ab9
parent98a05c03ef5a3f3f096b1c344e6a75c37fbeea47
S/390: Disable prediction of indirect branches

This patch implements GCC support for mitigating vulnerability
CVE-2017-5715 known as Spectre #2 on IBM Z.

In order to disable prediction of indirect branches the implementation
makes use of an IBM Z specific feature - the execute instruction.
Performing an indirect branch via execute prevents the branch from
being subject to dynamic branch prediction.

The implementation tries to stay close to the x86 solution regarding
user interface.

x86 style options supported (without thunk-inline):

-mindirect-branch=(keep|thunk|thunk-extern)
-mfunction-return=(keep|thunk|thunk-extern)

IBM Z specific options:

-mindirect-branch-jump=(keep|thunk|thunk-extern|thunk-inline)
-mindirect-branch-call=(keep|thunk|thunk-extern)
-mfunction-return-reg=(keep|thunk|thunk-extern)
-mfunction-return-mem=(keep|thunk|thunk-extern)

These options allow us to enable/disable the branch conversion at a
finer granularity.

-mindirect-branch sets the value of -mindirect-branch-jump and
 -mindirect-branch-call.

-mfunction-return sets the value of -mfunction-return-reg and
 -mfunction-return-mem.

All these options are supported on GCC command line as well as
function attributes.

'thunk' triggers the generation of out of line thunks (expolines) and
replaces the formerly indirect branch with a direct branch to the
thunk.  Depending on the -march= setting two different types of thunks
are generated.  With -march=z10 or higher exrl (execute relative long)
is being used while targeting older machines makes use of larl/ex
instead.  From a security perspective the exrl variant is preferable.

'thunk-extern' does the branch replacement like 'thunk' but does not
emit the thunks.

'thunk-inline' is only available for indirect jumps.  It should be used
in environments where correct CFI is important - known as user space.

Additionally the patch introduces the -mindirect-branch-table option
which generates tables pointing to the locations which have been
modified.  This is supposed to allow reverting the changes without
re-compilation in situations where it isn't required. The sections are
split up into one section per option.

gcc/ChangeLog:

2018-02-08  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>

* config/s390/s390-opts.h (enum indirect_branch): Define.
* config/s390/s390-protos.h (s390_return_addr_from_memory)
(s390_indirect_branch_via_thunk)
(s390_indirect_branch_via_inline_thunk): Add function prototypes.
(enum s390_indirect_branch_type): Define.
* config/s390/s390.c (struct s390_frame_layout, struct
machine_function): Remove.
(indirect_branch_prez10thunk_mask, indirect_branch_z10thunk_mask)
(indirect_branch_table_label_no, indirect_branch_table_name):
Define variables.
(INDIRECT_BRANCH_NUM_OPTIONS): Define macro.
(enum s390_indirect_branch_option): Define.
(s390_return_addr_from_memory): New function.
(s390_handle_string_attribute): New function.
(s390_attribute_table): Add new attribute handler.
(s390_execute_label): Handle UNSPEC_EXECUTE_JUMP patterns.
(s390_indirect_branch_via_thunk): New function.
(s390_indirect_branch_via_inline_thunk): New function.
(s390_function_ok_for_sibcall): When jumping via thunk disallow
sibling call optimization for non z10 compiles.
(s390_emit_call): Force indirect branch target to be a single
register.  Add r1 clobber for non-z10 compiles.
(s390_emit_epilogue): Emit return jump via return_use expander.
(s390_reorg): Handle JUMP_INSNs as execute targets.
(s390_option_override_internal): Perform validity checks for the
new command line options.
(s390_indirect_branch_attrvalue): New function.
(s390_indirect_branch_settings): New function.
(s390_set_current_function): Invoke s390_indirect_branch_settings.
(s390_output_indirect_thunk_function):  New function.
(s390_code_end): Implement target hook.
(s390_case_values_threshold): Implement target hook.
(TARGET_ASM_CODE_END, TARGET_CASE_VALUES_THRESHOLD): Define target
macros.
* config/s390/s390.h (struct s390_frame_layout)
(struct machine_function): Move here from s390.c.
(TARGET_INDIRECT_BRANCH_NOBP_RET)
(TARGET_INDIRECT_BRANCH_NOBP_JUMP)
(TARGET_INDIRECT_BRANCH_NOBP_JUMP_THUNK)
(TARGET_INDIRECT_BRANCH_NOBP_JUMP_INLINE_THUNK)
(TARGET_INDIRECT_BRANCH_NOBP_CALL)
(TARGET_DEFAULT_INDIRECT_BRANCH_TABLE)
(TARGET_INDIRECT_BRANCH_THUNK_NAME_EXRL)
(TARGET_INDIRECT_BRANCH_THUNK_NAME_EX)
(TARGET_INDIRECT_BRANCH_TABLE): Define macros.
* config/s390/s390.md (UNSPEC_EXECUTE_JUMP)
(INDIRECT_BRANCH_THUNK_REGNUM): Define constants.
(mnemonic attribute): Add values which aren't recognized
automatically.
("*cjump_long", "*icjump_long", "*basr", "*basr_r"): Disable
pattern for branch conversion.  Fix mnemonic attribute.
("*c<code>", "*sibcall_br", "*sibcall_value_br", "*return"): Emit
indirect branch via thunk if requested.
("indirect_jump", "<code>"): Expand patterns for branch conversion.
("*indirect_jump"): Disable for branch conversion using out of
line thunks.
("indirect_jump_via_thunk<mode>_z10")
("indirect_jump_via_thunk<mode>")
("indirect_jump_via_inlinethunk<mode>_z10")
("indirect_jump_via_inlinethunk<mode>", "*casesi_jump")
("casesi_jump_via_thunk<mode>_z10", "casesi_jump_via_thunk<mode>")
("casesi_jump_via_inlinethunk<mode>_z10")
("casesi_jump_via_inlinethunk<mode>", "*basr_via_thunk<mode>_z10")
("*basr_via_thunk<mode>", "*basr_r_via_thunk_z10")
("*basr_r_via_thunk", "return<mode>_prez10"): New pattern.
("*indirect2_jump"): Disable for branch conversion.
("casesi_jump"): Turn into expander and expand patterns for branch
conversion.
("return_use"): New expander.
("*return"): Emit return via thunk and rename it to ...
("*return<mode>"): ... this one.
* config/s390/s390.opt: Add new options and and enum for the
option values.

gcc/testsuite/ChangeLog:

2018-02-08  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>

* gcc.target/s390/nobp-function-pointer-attr.c: New test.
* gcc.target/s390/nobp-function-pointer-nothunk.c: New test.
* gcc.target/s390/nobp-function-pointer-z10.c: New test.
* gcc.target/s390/nobp-function-pointer-z900.c: New test.
* gcc.target/s390/nobp-indirect-jump-attr.c: New test.
* gcc.target/s390/nobp-indirect-jump-inline-attr.c: New test.
* gcc.target/s390/nobp-indirect-jump-inline-z10.c: New test.
* gcc.target/s390/nobp-indirect-jump-inline-z900.c: New test.
* gcc.target/s390/nobp-indirect-jump-nothunk.c: New test.
* gcc.target/s390/nobp-indirect-jump-z10.c: New test.
* gcc.target/s390/nobp-indirect-jump-z900.c: New test.
* gcc.target/s390/nobp-return-attr-all.c: New test.
* gcc.target/s390/nobp-return-attr-neg.c: New test.
* gcc.target/s390/nobp-return-mem-attr.c: New test.
* gcc.target/s390/nobp-return-mem-nothunk.c: New test.
* gcc.target/s390/nobp-return-mem-z10.c: New test.
* gcc.target/s390/nobp-return-mem-z900.c: New test.
* gcc.target/s390/nobp-return-reg-attr.c: New test.
* gcc.target/s390/nobp-return-reg-mixed.c: New test.
* gcc.target/s390/nobp-return-reg-nothunk.c: New test.
* gcc.target/s390/nobp-return-reg-z10.c: New test.
* gcc.target/s390/nobp-return-reg-z900.c: New test.
* gcc.target/s390/nobp-table-jump-inline-z10.c: New test.
* gcc.target/s390/nobp-table-jump-inline-z900.c: New test.
* gcc.target/s390/nobp-table-jump-z10.c: New test.
* gcc.target/s390/nobp-table-jump-z900.c: New test.

From-SVN: r257489
34 files changed:
gcc/ChangeLog
gcc/config/s390/s390-opts.h
gcc/config/s390/s390-protos.h
gcc/config/s390/s390.c
gcc/config/s390/s390.h
gcc/config/s390/s390.md
gcc/config/s390/s390.opt
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/s390/nobp-function-pointer-attr.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-function-pointer-nothunk.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-function-pointer-z10.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-function-pointer-z900.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-indirect-jump-attr.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-attr.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-z10.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-z900.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-indirect-jump-nothunk.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-indirect-jump-z10.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-indirect-jump-z900.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-return-attr-all.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-return-attr-neg.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-return-mem-attr.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-return-mem-nothunk.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-return-mem-z10.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-return-mem-z900.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-return-reg-attr.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-return-reg-mixed.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-return-reg-nothunk.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-return-reg-z10.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-return-reg-z900.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-table-jump-inline-z10.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-table-jump-inline-z900.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-table-jump-z10.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/nobp-table-jump-z900.c [new file with mode: 0644]