x86: Add -mharden-sls=[none|all|return|indirect-branch]

Message ID 20211116182003.3859036-1-hjl.tools@gmail.com
State New
Headers
Series x86: Add -mharden-sls=[none|all|return|indirect-branch] |

Commit Message

H.J. Lu Nov. 16, 2021, 6:20 p.m. UTC
  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
  

Comments

Uros Bizjak Nov. 17, 2021, 9:05 a.m. UTC | #1
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" : "";

>  /* 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.

>
>  /* 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. Lu Nov. 17, 2021, 1:45 p.m. UTC | #2
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
> >
  
Uros Bizjak Nov. 17, 2021, 2:07 p.m. UTC | #3
On Wed, Nov 17, 2021 at 2:46 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> 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.

Sorry for the thinko, output_asm_insn instead of fputs will do the trick.

Uros.

>
> > >  /* 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.
  
H.J. Lu Nov. 17, 2021, 3:39 p.m. UTC | #4
On Wed, Nov 17, 2021 at 6:08 AM Uros Bizjak <ubizjak@gmail.com> wrote:
>
> On Wed, Nov 17, 2021 at 2:46 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > 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.
>
> Sorry for the thinko, output_asm_insn instead of fputs will do the trick.

Fixed in the v2 patch.

Thanks.

> Uros.
>
> >
> > > >  /* 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.
  

Patch

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");
 }
 
 /* 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";
+    }
 }
 
 /* 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 } } */