From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx0a-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) by sourceware.org (Postfix) with ESMTPS id 74120383802A for ; Mon, 26 Apr 2021 16:03:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 74120383802A Received: from pps.filterd (m0098414.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.43/8.16.0.43) with SMTP id 13QFim6l049463; Mon, 26 Apr 2021 12:03:14 -0400 Received: from pps.reinject (localhost [127.0.0.1]) by mx0b-001b2d01.pphosted.com with ESMTP id 3860e5gju2-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 26 Apr 2021 12:03:13 -0400 Received: from m0098414.ppops.net (m0098414.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 13QFk45S052955; Mon, 26 Apr 2021 12:03:13 -0400 Received: from ppma04dal.us.ibm.com (7a.29.35a9.ip4.static.sl-reverse.com [169.53.41.122]) by mx0b-001b2d01.pphosted.com with ESMTP id 3860e5gjtb-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 26 Apr 2021 12:03:13 -0400 Received: from pps.filterd (ppma04dal.us.ibm.com [127.0.0.1]) by ppma04dal.us.ibm.com (8.16.0.43/8.16.0.43) with SMTP id 13QFr3Wf002929; Mon, 26 Apr 2021 16:03:12 GMT Received: from b03cxnp07029.gho.boulder.ibm.com (b03cxnp07029.gho.boulder.ibm.com [9.17.130.16]) by ppma04dal.us.ibm.com with ESMTP id 384ay9b3r0-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 26 Apr 2021 16:03:12 +0000 Received: from b03ledav003.gho.boulder.ibm.com (b03ledav003.gho.boulder.ibm.com [9.17.130.234]) by b03cxnp07029.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 13QG3BUp36372790 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 26 Apr 2021 16:03:11 GMT Received: from b03ledav003.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id D16216A054; Mon, 26 Apr 2021 16:03:11 +0000 (GMT) Received: from b03ledav003.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 720046A04F; Mon, 26 Apr 2021 16:03:11 +0000 (GMT) Received: from lexx (unknown [9.163.27.240]) by b03ledav003.gho.boulder.ibm.com (Postfix) with ESMTP; Mon, 26 Apr 2021 16:03:11 +0000 (GMT) Message-ID: <703b4c9fd3aea70363c58b6b883b5868c27d57ba.camel@vnet.ibm.com> Subject: Re: [PATCH 2/4] rs6000: Emit ROP-protect instructions in prologue and epilogue From: will schmidt To: Bill Schmidt , gcc-patches@gcc.gnu.org Cc: dje.gcc@gmail.com, segher@kernel.crashing.org Date: Mon, 26 Apr 2021 11:03:10 -0500 In-Reply-To: <19e943394d781d0d063ba1f61eb990a443383719.1619400506.git.wschmidt@linux.ibm.com> References: <19e943394d781d0d063ba1f61eb990a443383719.1619400506.git.wschmidt@linux.ibm.com> Content-Type: text/plain; charset="UTF-8" X-Mailer: Evolution 3.28.5 (3.28.5-10.el7) Mime-Version: 1.0 Content-Transfer-Encoding: 7bit X-TM-AS-GCONF: 00 X-Proofpoint-GUID: RSoVPxwpYsCItozzfkue2Oe6vAqzoVIh X-Proofpoint-ORIG-GUID: A9BotoGZQzqZ5kkXZTHc7whrfDTD0a7s X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.391, 18.0.761 definitions=2021-04-26_07:2021-04-26, 2021-04-26 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxlogscore=999 suspectscore=0 adultscore=0 impostorscore=0 mlxscore=0 lowpriorityscore=0 priorityscore=1501 spamscore=0 phishscore=0 bulkscore=0 clxscore=1015 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2104060000 definitions=main-2104260121 X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_EF, GIT_PATCH_0, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 26 Apr 2021 16:03:16 -0000 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 > > 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")