From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id LzYQEYGE0mjnLg8AWB0awg (envelope-from ) for ; Tue, 23 Sep 2025 07:29:05 -0400 Authentication-Results: simark.ca; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=YsEmjUc9; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 35F431E047; Tue, 23 Sep 2025 07:29:05 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-3.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,RCVD_IN_VALIDITY_CERTIFIED_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED,RCVD_IN_VALIDITY_SAFE_BLOCKED autolearn=ham autolearn_force=no version=4.0.1 Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 1B3901E047 for ; Tue, 23 Sep 2025 07:29:04 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id BC9883858C24 for ; Tue, 23 Sep 2025 11:29:03 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org BC9883858C24 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=YsEmjUc9 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.16]) by sourceware.org (Postfix) with ESMTPS id 1E34B385840B for ; Tue, 23 Sep 2025 11:19:56 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 1E34B385840B Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=intel.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 1E34B385840B Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=198.175.65.16 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1758626396; cv=none; b=Dml6U/Oi8BrUDBqa6raK1vG6AAaNMkkgTZUNoGGhG2FbJCqhX06iZOeS7BbO7MTOLI5q+4NtMGEV/1ogTcSd/ZTXgLtC3ZhwlfeoDnKJEV3NQLwdeoMJaSsFjjI3jGCoiSx17t3BzijMkfb/tuuVFAEqkEqYZ5ADDkTnKH0tpQI= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1758626396; c=relaxed/simple; bh=iWeHELehSUzBSM6gpQiXimviyHB+Tr0274ZMVs1OO1g=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=BEircnOZwbjiHMv84mE9EvaoS2tYdpZGuO1Y0dnLDTNa0UwJn26ahTSgUbGIe2cUkHET2y8GLpFiiCNz81ZlGx8A2sYzF9v400m4L5TPYWq3Wiorpwzaix4JVG6YiPeiO9H9Z984WhtNbLzVXFUyaXxovxyu9L7vTJVlWXFKUz4= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1E34B385840B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1758626396; x=1790162396; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=iWeHELehSUzBSM6gpQiXimviyHB+Tr0274ZMVs1OO1g=; b=YsEmjUc9PiryAJtPda+ItV3ghO9w9z828S94Li2+uCgk9NlpqcnazBG5 OMjjdFs+qWwqUmJawnSXkDm7l8ZVTriIJ4iT96pBz0Yv0kRjyMs80HVhi sTG2IpZ2ohNmgzjV9pXE/XmsI48oy+xRkp2KL9wtbW5zwvxgN+Hz/Azm1 69+r0LBWvdbw6UaGUavE7wbY/PtGWJQpPqVnptCVBoDE8MPmJkPAKd/1U uu/gVMu3QSy8YbE/+Ijfu7IqZ2at1fbBO7sNqk5X4mFewD9/0FyX2w9BQ sBPU9yZQyEFy6jPqi2qJxyRG8OfBSE3jnoRttNwU5J3eZHYxxJXLlmyuY w==; X-CSE-ConnectionGUID: KxDnvYo1TBWoyu56bvBKmA== X-CSE-MsgGUID: 9TOXE3HwTm6skoqqe2bZEA== X-IronPort-AV: E=McAfee;i="6800,10657,11561"; a="61071804" X-IronPort-AV: E=Sophos;i="6.18,287,1751266800"; d="scan'208";a="61071804" Received: from fmviesa007.fm.intel.com ([10.60.135.147]) by orvoesa108.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Sep 2025 04:19:55 -0700 X-CSE-ConnectionGUID: eC0Z6ybXSSe7sqRTtM/WLQ== X-CSE-MsgGUID: 61HWJcU0TQShmUlnF6I5sw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.18,287,1751266800"; d="scan'208";a="176335309" Received: from gkldtt-dev-004.igk.intel.com (HELO localhost) ([10.123.221.202]) by fmviesa007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Sep 2025 04:19:54 -0700 From: Christina Schimpe To: gdb-patches@sourceware.org Subject: [PATCH 8/9] gdb: Implement the hook 'is_no_return_shadow_stack_address' for amd64 linux. Date: Tue, 23 Sep 2025 11:18:41 +0000 Message-Id: <20250923111842.4091694-9-christina.schimpe@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250923111842.4091694-1-christina.schimpe@intel.com> References: <20250923111842.4091694-1-christina.schimpe@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~public-inbox=simark.ca@sourceware.org There can be elements on the shadow stack which are not return addresses. This can happen, for instance, in case of signals on amd64 linux. The old shadow stack pointer is pushed in a special format with bit 63 set. |1...old SSP| - Pointer to old pre-signal ssp in sigframe token format (bit 63 set to 1) Linux kernel documentation: https://docs.kernel.org/next/x86/shstk.html. Implement the gdbarch hook is_no_return_shadow_stack_address to detect this scenario to print the shadow stack backtrace correctly. --- gdb/amd64-linux-tdep.c | 43 +++++++++++++++ .../amd64-shadow-stack-backtrace-signal.exp | 54 +++++++++++++++++++ .../gdb.arch/amd64-shadow-stack-signal.c | 31 +++++++++++ 3 files changed, 128 insertions(+) create mode 100644 gdb/testsuite/gdb.arch/amd64-shadow-stack-backtrace-signal.exp create mode 100644 gdb/testsuite/gdb.arch/amd64-shadow-stack-signal.c diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c index f0db3b7a1b4..d72525a4cab 100644 --- a/gdb/amd64-linux-tdep.c +++ b/gdb/amd64-linux-tdep.c @@ -1952,6 +1952,46 @@ amd64_linux_get_shadow_stack_pointer (gdbarch *gdbarch, regcache *regcache, return ssp; } +/* Return true, if FRAME is a valid shadow stack frame while FRAME.VALUE + does not refer to a return address. This can happen, for instance, in + case of signals. The old shadow stack pointer is pushed in a special + format with bit 63 set. */ + +static bool +amd64_linux_is_no_return_shadow_stack_address + (gdbarch *gdbarch, const shadow_stack_frame_info &frame) +{ + /* FRAME must be a valid shadow stack frame. */ + std::pair range; + gdb_assert (gdbarch_address_in_shadow_stack_memory_range (gdbarch, + frame.ssp, + &range)); + + /* In case bit 63 is not configured, the address on the shadow stack + should be a return address. */ + constexpr CORE_ADDR mask = (CORE_ADDR) 1 << 63; + if ((frame.value & mask) == 0) + return false; + + /* To compare the shadow stack pointer of the previous frame with the + value of FRAME, we must clear bit 63. */ + CORE_ADDR shadow_stack_val_cleared = (frame.value & (~mask)); + + /* Compute the previous/old SSP. The shadow stack grows downwards. To + compute the previous shadow stack pointer, we need to increment + FRAME.SSP. */ + CORE_ADDR prev_ssp + = frame.ssp + gdbarch_shadow_stack_element_size_aligned (gdbarch); + + /* We incremented FRAME.SSP by one element to compute PREV_SSP before. + In case FRAME.SSP points to the first element of the shadow stack, + PREV_SSP must point to the bottom of the shadow stack (RANGE.SECOND), + but not beyond that address. */ + gdb_assert (prev_ssp > range.first && prev_ssp <= range.second); + + return (shadow_stack_val_cleared == prev_ssp); +} + static void amd64_linux_init_abi_common (struct gdbarch_info info, struct gdbarch *gdbarch, int num_disp_step_buffers) @@ -2012,6 +2052,9 @@ amd64_linux_init_abi_common (struct gdbarch_info info, struct gdbarch *gdbarch, set_gdbarch_get_shadow_stack_pointer (gdbarch, amd64_linux_get_shadow_stack_pointer); + + set_gdbarch_is_no_return_shadow_stack_address + (gdbarch, amd64_linux_is_no_return_shadow_stack_address); } static void diff --git a/gdb/testsuite/gdb.arch/amd64-shadow-stack-backtrace-signal.exp b/gdb/testsuite/gdb.arch/amd64-shadow-stack-backtrace-signal.exp new file mode 100644 index 00000000000..727bc87f632 --- /dev/null +++ b/gdb/testsuite/gdb.arch/amd64-shadow-stack-backtrace-signal.exp @@ -0,0 +1,54 @@ +# Copyright 2024-2025 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Test shadow stack backtrace for signal handling on linux. + +require allow_ssp_tests {istarget "*-*-linux*"} + +standard_testfile amd64-shadow-stack-signal.c + +save_vars { ::env(GLIBC_TUNABLES) } { + + append_environment GLIBC_TUNABLES "glibc.cpu.hwcaps" "SHSTK" + + if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \ + {debug additional_flags="-fcf-protection=return"}] } { + return + } + + if { ![runto_main] } { + return + } + + gdb_breakpoint "handler" + gdb_test "continue" \ + ".*Program received signal SIGUSR1, User defined signal 1.*" \ + "continue until signal" + gdb_continue_to_breakpoint "continue to breakpoint in handler" + + # Create shadow stack frame based on ssp in frame 2 and with bit 63 set. + gdb_test "frame 2" ".*" "move to frame 2" + set ssp_frame2 [get_hexadecimal_valueof "\$pl3_ssp" ""] + set ssp_frame2 [format 0x%x [expr (1 << 63) | $ssp_frame2]] + + # Test shadow stack backtrace including ssp of frame 2 with bit 63 set. + gdb_test "bt shadow" \ + [multi_line \ + "#0\[ \t\]*$hex in \[^\r\n\]+" \ + "#1\[ \t\]*$ssp_frame2" \ + "#2\[ \t\]*$hex in \[^\r\n\]+" \ + ".*" ] \ + "test shadow stack backtrace for signal handling." +} diff --git a/gdb/testsuite/gdb.arch/amd64-shadow-stack-signal.c b/gdb/testsuite/gdb.arch/amd64-shadow-stack-signal.c new file mode 100644 index 00000000000..f3aff8fc19c --- /dev/null +++ b/gdb/testsuite/gdb.arch/amd64-shadow-stack-signal.c @@ -0,0 +1,31 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2024 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +void +handler (int signo) +{ +} + +int +main (void) +{ + signal (SIGUSR1, handler); + raise (SIGUSR1); + return 0; +} -- 2.34.1 Intel Deutschland GmbH Registered Address: Am Campeon 10, 85579 Neubiberg, Germany Tel: +49 89 99 8853-0, www.intel.de Managing Directors: Sean Fennelly, Jeffrey Schneiderman, Tiffany Doon Silva Chairperson of the Supervisory Board: Nicole Lau Registered Office: Munich Commercial Register: Amtsgericht Muenchen HRB 186928