From patchwork Thu Mar 22 20:59:03 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 26434 Received: (qmail 44317 invoked by alias); 22 Mar 2018 20:59:11 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 44300 invoked by uid 89); 22 Mar 2018 20:59:10 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.3 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=csu, restoring, 68, 13 X-HELO: mail-oi0-f65.google.com X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=ueowuUUWJ+wOWHCU663kEIkvJsJRgZLGiKYrINuAsv4=; b=KvnNz4Y6XWP8iMS/i514sqdFP34DkwlcYCSXHlGCngF3ub1V6SoH8vTSgV20aMOniM UD+vrTebsVdQEOAxeQsfaRhQlnx5bCsBR4uNF3vkBTxCRsn7YWsJYKUScQYtx/rEjZAQ GT7sAsydecqSes1Ax1g4dJaaQnNMUhleoUmjGwpmRs+I+a7qnQMmDhVDElUxblNypZZI ccXlHgXFDQPKflXgKMz2Xg1J21w2p3R3TrAZgthNAyRVQqo+rqSQBJ15/EHYu0qfLEKr xr34KecTvDpVbkaRz7x2bby3uWXn8qs6d1s3kdQKqDtzd8ZV0iJi91xOKcT3cm2te2vu KDVA== X-Gm-Message-State: AElRT7HHjKwKp3M7hJFv83Sel0S9fHetiMqD8uF96lwabfwQtxN/Fu3C wtwTYjxj0FtgQoRjHbEXftEU0xTJ+wm+HdvI2oQ= X-Google-Smtp-Source: AG47ELtTkPNhXCwWbe5liVU3A5CA8YVWMwzek/mveLq2yeTllgv8s3GXSuSRWMOo6poQcdJDxzH6EIm7jyzjy5G4n3I= X-Received: by 10.202.74.83 with SMTP id x80mr10479970oia.228.1521752344530; Thu, 22 Mar 2018 13:59:04 -0700 (PDT) MIME-Version: 1.0 In-Reply-To: References: <87efkkxwah.fsf@mid.deneb.enyo.de> From: "H.J. Lu" Date: Thu, 22 Mar 2018 13:59:03 -0700 Message-ID: Subject: Re: [PATCH] x86: Add __sigsetjmp_cancel and __setjmp_cancel To: Florian Weimer Cc: Joseph Myers , "Carlos O'Donell" , "Tsimbalist, Igor V" , GNU C Library On Fri, Mar 16, 2018 at 4:28 AM, H.J. Lu wrote: > On Fri, Mar 16, 2018 at 1:24 AM, Florian Weimer wrote: >> * H. J. Lu: >> >>> +/* Function used in the macros. */ >>> +struct __jmp_buf_tag; >>> +extern int __sigsetjmp_cancel (struct __jmp_buf_tag *__env, int __savemask) >>> + __THROWNL __attribute_returns_twice__; >> >> How is __THROWNL correct here? We do unwind through this function. >> The __EXCEPTIONS guard is not effective because of LTO, and some >> applications undefine __EXCEPTIONS to avoid the table-based >> cancellation handlers. > > This is moved from : > > /* Function used in the macros. */ > struct __jmp_buf_tag; > extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) __THROWNL; > > Is wrong? It turns out that since libpthread provides compatible versions of longjmp and siglongjmp which don't save and restore shadow stack, new versions of longjmp and siglongjmp, which save and restore shadow stack, should be added to libc. Otherwise, porgrams linked with libpthread will pick the wrong longjmp. Here is the updated patch. OK for master? Thanks. From 25647d4e7f72138563da1da8492855321e77695d Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Sun, 25 Feb 2018 09:48:39 -0800 Subject: [PATCH] x86: Add __sigsetjmp_cancel and __setjmp_cancel Functions, like LIBC_START_MAIN, START_THREAD_DEFN as well as these with thread cancellation, call setjmp, but never return to their callers after longjmp returns. This patch adds and to provide a version of setjmp family functions, __setjmp_cancel and __sigsetjmp_cancel, which are used to implement thread cancellation. The default __setjmp_cancel and __sigsetjmp_cancel are defined as setjmp and __sigsetjmp, respectively, which are the same as before. On x86, __sigsetjmp_cancel, which is a public function used by macros in , and __setjmp_cancel, which is a private interface for cancellation implementation in libpthread, are added to avoid saving and restoring shadow stack register. A new version of __sigsetjmp is added to save and restore shadow stack register. The compatible version of __sigsetjmp, which doesn't save and restore shadow stack register, is provided for shared libraries built with glibc 2.27 or older. __libc_longjmp, which is a private interface for cancellation implementation in libpthread, is changed to call __longjmp_cancel instead of __longjmp. Since libpthread provides compatible versions of longjmp and siglongjmp which don't save and restore shadow stack, new versions of longjmp and siglongjmp, which save and restore shadow stack, are also added to libc. NB: Shared libraries built with glibc 2.27 or older are compatible with glibc 2.28. Relocatable objects compiled against glibc 2.27 or older are incompatible with glibc 2.28 since they reference the older version of __sigsetjmp. Tested with build-many-glibcs.py. * bits/setjmp-cancel.h: New file. * sysdeps/generic/setjmp-cancelP.h: Likewise. * sysdeps/x86/__longjmp_cancel.S: Likewise. * sysdeps/x86/bsd-_setjmp_cancel.S: Likewise. * sysdeps/x86/longjmp.c: Likewise. * sysdeps/x86/setjmp-cancelP.h: Likewise. * sysdeps/x86/setjmp_cancel.S: Likewise. * sysdeps/x86/bits/setjmp-cancel.h: Likewise. * sysdeps/x86_64/setjmp_cancel.S: Likewise. * csu/libc-start.c (LIBC_START_MAIN): Replace setjmp with __setjmp_cancel. * nptl/pthread_create.c (START_THREAD_DEFN): Likewise. * include/setjmp.h: Include and . * misc/sys/cdefs.h (__attribute_returns_twice__): New. * nptl/Makefile (headers): Add bits/setjmp-cancel.h. * setjmp/longjmp.c (__libc_longjmp): Don't define alias if defined. (longjmp): Likewise. (siglongjmp): Likewise. * sysdeps/i386/bsd-_setjmp.S (_setjmp): Don't add hidden_def. * sysdeps/x86_64/bsd-_setjmp.S (_setjmp): Likewise. * sysdeps/i386/setjmp.S (__sigsetjmp): Don't add hidden_def and redefined to __redirect___sigsetjmp in libc.so if __sigsetjmp is undefined. (__GI___sigsetjmp): New. Defined if __redirect___sigsetjmp is defined. (__sigsetjmp): Add to GLIBC_2_28 if __redirect___sigsetjmp is defined. * sysdeps/x86_64/setjmp.S: Likewise. * sysdeps/nptl/pthread.h (pthread_cleanup_push): Replace __sigsetjmp with __sigsetjmp_cancel. (pthread_cleanup_push_defer_np): Likewise. (__jmp_buf_tag): Removed. (__sigsetjmp): Likewise. Include . * sysdeps/unix/sysv/linux/i386/libc.abilist: Regenerated. * sysdeps/unix/sysv/linux/x86_64/64/libc.abilist: Likewise. * sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist: Likewise. * sysdeps/x86/Makefile (sysdep_routines): Add bsd-_setjmp_cancel, __longjmp_cancel and setjmp_cancel. * sysdeps/x86/Versions (longjmp): Add to GLIBC_2.28 in libc. (siglongjmp): Likewise. (__sigsetjmp_cancel): Likewise. (__setjmp_cancel): Add to GLIBC_PRIVATE in libc. * sysdeps/x86_64/bsd-_setjmp.S (SIGSETJMP): New. (_setjmp): Jmp to SIGSETJMP. --- bits/setjmp-cancel.h | 33 +++++++++++++++ csu/libc-start.c | 2 +- include/setjmp.h | 3 ++ misc/sys/cdefs.h | 6 +++ nptl/Makefile | 2 +- nptl/pthread_create.c | 2 +- setjmp/longjmp.c | 4 +- sysdeps/generic/setjmp-cancelP.h | 19 +++++++++ sysdeps/i386/bsd-_setjmp.S | 2 + sysdeps/i386/setjmp.S | 16 +++++++- sysdeps/nptl/pthread.h | 15 ++++--- sysdeps/unix/sysv/linux/i386/libc.abilist | 5 +++ sysdeps/unix/sysv/linux/x86_64/64/libc.abilist | 5 +++ sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist | 5 +++ sysdeps/x86/Makefile | 4 ++ sysdeps/x86/Versions | 15 +++++++ sysdeps/x86/__longjmp_cancel.S | 20 +++++++++ sysdeps/x86/bits/setjmp-cancel.h | 31 ++++++++++++++ sysdeps/x86/bsd-_setjmp_cancel.S | 22 ++++++++++ sysdeps/x86/longjmp.c | 54 +++++++++++++++++++++++++ sysdeps/x86/setjmp-cancelP.h | 24 +++++++++++ sysdeps/x86/setjmp_cancel.S | 26 ++++++++++++ sysdeps/x86_64/bsd-_setjmp.S | 25 +++++++++--- sysdeps/x86_64/setjmp.S | 16 +++++++- sysdeps/x86_64/setjmp_cancel.S | 21 ++++++++++ 25 files changed, 358 insertions(+), 19 deletions(-) create mode 100644 bits/setjmp-cancel.h create mode 100644 sysdeps/generic/setjmp-cancelP.h create mode 100644 sysdeps/x86/__longjmp_cancel.S create mode 100644 sysdeps/x86/bits/setjmp-cancel.h create mode 100644 sysdeps/x86/bsd-_setjmp_cancel.S create mode 100644 sysdeps/x86/longjmp.c create mode 100644 sysdeps/x86/setjmp-cancelP.h create mode 100644 sysdeps/x86/setjmp_cancel.S create mode 100644 sysdeps/x86_64/setjmp_cancel.S diff --git a/bits/setjmp-cancel.h b/bits/setjmp-cancel.h new file mode 100644 index 0000000000..a0c4566127 --- /dev/null +++ b/bits/setjmp-cancel.h @@ -0,0 +1,33 @@ +/* __sigsetjmp_cancel for thread cancellation. Generic version. + Copyright (C) 2018 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 + . */ + +#ifndef _BITS_SETJMP_CANCEL_H +#define _BITS_SETJMP_CANCEL_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#define __sigsetjmp_cancel __sigsetjmp + +struct __jmp_buf_tag; +/* Function used in the macros. */ +extern int __sigsetjmp (struct __jmp_buf_tag *__env, + int __savemask) __THROWNL; + +#endif /* bits/setjmp-cancel.h */ diff --git a/csu/libc-start.c b/csu/libc-start.c index 605222fa3f..0c1e2fa830 100644 --- a/csu/libc-start.c +++ b/csu/libc-start.c @@ -292,7 +292,7 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), struct pthread_unwind_buf unwind_buf; int not_first_call; - not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf); + not_first_call = __setjmp_cancel ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf); if (__glibc_likely (! not_first_call)) { struct pthread *self = THREAD_SELF; diff --git a/include/setjmp.h b/include/setjmp.h index 263bc64b3d..fa846c83cc 100644 --- a/include/setjmp.h +++ b/include/setjmp.h @@ -31,6 +31,9 @@ libc_hidden_proto (__sigsetjmp) extern __typeof (__sigsetjmp) __sigsetjmp attribute_hidden; # endif +# include +# include + /* Check jmp_buf sizes, alignments and offsets. */ # include # include diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h index e80a45ca68..5f704f41db 100644 --- a/misc/sys/cdefs.h +++ b/misc/sys/cdefs.h @@ -416,6 +416,12 @@ # endif #endif +#if __GNUC_PREREQ (4, 1) +# define __attribute_returns_twice__ __attribute__ ((__returns_twice__)) +#else +# define __attribute_returns_twice__ /* Ignore. */ +#endif + #if __GNUC_PREREQ (8, 0) /* Describes a char array whose address can safely be passed as the first argument to strncpy and strncat, as the char array is not necessarily diff --git a/nptl/Makefile b/nptl/Makefile index 94be92c789..fa3027072d 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -22,7 +22,7 @@ subdir := nptl include ../Makeconfig -headers := pthread.h semaphore.h bits/semaphore.h +headers := pthread.h semaphore.h bits/semaphore.h bits/setjmp-cancel.h extra-libs := libpthread extra-libs-others := $(extra-libs) diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c index caaf07c134..0728779994 100644 --- a/nptl/pthread_create.c +++ b/nptl/pthread_create.c @@ -432,7 +432,7 @@ START_THREAD_DEFN unwind_buf.priv.data.cleanup = NULL; int not_first_call; - not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf); + not_first_call = __setjmp_cancel ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf); if (__glibc_likely (! not_first_call)) { /* Store the new cleanup handler info. */ diff --git a/setjmp/longjmp.c b/setjmp/longjmp.c index a2a7065a85..4abf1662ac 100644 --- a/setjmp/longjmp.c +++ b/setjmp/longjmp.c @@ -40,10 +40,12 @@ __libc_siglongjmp (sigjmp_buf env, int val) } #ifndef __libc_siglongjmp +# ifndef __libc_longjmp /* __libc_longjmp is a private interface for cancellation implementation in libpthread. */ strong_alias (__libc_siglongjmp, __libc_longjmp) -weak_alias (__libc_siglongjmp, _longjmp) weak_alias (__libc_siglongjmp, longjmp) weak_alias (__libc_siglongjmp, siglongjmp) +# endif +weak_alias (__libc_siglongjmp, _longjmp) #endif diff --git a/sysdeps/generic/setjmp-cancelP.h b/sysdeps/generic/setjmp-cancelP.h new file mode 100644 index 0000000000..658a3306f3 --- /dev/null +++ b/sysdeps/generic/setjmp-cancelP.h @@ -0,0 +1,19 @@ +/* Internal header file for . Generic version. + Copyright (C) 2017-2018 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 + . */ + +#define __setjmp_cancel setjmp diff --git a/sysdeps/i386/bsd-_setjmp.S b/sysdeps/i386/bsd-_setjmp.S index a626cc6d22..51446a5614 100644 --- a/sysdeps/i386/bsd-_setjmp.S +++ b/sysdeps/i386/bsd-_setjmp.S @@ -53,4 +53,6 @@ ENTRY (_setjmp) movl %eax, JB_SIZE(%edx) /* No signal mask set. */ ret END (_setjmp) +#ifndef _setjmp libc_hidden_def (_setjmp) +#endif diff --git a/sysdeps/i386/setjmp.S b/sysdeps/i386/setjmp.S index 6a08701717..e7ba7a7ce5 100644 --- a/sysdeps/i386/setjmp.S +++ b/sysdeps/i386/setjmp.S @@ -25,6 +25,11 @@ #define JMPBUF PARMS #define SIGMSK JMPBUF+4 +#if !defined __sigsetjmp && defined SHARED && !IS_IN (rtld) +# define __sigsetjmp __redirect___sigsetjmp +# define __redirect___sigsetjmp __redirect___sigsetjmp +#endif + ENTRY (__sigsetjmp) movl JMPBUF(%esp), %eax @@ -55,4 +60,13 @@ ENTRY (__sigsetjmp) jmp __sigjmp_save #endif END (__sigsetjmp) -hidden_def (__sigsetjmp) +#ifdef __redirect___sigsetjmp +# undef __sigsetjmp + + .globl __GI___sigsetjmp + .hidden __GI___sigsetjmp + __GI___sigsetjmp = __redirect___sigsetjmp + +# include +versioned_symbol (libc, __redirect___sigsetjmp, __sigsetjmp, GLIBC_2_28); +#endif diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h index df049abf74..8568baff9d 100644 --- a/sysdeps/nptl/pthread.h +++ b/sysdeps/nptl/pthread.h @@ -667,8 +667,9 @@ __pthread_cleanup_routine (struct __pthread_cleanup_frame *__frame) __pthread_unwind_buf_t __cancel_buf; \ void (*__cancel_routine) (void *) = (routine); \ void *__cancel_arg = (arg); \ - int __not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) (void *) \ - __cancel_buf.__cancel_jmp_buf, 0); \ + int __not_first_call \ + = __sigsetjmp_cancel ((struct __jmp_buf_tag *) (void *) \ + __cancel_buf.__cancel_jmp_buf, 0); \ if (__glibc_unlikely (__not_first_call)) \ { \ __cancel_routine (__cancel_arg); \ @@ -702,8 +703,9 @@ extern void __pthread_unregister_cancel (__pthread_unwind_buf_t *__buf) __pthread_unwind_buf_t __cancel_buf; \ void (*__cancel_routine) (void *) = (routine); \ void *__cancel_arg = (arg); \ - int __not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) (void *) \ - __cancel_buf.__cancel_jmp_buf, 0); \ + int __not_first_call \ + = __sigsetjmp_cancel ((struct __jmp_buf_tag *) (void *) \ + __cancel_buf.__cancel_jmp_buf, 0); \ if (__glibc_unlikely (__not_first_call)) \ { \ __cancel_routine (__cancel_arg); \ @@ -739,10 +741,7 @@ extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf) ; #endif -/* Function used in the macros. */ -struct __jmp_buf_tag; -extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) __THROWNL; - +#include /* Mutex handling. */ diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist index 39c993fd79..4f1f689302 100644 --- a/sysdeps/unix/sysv/linux/i386/libc.abilist +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist @@ -2064,6 +2064,11 @@ GLIBC_2.27 wcstof64 F GLIBC_2.27 wcstof64_l F GLIBC_2.27 wcstof64x F GLIBC_2.27 wcstof64x_l F +GLIBC_2.28 GLIBC_2.28 A +GLIBC_2.28 __sigsetjmp F +GLIBC_2.28 __sigsetjmp_cancel F +GLIBC_2.28 longjmp F +GLIBC_2.28 siglongjmp F GLIBC_2.3 GLIBC_2.3 A GLIBC_2.3 __ctype_b_loc F GLIBC_2.3 __ctype_tolower_loc F diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist index 2a3cc40674..a94347b8d6 100644 --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist @@ -1905,6 +1905,11 @@ GLIBC_2.27 wcstof64 F GLIBC_2.27 wcstof64_l F GLIBC_2.27 wcstof64x F GLIBC_2.27 wcstof64x_l F +GLIBC_2.28 GLIBC_2.28 A +GLIBC_2.28 __sigsetjmp F +GLIBC_2.28 __sigsetjmp_cancel F +GLIBC_2.28 longjmp F +GLIBC_2.28 siglongjmp F GLIBC_2.3 GLIBC_2.3 A GLIBC_2.3 __ctype_b_loc F GLIBC_2.3 __ctype_tolower_loc F diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist index 8bc16b9004..e8dd56c69a 100644 --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist @@ -2148,3 +2148,8 @@ GLIBC_2.27 wcstof64 F GLIBC_2.27 wcstof64_l F GLIBC_2.27 wcstof64x F GLIBC_2.27 wcstof64x_l F +GLIBC_2.28 GLIBC_2.28 A +GLIBC_2.28 __sigsetjmp F +GLIBC_2.28 __sigsetjmp_cancel F +GLIBC_2.28 longjmp F +GLIBC_2.28 siglongjmp F diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile index 0d0326c21a..d23ee462f7 100644 --- a/sysdeps/x86/Makefile +++ b/sysdeps/x86/Makefile @@ -8,3 +8,7 @@ sysdep-dl-routines += dl-get-cpu-features tests += tst-get-cpu-features tests-static += tst-get-cpu-features-static endif + +ifeq ($(subdir),setjmp) +sysdep_routines += bsd-_setjmp_cancel __longjmp_cancel setjmp_cancel +endif diff --git a/sysdeps/x86/Versions b/sysdeps/x86/Versions index e02923708e..bcb86a73e0 100644 --- a/sysdeps/x86/Versions +++ b/sysdeps/x86/Versions @@ -3,3 +3,18 @@ ld { __get_cpu_features; } } +libc { + GLIBC_2.28 { + # New versions to avoid picking up old ones in libpthread. + longjmp; + siglongjmp; + __sigsetjmp; + + # used to implement thread cancellation. + __sigsetjmp_cancel; + } + GLIBC_PRIVATE { + # used to implement thread cancellation. + __setjmp_cancel; + } +} diff --git a/sysdeps/x86/__longjmp_cancel.S b/sysdeps/x86/__longjmp_cancel.S new file mode 100644 index 0000000000..b57dbfa376 --- /dev/null +++ b/sysdeps/x86/__longjmp_cancel.S @@ -0,0 +1,20 @@ +/* __longjmp_cancel for x86. + Copyright (C) 2018 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 + . */ + +#define __longjmp __longjmp_cancel +#include <__longjmp.S> diff --git a/sysdeps/x86/bits/setjmp-cancel.h b/sysdeps/x86/bits/setjmp-cancel.h new file mode 100644 index 0000000000..87fd6cf96f --- /dev/null +++ b/sysdeps/x86/bits/setjmp-cancel.h @@ -0,0 +1,31 @@ +/* __sigsetjmp_cancel for thread cancellation. x86 version. + Copyright (C) 2018 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 + . */ + +#ifndef _BITS_SETJMP_CANCEL_H +#define _BITS_SETJMP_CANCEL_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +/* Function used in the macros. */ +struct __jmp_buf_tag; +extern int __sigsetjmp_cancel (struct __jmp_buf_tag *__env, int __savemask) + __THROWNL __attribute_returns_twice__; + +#endif /* bits/setjmp-cancel.h */ diff --git a/sysdeps/x86/bsd-_setjmp_cancel.S b/sysdeps/x86/bsd-_setjmp_cancel.S new file mode 100644 index 0000000000..25b2a95960 --- /dev/null +++ b/sysdeps/x86/bsd-_setjmp_cancel.S @@ -0,0 +1,22 @@ +/* __setjmp_cancel for x86. + Copyright (C) 2018 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 + . */ + +#define _setjmp __setjmp_cancel +#include + +libc_hidden_def (__setjmp_cancel) diff --git a/sysdeps/x86/longjmp.c b/sysdeps/x86/longjmp.c new file mode 100644 index 0000000000..72c04a9584 --- /dev/null +++ b/sysdeps/x86/longjmp.c @@ -0,0 +1,54 @@ +/* __libc_siglongjmp for x86. + Copyright (C) 2018 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 + . */ + +#define __libc_longjmp __redirect___libc_longjmp +#include +#undef __libc_longjmp + +/* Since __libc_longjmp is a private interface for cancellation + implementation in libpthread, there is no need to restore shadow + stack register. */ + +void +__libc_longjmp (sigjmp_buf env, int val) +{ + /* Perform any cleanups needed by the frames being unwound. */ + _longjmp_unwind (env, val); + + if (env[0].__mask_was_saved) + /* Restore the saved signal mask. */ + (void) __sigprocmask (SIG_SETMASK, + (sigset_t *) &env[0].__saved_mask, + (sigset_t *) NULL); + + /* Call the machine-dependent function to restore machine state + without shadow stack. */ + __longjmp_cancel (env[0].__jmpbuf, val ?: 1); +} + +#include + +versioned_symbol (libc, __libc_siglongjmp, siglongjmp, GLIBC_2_28); +strong_alias (__libc_siglongjmp, __libc_siglongjmp_alias) +versioned_symbol (libc, __libc_siglongjmp_alias, longjmp, GLIBC_2_28); + +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_28) +compat_symbol (libc, __libc_longjmp, longjmp, GLIBC_2_0); +strong_alias (__libc_longjmp, __libc_longjmp_alias) +compat_symbol (libc, __libc_longjmp_alias, siglongjmp, GLIBC_2_0); +#endif diff --git a/sysdeps/x86/setjmp-cancelP.h b/sysdeps/x86/setjmp-cancelP.h new file mode 100644 index 0000000000..1cd4f94b50 --- /dev/null +++ b/sysdeps/x86/setjmp-cancelP.h @@ -0,0 +1,24 @@ +/* Internal header file for . x86 version. + Copyright (C) 2017-2018 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 + . */ + +extern int __setjmp_cancel (struct __jmp_buf_tag __env[1]) + __attribute__((__returns_twice__)); +libc_hidden_proto (__setjmp_cancel, __returns_twice__) + +extern void __longjmp_cancel (__jmp_buf __env, int __val) + __attribute__ ((__noreturn__)) attribute_hidden; diff --git a/sysdeps/x86/setjmp_cancel.S b/sysdeps/x86/setjmp_cancel.S new file mode 100644 index 0000000000..b2bca39883 --- /dev/null +++ b/sysdeps/x86/setjmp_cancel.S @@ -0,0 +1,26 @@ +/* __sigsetjmp_cancel for x86. + Copyright (C) 2018 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 + . */ + +#define __sigsetjmp __sigsetjmp_cancel +#include +#undef __sigsetjmp + +#include +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_28) +compat_symbol (libc, __sigsetjmp_cancel, __sigsetjmp, GLIBC_2_0); +#endif diff --git a/sysdeps/x86_64/bsd-_setjmp.S b/sysdeps/x86_64/bsd-_setjmp.S index 58c997de59..e4908b0081 100644 --- a/sysdeps/x86_64/bsd-_setjmp.S +++ b/sysdeps/x86_64/bsd-_setjmp.S @@ -25,13 +25,28 @@ #define _SETJMP_H #include +/* If _setjmp is defined for __setjmp_cancel, call __sigsetjmp_cancel + instead of __sigsetjmp. + */ +#ifdef _setjmp +# ifdef PIC +# define SIGSETJMP HIDDEN_JUMPTARGET (__sigsetjmp_cancel) +# else +# define SIGSETJMP __sigsetjmp_cancel +# endif +#else +# ifdef PIC +# define SIGSETJMP HIDDEN_JUMPTARGET (__sigsetjmp) +# else +# define SIGSETJMP __sigsetjmp +# endif +#endif + ENTRY (_setjmp) /* Set up arguments, we only need to set the second arg. */ xorl %esi, %esi -#ifdef PIC - jmp HIDDEN_JUMPTARGET (__sigsetjmp) -#else - jmp __sigsetjmp -#endif + jmp SIGSETJMP END (_setjmp) +#ifndef _setjmp libc_hidden_def (_setjmp) +#endif diff --git a/sysdeps/x86_64/setjmp.S b/sysdeps/x86_64/setjmp.S index e0a648e3e4..c7cbb29111 100644 --- a/sysdeps/x86_64/setjmp.S +++ b/sysdeps/x86_64/setjmp.S @@ -21,6 +21,11 @@ #include #include +#if !defined __sigsetjmp && defined SHARED && !IS_IN (rtld) +# define __sigsetjmp __redirect___sigsetjmp +# define __redirect___sigsetjmp __redirect___sigsetjmp +#endif + ENTRY (__sigsetjmp) /* Save registers. */ movq %rbx, (JB_RBX*8)(%rdi) @@ -63,4 +68,13 @@ ENTRY (__sigsetjmp) jmp __sigjmp_save #endif END (__sigsetjmp) -hidden_def (__sigsetjmp) +#ifdef __redirect___sigsetjmp +# undef __sigsetjmp + + .globl __GI___sigsetjmp + .hidden __GI___sigsetjmp + __GI___sigsetjmp = __redirect___sigsetjmp + +# include +versioned_symbol (libc, __redirect___sigsetjmp, __sigsetjmp, GLIBC_2_28); +#endif diff --git a/sysdeps/x86_64/setjmp_cancel.S b/sysdeps/x86_64/setjmp_cancel.S new file mode 100644 index 0000000000..3727a9c7dc --- /dev/null +++ b/sysdeps/x86_64/setjmp_cancel.S @@ -0,0 +1,21 @@ +/* __sigsetjmp_cancel for x86-64. + Copyright (C) 2018 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 + +libc_hidden_def (__sigsetjmp_cancel) -- 2.14.3