From patchwork Fri Dec 8 02:25:47 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 24792 Received: (qmail 8994 invoked by alias); 8 Dec 2017 02:25:53 -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 8983 invoked by uid 89); 8 Dec 2017 02:25:52 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.4 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= 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=v4xn+UQ/0pO3KmNYhIPYOlTf7tZ8R/tVGMp4ofqHhe0=; b=fiUBgwrZzqE70ASjW0pVikHjTLJzwMEpAANCpj0OxCu0t+Y48dp+ZucVmetBRSj9Sp CzNYlk2BQw8hIoPt0He0rTezqoIhozs8TIUlh8C3IZLumkdfx9/G6n+WC5DEtXzGRePB CZPz63L+Rm3r3bA7nskM2uPtVL4W3elQr9CNQctVOETv2MWcaDsE3zDU8aNDGFCRZdwi S4bCNOUtPtWGZNgWQazUvUr/GxjXu3Cc52n5Y8+RTl50qScUWzrhOBVShUoMLnzOIrkF yAUj881Gu5sI6GUhAd4x85x5KYHUlxjWOHpIDtcnAfUEaTWtEh+ukrY/pptGF1ccCz+A 0PiA== X-Gm-Message-State: AJaThX7Gjy0TsVIEigO6FGLUjDnbg7KQ4euoVtS1dwEXXxWFhizwB1Xq 7Ki1Ngq1TbrkrzUdj9rm1fWiXLszsddf9UFS1Mg= X-Google-Smtp-Source: AGs4zMZgzKYDH0pst/MD4t3L2D4UMZ/ZgR+I94zT3MIP2s/5ck9qJBGnwXsGrUA2LtY1FsS4/FLTsC5FoqIRRxV4vRM= X-Received: by 10.202.253.73 with SMTP id b70mr24822669oii.279.1512699947743; Thu, 07 Dec 2017 18:25:47 -0800 (PST) MIME-Version: 1.0 In-Reply-To: References: <20171207174057.GA32196@gmail.com> <7e890f53-c331-d86e-ad13-b380a69d99eb@redhat.com> <814691a7-d946-1794-d6d8-7861f9ed2067@redhat.com> <08cf7c54-8bf0-27c0-863a-65cb76dd0728@redhat.com> From: "H.J. Lu" Date: Thu, 7 Dec 2017 18:25:47 -0800 Message-ID: Subject: Re: [PATCH 1/2] Linux/x86: Update cancel_jmp_buf to match __jmp_buf_tag [BZ #22563] To: Florian Weimer Cc: GNU C Library On Thu, Dec 7, 2017 at 11:35 AM, H.J. Lu wrote: > On Thu, Dec 7, 2017 at 11:25 AM, Florian Weimer wrote: >> On 12/07/2017 08:19 PM, H.J. Lu wrote: >>> >>> On Thu, Dec 7, 2017 at 11:14 AM, Florian Weimer >>> wrote: >>>> >>>> On 12/07/2017 08:12 PM, H.J. Lu wrote: >>>>>> >>>>>> >>>>>> Sorry, what exactly is stored on the shadow stack? I assumed it was >>>>>> for >>>>>> verification of the targets of ret instructions. >>>>>> >>>>>> In this case, don't need to unwind the shadow stack (or preserve its >>>>>> contents) because there are no returns from existing stack frames once >>>>>> cancellation has started. >>>>>> >>>>> Shadow stack is the similar to normal call stack without local >>>>> variables. >>>>> SHSTK checks the return address of EACH "RET" instruction against >>>>> shadow stack. >>>> >>>> >>>> >>>> Then the shadow stack contents at the time of cancellation does not >>>> matter >>>> because all future RET instructions on this thread will match CALLs which >>>> happened *after* cancellation. (In other words, I still think I'm right >>>> about this.) >>>> >>> >>> We are updating setjmp/lonjmp to save and restore shadow stack pointer: >>> >>> >>> https://sourceware.org/git/?p=glibc.git;a=commit;h=ac195a2d554e3fb577e44474faf3ed7f4521de9f >> >> >> Please try to understand what I wrote. You don't need the restore during >> cancellation handling: >> >> if (__glibc_unlikely (__not_first_call)) \ >> { \ >> __cancel_routine (__cancel_arg); \ >> __pthread_unwind_next (&__cancel_buf); \ >> /* NOTREACHED */ \ >> } \ >> > > Who will sync shadow stack with call stack? > Here is call stack during stack unwind: (gdb) bt #0 __longjmp () at ../sysdeps/unix/sysv/linux/x86_64/__longjmp.S:30 #1 0x00007ffff7837f5f in __libc_siglongjmp (env=env@entry=0x7ffff7800da0, val=val@entry=1) at longjmp.c:39 #2 0x00007ffff7bc899d in unwind_stop (version=, actions=, exc_class=, exc_obj=, context=, stop_parameter=0x7ffff7800da0) at unwind.c:94 #3 0x00007ffff6df9b6e in _Unwind_ForcedUnwind_Phase2 ( exc=exc@entry=0x7ffff7801d70, context=context@entry=0x7ffff78005d0, frames_p=frames_p@entry=0x7ffff78004d8) at /export/gnu/import/git/sources/gcc/libgcc/unwind.inc:170 #4 0x00007ffff6dfa1c0 in _Unwind_ForcedUnwind (exc=0x7ffff7801d70, stop=stop@entry=0x7ffff7bc88e0 , stop_argument=) at /export/gnu/import/git/sources/gcc/libgcc/unwind.inc:217 #5 0x00007ffff7bc8a84 in __GI___pthread_unwind (buf=) at unwind.c:121 #6 0x00007ffff7bbe46a in __do_cancel () at ./pthreadP.h:297 #7 sigcancel_handler (sig=, si=0x7ffff7800870, ctx=) at nptl-init.c:216 #8 #9 0x00007ffff7bc8f04 in __libc_read (fd=fd@entry=3, buf=buf@entry=0x7ffff7800d30, nbytes=nbytes@entry=100) ---Type to continue, or q to quit--- sv/linux/read.c:27 #10 0x00000000004064a0 in tf_read (arg=) at tst-cancel4.c:102 #11 0x00007ffff7bbfcde in start_thread (arg=) at pthread_create.c:463 #12 0x00007ffff78f5f73 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95 (gdb) f 10 #10 0x00000000004064a0 in tf_read (arg=) at tst-cancel4.c:102 102 s = read (fd, buf, sizeof (buf)); (gdb) list 97 98 ssize_t s; 99 pthread_cleanup_push (cl, NULL); 100 101 char buf[100]; 102 s = read (fd, buf, sizeof (buf)); 103 104 pthread_cleanup_pop (0); 105 106 FAIL_EXIT1 ("read returns with %zd", s); (gdb) # define pthread_cleanup_push(routine, arg) \ do { \ __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); \ if (__glibc_unlikely (__not_first_call)) \ { \ __cancel_routine (__cancel_arg); \ __pthread_unwind_next (&__cancel_buf); \ /* NOTREACHED */ \ } To unwind shadow stack, we need to save shadow stack pointer in __cancel_buf. This updated patch adds bits/types/__cancel_jmp_buf_tag.h to define struct __cancel_jmp_buf_tag so that Linux/x86 can add saved_mask to __cancel_jmp_buf. We will check if shadow stack is enabled before saving and restoring shadow stack pointer so that it works with the old smaller cancel_jmp_buf which doesn't have space for shadow stack pointer. From b6aad5a9958354e236f42877575e9f76f90348d1 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Wed, 6 Dec 2017 15:00:46 -0800 Subject: [PATCH] Linux/x86: Update cancel_jmp_buf to match __jmp_buf_tag [BZ #22563] On x86, padding in struct __jmp_buf_tag is used for shadow stack pointer to support shadow stack in Intel Control-flow Enforcemen Technology. Since the cancel_jmp_buf array is passed to setjmp and longjmp by casting it to pointer to struct __jmp_buf_tag, it should be as large as struct __jmp_buf_tag. This patch adds bits/types/__cancel_jmp_buf_tag.h to define struct __cancel_jmp_buf_tag so that Linux/x86 can add saved_mask to cancel_jmp_buf. Tested by build-many-glibcs.py. [BZ #22563] * bits/types/__cancel_jmp_buf_tag.h: New file. * sysdeps/unix/sysv/linux/x86/bits/types/__cancel_jmp_buf_tag.h * sysdeps/unix/sysv/linux/x86/pthreaddef.h: Likewise. * sysdeps/unix/sysv/linux/x86/nptl/pthreadP.h: Likewise. * nptl/Makefile (headers): Add bits/types/__cancel_jmp_buf_tag.h. * nptl/descr.h [NEED_SAVED_MASK_IN_CANCEL_JMP_BUF] (pthread_unwind_buf): Add saved_mask to cancel_jmp_buf. * sysdeps/nptl/pthread.h: Include . (__pthread_unwind_buf_t): Use struct __cancel_jmp_buf_tag with __cancel_jmp_buf. --- bits/types/__cancel_jmp_buf_tag.h | 28 +++++++++++++++++ nptl/Makefile | 3 +- nptl/descr.h | 3 ++ sysdeps/nptl/pthread.h | 7 ++--- .../linux/x86/bits/types/__cancel_jmp_buf_tag.h | 31 +++++++++++++++++++ sysdeps/unix/sysv/linux/x86/nptl/pthreadP.h | 36 ++++++++++++++++++++++ sysdeps/unix/sysv/linux/x86/pthreaddef.h | 22 +++++++++++++ 7 files changed, 124 insertions(+), 6 deletions(-) create mode 100644 bits/types/__cancel_jmp_buf_tag.h create mode 100644 sysdeps/unix/sysv/linux/x86/bits/types/__cancel_jmp_buf_tag.h create mode 100644 sysdeps/unix/sysv/linux/x86/nptl/pthreadP.h create mode 100644 sysdeps/unix/sysv/linux/x86/pthreaddef.h diff --git a/bits/types/__cancel_jmp_buf_tag.h b/bits/types/__cancel_jmp_buf_tag.h new file mode 100644 index 0000000000..c843f44239 --- /dev/null +++ b/bits/types/__cancel_jmp_buf_tag.h @@ -0,0 +1,28 @@ +/* Define struct __cancel_jmp_buf_tag. + Copyright (C) 2017 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 ____cancel_jmp_buf_tag_defined +#define ____cancel_jmp_buf_tag_defined 1 + +struct __cancel_jmp_buf_tag + { + __jmp_buf __cancel_jmp_buf; + int __mask_was_saved; + }; + +#endif diff --git a/nptl/Makefile b/nptl/Makefile index 11e6ecd88b..46e110773c 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -22,7 +22,8 @@ subdir := nptl include ../Makeconfig -headers := pthread.h semaphore.h bits/semaphore.h +headers := pthread.h semaphore.h bits/semaphore.h \ + bits/types/__cancel_jmp_buf_tag.h extra-libs := libpthread extra-libs-others := $(extra-libs) diff --git a/nptl/descr.h b/nptl/descr.h index c83b17b674..fdeb397eab 100644 --- a/nptl/descr.h +++ b/nptl/descr.h @@ -65,6 +65,9 @@ struct pthread_unwind_buf { __jmp_buf jmp_buf; int mask_was_saved; +#ifdef NEED_SAVED_MASK_IN_CANCEL_JMP_BUF + __sigset_t saved_mask; +#endif } cancel_jmp_buf[1]; union diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h index 2b2b386ab3..787ac6e4cd 100644 --- a/sysdeps/nptl/pthread.h +++ b/sysdeps/nptl/pthread.h @@ -27,6 +27,7 @@ #include #include #include +#include /* Detach state. */ @@ -523,11 +524,7 @@ extern void pthread_testcancel (void); typedef struct { - struct - { - __jmp_buf __cancel_jmp_buf; - int __mask_was_saved; - } __cancel_jmp_buf[1]; + struct __cancel_jmp_buf_tag __cancel_jmp_buf[1]; void *__pad[4]; } __pthread_unwind_buf_t __attribute__ ((__aligned__)); diff --git a/sysdeps/unix/sysv/linux/x86/bits/types/__cancel_jmp_buf_tag.h b/sysdeps/unix/sysv/linux/x86/bits/types/__cancel_jmp_buf_tag.h new file mode 100644 index 0000000000..830a6ec90c --- /dev/null +++ b/sysdeps/unix/sysv/linux/x86/bits/types/__cancel_jmp_buf_tag.h @@ -0,0 +1,31 @@ +/* Define struct __cancel_jmp_buf_tag. + Copyright (C) 2017 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 ____cancel_jmp_buf_tag_defined +#define ____cancel_jmp_buf_tag_defined 1 + +#include + +struct __cancel_jmp_buf_tag + { + __jmp_buf __cancel_jmp_buf; + int __mask_was_saved; + __sigset_t __saved_mask; + }; + +#endif diff --git a/sysdeps/unix/sysv/linux/x86/nptl/pthreadP.h b/sysdeps/unix/sysv/linux/x86/nptl/pthreadP.h new file mode 100644 index 0000000000..8c36ba3a5d --- /dev/null +++ b/sysdeps/unix/sysv/linux/x86/nptl/pthreadP.h @@ -0,0 +1,36 @@ +/* Internal pthread header. Linux/x86 version. + Copyright (C) 2017 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_next + +#ifndef _PTHREADP_H_X86 +#define _PTHREADP_H_X86 1 + +extern struct pthread_unwind_buf ____pthread_unwind_buf_private; + +_Static_assert (sizeof (____pthread_unwind_buf_private.cancel_jmp_buf) + >= sizeof (struct __jmp_buf_tag), + "size of cancel_jmp_buf < sizeof __jmp_buf_tag"); + +extern __pthread_unwind_buf_t ____pthread_unwind_buf; + +_Static_assert (sizeof (____pthread_unwind_buf.__cancel_jmp_buf) + >= sizeof (struct __jmp_buf_tag), + "size of __cancel_jmp_buf < sizeof __jmp_buf_tag"); + +#endif diff --git a/sysdeps/unix/sysv/linux/x86/pthreaddef.h b/sysdeps/unix/sysv/linux/x86/pthreaddef.h new file mode 100644 index 0000000000..89d19d60a1 --- /dev/null +++ b/sysdeps/unix/sysv/linux/x86/pthreaddef.h @@ -0,0 +1,22 @@ +/* Pthread macros. Linux/x86 version. + Copyright (C) 2017 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_next + +/* Need saved_mask in cancel_jmp_buf. */ +#define NEED_SAVED_MASK_IN_CANCEL_JMP_BUF 1 -- 2.14.3