From patchwork Sun Jun 4 17:06:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Samuel Thibault X-Patchwork-Id: 70570 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D39253858039 for ; Sun, 4 Jun 2023 17:06:33 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from sonata.ens-lyon.org (domu-toccata.ens-lyon.fr [140.77.166.138]) by sourceware.org (Postfix) with ESMTPS id 486AB3858D32 for ; Sun, 4 Jun 2023 17:06:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 486AB3858D32 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=ens-lyon.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=bounce.ens-lyon.org Received: from localhost (localhost [127.0.0.1]) by sonata.ens-lyon.org (Postfix) with ESMTP id B5F3E201B9; Sun, 4 Jun 2023 19:06:19 +0200 (CEST) Received: from sonata.ens-lyon.org ([127.0.0.1]) by localhost (sonata.ens-lyon.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id mheNiaVWWxyo; Sun, 4 Jun 2023 19:06:19 +0200 (CEST) Received: from begin (lfbn-bor-1-1163-184.w92-158.abo.wanadoo.fr [92.158.138.184]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by sonata.ens-lyon.org (Postfix) with ESMTPSA id 970C6201B8; Sun, 4 Jun 2023 19:06:19 +0200 (CEST) Received: from samy by begin with local (Exim 4.96) (envelope-from ) id 1q5rBL-00CUEW-0e; Sun, 04 Jun 2023 19:06:19 +0200 From: Samuel Thibault To: libc-alpha@sourceware.org Cc: Sergey Bugaev , commit-hurd@gnu.org Subject: [hurd, commited] hurd: Fix x86_64 sigreturn restoring bogus reply_port Date: Sun, 4 Jun 2023 19:06:19 +0200 Message-Id: <20230604170619.2976145-1-samuel.thibault@ens-lyon.org> X-Mailer: git-send-email 2.39.2 MIME-Version: 1.0 X-Spam-Status: No, score=-13.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, JMQ_SPF_NEUTRAL, KAM_DMARC_STATUS, RCVD_IN_DNSWL_LOW, SPF_HELO_PASS, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE 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: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" From: Sergey Bugaev Since the area of the user's stack we use for the registers dump (and otherwise as __sigreturn2's stack) can and does overlap the sigcontext, we have to be very careful about the order of loads and stores that we do. In particular we have to load sc_reply_port before we start clobbering the sigcontext. Signed-off-by: Sergey Bugaev --- sysdeps/mach/hurd/x86_64/sigreturn.c | 84 +++++++++++++++------------- 1 file changed, 46 insertions(+), 38 deletions(-) diff --git a/sysdeps/mach/hurd/x86_64/sigreturn.c b/sysdeps/mach/hurd/x86_64/sigreturn.c index f37ae119ca..94a379d382 100644 --- a/sysdeps/mach/hurd/x86_64/sigreturn.c +++ b/sysdeps/mach/hurd/x86_64/sigreturn.c @@ -24,7 +24,7 @@ unlock SS off sigstack. */ void __sigreturn2 (struct hurd_sigstate *ss, uintptr_t *usp, - struct sigcontext *scp) + mach_port_t sc_reply_port) { mach_port_t reply_port; _hurd_sigstate_unlock (ss); @@ -44,7 +44,7 @@ __sigreturn2 (struct hurd_sigstate *ss, uintptr_t *usp, if (__glibc_likely (MACH_PORT_VALID (reply_port))) (void) __mach_port_mod_refs (__mach_task_self (), reply_port, MACH_PORT_RIGHT_RECEIVE, -1); - THREAD_SETMEM (THREAD_SELF, reply_port, scp->sc_reply_port); + THREAD_SETMEM (THREAD_SELF, reply_port, sc_reply_port); asm volatile ( /* Point the stack to the register dump. */ @@ -77,6 +77,8 @@ __sigreturn (struct sigcontext *scp) { struct hurd_sigstate *ss; struct hurd_userlink *link = (void *) &scp[1]; + uintptr_t *usp; + mach_port_t sc_reply_port; if (__glibc_unlikely (scp == NULL || (scp->sc_mask & _SIG_CANT_MASK))) return __hurd_fail (EINVAL); @@ -118,42 +120,48 @@ __sigreturn (struct sigcontext *scp) in the format the i387 `frstor' instruction uses to restore it. */ asm volatile ("frstor %0" : : "m" (scp->sc_fpsave)); - { - /* There are convenient instructions to pop state off the stack, so we - copy the registers onto the user's stack, switch there, pop and - return. */ - - uintptr_t *usp = (uintptr_t *) (scp->sc_ursp - 128); - - *--usp = scp->sc_rip; - *--usp = scp->sc_rfl; - *--usp = scp->sc_rax; - *--usp = scp->sc_rcx; - *--usp = scp->sc_rdx; - *--usp = scp->sc_rbx; - *--usp = scp->sc_rbp; - *--usp = scp->sc_rsi; - *--usp = scp->sc_rdi; - *--usp = scp->sc_r15; - *--usp = scp->sc_r14; - *--usp = scp->sc_r13; - *--usp = scp->sc_r12; - *--usp = scp->sc_r11; - *--usp = scp->sc_r10; - *--usp = scp->sc_r9; - *--usp = scp->sc_r8; - - /* Switch to the user's stack that we have just prepared, and call - __sigreturn2. Clobber "memory" to make sure GCC flushes the stack - setup to actual memory. We align the stack as per the ABI, but pass - the original usp to __sigreturn2 as an argument. */ - asm volatile ("movq %1, %%rsp\n" - "andq $-16, %%rsp\n" - "call __sigreturn2" : - : "D" (ss), "S" (usp), "d" (scp) - : "memory"); - __builtin_unreachable (); - } + /* Copy the registers onto the user's stack, to be able to release the + altstack (by unlocking sigstate). Note that unless an altstack is used, + the sigcontext will itself be located on the user's stack, so we may well + be overwriting it here (or later in __sigreturn2). + + So: do this very carefully. First, load sc_reply_port, which is the only + other bit of sigcontext that __sigreturn2 needs. Then copy the registers + without reordering them, but skipping the ones we won't need. We have to + copy starting from the larger addresses down, since our register dump is + located at a larger address than the sigcontext. */ + + sc_reply_port = scp->sc_reply_port; + usp = (uintptr_t *) (scp->sc_ursp - 128); + + *--usp = scp->sc_rip; + *--usp = scp->sc_rfl; + *--usp = scp->sc_rax; + *--usp = scp->sc_rcx; + *--usp = scp->sc_rdx; + *--usp = scp->sc_rbx; + *--usp = scp->sc_rbp; + *--usp = scp->sc_rsi; + *--usp = scp->sc_rdi; + *--usp = scp->sc_r15; + *--usp = scp->sc_r14; + *--usp = scp->sc_r13; + *--usp = scp->sc_r12; + *--usp = scp->sc_r11; + *--usp = scp->sc_r10; + *--usp = scp->sc_r9; + *--usp = scp->sc_r8; + + /* Switch to the user's stack that we have just prepared, and call + __sigreturn2. Clobber "memory" to make sure GCC flushes the stack + setup to actual memory. We align the stack as per the ABI, but pass + the original usp to __sigreturn2 as an argument. */ + asm volatile ("movq %1, %%rsp\n" + "andq $-16, %%rsp\n" + "call __sigreturn2" : + : "D" (ss), "S" (usp), "d" (sc_reply_port) + : "memory"); + __builtin_unreachable (); } weak_alias (__sigreturn, sigreturn)