From patchwork Sat Jun 6 18:43:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Samuel Thibault X-Patchwork-Id: 1304561 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=sourceware.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=libc-alpha-bounces@sourceware.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ens-lyon.org Received: from 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 RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49fT214VZYz9sRR for ; Sun, 7 Jun 2020 04:44:09 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A3D4A386F02B; Sat, 6 Jun 2020 18:44:07 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from hera.aquilenet.fr (hera.aquilenet.fr [IPv6:2a0c:e300::1]) by sourceware.org (Postfix) with ESMTPS id E9A72386F02B for ; Sat, 6 Jun 2020 18:44:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org E9A72386F02B Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=ens-lyon.org Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=samuel.thibault@ens-lyon.org Received: from localhost (localhost [127.0.0.1]) by hera.aquilenet.fr (Postfix) with ESMTP id DF9EE94CF; Sat, 6 Jun 2020 20:44:00 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at aquilenet.fr Received: from hera.aquilenet.fr ([127.0.0.1]) by localhost (hera.aquilenet.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id HFtDzneoUhXP; Sat, 6 Jun 2020 20:43:59 +0200 (CEST) Received: from function.home (unknown [IPv6:2a01:cb19:956:1b00:9eb6:d0ff:fe88:c3c7]) by hera.aquilenet.fr (Postfix) with ESMTPSA id 7DE5E12F2; Sat, 6 Jun 2020 20:43:59 +0200 (CEST) Received: from samy by function.home with local (Exim 4.93) (envelope-from ) id 1jhdnS-00FbW2-Ct; Sat, 06 Jun 2020 20:43:58 +0200 From: Samuel Thibault To: libc-alpha@sourceware.org Subject: [hurd, commited] hurd: fix clearing SS_ONSTACK when longjmp-ing from sighandler Date: Sat, 6 Jun 2020 20:43:58 +0200 Message-Id: <20200606184358.3719089-1-samuel.thibault@ens-lyon.org> X-Mailer: git-send-email 2.26.2 MIME-Version: 1.0 X-Spam-Status: No, score=-12.7 required=5.0 tests=BAYES_00, GIT_PATCH_0, JMQ_SPF_NEUTRAL, KAM_DMARC_STATUS, KAM_SHORT, SPF_HELO_PASS, SPF_NEUTRAL, 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: 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: , Cc: commit-hurd@gnu.org Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" * sysdeps/i386/htl/Makefile: New file. * sysdeps/i386/htl/tcb-offsets.sym: New file. * sysdeps/mach/hurd/i386/Makefile [setjmp] (gen-as-const-headers): Add signal-defines.sym. * sysdeps/mach/hurd/i386/____longjmp_chk.S: Include tcb-offsets.h. (____longjmp_chk): Harmonize with i386's __longjmp. Clear SS_ONSTACK when jumping off the alternate stack. * sysdeps/mach/hurd/i386/__longjmp.S: New file. --- sysdeps/i386/htl/Makefile | 20 ++++++ sysdeps/i386/htl/tcb-offsets.sym | 8 +++ sysdeps/mach/hurd/i386/Makefile | 4 ++ sysdeps/mach/hurd/i386/____longjmp_chk.S | 70 +++++++++++--------- sysdeps/mach/hurd/i386/__longjmp.S | 84 ++++++++++++++++++++++++ 5 files changed, 154 insertions(+), 32 deletions(-) create mode 100644 sysdeps/i386/htl/Makefile create mode 100644 sysdeps/i386/htl/tcb-offsets.sym create mode 100644 sysdeps/mach/hurd/i386/__longjmp.S diff --git a/sysdeps/i386/htl/Makefile b/sysdeps/i386/htl/Makefile new file mode 100644 index 0000000000..8573ce6990 --- /dev/null +++ b/sysdeps/i386/htl/Makefile @@ -0,0 +1,20 @@ +# Copyright (C) 2020 Free Software Foundation, Inc. +# This file is part of the GNU C Library. + +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. + +# The GNU C Library 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 +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, see +# . + +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif diff --git a/sysdeps/i386/htl/tcb-offsets.sym b/sysdeps/i386/htl/tcb-offsets.sym new file mode 100644 index 0000000000..7b7c719369 --- /dev/null +++ b/sysdeps/i386/htl/tcb-offsets.sym @@ -0,0 +1,8 @@ +#include +#include +#include + +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) +SYSINFO_OFFSET offsetof (tcbhead_t, sysinfo) +POINTER_GUARD offsetof (tcbhead_t, pointer_guard) +SIGSTATE_OFFSET offsetof (tcbhead_t, _hurd_sigstate) diff --git a/sysdeps/mach/hurd/i386/Makefile b/sysdeps/mach/hurd/i386/Makefile index 068f7d0419..495b927b82 100644 --- a/sysdeps/mach/hurd/i386/Makefile +++ b/sysdeps/mach/hurd/i386/Makefile @@ -7,6 +7,10 @@ ifeq ($(subdir),debug) gen-as-const-headers += signal-defines.sym endif +ifeq ($(subdir),setjmp) +gen-as-const-headers += signal-defines.sym +endif + ifeq ($(subdir),csu) ifeq (yes,$(build-shared)) sysdep_routines += divdi3 diff --git a/sysdeps/mach/hurd/i386/____longjmp_chk.S b/sysdeps/mach/hurd/i386/____longjmp_chk.S index 819e5dc875..4d3a331728 100644 --- a/sysdeps/mach/hurd/i386/____longjmp_chk.S +++ b/sysdeps/mach/hurd/i386/____longjmp_chk.S @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -47,65 +48,70 @@ longjmp_msg: .text ENTRY (____longjmp_chk) - movl 4(%esp), %ecx /* User's jmp_buf in %ecx. */ + movl 4(%esp), %eax /* User's jmp_buf in %eax. */ /* Save the return address now. */ - movl (JB_PC*4)(%ecx), %edx + movl (JB_PC*4)(%eax), %edx /* Get the stack pointer. */ - movl (JB_SP*4)(%ecx), %edi - cfi_undefined(%edi) + movl (JB_SP*4)(%eax), %ecx + cfi_undefined(%ecx) #ifdef PTR_DEMANGLE PTR_DEMANGLE (%edx) - PTR_DEMANGLE (%edi) + PTR_DEMANGLE (%ecx) #endif - cmpl %edi, %esp + movl %gs:SIGSTATE_OFFSET,%edi + + testl $SS_ONSTACK, (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_FLAGS__OFFSET)(%edi) + jnz .Lonstack + + /* We were on the main stack */ + + cmpl %ecx, %esp /* Jumping to a higher-address frame is always allowed. */ jbe .Lok - /* Passing here, we're either about to do something invalid, or we're - executing on an alternative signal stack. */ + /* Otherwise it's not allowed. */ + CALL_FAIL - /* TODO: need locking? */ - /* struct hurd_sigstate * _hurd_self_sigstate (void) */ - call HIDDEN_JUMPTARGET(_hurd_self_sigstate) - /* TODO: %eax and %eax->sigaltstack are always valid? */ +.Lonstack: + /* We were on the alternate stack, can't really easily check anything + since longjmp may get us out of the alternate stack. */ - testl $SS_ONSTACK, (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_FLAGS__OFFSET)(%eax) - /* Fail if SS_ONSTACK is not set. */ - jz .Lfail + cmpl (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_SP__OFFSET)(%edi), %ecx + jb .Loks /* We jump below the alternate stack, switch. */ - movl (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_SP__OFFSET)(%eax), %ebx - addl (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_SIZE__OFFSET)(%eax), %ebx - subl %edi, %ebx - cmpl (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_SIZE__OFFSET)(%eax), %ebx - /* TODO: comment this calculation. */ - jae .Lok + movl (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_SP__OFFSET)(%edi), %ebx + addl (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_SIZE__OFFSET)(%edi), %ebx + cmpl %ebx, %ecx + jb .Lok /* We jump inside the alternate stack, do not switch. */ -.Lfail: CALL_FAIL + /* We jump above the alternate stack, switch. */ + +.Loks: /* We jump out of the alternate stack, clear SS_ONSTACK flag. */ + andl $~(SS_ONSTACK), (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_FLAGS__OFFSET)(%edi) .Lok: /* We add unwind information for the target here. */ - cfi_def_cfa(%ecx, 0) + cfi_def_cfa(%eax, 0) cfi_register(%eip, %edx) - cfi_register(%esp, %edi) + cfi_register(%esp, %ecx) cfi_offset(%ebx, JB_BX*4) cfi_offset(%esi, JB_SI*4) cfi_offset(%edi, JB_DI*4) cfi_offset(%ebp, JB_BP*4) - - movl 8(%esp), %eax /* Second argument is return value. */ - movl %edi, %esp - /* Restore registers. */ - movl (JB_BX*4)(%ecx), %ebx - movl (JB_SI*4)(%ecx), %esi - movl (JB_DI*4)(%ecx), %edi - movl (JB_BP*4)(%ecx), %ebp + movl (JB_BX*4)(%eax), %ebx + movl (JB_SI*4)(%eax), %esi + movl (JB_DI*4)(%eax), %edi + movl (JB_BP*4)(%eax), %ebp cfi_restore(%ebx) cfi_restore(%esi) cfi_restore(%edi) cfi_restore(%ebp) + movl 8(%esp), %eax /* Second argument is return value. */ + movl %ecx, %esp + /* Jump to saved PC. */ jmp *%edx END (____longjmp_chk) diff --git a/sysdeps/mach/hurd/i386/__longjmp.S b/sysdeps/mach/hurd/i386/__longjmp.S new file mode 100644 index 0000000000..d123c214c9 --- /dev/null +++ b/sysdeps/mach/hurd/i386/__longjmp.S @@ -0,0 +1,84 @@ +/* Copyright (C) 2001-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include + +#include +/* #include */ +#define SS_ONSTACK 1 + + .text +ENTRY (__longjmp) + movl 4(%esp), %eax /* User's jmp_buf in %eax. */ + + /* Save the return address now. */ + movl (JB_PC*4)(%eax), %edx + /* Get the stack pointer. */ + movl (JB_SP*4)(%eax), %ecx + cfi_undefined(%ecx) +#ifdef PTR_DEMANGLE + PTR_DEMANGLE (%edx) + PTR_DEMANGLE (%ecx) +#endif + + movl %gs:SIGSTATE_OFFSET,%edi + + testl $SS_ONSTACK, (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_FLAGS__OFFSET)(%edi) + jz .Lok + + /* We were on the alternate stack. */ + + cmpl (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_SP__OFFSET)(%edi), %ecx + jb .Loks /* We jump below the alternate stack, switch. */ + + movl (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_SP__OFFSET)(%edi), %ebx + addl (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_SIZE__OFFSET)(%edi), %ebx + cmpl %ebx, %ecx + jb .Lok /* We jump inside the alternate stack, do not switch. */ + + /* We jump above the alternate stack, switch. */ + +.Loks: /* We jump out of the alternate stack, clear SS_ONSTACK flag. */ + andl $~(SS_ONSTACK), (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_FLAGS__OFFSET)(%edi) + +.Lok: /* We add unwind information for the target here. */ + cfi_def_cfa(%eax, 0) + cfi_register(%eip, %edx) + cfi_register(%esp, %ecx) + cfi_offset(%ebx, JB_BX*4) + cfi_offset(%esi, JB_SI*4) + cfi_offset(%edi, JB_DI*4) + cfi_offset(%ebp, JB_BP*4) + /* Restore registers. */ + movl (JB_BX*4)(%eax), %ebx + movl (JB_SI*4)(%eax), %esi + movl (JB_DI*4)(%eax), %edi + movl (JB_BP*4)(%eax), %ebp + cfi_restore(%ebx) + cfi_restore(%esi) + cfi_restore(%edi) + cfi_restore(%ebp) + + movl 8(%esp), %eax /* Second argument is return value. */ + movl %ecx, %esp + + /* Jump to saved PC. */ + jmp *%edx +END (__longjmp)