From 88bf1c3910e4cf97dcb85c6d32291c23e572a516 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Wed, 27 Oct 2021 07:48:54 -0700 Subject: [PATCH 1/4] x86: Add -mharden-sls=[none|all|return|indirect-branch] Add -mharden-sls= to mitigate against straight line speculation (SLS) for function return and indirect branch by adding an INT3 instruction after function return and indirect branch. gcc/ PR target/102952 * config/i386/i386-opts.h (harden_sls): New enum. * config/i386/i386.c (output_indirect_thunk): Mitigate against SLS for function return. (ix86_output_function_return): Likewise. (ix86_output_jmp_thunk_or_indirect): Mitigate against indirect branch. (ix86_output_indirect_jmp): Likewise. (ix86_output_call_insn): Likewise. * config/i386/i386.opt: Add -mharden-sls=. * doc/invoke.texi: Document -mharden-sls=. gcc/testsuite/ PR target/102952 * gcc.target/i386/harden-sls-1.c: New test. * gcc.target/i386/harden-sls-2.c: Likewise. * gcc.target/i386/harden-sls-3.c: Likewise. * gcc.target/i386/harden-sls-4.c: Likewise. * gcc.target/i386/harden-sls-5.c: Likewise. (cherry picked from commit 53a643f8568067d7700a9f2facc8ba39974973d3) --- gcc/config/i386/i386-opts.h | 7 +++++++ gcc/config/i386/i386.c | 22 +++++++++++++++----- gcc/config/i386/i386.opt | 20 ++++++++++++++++++ gcc/doc/invoke.texi | 10 ++++++++- gcc/testsuite/gcc.target/i386/harden-sls-1.c | 14 +++++++++++++ gcc/testsuite/gcc.target/i386/harden-sls-2.c | 14 +++++++++++++ gcc/testsuite/gcc.target/i386/harden-sls-3.c | 14 +++++++++++++ gcc/testsuite/gcc.target/i386/harden-sls-4.c | 16 ++++++++++++++ gcc/testsuite/gcc.target/i386/harden-sls-5.c | 17 +++++++++++++++ 9 files changed, 128 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-1.c create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-2.c create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-3.c create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-4.c create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-5.c diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h index 46366cbfa72..34718b6d52c 100644 --- a/gcc/config/i386/i386-opts.h +++ b/gcc/config/i386/i386-opts.h @@ -119,4 +119,11 @@ enum indirect_branch { indirect_branch_thunk_extern }; +enum harden_sls { + harden_sls_none = 0, + harden_sls_return = 1 << 0, + harden_sls_indirect_branch = 1 << 1, + harden_sls_all = harden_sls_return | harden_sls_indirect_branch +}; + #endif diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 31502774ef3..eb9303f8742 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -10977,6 +10977,9 @@ output_indirect_thunk (enum indirect_thunk_prefix need_prefix, fputs ("\tbnd ret\n", asm_out_file); else fputs ("\tret\n", asm_out_file); + + if ((ix86_harden_sls & harden_sls_return)) + fputs ("\tint3\n", asm_out_file); } /* Output a funtion with a call and return thunk for indirect branch. @@ -28728,6 +28731,8 @@ ix86_output_jmp_thunk_or_indirect (const char *thunk_name, fprintf (asm_out_file, "\tjmp\t"); assemble_name (asm_out_file, thunk_name); putc ('\n', asm_out_file); + if ((ix86_harden_sls & harden_sls_indirect_branch)) + fputs ("\tint3\n", asm_out_file); } else output_indirect_thunk (need_prefix, regno); @@ -28973,10 +28978,10 @@ ix86_output_indirect_jmp (rtx call_op) gcc_unreachable (); ix86_output_indirect_branch (call_op, "%0", true); - return ""; } else - return "%!jmp\t%A0"; + output_asm_insn ("%!jmp\t%A0", &call_op); + return (ix86_harden_sls & harden_sls_indirect_branch) ? "int3" : ""; } /* Output function return. CALL_OP is the jump target. Add a REP @@ -29018,9 +29023,11 @@ ix86_output_function_return (bool long_p) } if (!long_p || ix86_bnd_prefixed_insn_p (current_output_insn)) - return "%!ret"; + output_asm_insn ("%!ret", NULL); + else + output_asm_insn ("rep%; ret", NULL); - return "rep%; ret"; + return (ix86_harden_sls & harden_sls_return) ? "int3" : ""; } /* Output indirect function return. RET_OP is the function return @@ -29158,7 +29165,12 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op) if (output_indirect_p && !direct_p) ix86_output_indirect_branch (call_op, xasm, true); else - output_asm_insn (xasm, &call_op); + { + output_asm_insn (xasm, &call_op); + if (!direct_p + && (ix86_harden_sls & harden_sls_indirect_branch)) + return "int3"; + } return ""; } diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt index d9bd909a885..3ae48609e25 100644 --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -1055,3 +1055,23 @@ Support MOVDIRI built-in functions and code generation. mmovdir64b Target Report Mask(ISA_MOVDIR64B) Var(ix86_isa_flags2) Save Support MOVDIR64B built-in functions and code generation. + +mharden-sls= +Target RejectNegative Joined Enum(harden_sls) Var(ix86_harden_sls) Init(harden_sls_none) +Generate code to mitigate against straight line speculation. + +Enum +Name(harden_sls) Type(enum harden_sls) +Known choices for mitigation against straight line speculation with -mharden-sls=: + +EnumValue +Enum(harden_sls) String(none) Value(harden_sls_none) + +EnumValue +Enum(harden_sls) String(return) Value(harden_sls_return) + +EnumValue +Enum(harden_sls) String(indirect-branch) Value(harden_sls_indirect_branch) + +EnumValue +Enum(harden_sls) String(all) Value(harden_sls_all) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 78ca7738df2..1e20efd6969 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1284,7 +1284,7 @@ See RS/6000 and PowerPC Options. -mstack-protector-guard-symbol=@var{symbol} -mmitigate-rop @gol -mgeneral-regs-only -mcall-ms2sysv-xlogues @gol -mindirect-branch=@var{choice} -mfunction-return=@var{choice} @gol --mindirect-branch-register} +-mindirect-branch-register -mharden-sls=@var{choice}} @emph{x86 Windows Options} @gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol @@ -28036,6 +28036,14 @@ not be reachable in the large code model. @opindex -mindirect-branch-register Force indirect call and jump via register. +@item -mharden-sls=@var{choice} +@opindex mharden-sls +Generate code to mitigate against straight line speculation (SLS) with +@var{choice}. The default is @samp{none} which disables all SLS +hardening. @samp{return} enables SLS hardening for function return. +@samp{indirect-branch} enables SLS hardening for indirect branch. +@samp{all} enables all SLS hardening. + @end table These @samp{-m} switches are supported in addition to the above diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-1.c b/gcc/testsuite/gcc.target/i386/harden-sls-1.c new file mode 100644 index 00000000000..6f70dc94a23 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/harden-sls-1.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mindirect-branch=thunk-extern -mharden-sls=all" } */ +/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */ + +extern void foo (void); + +void +bar (void) +{ + foo (); +} + +/* { dg-final { scan-assembler "jmp\[ \t\]+_?foo" } } */ +/* { dg-final { scan-assembler-not {int3} } } */ diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-2.c b/gcc/testsuite/gcc.target/i386/harden-sls-2.c new file mode 100644 index 00000000000..a7c59078d03 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/harden-sls-2.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mindirect-branch=thunk-extern -mharden-sls=all" } */ +/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */ + +extern void (*fptr) (void); + +void +foo (void) +{ + fptr (); +} + +/* { dg-final { scan-assembler "jmp\[ \t\]+_?__x86_indirect_thunk_(r|e)ax" } } */ +/* { dg-final { scan-assembler-times "int3" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-3.c b/gcc/testsuite/gcc.target/i386/harden-sls-3.c new file mode 100644 index 00000000000..1a6056b6d7b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/harden-sls-3.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mindirect-branch=thunk -mharden-sls=all" } */ +/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */ + +extern void (*fptr) (void); + +void +foo (void) +{ + fptr (); +} + +/* { dg-final { scan-assembler "jmp\[ \t\]+_?__x86_indirect_thunk_(r|e)ax" } } */ +/* { dg-final { scan-assembler-times "int3" 2 } } */ diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-4.c b/gcc/testsuite/gcc.target/i386/harden-sls-4.c new file mode 100644 index 00000000000..f70dd1379d3 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/harden-sls-4.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mindirect-branch=keep -mharden-sls=all" } */ +/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */ + +extern void (*fptr) (void); + +void +foo (void) +{ + fptr (); +} + +/* { dg-final { scan-assembler "jmp\[ \t\]+\\*_?fptr" { target { ! x32 } } } } */ +/* { dg-final { scan-assembler "movl\[ \t\]+fptr\\(%rip\\), %eax" { target x32 } } } */ +/* { dg-final { scan-assembler "jmp\[ \t\]+\\*%rax" { target x32 } } } */ +/* { dg-final { scan-assembler-times "int3" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-5.c b/gcc/testsuite/gcc.target/i386/harden-sls-5.c new file mode 100644 index 00000000000..613c44c6f82 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/harden-sls-5.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -mharden-sls=return" } */ +/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */ + +typedef void (*dispatch_t)(long offset); + +dispatch_t dispatch; + +int +male_indirect_jump (long offset) +{ + dispatch(offset); + return 0; +} + +/* { dg-final { scan-assembler-times "ret" 1 } } */ +/* { dg-final { scan-assembler-times "int3" 1 } } */ -- 2.36.1