'Retpoline' mitigation technique for Spectre (branch target injection) [CVE-2017-5715]: https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html https://support.google.com/faqs/answer/7625886 https://spectreattack.com/ https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715 Patch copied from the 'retpoline-20180107' branch of upstream source repository (please add new / update existing patches when new 'retpoline-xxxxxxxx' branch appears): http://git.infradead.org/users/dwmw2/gcc-retpoline.git From f96e28553b0f2253184441f22852d76976e19968 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Tue, 12 Dec 2017 19:15:25 -0800 Subject: [PATCH 15/17] Disable red zone with local indirect jump --- gcc/config/i386/i386-protos.h | 2 +- gcc/config/i386/i386.c | 22 +++++++++++++++++----- gcc/config/i386/i386.h | 4 ++++ gcc/config/i386/i386.md | 8 +++++--- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 213663811de..a78bfa00427 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -315,7 +315,7 @@ extern enum attr_cpu ix86_schedule; #endif extern const char * ix86_output_call_insn (rtx_insn *insn, rtx call_op); -extern const char * ix86_output_indirect_jmp (rtx call_op); +extern const char * ix86_output_indirect_jmp (rtx call_op, bool ret_p); extern const char * ix86_output_function_return (bool long_p); extern bool ix86_operands_ok_for_move_multiple (rtx *operands, bool load, enum machine_mode mode); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 7ae3523095c..344cafe3dac 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -4209,12 +4209,19 @@ make_pass_stv (gcc::context *ctxt) return new pass_stv (ctxt); } -/* Return true if a red-zone is in use. */ +/* Return true if a red-zone is in use. We can't use red-zone when + there are local indirect jumps, like "indirect_jump" or "tablejump", + which jumps to another place in the function, since "call" in the + indirect thunk pushes the return address onto stack, destroying + red-zone. */ bool ix86_using_red_zone (void) { - return TARGET_RED_ZONE && !TARGET_64BIT_MS_ABI; + return (TARGET_RED_ZONE + && !TARGET_64BIT_MS_ABI + && (!cfun->machine->has_local_indirect_jump + || cfun->machine->indirect_branch_type == indirect_branch_keep)); } /* Return a string that documents the current -m options. The caller is @@ -28919,11 +28926,16 @@ ix86_output_indirect_branch (rtx call_op, const char *xasm, } const char * -ix86_output_indirect_jmp (rtx call_op) +ix86_output_indirect_jmp (rtx call_op, bool ret_p) { - if (ix86_red_zone_size == 0 - && cfun->machine->indirect_branch_type != indirect_branch_keep) + if (cfun->machine->indirect_branch_type != indirect_branch_keep) { + /* We can't have red-zone if this isn't a function return since + "call" in the indirect thunk pushes the return address onto + stack, destroying red-zone. */ + if (!ret_p && ix86_red_zone_size != 0) + gcc_unreachable (); + ix86_output_indirect_branch (call_op, "%0", true); return ""; } diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index f248f3ba2f5..5f30d3f8d19 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -2607,6 +2607,10 @@ struct GTY(()) machine_function { /* How to generate indirec branch. */ ENUM_BITFIELD(indirect_branch) indirect_branch_type : 3; + /* If true, the current function has local indirect jumps, like + "indirect_jump" or "tablejump". */ + BOOL_BITFIELD has_local_indirect_jump : 1; + /* How to generate function return. */ ENUM_BITFIELD(indirect_branch) function_return_type : 3; diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 473fa5c089b..ea95aad7540 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -11610,12 +11610,13 @@ { if (TARGET_X32 || ix86_indirect_branch_thunk_register) operands[0] = convert_memory_address (word_mode, operands[0]); + cfun->machine->has_local_indirect_jump = true; }) (define_insn "*indirect_jump" [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rBw"))] "" - "* return ix86_output_indirect_jmp (operands[0]);" + "* return ix86_output_indirect_jmp (operands[0], false);" [(set_attr "type" "ibr") (set_attr "length_immediate" "0") (set_attr "maybe_prefix_bnd" "1")]) @@ -11659,13 +11660,14 @@ if (TARGET_X32 || ix86_indirect_branch_thunk_register) operands[0] = convert_memory_address (word_mode, operands[0]); + cfun->machine->has_local_indirect_jump = true; }) (define_insn "*tablejump_1" [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rBw")) (use (label_ref (match_operand 1)))] "" - "* return ix86_output_indirect_jmp (operands[0]);" + "* return ix86_output_indirect_jmp (operands[0], false);" [(set_attr "type" "ibr") (set_attr "length_immediate" "0") (set_attr "maybe_prefix_bnd" "1")]) @@ -12342,7 +12344,7 @@ [(simple_return) (use (match_operand:SI 0 "register_operand" "r"))] "reload_completed" - "* return ix86_output_indirect_jmp (operands[0]);" + "* return ix86_output_indirect_jmp (operands[0], true);" [(set_attr "type" "ibr") (set_attr "length_immediate" "0") (set_attr "maybe_prefix_bnd" "1")]) -- 2.15.1