From patchwork Wed Sep 21 20:42:06 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 1348 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:5044:0:0:0:0:0 with SMTP id h4csp2118072wrt; Wed, 21 Sep 2022 13:43:45 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6Y85EJ4N2urP/2q2MgOdG8H5kD+ouXOYLH8wmZoIC2NsbJTQmV4zjQ8TFnFpNjoqgDNa3t X-Received: by 2002:a17:907:2723:b0:77c:8beb:643b with SMTP id d3-20020a170907272300b0077c8beb643bmr102245ejl.86.1663793025480; Wed, 21 Sep 2022 13:43:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1663793025; cv=none; d=google.com; s=arc-20160816; b=dBNw1B9awobiI5Op5BwZHz441pTwuDbOuakk48/Wi0RwlayYlaEF1BC7UufYQukfah LeRom1FxNkqytJ87kVR7oHgwvA7SliezN2gGzAnW4xqxUATDKB697oQoDhzzM9HnSYaF hDzliVQrRGKY1vpPUddauzItD6hSMZ0wR38edaFAB/w9ry54F0Abpobmj9lZWPtk2g+6 KtpnrfMPIx6GTpJOzwDWe+Dn4Z3ObRvChuJGF4IO3fKea4q7Gk3Q117s1wpyqiHlnLCa nXImqplBMdMlDXe5Ul8g4Sr9ZonCADibQ7Vr3dcixvmIPeOdLffMjAo8/MuTb4+h7jjI 4EBQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:from:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence :content-transfer-encoding:mime-version:message-id:date:subject:to :dmarc-filter:delivered-to:dkim-signature:dkim-filter; bh=pOsi3005qiA087ZZ44gvqi9xMykkSbqxrM8G7f96d9w=; b=JU7F6Fp7v+qfzZ7DTpZAkYuIc1ZLz38WuRDIvN27cOMrqM8jgB7+GvlXTdabYAXAdf 6bkj+/HW7IGB6Yd81obhOZXevYu9Mat6CN7YTBEEa0HqExzTI9SWwyEYM+xWVCMmRvv3 kwsj9GK6ct4t9SjCYGzjc0DJoJpTJv2uTi5jfLb23WxKBMZte7NA4hVlEIiHEncVwCI8 bwDN9crN0QxwlfCtle0Ls817XhuVH3yxaJZPx0FRXd2JcLbzAI1WvvACacdjXwmwq/4d 76dRtZTCaT8Sn/E0sDlhThd4aoITlKWVeXzMO/bE7mevJz8rBfLok8BT4OMS4V5k2l3S QJwA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=s7OlCzXx; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id e18-20020a17090658d200b0073d84d209b6si4056959ejs.418.2022.09.21.13.43.45 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Sep 2022 13:43:45 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=s7OlCzXx; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 2796B38582B8 for ; Wed, 21 Sep 2022 20:43:44 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2796B38582B8 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1663793024; bh=pOsi3005qiA087ZZ44gvqi9xMykkSbqxrM8G7f96d9w=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=s7OlCzXxI0k9OSU4izg1vm6xwTspN6BkpP0AYCbFv7kh9cpKy7rdT1WlHmfQPJowK ta4xSsPnhJa6XioNADIoo/iBRGUN6hXPIWCp7gE9APSD96ukGYm9N0qi5I4U0aUq+9 HzQimnUgtGQHlBbumKjS0S1d2B8BV6KMdTqE7lVw= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pj1-x1031.google.com (mail-pj1-x1031.google.com [IPv6:2607:f8b0:4864:20::1031]) by sourceware.org (Postfix) with ESMTPS id 30A933858CDB for ; Wed, 21 Sep 2022 20:43:00 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 30A933858CDB Received: by mail-pj1-x1031.google.com with SMTP id g1-20020a17090a708100b00203c1c66ae3so9473pjk.2 for ; Wed, 21 Sep 2022 13:43:00 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date; bh=pOsi3005qiA087ZZ44gvqi9xMykkSbqxrM8G7f96d9w=; b=CCPiDt8K6WeEV+UXzc6c6yXx5S/71myz+GZMH1onso7yQgpW8uyLBxEbsS+WuTprJF GRxq7JtjJ4LH5/CvYH3XP/VZmPKoiDMPDg+SewHhvJ/OczgjeTpmTCQErDL9erIShuJj +k06O83GhT45TBGBk4UL+JqFP+aP24xaHmkqV/aDWb5Sv6MfIjvJHOF0F7ysXQXSr3uu N8mtmyv1KTfr/qfnwjnUF0UTJQz/SCCKl415pJFU2b1rZr+j7Q1uXldMYGYHDhVcyUsH AHH+yaoTcKAAlQrZyeqRLm4zKLpwuD1ljJ2ndvRnQ9gzL60hWTNnNGjWRpYAJhGwm3qB xuUw== X-Gm-Message-State: ACrzQf2TaErRJdkfyLLR5B9z33HDY/xzOMZ22Gzhd9CKsvCNUahQJuaZ 2Nk9kMmHvo0E5Qw67Xi7l3qdG4PRe8o= X-Received: by 2002:a17:903:2601:b0:178:a68:82ee with SMTP id jd1-20020a170903260100b001780a6882eemr6542080plb.163.1663792978876; Wed, 21 Sep 2022 13:42:58 -0700 (PDT) Received: from gnu-tgl-3.localdomain ([172.56.31.7]) by smtp.gmail.com with ESMTPSA id c5-20020a170903234500b001755f43bc22sm2464417plh.175.2022.09.21.13.42.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Sep 2022 13:42:27 -0700 (PDT) Received: from gnu-tgl-3.. (localhost [IPv6:::1]) by gnu-tgl-3.localdomain (Postfix) with ESMTP id A3470C021F; Wed, 21 Sep 2022 13:42:06 -0700 (PDT) To: gcc-patches@gcc.gnu.org Subject: [PATCH] x86: Check corrupted return address when unwinding stack Date: Wed, 21 Sep 2022 13:42:06 -0700 Message-Id: <20220921204206.95480-1-hjl.tools@gmail.com> X-Mailer: git-send-email 2.37.3 MIME-Version: 1.0 X-Spam-Status: No, score=-3026.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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: "H.J. Lu via Gcc-patches" From: "H.J. Lu" Reply-To: "H.J. Lu" Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1744613435490541403?= X-GMAIL-MSGID: =?utf-8?q?1744613435490541403?= If shadow stack is enabled, when unwinding stack, we count how many stack frames we pop to reach the landing pad and adjust shadow stack by the same amount. When counting the stack frame, we compare the return address on normal stack against the return address on shadow stack. If they don't match, return _URC_FATAL_PHASE2_ERROR for the corrupted return address on normal stack. Don't check the return address for 1. Non-catchable exception where exception_class == 0. Process will be terminated. 2. Zero return address which marks the outermost stack frame. 3. Signal stack frame since kernel puts a restore token on shadow stack. * unwind-generic.h (_Unwind_Frames_Increment): Add the EXC argument. * unwind.inc (_Unwind_RaiseException_Phase2): Pass EXC to _Unwind_Frames_Increment. (_Unwind_ForcedUnwind_Phase2): Likewise. * config/i386/shadow-stack-unwind.h (_Unwind_Frames_Increment): Take the EXC argument. Return _URC_FATAL_PHASE2_ERROR if the return address on normal stack doesn't match the return address on shadow stack. --- libgcc/config/i386/shadow-stack-unwind.h | 51 ++++++++++++++++++++++-- libgcc/unwind-generic.h | 2 +- libgcc/unwind.inc | 4 +- 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/libgcc/config/i386/shadow-stack-unwind.h b/libgcc/config/i386/shadow-stack-unwind.h index 2b02682bdae..89d44165000 100644 --- a/libgcc/config/i386/shadow-stack-unwind.h +++ b/libgcc/config/i386/shadow-stack-unwind.h @@ -54,10 +54,39 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see aligned. If the original shadow stack is 8 byte aligned, we just need to pop 2 slots, one restore token, from shadow stack. Otherwise, we need to pop 3 slots, one restore token + 4 byte padding, from - shadow stack. */ -#ifndef __x86_64__ + shadow stack. + + When popping a stack frame, we compare the return address on normal + stack against the return address on shadow stack. If they don't match, + return _URC_FATAL_PHASE2_ERROR for the corrupted return address on + normal stack. Don't check the return address for + 1. Non-catchable exception where exception_class == 0. Process will + be terminated. + 2. Zero return address which marks the outermost stack frame. + 3. Signal stack frame since kernel puts a restore token on shadow + stack. + */ #undef _Unwind_Frames_Increment -#define _Unwind_Frames_Increment(context, frames) \ +#ifdef __x86_64__ +#define _Unwind_Frames_Increment(exc, context, frames) \ + { \ + frames++; \ + if (exc->exception_class != 0 \ + && _Unwind_GetIP (context) != 0 \ + && !_Unwind_IsSignalFrame (context)) \ + { \ + _Unwind_Word ssp = _get_ssp (); \ + if (ssp != 0) \ + { \ + ssp += 8 * frames; \ + _Unwind_Word ra = *(_Unwind_Word *) ssp; \ + if (ra != _Unwind_GetIP (context)) \ + return _URC_FATAL_PHASE2_ERROR; \ + } \ + } \ + } +#else +#define _Unwind_Frames_Increment(exc, context, frames) \ if (_Unwind_IsSignalFrame (context)) \ do \ { \ @@ -83,5 +112,19 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see } \ while (0); \ else \ - frames++; + { \ + frames++; \ + if (exc->exception_class != 0 \ + && _Unwind_GetIP (context) != 0) \ + { \ + _Unwind_Word ssp = _get_ssp (); \ + if (ssp != 0) \ + { \ + ssp += 4 * frames; \ + _Unwind_Word ra = *(_Unwind_Word *) ssp; \ + if (ra != _Unwind_GetIP (context)) \ + return _URC_FATAL_PHASE2_ERROR; \ + } \ + } \ + } #endif diff --git a/libgcc/unwind-generic.h b/libgcc/unwind-generic.h index a87c9b3ccf6..bf721282d03 100644 --- a/libgcc/unwind-generic.h +++ b/libgcc/unwind-generic.h @@ -292,6 +292,6 @@ EXCEPTION_DISPOSITION _GCC_specific_handler (PEXCEPTION_RECORD, void *, #define _Unwind_Frames_Extra(frames) /* Increment frame count. */ -#define _Unwind_Frames_Increment(context, frames) frames++ +#define _Unwind_Frames_Increment(exc, context, frames) frames++ #endif /* unwind.h */ diff --git a/libgcc/unwind.inc b/libgcc/unwind.inc index 5efd8af1b15..a7111a7b3a8 100644 --- a/libgcc/unwind.inc +++ b/libgcc/unwind.inc @@ -73,7 +73,7 @@ _Unwind_RaiseException_Phase2(struct _Unwind_Exception *exc, gcc_assert (!match_handler); uw_update_context (context, &fs); - _Unwind_Frames_Increment (context, frames); + _Unwind_Frames_Increment (exc, context, frames); } *frames_p = frames; @@ -191,7 +191,7 @@ _Unwind_ForcedUnwind_Phase2 (struct _Unwind_Exception *exc, /* Update cur_context to describe the same frame as fs, and discard the previous context if necessary. */ uw_advance_context (context, &fs); - _Unwind_Frames_Increment (context, frames); + _Unwind_Frames_Increment (exc, context, frames); } *frames_p = frames;