This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PING^1: [PATCH 08/24] x86: Update vfork to pop shadow stack


On Wed, Jun 13, 2018 at 8:31 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> Since we can't change return address on shadow stack, if shadow stack
> is in use, we need to pop shadow stack and jump back to caller directly.
>
>         * sysdeps/unix/sysv/linux/i386/vfork.S (SYSCALL_ERROR_HANDLER):
>         Redefine if shadow stack is enabled.
>         (SYSCALL_ERROR_LABEL): Likewise.
>         (__vfork): Pop shadow stack and jump back to to caller directly
>         when shadow stack is in use.
>         * sysdeps/unix/sysv/linux/x86_64/vfork.S (SYSCALL_ERROR_HANDLER):
>         Redefine if shadow stack is enabled.
>         (SYSCALL_ERROR_LABEL): Likewise.
>         (__vfork): Pop shadow stack and jump back to to caller directly
>         when shadow stack is in use.
> ---
>  sysdeps/unix/sysv/linux/i386/vfork.S   | 54 ++++++++++++++++++++++++++
>  sysdeps/unix/sysv/linux/x86_64/vfork.S | 35 +++++++++++++++++
>  2 files changed, 89 insertions(+)
>
> diff --git a/sysdeps/unix/sysv/linux/i386/vfork.S b/sysdeps/unix/sysv/linux/i386/vfork.S
> index 8f40d02d09..06d834d632 100644
> --- a/sysdeps/unix/sysv/linux/i386/vfork.S
> +++ b/sysdeps/unix/sysv/linux/i386/vfork.S
> @@ -21,6 +21,35 @@
>  #include <bits/errno.h>
>  #include <tcb-offsets.h>
>
> +#if defined __CET__ && (__CET__ & 2) != 0
> +/* When shadow stack is in use, we need to pop shadow stack and jump
> +   back to caller directly.   */
> +# undef SYSCALL_ERROR_HANDLER
> +# ifdef PIC
> +#  define SYSCALL_ERROR_HANDLER                                \
> +0:                                                     \
> +  calll .L1;                                           \
> +.L1:                                                   \
> +  popl %edx;                                           \
> +.L2:                                                   \
> +  addl $_GLOBAL_OFFSET_TABLE_ + (.L2 - .L1), %edx;     \
> +  movl __libc_errno@gotntpoff(%edx), %edx;             \
> +  negl %eax;                                           \
> +  movl %eax, %gs:(%edx);                               \
> +  orl $-1, %eax;                                       \
> +  jmp 1b;
> +# else
> +#  define SYSCALL_ERROR_HANDLER                                \
> +0:                                                     \
> +  movl __libc_errno@indntpoff, %edx;                   \
> +  negl %eax;                                           \
> +  movl %eax, %gs:(%edx);                               \
> +  orl $-1, %eax;                                       \
> +  jmp 1b;
> +# endif
> +# undef SYSCALL_ERROR_LABEL
> +# define SYSCALL_ERROR_LABEL 0f
> +#endif
>
>  /* Clone the calling process, but without copying the whole address space.
>     The calling process is suspended until the new process exits or is
> @@ -38,16 +67,41 @@ ENTRY (__vfork)
>         movl    $SYS_ify (vfork), %eax
>         int     $0x80
>
> +#if !defined __CET__ || (__CET__ & 2) == 0
>         /* Jump to the return PC.  Don't jump directly since this
>            disturbs the branch target cache.  Instead push the return
>            address back on the stack.  */
>         pushl   %ecx
>         cfi_adjust_cfa_offset (4)
> +#endif
>
>         cmpl    $-4095, %eax
>         /* Branch forward if it failed.  */
>         jae     SYSCALL_ERROR_LABEL
>
> +#if defined __CET__ && (__CET__ & 2) != 0
> +1:
> +       /* Check if shadow stack is in use.  */
> +       xorl    %edx, %edx
> +       rdsspd  %edx
> +       testl   %edx, %edx
> +       /* Normal return if shadow stack isn't in use.  */
> +       je      L(no_shstk)
> +
> +       /* Pop return address from shadow stack and jump back to caller
> +          directly.  */
> +       movl    $1, %edx
> +       incsspd %edx
> +       jmp     *%ecx
> +
> +L(no_shstk):
> +       /* Jump to the return PC.  Don't jump directly since this
> +          disturbs the branch target cache.  Instead push the return
> +          address back on the stack.  */
> +       pushl   %ecx
> +       cfi_adjust_cfa_offset (4)
> +#endif
> +
>         ret
>
>  PSEUDO_END (__vfork)
> diff --git a/sysdeps/unix/sysv/linux/x86_64/vfork.S b/sysdeps/unix/sysv/linux/x86_64/vfork.S
> index e4c8269e3d..cab3ad34a0 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/vfork.S
> +++ b/sysdeps/unix/sysv/linux/x86_64/vfork.S
> @@ -20,6 +20,18 @@
>  #include <bits/errno.h>
>  #include <tcb-offsets.h>
>
> +#if defined __CET__ && (__CET__ & 2) != 0
> +/* When shadow stack is in use, we need to pop shadow stack and jump
> +   back to caller directly.   */
> +# undef SYSCALL_ERROR_HANDLER
> +# define SYSCALL_ERROR_HANDLER                 \
> +0:                                             \
> +  SYSCALL_SET_ERRNO;                           \
> +  or $-1, %RAX_LP;                             \
> +  jmp 1b;
> +# undef SYSCALL_ERROR_LABEL
> +# define SYSCALL_ERROR_LABEL 0f
> +#endif
>
>  /* Clone the calling process, but without copying the whole address space.
>     The calling process is suspended until the new process exits or is
> @@ -38,13 +50,36 @@ ENTRY (__vfork)
>         movl    $SYS_ify (vfork), %eax
>         syscall
>
> +#if !defined __CET__ || (__CET__ & 2) == 0
>         /* Push back the return PC.  */
>         pushq   %rdi
>         cfi_adjust_cfa_offset(8)
> +#endif
>
>         cmpl    $-4095, %eax
>         jae SYSCALL_ERROR_LABEL         /* Branch forward if it failed.  */
>
> +#if defined __CET__ && (__CET__ & 2) != 0
> +1:
> +       /* Check if shadow stack is in use.  */
> +       xorl    %esi, %esi
> +       rdsspq  %rsi
> +       testq   %rsi, %rsi
> +       /* Normal return if shadow stack isn't in use.  */
> +       je      L(no_shstk)
> +
> +       /* Pop return address from shadow stack and jump back to caller
> +          directly.  */
> +       movl    $1, %esi
> +       incsspq %rsi
> +       jmp     *%rdi
> +
> +L(no_shstk):
> +       /* Push back the return PC.  */
> +       pushq   %rdi
> +       cfi_adjust_cfa_offset(8)
> +#endif
> +
>         /* Normal return.  */
>         ret
>
> --
> 2.17.1
>

PING.

-- 
H.J.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]