[PATCH] x86: Use pad in pthread_unwind_buf to preserve shadow stack register

H.J. Lu hjl.tools@gmail.com
Fri Apr 6 20:26:00 GMT 2018


On Fri, Apr 6, 2018 at 5:59 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Thu, Apr 5, 2018 at 9:46 PM, Carlos O'Donell <carlos@redhat.com> wrote:
>> On 03/30/2018 12:41 PM, H.J. Lu wrote:
>>> On Thu, Mar 29, 2018 at 1:20 PM, Florian Weimer <fw@deneb.enyo.de> wrote:
>>>> * H. J. Lu:
>>>>
>>>>> On Thu, Mar 29, 2018 at 1:15 PM, Florian Weimer <fw@deneb.enyo.de> wrote:
>>>>>> * H. J. Lu:
>>>>>>
>>>>>>> You need to make a choice.  You either don't introduce a new symbol
>>>>>>> version or don't save shadow stack for thread cancellation.  You
>>>>>>> can't have both.
>>>>>> I don't understand.  We have room to save the shadow stack pointer in
>>>>>> the existing struct.
>>>>> No, we don't have room in struct pthread_unwind_buf:
>>>>>
>>>>> Note: There is an unused pointer space in pthread_unwind_buf_data.  But
>>>>> it isn't suitable for saving and restoring shadow stack register since
>>>>> x32 is a 64-bit process with 32-bit software pointer and kernel may
>>>>> place x32 shadow stack above 4GB.  We need to save and restore 64-bit
>>>>> shadow stack register for x32.
>>>> We have for void * fields.  They are subsequently overwritten by
>>>> __pthread_register_cancel.  But __sigsetjmp can write to them first
>>>> without causing any harm.  We just need a private __longjmp_cancel
>>>> that doesn't restore the shadow stack pointer.
>>> Here is the patch which does that.   Any comments?
>>
>> OK, so I have reviewed https://github.com/hjl-tools/glibc/ hjl/cet/master,
>> please confirm that this is the correct branch of the required implementation
>> for CET. It really helps to review the rest of the patch set, you should be
>> preparing this as a patch set instead of having it reviewed one-at-a-time.
>> This issue was already raised in the thread with Zack.
>
> Thanks for your feedbacks.
>
>> Architecture:
>>
>> * We avoid a "flag day" with feature_1 TCB flag to switch to a new ABI,
>>   which we have discussed is a fragile process which should be avoided if
>>   a supportable alternative solution exists.
>>
>> * We avoid versioned symbols, this makes CET backportable, and this has a
>>   bigger benefit for long-term stable distributions.
>>
>> * A key design problem has been that cancellation jump buffers within glibc
>>   are truncated to optimize on-stack size, and this means that setjmp could
>>   write beyond the structure because setjmp now tries to save the shadowstack
>>   pointer into space that the cancellation jump buffer did not allocate.
>>   For the record this optimization seems premature and I'm sad we did it, this
>>   is a lesson we should learn from.
>>
>> * We have all agreed to the following concepts:
>>
>>   * The cancellation process, in particular the unwinder, never returns from
>>     any of the functions we call, it just keeps calling into the unwinder to
>>     jump to the next unwound cancellation function all the way to the thread
>>     start routine. Therefore because we never return from one of these functions
>>     we never need to restore the shadow stack, and consequently wherever it is
>>     stored in the cancellation jump buffer can be overwritten if we need the
>>     space (it's a dead store).
>>
>>     * The corollary to this is that function calls made from cancellation handlers
>>       will continue to advance the shadowstack from the deepest point at which
>>       cancellation is initiated from. This means that the depth of the shadowstack
>>       doesn't match the depth of the real stack while we are unwinding. I don't
>>       know if this will have consequences on analysis tooling or not, or debug
>>       tools during unwinding. It's a fairly advanced situation and corner case,
>>       and restoring the shadowstack is not useful becuase we don't need it and
>>       simplifies the implementation.
>>
>>   * The cancellation jump buffer has private data used for chaining the cancel
>>     jump buffers together such that the custom unwinder can follow them and
>>     call them in sequence. This space constitutes 4 void *'s which is space
>>     that setjmp can write to, because we will just overwrite it when we register
>>     the cancel handler.
>>
>>   * If the new shadowstack-enabled setjmp stores the shadowstack pointer into
>>     the space taken by the 4 void*'s then we won't overflow the stack, and we
>>     don't need to change the layout of the cancellation jump buffer. The 4 void*'s
>>     are sufficient, even for x32 to write a 64-bit shadow stack address.
>>
>> * After fixing the cancellation jump buffers the following work needs to be reviewed:
>>
>>   * Add feature_1 in tcb head to track CET status and make it easily available
>>     to runtime for checking.
>>
>>   * Save and restore shadowstack in setjmp/longjmp.
>>
>>   * Add CET support to ld.so et. al. and track runtime status.
>>
>>   * Adjust vfork for shadow stack usage.
>>
>>   * Add ENDBR or NOTRACK where required in assembly.
>>
>>   * CET and makecontext incompatible.
>>     - Probably need to discuss which default is appropriate.
>>     - Should the user get CET automatically disabled in makecontext() et. al. silently?
>>     - Should your current solution, which is to error out during the build, and require
>>       flag changes, be the default? This forces the user to review the security for their
>>       application.
>
> I'd like to reserve 4 slots in ucontext for shadow stack:
>
> https://github.com/hjl-tools/glibc/commit/9bf6aefa8fb45f8df140d42ce9cf890bb24076e1
>
> It should be binary backward compatible.  I will investigate if there is a way
> to support shadow stack with existing API.  Otherwise, we need to add a new
> API for ucontext functions with shadow stack.
>
>>   * prctl for CET.
>
> We have been experimenting different approaches to get the best implementation.
> I am expecting that this patch may change as we collect more data.
>
>> * The work to review after this patch appears to be less contentious in terms of
>>   the kinds of changes that are required. Most of the changes are internal details
>>   of enabling CET and not ABI details, with the exception of the possible pain we
>>   might cause with makecontext() being unsupported and what default position to take
>>   there.
>>
>> Design:
>>
>> * Overall the implementation looks exactly how I might expect it to look, but some
>>   of the math that places the shadowstack pointer appears to need either commenting
>>   or fixing because I don't understand it. You need to make it easy for me to see
>>   that we have placed the shadowstack pointer into the 4 pad words.
>>
>> Details:
>>
>> * One comment needs filling out a bit more, noted below.
>>
>>> 0001-x86-Use-pad-in-pthread_unwind_buf-to-preserve-shadow.patch
>>>
>>>
>>> From f222537447f5ec879427f318b7c0396362b7453a Mon Sep 17 00:00:00 2001
>>> From: "H.J. Lu" <hjl.tools@gmail.com>
>>> Date: Sat, 24 Feb 2018 17:23:54 -0800
>>> Subject: [PATCH] x86: Use pad in pthread_unwind_buf to preserve shadow stack
>>>  register
>>>
>>> The pad array in struct pthread_unwind_buf is used by setjmp to save
>>> shadow stack register.  We assert that size of struct pthread_unwind_buf
>>> is no less than offset of shadow stack pointer + shadow stack pointer
>>> size.
>>>
>>
>> OK.
>>
>>> Since functions, like LIBC_START_MAIN, START_THREAD_DEFN as well as
>>> these with thread cancellation, call setjmp, but never return after
>>> __libc_unwind_longjmp, __libc_unwind_longjmp, which is defined as
>>> __libc_longjmp on x86, doesn't need to restore shadow stack register.
>>
>> OK.
>>
>>> __libc_longjmp, which is a private interface for thread cancellation
>>> implementation in libpthread, is changed to call __longjmp_cancel,
>>> instead of __longjmp.  __longjmp_cancel is a new internal function
>>> in libc, which is similar to __longjmp, but doesn't restore shadow
>>> stack register.
>>
>> OK. Good. I like the use of a __longjmp_cancel name to call out what's
>> going on in the API (clear semantics).
>>
>>>
>>> The compatibility longjmp and siglongjmp in libpthread.so are changed
>>> to call __libc_siglongjmp, instead of __libc_longjmp, so that they will
>>> restore shadow stack register.
>>
>> OK.
>>
>>>
>>> Tested with build-many-glibcs.py.
>>>
>>>       * nptl/pthread_create.c (START_THREAD_DEFN): Clear previous
>>>       handlers after setjmp.
>>>       * setjmp/longjmp.c (__libc_longjmp): Don't define alias if
>>>       defined.
>>>       * sysdeps/unix/sysv/linux/x86/setjmpP.h (_JUMP_BUF_SIGSET_NSIG):
>>>       Changed to 97.
>>>       * sysdeps/x86/Makefile (sysdep_routines): Add __longjmp_cancel.
>>>       * sysdeps/x86/__longjmp_cancel.S: New file.
>>>       * sysdeps/x86/longjmp.c: Likewise.
>>>       * sysdeps/x86/nptl/pt-longjmp.c: Likewise.
>>
>> This looks much better.
>>
>>> ---
>>>  nptl/pthread_create.c                 |  9 ++--
>>>  setjmp/longjmp.c                      |  2 +
>>>  sysdeps/unix/sysv/linux/x86/setjmpP.h |  4 +-
>>>  sysdeps/x86/Makefile                  |  4 ++
>>>  sysdeps/x86/__longjmp_cancel.S        | 20 ++++++++
>>>  sysdeps/x86/longjmp.c                 | 45 ++++++++++++++++
>>>  sysdeps/x86/nptl/pt-longjmp.c         | 97 +++++++++++++++++++++++++++++++++++
>>>  7 files changed, 176 insertions(+), 5 deletions(-)
>>>  create mode 100644 sysdeps/x86/__longjmp_cancel.S
>>>  create mode 100644 sysdeps/x86/longjmp.c
>>>  create mode 100644 sysdeps/x86/nptl/pt-longjmp.c
>>>
>>> diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
>>> index caaf07c134..1c5b3780c6 100644
>>> --- a/nptl/pthread_create.c
>>> +++ b/nptl/pthread_create.c
>>> @@ -427,12 +427,15 @@ START_THREAD_DEFN
>>>       compilers without that support we do use setjmp.  */
>>>    struct pthread_unwind_buf unwind_buf;
>>>
>>> -  /* No previous handlers.  */
>>> +  int not_first_call;
>>> +  not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf);
>>> +
>>> +  /* No previous handlers.  NB: This must be done after setjmp since
>>> +     the same space may be used by setjmp to store extra data which
>>> +     should never be used by __libc_unwind_longjmp.  */
>>
>> Suggest:
>> ~~~
>> No previous handlers.  NB: This must be done after setjmp since
>> the private space in the unwind jump buffer may overlap space
>> used by setjmp to store extra architecture-specific information
>> which is never be used by the cancellation-specific
>> __libc_unwind_longjmp.
>>
>> The private space is allowed to overlap because the unwinder never
>> has to return through any of the jumped-to call frames, and thus
>> only a minimum amount of saved data need be stored, and for example,
>> need not include the process signal mask information. This is all
>> an optimization to reduce stack usage when pushing cancellation
>> handlers.
>> ~~~
>
> Will fix it.
>
>>>    unwind_buf.priv.data.prev = NULL;
>>>    unwind_buf.priv.data.cleanup = NULL;
>>>
>>> -  int not_first_call;
>>> -  not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf);
>>
>> OK.
>>
>>>    if (__glibc_likely (! not_first_call))
>>>      {
>>>        /* Store the new cleanup handler info.  */
>>> diff --git a/setjmp/longjmp.c b/setjmp/longjmp.c
>>> index a2a7065a85..453889e103 100644
>>> --- a/setjmp/longjmp.c
>>> +++ b/setjmp/longjmp.c
>>> @@ -40,9 +40,11 @@ __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)
>>> +# endif
>>
>> OK.
>>
>>>  weak_alias (__libc_siglongjmp, _longjmp)
>>>  weak_alias (__libc_siglongjmp, longjmp)
>>>  weak_alias (__libc_siglongjmp, siglongjmp)
>>> diff --git a/sysdeps/unix/sysv/linux/x86/setjmpP.h b/sysdeps/unix/sysv/linux/x86/setjmpP.h
>>> index c0ed767a0d..90a6bbcf32 100644
>>> --- a/sysdeps/unix/sysv/linux/x86/setjmpP.h
>>> +++ b/sysdeps/unix/sysv/linux/x86/setjmpP.h
>>> @@ -22,8 +22,8 @@
>>>  #include <bits/types/__sigset_t.h>
>>>
>>>  /* The biggest signal number + 1.  As of kernel 4.14, x86 _NSIG is 64.
>>> -   Define it to 513 to leave some rooms for future use.  */
>>> -#define _JUMP_BUF_SIGSET_NSIG        513
>>> +   Define it to 97 to leave some rooms for future use.  */
>>
>> OK.
>>
>>> +#define _JUMP_BUF_SIGSET_NSIG        97
>>
>> Please provide proof in the way of a comment or rewriting this constant
>> to show that it places the shadow stack pointer on both x86_64 and x32
>> into the range of the private pad.
>
> sysdeps/x86/nptl/pt-longjmp.c has
>
> _Static_assert ((sizeof (struct pthread_unwind_buf)
>>= (SHADOW_STACK_POINTER_OFFSET
>      + SHADOW_STACK_POINTER_SIZE)),
> "size of struct pthread_unwind_buf < "
> "(SHADOW_STACK_POINTER_OFFSET + SHADOW_STACK_POINTER_SIZE)");
>
> If shadow stack pointer is saved in the offset bigger than the size of
> struct pthread_unwind_buf, assert will trigger at compile-time.
>
>> Also, from commit  f33632ccd1dec3217583fcfdd965afb62954203c,
>> where did this math come from?
>>
>> ((_JUMP_BUF_SIGSET_NSIG - 1 + 7) / (8 * sizeof (unsigned long int)))
>>
>> Why the +7?
>
> _JUMP_BUF_SIGSET_NSIG is the biggest signal number + 1.
> _JUMP_BUF_SIGSET_NSIG - 1 gives the biggest signal number.
> _JUMP_BUF_SIGSET_NSIG - 1 + 7 rounds up to the number of bytes
> which are needed to store the biggest signal number.
>
>>>  /* Number of longs to hold all signals.  */
>>>  #define _JUMP_BUF_SIGSET_NWORDS \
>>>    ((_JUMP_BUF_SIGSET_NSIG - 1 + 7) / (8 * sizeof (unsigned long int)))
>>> diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
>>> index 0d0326c21a..d25d6f0ae4 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 += __longjmp_cancel
>>> +endif
>>
>> OK.
>>
>>> 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
>>> +   <http://www.gnu.org/licenses/>.  */
>>> +
>>> +#define __longjmp __longjmp_cancel
>>> +#include <__longjmp.S>
>>
>> OK.
>>
>>> diff --git a/sysdeps/x86/longjmp.c b/sysdeps/x86/longjmp.c
>>> new file mode 100644
>>> index 0000000000..a53f31e1dd
>>> --- /dev/null
>>> +++ b/sysdeps/x86/longjmp.c
>>> @@ -0,0 +1,45 @@
>>> +/* __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
>>> +   <http://www.gnu.org/licenses/>.  */
>>> +
>>> +#define __libc_longjmp __redirect___libc_longjmp
>>> +#include <setjmp/longjmp.c>
>>> +#undef __libc_longjmp
>>> +
>>> +extern void __longjmp_cancel (__jmp_buf __env, int __val)
>>> +     __attribute__ ((__noreturn__)) attribute_hidden;
>>> +
>>> +/* 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);
>>
>> OK.
>>
>>> +
>>> +  if (env[0].__mask_was_saved)
>>> +    /* Restore the saved signal mask.  */
>>> +    (void) __sigprocmask (SIG_SETMASK,
>>> +                       (sigset_t *) &env[0].__saved_mask,
>>> +                       (sigset_t *) NULL);
>>
>> OK.
>>
>>> +
>>> +  /* Call the machine-dependent function to restore machine state
>>> +     without shadow stack.  */
>>> +  __longjmp_cancel (env[0].__jmpbuf, val ?: 1);
>>
>> OK.
>>
>>> +}
>>> diff --git a/sysdeps/x86/nptl/pt-longjmp.c b/sysdeps/x86/nptl/pt-longjmp.c
>>> new file mode 100644
>>> index 0000000000..7eb8651cfe
>>> --- /dev/null
>>> +++ b/sysdeps/x86/nptl/pt-longjmp.c
>>> @@ -0,0 +1,97 @@
>>> +/* ABI compatibility for 'longjmp' and 'siglongjmp' symbols in libpthread ABI.
>>> +   X86 version.
>>> +   Copyright (C) 18 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
>>> +   <http://www.gnu.org/licenses/>.  */
>>> +
>>> +/* <nptl/descr.h> has
>>> +
>>> +struct pthread_unwind_buf
>>> +{
>>> +  struct
>>> +  {
>>> +    __jmp_buf jmp_buf;
>>> +    int mask_was_saved;
>>> +  } cancel_jmp_buf[1];
>>> +
>>> +  union
>>> +  {
>>> +    void *pad[4];
>>> +    struct
>>> +    {
>>> +      struct pthread_unwind_buf *prev;
>>> +      struct _pthread_cleanup_buffer *cleanup;
>>> +      int canceltype;
>>> +    } data;
>>> +  } priv;
>>> +};
>>> +
>>> +  The pad array in struct pthread_unwind_buf is used by setjmp to save
>>
>> This appears to be SHADOW_STACK_POINTER_OFFSET in subsequent patches.
>>
>> However on your hjl/cet/master branch it appears that this offset is not
>> defined to be *just after* the mask_was_saved?
>
> sysdeps/unix/sysv/linux/x86/setjmpP.h has
>
> typedef struct
>   {
>     unsigned long int __val[_JUMP_BUF_SIGSET_NWORDS];
>   } __jmp_buf_sigset_t;
>
> typedef union
>   {
>     __sigset_t __saved_mask_compat;
>     struct
>       {
>          __jmp_buf_sigset_t __saved_mask;
>           /* Used for shadow stack pointer.  */
>          unsigned long int __shadow_stack_pointer;
>       } __saved;
>   } __jmpbuf_arch_t;
>
> __shadow_stack_pointer is placed after __saved_mask, aka mask_was_saved.
>
>>> +  shadow stack register.  Assert that size of struct pthread_unwind_buf
>>> +  is no less than offset of shadow stack pointer plus shadow stack
>>> +  pointer size.
>>> +
>>> +  NB: setjmp is called in libpthread to save shadow stack register.  But
>>> +  __libc_unwind_longjmp doesn't restore shadow stack register since they
>>> +  never return after longjmp.  */
>>> +
>>> +#include <pthreadP.h>
>>> +#include <jmp_buf-ssp.h>
>>> +
>>> +#ifdef __x86_64__
>>> +# define SHADOW_STACK_POINTER_SIZE 8
>>> +#else
>>> +# define SHADOW_STACK_POINTER_SIZE 4
>>> +#endif
>>> +
>>> +_Static_assert ((sizeof (struct pthread_unwind_buf)
>>> +              >= (SHADOW_STACK_POINTER_OFFSET
>>> +                  + SHADOW_STACK_POINTER_SIZE)),
>>> +             "size of struct pthread_unwind_buf < "
>>> +             "(SHADOW_STACK_POINTER_OFFSET + SHADOW_STACK_POINTER_SIZE)");
>>
>> OK.
>>
>>> +
>>> +#include <shlib-compat.h>
>>> +
>>> +/* libpthread once had its own longjmp (and siglongjmp alias), though there
>>> +   was no apparent reason for it.  There is no use in having a separate
>>> +   symbol in libpthread, but the historical ABI requires it.  For static
>>> +   linking, there is no need to provide anything here--the libc version
>>> +   will be linked in.  For shared library ABI compatibility, there must be
>>> +   longjmp and siglongjmp symbols in libpthread.so.
>>> +
>>> +   With an IFUNC resolver, it would be possible to avoid the indirection,
>>> +   but the IFUNC resolver might run before the __libc_longjmp symbol has
>>> +   been relocated, in which case the IFUNC resolver would not be able to
>>> +   provide the correct address.  */
>>> +
>>> +#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_22)
>>> +
>>> +static void __attribute__ ((noreturn, used))
>>> +longjmp_compat (jmp_buf env, int val)
>>> +{
>>> +  /* NB: We call __libc_siglongjmp,  instead of __libc_longjmp, since
>>> +     __libc_longjmp is a private interface for cancellation which
>>> +     doesn't restore shadow stack register.  */
>>> +  __libc_siglongjmp (env, val);
>>
>> OK.
>>
>>> +}
>>> +
>>> +strong_alias (longjmp_compat, longjmp_alias)
>>> +compat_symbol (libpthread, longjmp_alias, longjmp, GLIBC_2_0);
>>> +
>>> +strong_alias (longjmp_alias, siglongjmp_alias)
>>> +compat_symbol (libpthread, siglongjmp_alias, siglongjmp, GLIBC_2_0);
>>> +
>>> +#endif
>>> -- 2.14.3
>>
>>

Here is the updated patch.  OK for master?

I will submit a CET patch set after this patch is merged.

Thanks.

-- 
H.J.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-x86-Use-pad-in-pthread_unwind_buf-to-preserve-shadow.patch
Type: text/x-patch
Size: 11739 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/libc-alpha/attachments/20180406/8663d8cc/attachment.bin>


More information about the Libc-alpha mailing list