From patchwork Mon Apr 26 01:50:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bill Schmidt X-Patchwork-Id: 1470149 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=8.43.85.97; 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=ScbgL+tn; dkim-atps=neutral Received: from sourceware.org (ip-8-43-85-97.sourceware.org [8.43.85.97]) (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 4FT7CM0c78z9sW7 for ; Mon, 26 Apr 2021 11:50:55 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C0AD53839C47; Mon, 26 Apr 2021 01:50:40 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C0AD53839C47 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1619401840; bh=R+v9qzt/snhFDGxuaRgDPHnfenYDVjjofxRH8DVbsXU=; h=To:Subject:Date:In-Reply-To:References:In-Reply-To:References: List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help: List-Subscribe:From:Reply-To:Cc:From; b=ScbgL+tn4vVtPpQs8tijeBSTs8uM+akWZBWmnDVm2dGUCHIa9Gdg/KQSibrBWjqAf GpPV0qGuAUtDci+cdt3AK2/B+95wkDHiDhIlEEVsLijDvfHwo5d9G4RPiwysuXGzJY 6Z2/KEDix/Y9wZ6unDkYTA7Fm7FFhSfqOyRKKE1Q= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) by sourceware.org (Postfix) with ESMTPS id B6E42385780C for ; Mon, 26 Apr 2021 01:50:36 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org B6E42385780C Received: from pps.filterd (m0187473.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.43/8.16.0.43) with SMTP id 13Q1Z2P4181373; Sun, 25 Apr 2021 21:50:35 -0400 Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 385hwn2740-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sun, 25 Apr 2021 21:50:35 -0400 Received: from m0187473.ppops.net (m0187473.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 13Q1ZLZ2182131; Sun, 25 Apr 2021 21:50:35 -0400 Received: from ppma03dal.us.ibm.com (b.bd.3ea9.ip4.static.sl-reverse.com [169.62.189.11]) by mx0a-001b2d01.pphosted.com with ESMTP id 385hwn273u-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sun, 25 Apr 2021 21:50:35 -0400 Received: from pps.filterd (ppma03dal.us.ibm.com [127.0.0.1]) by ppma03dal.us.ibm.com (8.16.0.43/8.16.0.43) with SMTP id 13Q1lpIr023172; Mon, 26 Apr 2021 01:50:34 GMT Received: from b01cxnp22033.gho.pok.ibm.com (b01cxnp22033.gho.pok.ibm.com [9.57.198.23]) by ppma03dal.us.ibm.com with ESMTP id 384ay8nr0k-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 26 Apr 2021 01:50:34 +0000 Received: from b01ledav006.gho.pok.ibm.com (b01ledav006.gho.pok.ibm.com [9.57.199.111]) by b01cxnp22033.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 13Q1oXHA32571756 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 26 Apr 2021 01:50:33 GMT Received: from b01ledav006.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 7EDD0AC05B; Mon, 26 Apr 2021 01:50:33 +0000 (GMT) Received: from b01ledav006.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5C1E7AC059; Mon, 26 Apr 2021 01:50:33 +0000 (GMT) Received: from localhost (unknown [9.40.194.84]) by b01ledav006.gho.pok.ibm.com (Postfix) with ESMTP; Mon, 26 Apr 2021 01:50:33 +0000 (GMT) To: gcc-patches@gcc.gnu.org Subject: [PATCH 2/4] rs6000: Emit ROP-protect instructions in prologue and epilogue Date: Sun, 25 Apr 2021 20:50:16 -0500 Message-Id: <19e943394d781d0d063ba1f61eb990a443383719.1619400506.git.wschmidt@linux.ibm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: References: In-Reply-To: References: X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: UIRDOe4Oa1D9F59k4DIXkyY68gTVq1LG X-Proofpoint-GUID: RE9SZUrRrqNzVoHshRYp9115AP40GVrB X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.391, 18.0.761 definitions=2021-04-25_11:2021-04-23, 2021-04-25 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 adultscore=0 suspectscore=0 phishscore=0 mlxscore=0 malwarescore=0 priorityscore=1501 mlxlogscore=999 lowpriorityscore=0 bulkscore=0 spamscore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2104060000 definitions=main-2104260006 X-Spam-Status: No, score=-9.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_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-Patchwork-Original-From: Bill Schmidt via Gcc-patches From: Bill Schmidt Reply-To: Bill Schmidt Cc: dje.gcc@gmail.com, segher@kernel.crashing.org Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" 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. --- 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 */ 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 @@ -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; + } + else + info->rop_check_size = 0; + /* 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; } 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); + 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); 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)); + } + /* 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)); + } + 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")]) (include "sync.md")