public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: will schmidt <will_schmidt@vnet.ibm.com>
To: Bill Schmidt <wschmidt@linux.ibm.com>, gcc-patches@gcc.gnu.org
Cc: dje.gcc@gmail.com, segher@kernel.crashing.org
Subject: Re: [PATCH 2/4] rs6000: Emit ROP-protect instructions in prologue and epilogue
Date: Mon, 26 Apr 2021 11:03:10 -0500	[thread overview]
Message-ID: <703b4c9fd3aea70363c58b6b883b5868c27d57ba.camel@vnet.ibm.com> (raw)
In-Reply-To: <19e943394d781d0d063ba1f61eb990a443383719.1619400506.git.wschmidt@linux.ibm.com>

On Sun, 2021-04-25 at 20:50 -0500, Bill Schmidt via Gcc-patches wrote:
> Insert the hashst and hashchk instructions when -mrop-protect has been
> selected.  The encrypted save slot for ROP mitigation is placed
> between the parameter save area and the alloca space (if any;
> otherwise the local variable space).
> 
> Note that ROP-mitigation instructions are currently only provided for
> the ELFv2 ABI.
> 
> 2021-03-25  Bill Schmidt  <wschmidt@linux.ibm.com>
> 
> gcc/
> 	* config/rs6000/rs6000-internal.h (rs6000_stack): Add
> 	rop_check_save_offset and rop_check_size.
> 	* config/rs6000/rs6000-logue.c (rs6000_stack_info): Compute
> 	rop_check_size and rop_check_save_offset.
> 	(debug_stack_info): Dump rop_save_offset and rop_check_size.
> 	(rs6000_emit_prologue): Assert if WORLD_SAVE used with
> 	-mrop-protect; emit hashst[p] in prologue; emit hashchk[p] in
> 	epilogue.
> 	* config/rs6000/rs6000.md (unspec): Add UNSPEC_HASHST[P] and
> 	UNSPEC_HASHCHK[P].
> 	(hashst): New define_insn.
> 	(hashstp): Likewise.
> 	(hashchk): Likewise.
> 	(hashchkp): Likewise.

ok

> ---
>  gcc/config/rs6000/rs6000-internal.h |  2 +
>  gcc/config/rs6000/rs6000-logue.c    | 86 +++++++++++++++++++++++++----
>  gcc/config/rs6000/rs6000.md         | 39 +++++++++++++
>  3 files changed, 116 insertions(+), 11 deletions(-)
> 
> diff --git a/gcc/config/rs6000/rs6000-internal.h b/gcc/config/rs6000/rs6000-internal.h
> index 428a7861a98..8fc77ba6138 100644
> --- a/gcc/config/rs6000/rs6000-internal.h
> +++ b/gcc/config/rs6000/rs6000-internal.h
> @@ -39,6 +39,7 @@ typedef struct rs6000_stack {
>    int gp_save_offset;		/* offset to save GP regs from initial SP */
>    int fp_save_offset;		/* offset to save FP regs from initial SP */
>    int altivec_save_offset;	/* offset to save AltiVec regs from initial SP */
> +  int rop_check_save_offset;	/* offset to save ROP check from initial SP */
>    int lr_save_offset;		/* offset to save LR from initial SP */
>    int cr_save_offset;		/* offset to save CR from initial SP */
>    int vrsave_save_offset;	/* offset to save VRSAVE from initial SP */
> @@ -53,6 +54,7 @@ typedef struct rs6000_stack {
>    int gp_size;			/* size of saved GP registers */
>    int fp_size;			/* size of saved FP registers */
>    int altivec_size;		/* size of saved AltiVec registers */
> +  int rop_check_size;		/* size of ROP check slot */
>    int cr_size;			/* size to hold CR if not in fixed area */
>    int vrsave_size;		/* size to hold VRSAVE */
>    int altivec_padding_size;	/* size of altivec alignment padding */

ok

> diff --git a/gcc/config/rs6000/rs6000-logue.c b/gcc/config/rs6000/rs6000-logue.c
> index b0ac183ceff..10cf7a2de93 100644
> --- a/gcc/config/rs6000/rs6000-logue.c
> +++ b/gcc/config/rs6000/rs6000-logue.c
> @@ -595,19 +595,21 @@ rs6000_savres_strategy (rs6000_stack_t *info,
>  		+---------------------------------------+
>  		| Parameter save area (+padding*) (P)	|  32
>  		+---------------------------------------+
> -		| Alloca space (A)			|  32+P
> +		| Optional ROP check slot (R)		|  32+P
>  		+---------------------------------------+
> -		| Local variable space (L)		|  32+P+A
> +		| Alloca space (A)			|  32+P+R
>  		+---------------------------------------+
> -		| Save area for AltiVec registers (W)	|  32+P+A+L
> +		| Local variable space (L)		|  32+P+R+A
>  		+---------------------------------------+
> -		| AltiVec alignment padding (Y)		|  32+P+A+L+W
> +		| Save area for AltiVec registers (W)	|  32+P+R+A+L
>  		+---------------------------------------+
> -		| Save area for GP registers (G)	|  32+P+A+L+W+Y
> +		| AltiVec alignment padding (Y)		|  32+P+R+A+L+W
>  		+---------------------------------------+
> -		| Save area for FP registers (F)	|  32+P+A+L+W+Y+G
> +		| Save area for GP registers (G)	|  32+P+R+A+L+W+Y
>  		+---------------------------------------+
> -	old SP->| back chain to caller's caller		|  32+P+A+L+W+Y+G+F
> +		| Save area for FP registers (F)	|  32+P+R+A+L+W+Y+G
> +		+---------------------------------------+
> +	old SP->| back chain to caller's caller		|  32+P+R+A+L+W+Y+G+F
>  		+---------------------------------------+
> 
>       * If the alloca area is present, the parameter save area is

ok

> @@ -717,6 +719,19 @@ rs6000_stack_info (void)
>    /* Does this function call anything (apart from sibling calls)?  */
>    info->calls_p = (!crtl->is_leaf || cfun->machine->ra_needs_full_frame);
> 
> +  if (TARGET_POWER10 && info->calls_p
> +      && DEFAULT_ABI == ABI_ELFv2 && rs6000_rop_protect)
> +    info->rop_check_size = 8;
> +  else if (rs6000_rop_protect && DEFAULT_ABI != ABI_ELFv2)
> +    {
> +      /* We can't check this in rs6000_option_override_internal since
> +	 DEFAULT_ABI isn't established yet.  */
> +      error ("%qs requires the ELFv2 ABI", "-mrop-protect");
> +      info->rop_check_size = 0;
ok
> +    }
> +  else
> +    info->rop_check_size = 0;
> +
ok

>    /* Determine if we need to save the condition code registers.  */
>    if (save_reg_p (CR2_REGNO)
>        || save_reg_p (CR3_REGNO)
> @@ -806,8 +821,14 @@ rs6000_stack_info (void)
>  	  gcc_assert (info->altivec_size == 0
>  		      || info->altivec_save_offset % 16 == 0);
> 
> -	  /* Adjust for AltiVec case.  */
> -	  info->ehrd_offset = info->altivec_save_offset - ehrd_size;
> +	  if (info->rop_check_size != 0)
> +	    {
> +	      info->rop_check_save_offset
> +		= info->altivec_save_offset - info->rop_check_size;
> +	      info->ehrd_offset = info->rop_check_save_offset - ehrd_size;
> +	    }
> +	  else
> +	    info->ehrd_offset = info->altivec_save_offset - ehrd_size;
ok

>  	}
>        else
>  	info->ehrd_offset = info->gp_save_offset - ehrd_size;
> @@ -849,6 +870,7 @@ rs6000_stack_info (void)
>  				  + info->gp_size
>  				  + info->altivec_size
>  				  + info->altivec_padding_size
> +				  + info->rop_check_size
>  				  + ehrd_size
>  				  + ehcr_size
>  				  + info->cr_size
> @@ -987,6 +1009,10 @@ debug_stack_info (rs6000_stack_t *info)
>      fprintf (stderr, "\tvrsave_save_offset  = %5d\n",
>  	     info->vrsave_save_offset);
> 
> +  if (info->rop_check_size)
> +    fprintf (stderr, "\trop_check_save_offset = %5d\n",
> +	     info->rop_check_save_offset);
> +

ok

>    if (info->lr_save_p)
>      fprintf (stderr, "\tlr_save_offset      = %5d\n", info->lr_save_offset);
> 
> @@ -1026,6 +1052,9 @@ debug_stack_info (rs6000_stack_t *info)
>      fprintf (stderr, "\taltivec_padding_size= %5d\n",
>  	     info->altivec_padding_size);
> 
> +  if (info->rop_check_size)
> +    fprintf (stderr, "\trop_check_size      = %5d\n", info->rop_check_size);
> +
>    if (info->cr_size)
>      fprintf (stderr, "\tcr_size             = %5d\n", info->cr_size);
> 
> @@ -3044,7 +3073,6 @@ rs6000_emit_prologue (void)
>  	cfun->machine->r2_setup_needed = true;
>      }
> 
> -
>    if (flag_stack_usage_info)
>      current_function_static_stack_size = info->total_size;
> 
> @@ -3105,7 +3133,8 @@ rs6000_emit_prologue (void)
>  		  && (!crtl->calls_eh_return
>  		      || info->ehrd_offset == -432)
>  		  && info->vrsave_save_offset == -224
> -		  && info->altivec_save_offset == -416);
> +		  && info->altivec_save_offset == -416
> +		  && !rs6000_rop_protect);
> 

ok


>        treg = gen_rtx_REG (SImode, 11);
>        emit_move_insn (treg, GEN_INT (-info->total_size));
> @@ -3252,6 +3281,24 @@ rs6000_emit_prologue (void)
>  	}
>      }
> 
> +  /* The ROP hash store must occur before a stack frame is created.  */
> +  /* NOTE: The hashst isn't needed if we're going to do a sibcall,
> +     but there's no way to know that here.  Harmless except for
> +     performance, of course.  */
> +  if (TARGET_POWER10 && rs6000_rop_protect && info->rop_check_size != 0)
> +    {
> +      gcc_assert (DEFAULT_ABI == ABI_ELFv2);
> +      rtx stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
> +      rtx addr = gen_rtx_PLUS (Pmode, stack_ptr,
> +			       GEN_INT (info->rop_check_save_offset));
> +      rtx mem = gen_rtx_MEM (Pmode, addr);
> +      rtx reg0 = gen_rtx_REG (Pmode, 0);
> +      if (rs6000_privileged)
> +	emit_insn (gen_hashstp (mem, reg0));
> +      else
> +	emit_insn (gen_hashst (mem, reg0));
> +    }
> +

ok


>    /* If we need to save CR, put it into r12 or r11.  Choose r12 except when
>       r12 will be needed by out-of-line gpr save.  */
>    cr_save_regno = ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
> @@ -4980,6 +5027,23 @@ rs6000_emit_epilogue (enum epilogue_type epilogue_type)
>        emit_insn (gen_add3_insn (sp_reg_rtx, sp_reg_rtx, sa));
>      }
> 
> +  /* The ROP hash check must occur after the stack pointer is restored,
> +     and is not performed for a sibcall.  */
> +  if (TARGET_POWER10 && rs6000_rop_protect && info->rop_check_size != 0
> +      && epilogue_type != EPILOGUE_TYPE_SIBCALL)
> +    {
> +      gcc_assert (DEFAULT_ABI == ABI_ELFv2);
> +      rtx stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
> +      rtx addr = gen_rtx_PLUS (Pmode, stack_ptr,
> +			       GEN_INT (info->rop_check_save_offset));
> +      rtx mem = gen_rtx_MEM (Pmode, addr);
> +      rtx reg0 = gen_rtx_REG (Pmode, 0);
> +      if (rs6000_privileged)
> +	emit_insn (gen_hashchkp (reg0, mem));
> +      else
> +	emit_insn (gen_hashchk (reg0, mem));
> +    }
> +

ok

>    if (epilogue_type != EPILOGUE_TYPE_SIBCALL && restoring_FPRs_inline)
>      {
>        if (cfa_restores)
> diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
> index c8cdc42533c..eec2e7532e1 100644
> --- a/gcc/config/rs6000/rs6000.md
> +++ b/gcc/config/rs6000/rs6000.md
> @@ -154,6 +154,10 @@ (define_c_enum "unspec"
>     UNSPEC_CNTTZDM
>     UNSPEC_PDEPD
>     UNSPEC_PEXTD
> +   UNSPEC_HASHST
> +   UNSPEC_HASHSTP
> +   UNSPEC_HASHCHK
> +   UNSPEC_HASHCHKP
>    ])
> 
>  ;;
> @@ -14948,6 +14952,41 @@ (define_insn "*cmpeqb_internal"
>    "TARGET_P9_MISC && TARGET_64BIT"
>    "cmpeqb %0,%1,%2"
>    [(set_attr "type" "logical")])
> +
> +
> +;; ROP mitigation instructions.
> +
> +(define_insn "hashst"
> +  [(set (match_operand:DI 0 "simple_offsettable_mem_operand" "=m")
> +        (unspec:DI [(match_operand:DI 1 "int_reg_operand" "r")]
> +	           UNSPEC_HASHST))]
> +  "TARGET_POWER10 && rs6000_rop_protect"
> +  "hashst %1,%0"
> +  [(set_attr "type" "store")])
> +
> +(define_insn "hashstp"
> +  [(set (match_operand:DI 0 "simple_offsettable_mem_operand" "=m")
> +        (unspec:DI [(match_operand:DI 1 "int_reg_operand" "r")]
> +	           UNSPEC_HASHSTP))]
> +  "TARGET_POWER10 && rs6000_rop_protect && rs6000_privileged"
> +  "hashstp %1,%0"
> +  [(set_attr "type" "store")])
> +
> +(define_insn "hashchk"
> +  [(unspec_volatile [(match_operand:DI 0 "int_reg_operand" "r")
> +		     (match_operand:DI 1 "simple_offsettable_mem_operand" "m")]
> +		    UNSPEC_HASHCHK)]
> +  "TARGET_POWER10 && rs6000_rop_protect"
> +  "hashchk %0,%1"
> +  [(set_attr "type" "load")])
> +
> +(define_insn "hashchkp"
> +  [(unspec_volatile [(match_operand:DI 0 "int_reg_operand" "r")
> +		     (match_operand:DI 1 "simple_offsettable_mem_operand" "m")]
> +		    UNSPEC_HASHCHKP)]
> +  "TARGET_POWER10 && rs6000_rop_protect && rs6000_privileged"
> +  "hashchkp %0,%1"
> +  [(set_attr "type" "load")])

ok


lgtm, 
thanks,
-Will

>  
> 
>  (include "sync.md")


  reply	other threads:[~2021-04-26 16:03 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-26  1:50 [PATCH 0/4] [rs6000] ROP support Bill Schmidt
2021-04-26  1:50 ` [PATCH 1/4] rs6000: Add -mrop-protect and -mprivileged flags Bill Schmidt
2021-04-26 16:02   ` will schmidt
2021-05-12 20:40     ` Segher Boessenkool
2021-05-12 20:26   ` Segher Boessenkool
2021-04-26  1:50 ` [PATCH 2/4] rs6000: Emit ROP-protect instructions in prologue and epilogue Bill Schmidt
2021-04-26 16:03   ` will schmidt [this message]
2021-05-12 23:09   ` Segher Boessenkool
2021-04-26  1:50 ` [PATCH 3/4] rs6000: Conditionally define __ROP_PROTECT__ Bill Schmidt
2021-04-26 16:03   ` will schmidt
2021-05-12 23:19     ` Segher Boessenkool
2021-05-12 23:20   ` Segher Boessenkool
2021-04-26  1:50 ` [PATCH 4/4] rs6000: Add ROP tests Bill Schmidt
2021-04-26 16:04   ` will schmidt
2021-04-26 19:27     ` Bill Schmidt
2021-05-12 23:25       ` Segher Boessenkool
2021-05-12 23:42   ` Segher Boessenkool
2021-04-26 16:01 ` [PATCH 0/4] [rs6000] ROP support will schmidt
2021-04-26 16:33   ` Bill Schmidt
2021-05-11 15:56 ` Bill Schmidt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=703b4c9fd3aea70363c58b6b883b5868c27d57ba.camel@vnet.ibm.com \
    --to=will_schmidt@vnet.ibm.com \
    --cc=dje.gcc@gmail.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=segher@kernel.crashing.org \
    --cc=wschmidt@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).