From patchwork Fri May 14 03:34:55 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bill Schmidt X-Patchwork-Id: 1478304 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=iidDytuU; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FhDgh6NwKz9sWW for ; Fri, 14 May 2021 13:35:28 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 30E6D38930EE; Fri, 14 May 2021 03:35:24 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 30E6D38930EE DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1620963324; bh=jLaK7s7pVEf1lNzx3cY2n0KxBPzF5JF2bTWW9Ss4wys=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=iidDytuUAsmsVgRoUPhXnC4myTYA13kyh3Tw9iSogmCtjJh5+3fut1/WYt2Wd7jq7 dMaIQlzXeOA+OdLfdNm+QM8K3oY49Q6L1eshcEgzCGYp4dgKQMA5Vl33RhXiw9uvCD SJQvgufN54/UQOQFMvwY+CjShmwA/EOPW+iVJFno= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) by sourceware.org (Postfix) with ESMTPS id ACBC3389244E for ; Fri, 14 May 2021 03:35:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org ACBC3389244E Received: from pps.filterd (m0127361.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.43/8.16.0.43) with SMTP id 14E3Xqqo008427; Thu, 13 May 2021 23:35:20 -0400 Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 38hghb0yj8-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 13 May 2021 23:35:20 -0400 Received: from m0127361.ppops.net (m0127361.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 14E3Z0EU016534; Thu, 13 May 2021 23:35:19 -0400 Received: from ppma04wdc.us.ibm.com (1a.90.2fa9.ip4.static.sl-reverse.com [169.47.144.26]) by mx0a-001b2d01.pphosted.com with ESMTP id 38hghb0yj1-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 13 May 2021 23:35:19 -0400 Received: from pps.filterd (ppma04wdc.us.ibm.com [127.0.0.1]) by ppma04wdc.us.ibm.com (8.16.0.43/8.16.0.43) with SMTP id 14E3MMqT017294; Fri, 14 May 2021 03:35:18 GMT Received: from b03cxnp07027.gho.boulder.ibm.com (b03cxnp07027.gho.boulder.ibm.com [9.17.130.14]) by ppma04wdc.us.ibm.com with ESMTP id 38hc7a1kj5-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 14 May 2021 03:35:18 +0000 Received: from b03ledav004.gho.boulder.ibm.com (b03ledav004.gho.boulder.ibm.com [9.17.130.235]) by b03cxnp07027.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 14E3ZIJN22151596 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 14 May 2021 03:35:18 GMT Received: from b03ledav004.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 0792D78063; Fri, 14 May 2021 03:35:18 +0000 (GMT) Received: from b03ledav004.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id DFE7F7805E; Fri, 14 May 2021 03:35:17 +0000 (GMT) Received: from ltcden2-lp1.aus.stglabs.ibm.com (unknown [9.53.174.68]) by b03ledav004.gho.boulder.ibm.com (Postfix) with ESMTPS; Fri, 14 May 2021 03:35:17 +0000 (GMT) Received: by ltcden2-lp1.aus.stglabs.ibm.com (Postfix, from userid 1006) id 0A14C4169DC4; Thu, 13 May 2021 22:35:17 -0500 (CDT) To: gcc-patches@gcc.gnu.org Subject: [PATCH 2/4] rs6000: Emit ROP-mitigation instructions in prologue and epilogue Date: Thu, 13 May 2021 22:34:55 -0500 Message-Id: <95c7f5db172ccc5bc1a5f910952c0883066c0014.1620958221.git.wschmidt@linux.ibm.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: References: MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: yGyuC83B4xqUv7t6F2T_zFNd-CERr2pg X-Proofpoint-GUID: BYElbXcDE1mf4hWH-h8OR5qXJGRgNeZe X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.391, 18.0.761 definitions=2021-05-14_01:2021-05-12, 2021-05-14 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 adultscore=0 clxscore=1015 impostorscore=0 suspectscore=0 priorityscore=1501 malwarescore=0 bulkscore=0 lowpriorityscore=0 spamscore=0 phishscore=0 mlxscore=0 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2104190000 definitions=main-2105140021 X-Spam-Status: No, score=-12.8 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_NONE, 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-Patchwork-Original-From: Bill Schmidt via Gcc-patches From: Bill Schmidt Reply-To: Bill Schmidt Cc: Bill Schmidt , dje.gcc@gmail.com, segher@kernel.crashing.org Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" 2021-05-13 Bill Schmidt gcc/ * config/rs6000/rs6000-internal.h (rs6000_stack): Add rop_hash_save_offset and rop_hash_size. * config/rs6000/rs6000-logue.c (rs6000_stack_info): Compute rop_hash_size and rop_hash_save_offset. (debug_stack_info): Dump rop_hash_save_offset and rop_hash_size. (rs6000_emit_prologue): Emit hashst[p] in prologue. (rs6000_emit_epilogue): Emit hashchk[p] in epilogue. * config/rs6000/rs6000.md (unspec): Add UNSPEC_HASHST and UNSPEC_HASHCHK. (hashst): New define_insn. (hashchk): Likewise. --- gcc/config/rs6000/rs6000-internal.h | 2 + gcc/config/rs6000/rs6000-logue.c | 74 ++++++++++++++++++++++++++--- gcc/config/rs6000/rs6000.md | 47 ++++++++++++++++++ 3 files changed, 116 insertions(+), 7 deletions(-) diff --git a/gcc/config/rs6000/rs6000-internal.h b/gcc/config/rs6000/rs6000-internal.h index 428a7861a98..88cf9bd5692 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_hash_save_offset; /* offset to save ROP hash 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_hash_size; /* size of ROP hash 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 */ diff --git a/gcc/config/rs6000/rs6000-logue.c b/gcc/config/rs6000/rs6000-logue.c index b0ac183ceff..13c00e740d6 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 hash 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 @@ -716,6 +718,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); + info->rop_hash_size = 0; + + if (TARGET_POWER10 + && info->calls_p + && DEFAULT_ABI == ABI_ELFv2 + && rs6000_rop_protect) + info->rop_hash_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"); + } /* Determine if we need to save the condition code registers. */ if (save_reg_p (CR2_REGNO) @@ -808,6 +823,11 @@ rs6000_stack_info (void) /* Adjust for AltiVec case. */ info->ehrd_offset = info->altivec_save_offset - ehrd_size; + + /* Adjust for ROP protection. */ + info->rop_hash_save_offset + = info->altivec_save_offset - info->rop_hash_size; + info->ehrd_offset -= info->rop_hash_size; } else info->ehrd_offset = info->gp_save_offset - ehrd_size; @@ -849,6 +869,7 @@ rs6000_stack_info (void) + info->gp_size + info->altivec_size + info->altivec_padding_size + + info->rop_hash_size + ehrd_size + ehcr_size + info->cr_size @@ -987,6 +1008,10 @@ debug_stack_info (rs6000_stack_t *info) fprintf (stderr, "\tvrsave_save_offset = %5d\n", info->vrsave_save_offset); + if (info->rop_hash_size) + fprintf (stderr, "\trop_hash_save_offset = %5d\n", + info->rop_hash_save_offset); + if (info->lr_save_p) fprintf (stderr, "\tlr_save_offset = %5d\n", info->lr_save_offset); @@ -1026,6 +1051,9 @@ debug_stack_info (rs6000_stack_t *info) fprintf (stderr, "\taltivec_padding_size= %5d\n", info->altivec_padding_size); + if (info->rop_hash_size) + fprintf (stderr, "\trop_hash_size = %5d\n", info->rop_hash_size); + if (info->cr_size) fprintf (stderr, "\tcr_size = %5d\n", info->cr_size); @@ -3252,6 +3280,22 @@ rs6000_emit_prologue (void) } } + /* The ROP hash store must occur before a stack frame is created, + since the hash operates on r1. */ + /* 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_hash_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_hash_save_offset)); + rtx mem = gen_rtx_MEM (Pmode, addr); + rtx reg0 = gen_rtx_REG (Pmode, 0); + emit_insn (gen_hashst (mem, reg0)); + } + /* 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 +5024,22 @@ 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 + (since the hash involves r1), and is not performed for a sibcall. */ + if (TARGET_POWER10 + && rs6000_rop_protect + && info->rop_hash_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_hash_save_offset)); + rtx mem = gen_rtx_MEM (Pmode, addr); + rtx reg0 = gen_rtx_REG (Pmode, 0); + emit_insn (gen_hashchk (reg0, mem)); + } + 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..ce58ecd6b73 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -154,6 +154,8 @@ (define_c_enum "unspec" UNSPEC_CNTTZDM UNSPEC_PDEPD UNSPEC_PEXTD + UNSPEC_HASHST + UNSPEC_HASHCHK ]) ;; @@ -14948,6 +14950,51 @@ (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" +{ + static char templ[14]; + char p[2]; + + if (rs6000_privileged) + { + p[0] = 'p'; + p[1] = 0; + } + else + p[0] = 0; + sprintf (templ, "hashst%s %%1,%%0", p); + return templ; +} + [(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" +{ + static char templ[15]; + char p[2]; + + if (rs6000_privileged) + { + p[0] = 'p'; + p[1] = 0; + } + else + p[0] = 0; + sprintf (templ, "hashchk%s %%0,%%1", p); + return templ; +} + [(set_attr "type" "load")]) (include "sync.md")