[PATCH] x86: Add -mharden-sls=[none|all|return|indirect-branch]
H.J. Lu
hjl.tools@gmail.com
Wed Nov 17 13:45:11 GMT 2021
On Wed, Nov 17, 2021 at 1:05 AM Uros Bizjak <ubizjak@gmail.com> wrote:
>
> On Tue, Nov 16, 2021 at 7:20 PM H.J. Lu via Gcc-patches
> <gcc-patches@gcc.gnu.org> wrote:
> >
> > 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/config/i386/i386-opts.h | 7 +++++
> > gcc/config/i386/i386.c | 30 ++++++++++++++++----
> > 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 | 14 +++++++++
> > 8 files changed, 116 insertions(+), 7 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
> >
> > diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h
> > index 04e4ad608fb..171d3106d0a 100644
> > --- a/gcc/config/i386/i386-opts.h
> > +++ b/gcc/config/i386/i386-opts.h
> > @@ -121,4 +121,11 @@ enum instrument_return {
> > instrument_return_nop5
> > };
> >
> > +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 cc9f9322fad..0a902d66321 100644
> > --- a/gcc/config/i386/i386.c
> > +++ b/gcc/config/i386/i386.c
> > @@ -5914,6 +5914,8 @@ output_indirect_thunk (unsigned int regno)
> > }
> >
> > 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.
> > @@ -15987,6 +15989,8 @@ ix86_output_jmp_thunk_or_indirect (const char *thunk_name, const int regno)
> > 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 (regno);
> > @@ -16212,10 +16216,14 @@ ix86_output_indirect_jmp (rtx call_op)
> > gcc_unreachable ();
> >
> > ix86_output_indirect_branch (call_op, "%0", true);
> > - return "";
> > + if ((ix86_harden_sls & harden_sls_indirect_branch))
> > + return "int3";
> > + else
> > + return "";
> > }
> > else
> > - return "%!jmp\t%A0";
> > + return ((ix86_harden_sls & harden_sls_indirect_branch)
> > + ? "%!jmp\t%A0\n\tint3" : "%!jmp\t%A0");
> > }
>
> Just change existing returns to fputs and end function with:
>
> return (ix86_harden_sls & harden_sls_indirect_branch) ? "int3" : "";
But fputs doesn't support %A0.
> > /* Output return instrumentation for current function if needed. */
> > @@ -16283,10 +16291,15 @@ ix86_output_function_return (bool long_p)
> > return "";
> > }
> >
> > - if (!long_p)
> > - return "%!ret";
> > + if ((ix86_harden_sls & harden_sls_return))
> > + return "%!ret\n\tint3";
> > + else
> > + {
> > + if (!long_p)
> > + return "%!ret";
> >
> > - return "rep%; ret";
> > + return "rep%; ret";
> > + }
> > }
>
> Also here.
But fputs doesn't know "%!".
>
> >
> > /* Output indirect function return. RET_OP is the function return
> > @@ -16381,7 +16394,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 b38ac13fc91..c5452c49597 100644
> > --- a/gcc/config/i386/i386.opt
> > +++ b/gcc/config/i386/i386.opt
> > @@ -1121,6 +1121,26 @@ mrecord-return
> > Target Var(ix86_flag_record_return) Init(0)
> > Generate a __return_loc section pointing to all return instrumentation code.
> >
> > +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(all) Value(harden_sls_all)
> > +
> > +EnumValue
> > +Enum(harden_sls) String(return) Value(harden_sls_return)
> > +
> > +EnumValue
> > +Enum(harden_sls) String(indirect-branch) Value(harden_sls_indirect_branch)
> > +
> > mavx512bf16
> > Target Mask(ISA2_AVX512BF16) Var(ix86_isa_flags2) Save
> > Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and
> > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> > index 6070288856c..f3b4b467765 100644
> > --- a/gcc/doc/invoke.texi
> > +++ b/gcc/doc/invoke.texi
> > @@ -1425,7 +1425,7 @@ See RS/6000 and PowerPC Options.
> > -mstack-protector-guard-symbol=@var{symbol} @gol
> > -mgeneral-regs-only -mcall-ms2sysv-xlogues -mrelax-cmpxchg-loop @gol
> > -mindirect-branch=@var{choice} -mfunction-return=@var{choice} @gol
> > --mindirect-branch-register -mneeded}
> > +-mindirect-branch-register -mharden-sls=@var{choice} -mneeded}
> >
> > @emph{x86 Windows Options}
> > @gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol
> > @@ -32382,6 +32382,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..c33147f11b5
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/harden-sls-4.c
> > @@ -0,0 +1,14 @@
> > +/* { 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" } } */
> > +/* { dg-final { scan-assembler-times "int3" 1 } } */
> > --
> > 2.33.1
> >
--
H.J.
More information about the Gcc-patches
mailing list