This is the mail archive of the glibc-cvs@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]

GNU C Library master sources branch hjl/cet/master created. glibc-2.26.9000-992-g9a93ebb


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, hjl/cet/master has been created
        at  9a93ebb3782acecc577e56705169a7942c33ce9f (commit)

- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=9a93ebb3782acecc577e56705169a7942c33ce9f

commit 9a93ebb3782acecc577e56705169a7942c33ce9f
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Fri Dec 8 04:47:49 2017 -0800

    x86: Check GNU_PROPERTY_X86_FEATURE_1_SHSTK isn't set
    
    -fcf-protection -mcet is incompatible with makecontext family functions
    since they can't properly set up and destroy shadow stack pointer.  When
    they are used, GNU_PROPERTY_X86_FEATURE_1_SHSTK shouldn't be set on the
    program.  Add a test to check it, which is expected to fail until the
    GCC bug:
    
    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81842
    
    is fixed.
    
    	* sysdeps/unix/sysv/linux/x86/Makefile (tests-special): Add
    	$(objpfx)tst-setcontext3-shstk.out.
    	($(objpfx)tst-setcontext3-shstk.out): New target.
    	* sysdeps/unix/sysv/linux/x86/tst-setcontext3-shstk.sh: New file.

diff --git a/sysdeps/unix/sysv/linux/x86/Makefile b/sysdeps/unix/sysv/linux/x86/Makefile
index d141984..c77d2a2 100644
--- a/sysdeps/unix/sysv/linux/x86/Makefile
+++ b/sysdeps/unix/sysv/linux/x86/Makefile
@@ -25,6 +25,15 @@ gen-as-const-headers += jmp_buf-ssp.sym
 tests += tst-saved_mask-1
 endif
 
+ifeq ($(subdir),stdlib)
+# Check that GNU_PROPERTY_X86_FEATURE_1_SHSTK isn't set.
+tests-special += $(objpfx)tst-setcontext3-shstk.out
+endif
+
+$(objpfx)tst-setcontext3-shstk.out: $(..)sysdeps/unix/sysv/linux/x86/tst-setcontext3-shstk.sh $(objpfx)tst-setcontext3
+	$(SHELL) $< $(common-objpfx)stdlib/ $(READELF) > $@; \
+	$(evaluate-test)
+
 ifeq ($(enable-cet),yes)
 ifeq ($(subdir),elf)
 sysdep-dl-routines += dl-cet
diff --git a/sysdeps/unix/sysv/linux/x86/tst-setcontext3-shstk.sh b/sysdeps/unix/sysv/linux/x86/tst-setcontext3-shstk.sh
new file mode 100644
index 0000000..9ce34eb
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/tst-setcontext3-shstk.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+# GCC bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81842
+# Check that GNU_PROPERTY_X86_FEATURE_1_SHSTK isn't set when setcontext()
+# is used.
+# 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
+# <http://www.gnu.org/licenses/>.
+
+set -e
+
+objpfx=$1
+readelf=$2
+
+test="${objpfx}tst-setcontext3"
+
+if $readelf -n $test | grep SHSTK; then
+  echo "FAIL: GNU_PROPERTY_X86_FEATURE_1_SHSTK is set on tst-setcontext3"
+  exit 1
+else
+  echo "PASS: GNU_PROPERTY_X86_FEATURE_1_SHSTK isn't set on tst-setcontext3"
+  exit 0
+fi

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=bf09ee6f431db892b872f0d9ee2c23d5d278d01b

commit bf09ee6f431db892b872f0d9ee2c23d5d278d01b
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Tue Dec 5 11:58:23 2017 -0800

    Linux/x86: Support shadow stack pointer in setjmp/longjmp
    
    Save and restore shadow stack pointer in setjmp and longjmp to support
    shadow stack in Intel CET.  Use feature_1 in tcbhead_t to 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.
    
    2017-12-07  Igor Tsimbalist  <igor.v.tsimbalist@intel.com>
    	    H.J. Lu  <hongjiu.lu@intel.com>
    
    	* sysdeps/unix/sysv/linux/i386/____longjmp_chk.S: Include
    	<jmp_buf-ssp.h>.  Restore shadow stack pointer if shadow
    	stack is enabled.
    	* sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S: Likewise.
    	* sysdeps/unix/sysv/linux/i386/__longjmp.S: New file.
    	* sysdeps/unix/sysv/linux/i386/bsd-_setjmp.S: Likewise.
    	* sysdeps/unix/sysv/linux/i386/bsd-setjmp.S: Likewise.
    	* sysdeps/unix/sysv/linux/i386/setjmp.S: Likewise.
    	* sysdeps/unix/sysv/linux/x86_64/__longjmp.S: Likewise.
    	* sysdeps/unix/sysv/linux/x86_64/setjmp.S: Likewise.

diff --git a/sysdeps/unix/sysv/linux/i386/____longjmp_chk.S b/sysdeps/unix/sysv/linux/i386/____longjmp_chk.S
index 2e4427a..3c2d94e 100644
--- a/sysdeps/unix/sysv/linux/i386/____longjmp_chk.S
+++ b/sysdeps/unix/sysv/linux/i386/____longjmp_chk.S
@@ -19,7 +19,7 @@
 #include <jmpbuf-offsets.h>
 #include <asm-syntax.h>
 #include <stap-probe.h>
-
+#include <jmp_buf-ssp.h>
 
 	.section .rodata.str1.1,"aMS",@progbits,1
 	.type	longjmp_msg,@object
@@ -46,6 +46,40 @@ longjmp_msg:
 ENTRY (____longjmp_chk)
 	movl	4(%esp), %ecx	/* User's jmp_buf in %ecx.  */
 
+#ifdef __SHSTK__
+# if IS_IN (libc) && defined SHARED
+	/* Check if Shadow Stack is enabled.  */
+	testl   $(1 << 1), %gs:FEATURE_1_OFFSET
+	jz      .Lnoadj
+# endif
+	/* Check and adjust the Shadow-Stack-Pointer.  */
+	xorl	%edx, %edx
+	/* Get the current ssp.  */
+	rdsspd	%edx
+	/* And compare it with the saved ssp value.  */
+	subl	SHADOW_STACK_POINTER_OFFSET(%ecx), %edx
+	je	.Lnoadj
+	/* Count the number of frames to adjust and adjust it
+	   with incssp instruction.  The instruction can adjust
+	   the ssp by [0..255] value only thus use a loop if
+	   the number of frames is bigger than 255.  */
+	negl	%edx
+	shrl	$2, %edx
+	/* NB: We saved Shadow-Stack-Pointer of setjmp.  Since we are
+	       restoring Shadow-Stack-Pointer of setjmp's caller, we
+	       need to unwind shadow stack by one more frame.  */
+	addl	$1, %edx
+	cmpl	$255, %edx
+	jbe	.Lonetime
+.Loopadj:
+	incsspd	%edx
+	subl	$255, %edx
+	cmpl	$255, %edx
+	ja	.Loopadj
+.Lonetime:
+	incsspd	%edx
+.Lnoadj:
+#endif
 	/* Save the return address now.  */
 	movl	(JB_PC*4)(%ecx), %edx
 	/* Get the stack pointer.  */
diff --git a/sysdeps/unix/sysv/linux/i386/__longjmp.S b/sysdeps/unix/sysv/linux/i386/__longjmp.S
new file mode 100644
index 0000000..c41dac1
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/__longjmp.S
@@ -0,0 +1,137 @@
+/* longjmp for Linux/i386 with shadow stack support.
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <jmpbuf-offsets.h>
+#include <asm-syntax.h>
+#include <stap-probe.h>
+#include <jmp_buf-ssp.h>
+
+	.text
+ENTRY (__longjmp)
+#ifdef PTR_DEMANGLE
+	movl 4(%esp), %eax	/* User's jmp_buf in %eax.  */
+
+# ifdef __SHSTK__
+#  if IS_IN (libc) && defined SHARED
+	/* Check if Shadow Stack is enabled.  */
+	testl   $(1 << 1), %gs:FEATURE_1_OFFSET
+	jz      .Lnoadj
+#  endif
+	/* Check and adjust the Shadow-Stack-Pointer.  */
+	xorl	%ecx, %ecx
+	/* Get the current ssp.  */
+	rdsspd	%ecx
+	/* And compare it with the saved ssp value.  */
+	subl	SHADOW_STACK_POINTER_OFFSET(%eax), %ecx
+	je	.Lnoadj
+	/* Count the number of frames to adjust and adjust it
+	   with incssp instruction.  The instruction can adjust
+	   the ssp by [0..255] value only thus use a loop if
+	   the number of frames is bigger than 255.  */
+	negl	%ecx
+	shrl	$2, %ecx
+	/* NB: We saved Shadow-Stack-Pointer of setjmp.  Since we are
+	       restoring Shadow-Stack-Pointer of setjmp's caller, we
+	       need to unwind shadow stack by one more frame.  */
+	addl	$1, %ecx
+	cmpl	$255, %ecx
+	jbe	.Lonetime
+.Loopadj:
+	incsspd	%ecx
+	subl	$255, %ecx
+	cmpl	$255, %ecx
+	ja	.Loopadj
+.Lonetime:
+	incsspd	%ecx
+.Lnoadj:
+# endif
+	/* Save the return address now.  */
+	movl (JB_PC*4)(%eax), %edx
+	/* Get the stack pointer.  */
+	movl (JB_SP*4)(%eax), %ecx
+	PTR_DEMANGLE (%edx)
+	PTR_DEMANGLE (%ecx)
+	LIBC_PROBE (longjmp, 3, 4@%eax, -4@8(%esp), 4@%edx)
+	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)
+
+	LIBC_PROBE (longjmp_target, 3, 4@%eax, -4@8(%esp), 4@%edx)
+	movl 8(%esp), %eax	/* Second argument is return value.  */
+	movl %ecx, %esp
+#else
+	movl 4(%esp), %ecx	/* User's jmp_buf in %ecx.  */
+	movl 8(%esp), %eax	/* Second argument is return value.  */
+# ifdef __SHSTK__
+#  if IS_IN (libc) && defined SHARED
+	/* Check if Shadow Stack is enabled.  */
+	testl   $(1 << 1), %gs:FEATURE_1_OFFSET
+	jz      .Lnoadj
+#  endif
+	/* Check and adjust the Shadow-Stack-Pointer.  */
+	xorl	%edx, %edx
+	/* Get the current ssp.  */
+	rdsspd	%edx
+	/* And compare it with the saved ssp value.  */
+	subl	SHADOW_STACK_POINTER_OFFSET(%ecx), %edx
+	je	.Lnoadj
+	/* Count the number of frames to adjust and adjust it
+	   with incssp instruction.  The instruction can adjust
+	   the ssp by [0..255] value only thus use a loop if
+	   the number of frames is bigger than 255.  */
+	negl	%edx
+	shrl	$3, %edx
+	cmpl	$255, %edx
+	jbe	.Lonetime
+.Loopadj:
+	incsspd	%edx
+	subl	$255, %edx
+	cmpl	$255, %edx
+	ja	.Loopadj
+.Lonetime:
+	incsspd	%edx
+.Lnoadj:
+# endif
+	/* Save the return address now.  */
+	movl (JB_PC*4)(%ecx), %edx
+	LIBC_PROBE (longjmp, 3, 4@%ecx, -4@%eax, 4@%edx)
+	/* 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_SP*4)(%ecx), %esp
+	LIBC_PROBE (longjmp_target, 3, 4@%ecx, -4@%ecx, 4@%edx)
+#endif
+	/* Jump to saved PC.  */
+	jmp *%edx
+END (__longjmp)
diff --git a/sysdeps/unix/sysv/linux/i386/bsd-_setjmp.S b/sysdeps/unix/sysv/linux/i386/bsd-_setjmp.S
new file mode 100644
index 0000000..7b2f1f7
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/bsd-_setjmp.S
@@ -0,0 +1,72 @@
+/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'.  Linux/i386 version
+   with shadow stack support.
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+/* This just does a tail-call to `__sigsetjmp (ARG, 0)'.
+   We cannot do it in C because it must be a tail-call, so frame-unwinding
+   in setjmp doesn't clobber the state restored by longjmp.  */
+
+#include <sysdep.h>
+#include <jmpbuf-offsets.h>
+#include <stap-probe.h>
+#include <jmp_buf-ssp.h>
+
+#define PARMS	4		/* no space for saved regs */
+#define JMPBUF	PARMS
+#define SIGMSK	JMPBUF+4
+
+ENTRY (_setjmp)
+
+	xorl %eax, %eax
+	movl JMPBUF(%esp), %edx
+
+	/* Save registers.  */
+	movl %ebx, (JB_BX*4)(%edx)
+	movl %esi, (JB_SI*4)(%edx)
+	movl %edi, (JB_DI*4)(%edx)
+	leal JMPBUF(%esp), %ecx	/* Save SP as it will be after we return.  */
+#ifdef PTR_MANGLE
+	PTR_MANGLE (%ecx)
+#endif
+	movl %ecx, (JB_SP*4)(%edx)
+	movl 0(%esp), %ecx	/* Save PC we are returning to now.  */
+	LIBC_PROBE (setjmp, 3, 4@%edx, -4@$0, 4@%ecx)
+#ifdef PTR_MANGLE
+	PTR_MANGLE (%ecx)
+#endif
+	movl %ecx, (JB_PC*4)(%edx)
+	movl %ebp, (JB_BP*4)(%edx) /* Save caller's frame pointer.  */
+
+	movl %eax, JB_SIZE(%edx) /* No signal mask set.  */
+#ifdef __SHSTK__
+# if IS_IN (libc) && defined SHARED
+	/* Check if Shadow Stack is enabled.  */
+	testl   $(1 << 1), %gs:FEATURE_1_OFFSET
+	jz      .Lskip_ssp
+# endif
+	/* Get the current Shadow-Stack-Pointer and save it.  */
+	xorl    %ecx, %ecx
+	rdsspd  %ecx
+	movl    %ecx, SHADOW_STACK_POINTER_OFFSET(%edx)
+# if IS_IN (libc) && defined SHARED
+.Lskip_ssp:
+# endif
+#endif
+	ret
+END (_setjmp)
+libc_hidden_def (_setjmp)
diff --git a/sysdeps/unix/sysv/linux/i386/bsd-setjmp.S b/sysdeps/unix/sysv/linux/i386/bsd-setjmp.S
new file mode 100644
index 0000000..9019532
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/bsd-setjmp.S
@@ -0,0 +1,82 @@
+/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'.  Linux/i386 version
+   with shadow stack support.
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+/* This just does a tail-call to `__sigsetjmp (ARG, 1)'.
+   We cannot do it in C because it must be a tail-call, so frame-unwinding
+   in setjmp doesn't clobber the state restored by longjmp.  */
+
+#include <sysdep.h>
+#include <jmpbuf-offsets.h>
+#include <stap-probe.h>
+#include <jmp_buf-ssp.h>
+
+#define PARMS  4		/* no space for saved regs */
+#define JMPBUF PARMS
+#define SIGMSK JMPBUF+4
+
+ENTRY (setjmp)
+	/* Note that we have to use a non-exported symbol in the next
+	   jump since otherwise gas will emit it as a jump through the
+	   PLT which is what we cannot use here.  */
+
+	movl JMPBUF(%esp), %eax
+
+	/* Save registers.  */
+	movl %ebx, (JB_BX*4)(%eax)
+	movl %esi, (JB_SI*4)(%eax)
+	movl %edi, (JB_DI*4)(%eax)
+	leal JMPBUF(%esp), %ecx	/* Save SP as it will be after we return.  */
+#ifdef PTR_MANGLE
+	PTR_MANGLE (%ecx)
+#endif
+	movl %ecx, (JB_SP*4)(%eax)
+	movl 0(%esp), %ecx	/* Save PC we are returning to now.  */
+	LIBC_PROBE (setjmp, 3, 4@%eax, -4@$1, 4@%ecx)
+#ifdef PTR_MANGLE
+	PTR_MANGLE (%ecx)
+#endif
+	movl %ecx, (JB_PC*4)(%eax)
+	movl %ebp, (JB_BP*4)(%eax) /* Save caller's frame pointer.  */
+#ifdef __SHSTK__
+# if IS_IN (libc) && defined SHARED
+	/* Check if Shadow Stack is enabled.  */
+	testl   $(1 << 1), %gs:FEATURE_1_OFFSET
+	jz      .Lskip_ssp
+# endif
+	/* Get the current Shadow-Stack-Pointer and save it.  */
+	xorl    %ecx, %ecx
+	rdsspd  %ecx
+	movl    %ecx, SHADOW_STACK_POINTER_OFFSET(%eax)
+# if IS_IN (libc) && defined SHARED
+.Lskip_ssp:
+# endif
+#endif
+
+	/* Call __sigjmp_save.  */
+	pushl $1
+	cfi_adjust_cfa_offset (4)
+	pushl 8(%esp)
+	cfi_adjust_cfa_offset (4)
+	call __sigjmp_save
+	popl %ecx
+	cfi_adjust_cfa_offset (-4)
+	popl %edx
+	cfi_adjust_cfa_offset (-4)
+	ret
+END (setjmp)
diff --git a/sysdeps/unix/sysv/linux/i386/setjmp.S b/sysdeps/unix/sysv/linux/i386/setjmp.S
new file mode 100644
index 0000000..82efc5f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/setjmp.S
@@ -0,0 +1,73 @@
+/* setjmp for Linux/i386 with shadow stack support.
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <jmpbuf-offsets.h>
+#include <asm-syntax.h>
+#include <stap-probe.h>
+#include <jmp_buf-ssp.h>
+
+#define PARMS	4		/* no space for saved regs */
+#define JMPBUF	PARMS
+#define SIGMSK	JMPBUF+4
+
+ENTRY (__sigsetjmp)
+
+	movl JMPBUF(%esp), %eax
+
+	/* Save registers.  */
+	movl %ebx, (JB_BX*4)(%eax)
+	movl %esi, (JB_SI*4)(%eax)
+	movl %edi, (JB_DI*4)(%eax)
+	leal JMPBUF(%esp), %ecx	/* Save SP as it will be after we return.  */
+#ifdef PTR_MANGLE
+	PTR_MANGLE (%ecx)
+#endif
+	movl %ecx, (JB_SP*4)(%eax)
+	movl 0(%esp), %ecx	/* Save PC we are returning to now.  */
+	LIBC_PROBE (setjmp, 3, 4@%eax, -4@SIGMSK(%esp), 4@%ecx)
+#ifdef PTR_MANGLE
+	PTR_MANGLE (%ecx)
+#endif
+	movl %ecx, (JB_PC*4)(%eax)
+	movl %ebp, (JB_BP*4)(%eax) /* Save caller's frame pointer.  */
+
+#ifdef __SHSTK__
+# if IS_IN (libc) && defined SHARED
+	/* Check if Shadow Stack is enabled.  */
+	testl   $(1 << 1), %gs:FEATURE_1_OFFSET
+	jz      .Lskip_ssp
+# endif
+	/* Get the current Shadow-Stack-Pointer and save it.  */
+	xorl    %ecx, %ecx
+	rdsspd  %ecx
+	movl    %ecx, SHADOW_STACK_POINTER_OFFSET(%eax)
+# if IS_IN (libc) && defined SHARED
+.Lskip_ssp:
+# endif
+#endif
+#if IS_IN (rtld)
+	/* In ld.so we never save the signal mask.  */
+	xorl %eax, %eax
+	ret
+#else
+	/* Make a tail call to __sigjmp_save; it takes the same args.  */
+	jmp __sigjmp_save
+#endif
+END (__sigsetjmp)
+hidden_def (__sigsetjmp)
diff --git a/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S b/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S
index 2955c56..1e7c543 100644
--- a/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S
+++ b/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S
@@ -21,6 +21,7 @@
 #include <stap-probe.h>
 
 #include <sigaltstack-offsets.h>
+#include <jmp_buf-ssp.h>
 
 	.section .rodata.str1.1,"aMS",@progbits,1
 	.type	longjmp_msg,@object
@@ -105,6 +106,40 @@ ENTRY(____longjmp_chk)
 	cfi_restore (%rsi)
 
 .Lok:
+#ifdef __SHSTK__
+# if IS_IN (libc) && defined SHARED
+	/* Check if Shadow Stack is enabled.  */
+	testl	$(1 << 1), %fs:FEATURE_1_OFFSET
+	jz	.Lnoadj
+# endif
+	/* Check and adjust the Shadow-Stack-Pointer.  */
+	xorq    %rax, %rax
+	/* Get the current ssp.  */
+	rdsspq  %rax
+	/* And compare it with the saved ssp value.  */
+	subq    SHADOW_STACK_POINTER_OFFSET(%rdi), %rax
+	je      .Lnoadj
+	/* Count the number of frames to adjust and adjust it
+	   with incssp instruction.  The instruction can adjust
+	   the ssp by [0..255] value only thus use a loop if
+	   the number of frames is bigger than 255.  */
+	negq    %rax
+	shrq    $3, %rax
+	/* NB: We saved Shadow-Stack-Pointer of setjmp.  Since we are
+	       restoring Shadow-Stack-Pointer of setjmp's caller, we
+	       need to unwind shadow stack by one more frame.  */
+	addq	$1, %rax
+	cmpq    $255, %rax
+	jbe     .Lonetime
+.Loopadj:
+	incsspq %rax
+	subq    $255, %rax
+	cmpq    $255, %rax
+	ja      .Loopadj
+.Lonetime:
+	incsspq %rax
+.Lnoadj:
+#endif
 	LIBC_PROBE (longjmp, 3, LP_SIZE@%RDI_LP, -4@%esi, LP_SIZE@%RDX_LP)
 	/* We add unwind information for the target here.  */
 	cfi_def_cfa(%rdi, 0)
diff --git a/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S b/sysdeps/unix/sysv/linux/x86_64/__longjmp.S
similarity index 50%
copy from sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S
copy to sysdeps/unix/sysv/linux/x86_64/__longjmp.S
index 2955c56..48045c5 100644
--- a/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S
+++ b/sysdeps/unix/sysv/linux/x86_64/__longjmp.S
@@ -1,4 +1,5 @@
-/* Copyright (C) 2001-2017 Free Software Foundation, Inc.
+/* longjmp for Linux/x86-64 with shadow stack support.
+   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
@@ -17,47 +18,20 @@
 
 #include <sysdep.h>
 #include <jmpbuf-offsets.h>
+#include <jmp_buf-ssp.h>
 #include <asm-syntax.h>
 #include <stap-probe.h>
-
-#include <sigaltstack-offsets.h>
-
-	.section .rodata.str1.1,"aMS",@progbits,1
-	.type	longjmp_msg,@object
-longjmp_msg:
-	.string "longjmp causes uninitialized stack frame"
-	.size	longjmp_msg, .-longjmp_msg
-
-
-//#define __longjmp ____longjmp_chk
-
-#ifdef PIC
-# define CALL_FAIL	sub	$8, %RSP_LP;				      \
-			cfi_remember_state;				      \
-			cfi_def_cfa_offset(16);				      \
-			lea	longjmp_msg(%rip), %RDI_LP;		      \
-			call	HIDDEN_JUMPTARGET(__fortify_fail);	      \
-			nop;						      \
-			cfi_restore_state
-#else
-# define CALL_FAIL	sub	$8, %RSP_LP;				      \
-			cfi_remember_state;				      \
-			cfi_def_cfa_offset(16);				      \
-			mov	$longjmp_msg, %RDI_LP;			      \
-			call	HIDDEN_JUMPTARGET(__fortify_fail);	      \
-			nop;						      \
-			cfi_restore_state
-#endif
+#include <jmp_buf-ssp.h>
 
 /* Jump to the position specified by ENV, causing the
    setjmp call there to return VAL, or 1 if VAL is 0.
    void __longjmp (__jmp_buf env, int val).  */
 	.text
-ENTRY(____longjmp_chk)
+ENTRY(__longjmp)
 	/* Restore registers.  */
-	mov	(JB_RSP*8)(%rdi), %R8_LP
-	mov	(JB_RBP*8)(%rdi),%R9_LP
-	mov	(JB_PC*8)(%rdi), %RDX_LP
+	mov (JB_RSP*8)(%rdi),%R8_LP
+	mov (JB_RBP*8)(%rdi),%R9_LP
+	mov (JB_PC*8)(%rdi),%RDX_LP
 #ifdef PTR_DEMANGLE
 	PTR_DEMANGLE (%R8_LP)
 	PTR_DEMANGLE (%R9_LP)
@@ -71,40 +45,40 @@ ENTRY(____longjmp_chk)
 	orq %rax, %r9
 # endif
 #endif
-
-	cmp	%R8_LP, %RSP_LP
-	jbe	.Lok
-
-	/* Save function parameters.  */
-	movq	%rdi, %r10
-	cfi_register (%rdi, %r10)
-	movl	%esi, %ebx
-	cfi_register (%rsi, %rbx)
-
-	xorl	%edi, %edi
-	lea	-sizeSS(%rsp), %RSI_LP
-	movl	$__NR_sigaltstack, %eax
-	syscall
-	/* Without working sigaltstack we cannot perform the test.  */
-	testl	%eax, %eax
-	jne	.Lok2
-	testl	$1, (-sizeSS + oSS_FLAGS)(%rsp)
-	jz	.Lfail
-
-	mov	(-sizeSS + oSS_SP)(%rsp), %RAX_LP
-	add	(-sizeSS + oSS_SIZE)(%rsp), %RAX_LP
-	sub	%R8_LP, %RAX_LP
-	cmp	(-sizeSS + oSS_SIZE)(%rsp), %RAX_LP
-	jae	.Lok2
-
-.Lfail:	CALL_FAIL
-
-.Lok2:	movq	%r10, %rdi
-	cfi_restore (%rdi)
-	movl	%ebx, %esi
-	cfi_restore (%rsi)
-
-.Lok:
+#ifdef __SHSTK__
+# if IS_IN (libc) && defined SHARED
+	/* Check if Shadow Stack is enabled.  */
+	testl	$(1 << 1), %fs:FEATURE_1_OFFSET
+	jz	.Lnoadj
+# endif
+	/* Check and adjust the Shadow-Stack-Pointer.  */
+	xorl	%eax, %eax
+	/* Get the current ssp.  */
+	rdsspq  %rax
+	/* And compare it with the saved ssp value.  */
+	subq    SHADOW_STACK_POINTER_OFFSET(%rdi), %rax
+	je      .Lnoadj
+	/* Count the number of frames to adjust and adjust it
+	   with incssp instruction.  The instruction can adjust
+	   the ssp by [0..255] value only thus use a loop if
+	   the number of frames is bigger than 255.  */
+	negq    %rax
+	shrq    $3, %rax
+	/* NB: We saved Shadow-Stack-Pointer of setjmp.  Since we are
+	       restoring Shadow-Stack-Pointer of setjmp's caller, we
+	       need to unwind shadow stack by one more frame.  */
+	addq	$1, %rax
+	cmpq    $255, %rax
+	jbe     .Lonetime
+.Loopadj:
+	incsspq %rax
+	subq    $255, %rax
+	cmpq    $255, %rax
+	ja      .Loopadj
+.Lonetime:
+	incsspq %rax
+.Lnoadj:
+#endif
 	LIBC_PROBE (longjmp, 3, LP_SIZE@%RDI_LP, -4@%esi, LP_SIZE@%RDX_LP)
 	/* We add unwind information for the target here.  */
 	cfi_def_cfa(%rdi, 0)
@@ -116,16 +90,16 @@ ENTRY(____longjmp_chk)
 	cfi_offset(%r13,JB_R13*8)
 	cfi_offset(%r14,JB_R14*8)
 	cfi_offset(%r15,JB_R15*8)
-	movq	(JB_RBX*8)(%rdi), %rbx
-	movq	(JB_R12*8)(%rdi), %r12
-	movq	(JB_R13*8)(%rdi), %r13
-	movq	(JB_R14*8)(%rdi), %r14
-	movq	(JB_R15*8)(%rdi), %r15
+	movq (JB_RBX*8)(%rdi),%rbx
+	movq (JB_R12*8)(%rdi),%r12
+	movq (JB_R13*8)(%rdi),%r13
+	movq (JB_R14*8)(%rdi),%r14
+	movq (JB_R15*8)(%rdi),%r15
 	/* Set return value for setjmp.  */
-	movl	%esi, %eax
-	mov	%R8_LP, %RSP_LP
-	movq	%r9,%rbp
+	mov %esi, %eax
+	mov %R8_LP,%RSP_LP
+	movq %r9,%rbp
 	LIBC_PROBE (longjmp_target, 3,
 		    LP_SIZE@%RDI_LP, -4@%eax, LP_SIZE@%RDX_LP)
-	jmpq	*%rdx
-END (____longjmp_chk)
+	jmpq *%rdx
+END (__longjmp)
diff --git a/sysdeps/unix/sysv/linux/x86_64/setjmp.S b/sysdeps/unix/sysv/linux/x86_64/setjmp.S
new file mode 100644
index 0000000..a8710ca
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/setjmp.S
@@ -0,0 +1,82 @@
+/* setjmp for Linux/x86-64 with shadow stack support.
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <jmpbuf-offsets.h>
+#include <jmp_buf-ssp.h>
+#include <asm-syntax.h>
+#include <stap-probe.h>
+#include <jmp_buf-ssp.h>
+
+ENTRY (__sigsetjmp)
+	/* Save registers.  */
+	movq %rbx, (JB_RBX*8)(%rdi)
+#ifdef PTR_MANGLE
+# ifdef __ILP32__
+	/* Save the high bits of %rbp first, since PTR_MANGLE will
+	   only handle the low bits but we cannot presume %rbp is
+	   being used as a pointer and truncate it.  Here we write all
+	   of %rbp, but the low bits will be overwritten below.  */
+	movq %rbp, (JB_RBP*8)(%rdi)
+# endif
+	mov %RBP_LP, %RAX_LP
+	PTR_MANGLE (%RAX_LP)
+	mov %RAX_LP, (JB_RBP*8)(%rdi)
+#else
+	movq %rbp, (JB_RBP*8)(%rdi)
+#endif
+	movq %r12, (JB_R12*8)(%rdi)
+	movq %r13, (JB_R13*8)(%rdi)
+	movq %r14, (JB_R14*8)(%rdi)
+	movq %r15, (JB_R15*8)(%rdi)
+	lea 8(%rsp), %RDX_LP	/* Save SP as it will be after we return.  */
+#ifdef PTR_MANGLE
+	PTR_MANGLE (%RDX_LP)
+#endif
+	movq %rdx, (JB_RSP*8)(%rdi)
+	mov (%rsp), %RAX_LP	/* Save PC we are returning to now.  */
+	LIBC_PROBE (setjmp, 3, LP_SIZE@%RDI_LP, -4@%esi, LP_SIZE@%RAX_LP)
+#ifdef PTR_MANGLE
+	PTR_MANGLE (%RAX_LP)
+#endif
+	movq %rax, (JB_PC*8)(%rdi)
+
+#ifdef __SHSTK__
+# if IS_IN (libc) && defined SHARED
+	/* Check if Shadow Stack is enabled.  */
+	testl	$(1 << 1), %fs:FEATURE_1_OFFSET
+	jz	.Lskip_ssp
+# endif
+	/* Get the current Shadow-Stack-Pointer and save it.  */
+	xorl %eax, %eax
+	rdsspq %rax
+	movq %rax, SHADOW_STACK_POINTER_OFFSET(%rdi)
+# if IS_IN (libc) && defined SHARED
+.Lskip_ssp:
+# endif
+#endif
+#if IS_IN (rtld)
+	/* In ld.so we never save the signal mask.  */
+	xorl %eax, %eax
+	retq
+#else
+	/* Make a tail call to __sigjmp_save; it takes the same args.  */
+	jmp __sigjmp_save
+#endif
+END (__sigsetjmp)
+hidden_def (__sigsetjmp)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=a1cef7a7b1bb777b2091ca388c0fb51f336c9b73

commit a1cef7a7b1bb777b2091ca388c0fb51f336c9b73
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Thu Jun 22 04:15:39 2017 -0700

    x86: Support IBT and SHSTK in Intel CET [BZ #21598]
    
    Intel Control-flow Enforcement Technology (CET) instructions:
    
    https://software.intel.com/sites/default/files/managed/4d/2a/control-flow-en
    forcement-technology-preview.pdf
    
    includes Indirect Branch Tracking (IBT) and Shadow Stack (SHSTK).
    
    GNU_PROPERTY_X86_FEATURE_1_IBT is added to GNU program property to
    indicate that all executable sections are compatible with IBT when
    ENDBR instruction starts each valid target where an indirect branch
    instruction can land.  Linker sets GNU_PROPERTY_X86_FEATURE_1_IBT on
    output only if it is set on all relocatable inputs.
    
    On an IBT capable processor, the following steps should be taken:
    
    1. When loading an executable without an interpreter, enable IBT and
    lock IBT if GNU_PROPERTY_X86_FEATURE_1_IBT is set on the executable.
    2. When loading an executable with an interpreter, enable IBT if
    GNU_PROPERTY_X86_FEATURE_1_IBT is set on the interpreter.
      a. If GNU_PROPERTY_X86_FEATURE_1_IBT isn't set on the executable,
         disable IBT.
      b. Lock IBT.
    3. If IBT is enabled, when loading a shared object without
    GNU_PROPERTY_X86_FEATURE_1_IBT:
      a. If legacy interwork is allowed, then mark all pages in executable
         PT_LOAD segments in legacy code page bitmap.  Failure of legacy code
         page bitmap allocation causes an error.
      b. If legacy interwork isn't allowed, it causes an error.
    
    GNU_PROPERTY_X86_FEATURE_1_SHSTK is added to GNU program property to
    indicate that all executable sections are compatible with SHSTK where
    return address popped from shadow stack always matches return address
    popped from normal stack.  Linker sets GNU_PROPERTY_X86_FEATURE_1_SHSTK
    on output only if it is set on all relocatable inputs.
    
    On a SHSTK capable processor, the following steps should be taken:
    
    1. When loading an executable without an interpreter, enable SHSTK if
    GNU_PROPERTY_X86_FEATURE_1_SHSTK is set on the executable.
    2. When loading an executable with an interpreter, enable SHSTK if
    GNU_PROPERTY_X86_FEATURE_1_SHSTK is set on interpreter.
      a. If GNU_PROPERTY_X86_FEATURE_1_SHSTK isn't set on the executable
         or any shared objects loaded via the DT_NEEDED tag, disable SHSTK.
      b. Otherwise lock SHSTK.
    3. After SHSTK is enabled, it is an error to load a shared object
    without GNU_PROPERTY_X86_FEATURE_1_SHSTK.
    
    When glibc is built with a CET-enabled compiler, CET is enabled by
    default, unless --disable-cet is used to configure glibc.  When CET is
    enabled, both compiler and assembler must support CET.  Otherwise, it
    is a configure-time error.
    
    To support CET run-time control,
    
    1. _dl_x86_feature_1 is added to the writable ld.so namespace to indicate
    if IBT or SHSTK are enabled at run-time.  It should be initialized by
    init_cpu_features.
    2. For dynamic executables:
       a. A l_cet field is added to struct link_map to indicate if IBT or
          SHSTK is enabled in an ELF module.  The optional DL_PROCESS_PT_NOTE
          is called to process PT_NOTE segment for GNU program property and
          set l_cet.
       b. _dl_start_user calls _dl_cet_init, instead of _dl_init, which sets
          up IBT and SHSTK.
       c. DL_OPEN_CHECK is added to check IBT and SHSTK compatibilty when
          dlopening a shared object.
    3. Replace i386 _dl_runtime_resolve and _dl_runtime_profile with
    _dl_runtime_resolve_shstk and _dl_runtime_profile_shstk, respectively if
    SHSTK is enabled.
    
    <cet.h> from CET-enabled GCC is automatically included by assembly codes
    to add GNU_PROPERTY_X86_FEATURE_1_IBT and GNU_PROPERTY_X86_FEATURE_1_SHSTK
    to GNU program property.  _CET_ENDBR is added at the entrance of all
    assembly functions whose address may be taken.
    
    	 [BZ #21598]
    	* config.h.in (ENABLE_CET): New #undef.
    	* configure.ac: Add --enable-cet.
    	* configure: Regenerated.
    	* elf/dl-load.c (filebuf): Moved before "dynamic-link.h".
    	(_dl_map_object_from_fd): Call DL_PROCESS_PT_NOTE on PT_NOTE
    	segment if DL_PROCESS_PT_NOTE is defined.
    	* elf/rtld.c (dl_main): Likewise.
    	* elf/dl-open.c (dl_open_worker): Call DL_OPEN_CHECK if it is
    	defined.
    	* elf/dl-support.c: Include <dl-procruntime.c>.
    	* include/link.h: Include <link_map.h>.
    	* sysdeps/generic/dl-procruntime.c: New file.
    	* sysdeps/generic/link_map.h: Likewise.
    	* sysdeps/unix/sysv/linux/i386/dl-cet.c: Likewise.
    	* sysdeps/unix/sysv/linux/i386/dl-machine.h: Likewise.
    	* sysdeps/unix/sysv/linux/x86/check-cet.awk: Likewise.
    	* sysdeps/unix/sysv/linux/x86/configure: Likewise.
    	* sysdeps/unix/sysv/linux/x86/configure.ac: Likewise.
    	* sysdeps/unix/sysv/linux/x86/dl-cet.c: Likewise.
    	* sysdeps/unix/sysv/linux/x86/dl-cet.h: Likewise.
    	* sysdeps/unix/sysv/linux/x86/dl-procruntime.c: Likewise.
    	* sysdeps/unix/sysv/linux/x86/link_map.h: Likewise.
    	* sysdeps/unix/sysv/linux/x86_64/dl-machine.h: Likewise.
    	* sysdeps/generic/ldsodefs.h: Include <dl-procruntime.c> in
    	the writable ld.so namespace.
    	* sysdeps/i386/dl-machine.h (DL_INIT): New.
    	(_dl_start_user): Replace _dl_init with DL_INIT.
    	* sysdeps/i386/dl-trampoline.S (_dl_runtime_resolve): Add
    	_CET_ENDBR.
    	(_dl_runtime_profile): Likewise.
    	(_dl_runtime_resolve_shstk): New.
    	(_dl_runtime_profile_shstk): Likewise.
    	* sysdeps/unix/sysv/linux/x86/Makefile (sysdep_routines): Add
    	dl-cet-nonshared if CET is enabled.
    	(sysdep-dl-routines): Add dl-cet if CET is enabled.
    	(CFLAGS-.o): Add -fcf-protection -mcet if CET is enabled.
    	(CFLAGS-.os): Likewise.
    	(CFLAGS-.op): Likewise.
    	(CFLAGS-.oS): Likewise.
    	(asm-CPPFLAGS): Add -fcf-protection -mcet -include cet.h if CET
    	is enabled.
    	* sysdeps/unix/sysv/linux/x86/Makefile (CFLAGS-tst-context1.c):
    	Add -fcf-protection=branch -mno-shstk -mibt.
    	(CFLAGS-bug-getcontext.c): Likewise.
    	(CFLAGS-tst-makecontext.c): Likewise.
    	(CFLAGS-tst-makecontext2.c): Likewise.
    	(CFLAGS-tst-makecontext3.c): Likewise.
    	(CFLAGS-tst-setcontext.c): Likewise.
    	(CFLAGS-tst-setcontext2.c): Likewise.
    	(CFLAGS-tst-setcontext3.c): Likewise.
    	(CFLAGS-tst-xbzero-opt.c): Likewise.
    	(tests-special): Add $(objpfx)check-cet.out.
    	(cet-built-dso): New.
    	(+$(cet-built-dso:=.note)): Likewise.
    	(common-generated): Add $(cet-built-dso:$(common-objpfx)%=%.note).
    	($(objpfx)check-cet.out): New.
    	(generated): Add check-cet.out.
    	* sysdeps/x86/sysdep.h (_CET_ENDBR): Define if not defined.
    	(ENTRY): Add _CET_ENDBR.
    	* sysdeps/x86_64/dl-machine.h (DL_INIT): New.
    	(_dl_start_user): Replace _dl_init with DL_INIT.
    	* sysdeps/x86_64/x32/dl-machine.h (_dl_start_user): Likewise.
    	* sysdeps/x86_64/dl-trampoline.h (_dl_runtime_resolve): Add
    	_CET_ENDBR.
    	(_dl_runtime_profile): Likewise.

diff --git a/config.h.in b/config.h.in
index 3c91d59..37bdf98 100644
--- a/config.h.in
+++ b/config.h.in
@@ -131,6 +131,10 @@
 /* Define if __stack_chk_guard canary should be randomized at program startup.  */
 #undef ENABLE_STACKGUARD_RANDOMIZE
 
+/* Define if Intel Control-flow Enforcement Technology (CET) should be
+   enabled.  */
+#undef ENABLE_CET
+
 /* Package description.  */
 #undef PKGVERSION
 
diff --git a/configure b/configure
index 4a85706..085ecfd 100755
--- a/configure
+++ b/configure
@@ -786,6 +786,7 @@ enable_nscd
 enable_pt_chown
 enable_tunables
 enable_mathvec
+enable_cet
 with_cpu
 '
       ac_precious_vars='build_alias
@@ -1457,6 +1458,8 @@ Optional Features:
                           'no' and 'valstring'
   --enable-mathvec        Enable building and installing mathvec [default
                           depends on architecture]
+  --enable-cet            enable Intel Control-flow Enforcement Technology
+                          (CET), x86 only
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
@@ -3730,6 +3733,14 @@ else
 fi
 
 
+# Check whether --enable-cet was given.
+if test "${enable_cet+set}" = set; then :
+  enableval=$enable_cet; enable_cet=$enableval
+else
+  enable_cet=default
+fi
+
+
 # We keep the original values in `$config_*' and never modify them, so we
 # can write them unchanged into config.make.  Everything else uses
 # $machine, $vendor, and $os, and changes them whenever convenient.
diff --git a/configure.ac b/configure.ac
index edf6627..7f00f2f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -448,6 +448,12 @@ AC_ARG_ENABLE([mathvec],
 	      [build_mathvec=$enableval],
 	      [build_mathvec=notset])
 
+AC_ARG_ENABLE([cet],
+	      AC_HELP_STRING([--enable-cet],
+			     [enable Intel Control-flow Enforcement Technology (CET), x86 only]),
+	      [enable_cet=$enableval],
+	      [enable_cet=default])
+
 # We keep the original values in `$config_*' and never modify them, so we
 # can write them unchanged into config.make.  Everything else uses
 # $machine, $vendor, and $os, and changes them whenever convenient.
diff --git a/elf/dl-load.c b/elf/dl-load.c
index bbd3be9..a734955 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -30,6 +30,32 @@
 #include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+
+/* Type for the buffer we put the ELF header and hopefully the program
+   header.  This buffer does not really have to be too large.  In most
+   cases the program header follows the ELF header directly.  If this
+   is not the case all bets are off and we can make the header
+   arbitrarily large and still won't get it read.  This means the only
+   question is how large are the ELF and program header combined.  The
+   ELF header 32-bit files is 52 bytes long and in 64-bit files is 64
+   bytes long.  Each program header entry is again 32 and 56 bytes
+   long respectively.  I.e., even with a file which has 10 program
+   header entries we only have to read 372B/624B respectively.  Add to
+   this a bit of margin for program notes and reading 512B and 832B
+   for 32-bit and 64-bit files respecitvely is enough.  If this
+   heuristic should really fail for some file the code in
+   `_dl_map_object_from_fd' knows how to recover.  */
+struct filebuf
+{
+  ssize_t len;
+#if __WORDSIZE == 32
+# define FILEBUF_SIZE 512
+#else
+# define FILEBUF_SIZE 832
+#endif
+  char buf[FILEBUF_SIZE] __attribute__ ((aligned (__alignof (ElfW(Ehdr)))));
+};
+
 #include "dynamic-link.h"
 #include <abi-tag.h>
 #include <stackinfo.h>
@@ -70,31 +96,6 @@ int __stack_prot attribute_hidden attribute_relro
 #endif
 
 
-/* Type for the buffer we put the ELF header and hopefully the program
-   header.  This buffer does not really have to be too large.  In most
-   cases the program header follows the ELF header directly.  If this
-   is not the case all bets are off and we can make the header
-   arbitrarily large and still won't get it read.  This means the only
-   question is how large are the ELF and program header combined.  The
-   ELF header 32-bit files is 52 bytes long and in 64-bit files is 64
-   bytes long.  Each program header entry is again 32 and 56 bytes
-   long respectively.  I.e., even with a file which has 10 program
-   header entries we only have to read 372B/624B respectively.  Add to
-   this a bit of margin for program notes and reading 512B and 832B
-   for 32-bit and 64-bit files respecitvely is enough.  If this
-   heuristic should really fail for some file the code in
-   `_dl_map_object_from_fd' knows how to recover.  */
-struct filebuf
-{
-  ssize_t len;
-#if __WORDSIZE == 32
-# define FILEBUF_SIZE 512
-#else
-# define FILEBUF_SIZE 832
-#endif
-  char buf[FILEBUF_SIZE] __attribute__ ((aligned (__alignof (ElfW(Ehdr)))));
-};
-
 /* This is the decomposed LD_LIBRARY_PATH search path.  */
 static struct r_search_path_struct env_path_list attribute_relro;
 
@@ -1151,6 +1152,16 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
 	  l->l_relro_addr = ph->p_vaddr;
 	  l->l_relro_size = ph->p_memsz;
 	  break;
+
+#ifdef DL_PROCESS_PT_NOTE
+	case PT_NOTE:
+	  if (DL_PROCESS_PT_NOTE (l, ph, fd, fbp))
+	    {
+	      errstring = N_("cannot process note segment");
+	      goto call_lose;
+	    }
+	  break;
+#endif
 	}
 
     if (__glibc_unlikely (nloadcmds == 0))
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 68907bf..0db0741 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -299,6 +299,10 @@ dl_open_worker (void *a)
   _dl_debug_state ();
   LIBC_PROBE (map_complete, 3, args->nsid, r, new);
 
+#ifdef DL_OPEN_CHECK
+  DL_OPEN_CHECK (new);
+#endif
+
   /* Print scope information.  */
   if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
     _dl_show_scope (new, 0);
diff --git a/elf/rtld.c b/elf/rtld.c
index cfd3729..a0b3dca 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1241,6 +1241,14 @@ of this helper program; chances are you did not intend to run this program.\n\
 	main_map->l_relro_addr = ph->p_vaddr;
 	main_map->l_relro_size = ph->p_memsz;
 	break;
+
+#ifdef DL_PROCESS_PT_NOTE
+      case PT_NOTE:
+	if (DL_PROCESS_PT_NOTE (main_map, ph))
+	  _dl_error_printf ("\
+ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
+	break;
+#endif
       }
 
   /* Adjust the address of the TLS initialization image in case
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
index 2e17eba..77a2049 100644
--- a/sysdeps/i386/dl-machine.h
+++ b/sysdeps/i386/dl-machine.h
@@ -137,6 +137,10 @@ extern ElfW(Addr) _dl_profile_fixup (struct link_map *l,
    where the dynamic linker should not map anything.  */
 #define ELF_MACHINE_USER_ADDRESS_MASK	0xf8000000UL
 
+#ifndef DL_INIT
+# define DL_INIT	"_dl_init"
+#endif
+
 /* Initial entry point code for the dynamic linker.
    The C function `_dl_start' is the real entry point;
    its return value is the user program's entry point.  */
@@ -194,7 +198,7 @@ _dl_start_user:\n\
 	# Clear %ebp, so that even constructors have terminated backchain.\n\
 	xorl %ebp, %ebp\n\
 	# Call the function to run the initializers.\n\
-	call _dl_init\n\
+	call " DL_INIT "\n\
 	# Pass our finalizer function to the user in %edx, as per ELF ABI.\n\
 	leal _dl_fini@GOTOFF(%ebx), %edx\n\
 	# Restore %esp _start expects.\n\
diff --git a/sysdeps/i386/dl-trampoline.S b/sysdeps/i386/dl-trampoline.S
index 6e7f3ae..cd3c1a5 100644
--- a/sysdeps/i386/dl-trampoline.S
+++ b/sysdeps/i386/dl-trampoline.S
@@ -32,6 +32,7 @@
 	.align 16
 _dl_runtime_resolve:
 	cfi_adjust_cfa_offset (8)
+	_CET_ENDBR
 	pushl %eax		# Preserve registers otherwise clobbered.
 	cfi_adjust_cfa_offset (4)
 	pushl %ecx
@@ -50,14 +51,85 @@ _dl_runtime_resolve:
 	cfi_endproc
 	.size _dl_runtime_resolve, .-_dl_runtime_resolve
 
+# The SHSTK compatible version.
+	.text
+	.globl _dl_runtime_resolve_shstk
+	.type _dl_runtime_resolve_shstk, @function
+	cfi_startproc
+	.align 16
+_dl_runtime_resolve_shstk:
+	cfi_adjust_cfa_offset (8)
+	_CET_ENDBR
+	pushl %eax		# Preserve registers otherwise clobbered.
+	cfi_adjust_cfa_offset (4)
+	pushl %edx
+	cfi_adjust_cfa_offset (4)
+	movl 12(%esp), %edx	# Copy args pushed by PLT in register.  Note
+	movl 8(%esp), %eax	# that `fixup' takes its parameters in regs.
+	call _dl_fixup		# Call resolver.
+	movl (%esp), %edx	# Get register content back.
+	movl %eax, %ecx		# Store the function address.
+	movl 4(%esp), %eax	# Get register content back.
+	addl $16, %esp		# Adjust stack: PLT1 + PLT2 + %eax + %edx
+	cfi_adjust_cfa_offset (-16)
+	jmp *%ecx		# Jump to function address.
+	cfi_endproc
+	.size _dl_runtime_resolve_shstk, .-_dl_runtime_resolve_shstk
 
 #ifndef PROF
+# The SHSTK compatible version.
+	.globl _dl_runtime_profile_shstk
+	.type _dl_runtime_profile_shstk, @function
+	cfi_startproc
+	.align 16
+_dl_runtime_profile_shstk:
+	cfi_adjust_cfa_offset (8)
+	_CET_ENDBR
+	pushl %esp
+	cfi_adjust_cfa_offset (4)
+	addl $8, (%esp)		# Account for the pushed PLT data
+	pushl %ebp
+	cfi_adjust_cfa_offset (4)
+	pushl %eax		# Preserve registers otherwise clobbered.
+	cfi_adjust_cfa_offset (4)
+	pushl %ecx
+	cfi_adjust_cfa_offset (4)
+	pushl %edx
+	cfi_adjust_cfa_offset (4)
+	movl %esp, %ecx
+	subl $8, %esp
+	cfi_adjust_cfa_offset (8)
+	movl $-1, 4(%esp)
+	leal 4(%esp), %edx
+	movl %edx, (%esp)
+	pushl %ecx		# Address of the register structure
+	cfi_adjust_cfa_offset (4)
+	movl 40(%esp), %ecx	# Load return address
+	movl 36(%esp), %edx	# Copy args pushed by PLT in register.  Note
+	movl 32(%esp), %eax	# that `fixup' takes its parameters in regs.
+	call _dl_profile_fixup	# Call resolver.
+	cfi_adjust_cfa_offset (-8)
+	movl (%esp), %edx
+	testl %edx, %edx
+	jns 1f
+	movl 4(%esp), %edx	# Get register content back.
+	movl %eax, %ecx		# Store the function address.
+	movl 12(%esp), %eax	# Get register content back.
+	# Adjust stack: PLT1 + PLT2 + %esp + %ebp + %eax + %ecx + %edx
+	# + free.
+	addl $32, %esp
+	cfi_adjust_cfa_offset (-32)
+	jmp *%ecx		# Jump to function address.
+	cfi_endproc
+	.size _dl_runtime_profile_shstk, .-_dl_runtime_profile_shstk
+
 	.globl _dl_runtime_profile
 	.type _dl_runtime_profile, @function
 	cfi_startproc
 	.align 16
 _dl_runtime_profile:
 	cfi_adjust_cfa_offset (8)
+	_CET_ENDBR
 	pushl %esp
 	cfi_adjust_cfa_offset (4)
 	addl $8, (%esp)		# Account for the pushed PLT data
diff --git a/sysdeps/unix/sysv/linux/i386/dl-cet.c b/sysdeps/unix/sysv/linux/i386/dl-cet.c
new file mode 100644
index 0000000..11d9010
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/dl-cet.c
@@ -0,0 +1,66 @@
+/* Linux/i386 CET initializers function.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+
+   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/>.  */
+
+#ifdef SHARED
+# define LINKAGE static inline
+# define _dl_cet_init cet_init
+# include <sysdeps/unix/sysv/linux/x86/dl-cet.c>
+# undef _dl_cet_init
+
+void
+_dl_cet_init (struct link_map *main_map, int argc, char **argv, char **env)
+{
+  cet_init (main_map, argc, argv, env);
+
+  if ((GL(dl_x86_feature_1) & GNU_PROPERTY_X86_FEATURE_1_SHSTK))
+    {
+      /* Replace _dl_runtime_resolve and _dl_runtime_profile with
+         _dl_runtime_resolve_shstk and _dl_runtime_profile_shstk,
+	 respectively if SHSTK is enabled.  */
+      extern void _dl_runtime_resolve (Elf32_Word) attribute_hidden;
+      extern void _dl_runtime_resolve_shstk (Elf32_Word) attribute_hidden;
+      extern void _dl_runtime_profile (Elf32_Word) attribute_hidden;
+      extern void _dl_runtime_profile_shstk (Elf32_Word) attribute_hidden;
+      unsigned int i;
+      struct link_map *l;
+      Elf32_Addr *got;
+
+      if (main_map->l_info[DT_JMPREL])
+	{
+	  got = (Elf32_Addr *) D_PTR (main_map, l_info[DT_PLTGOT]);
+	  if (got[2] == (Elf32_Addr) &_dl_runtime_resolve)
+	    got[2] = (Elf32_Addr) &_dl_runtime_resolve_shstk;
+	  else if (got[2] == (Elf32_Addr) &_dl_runtime_profile)
+	    got[2] = (Elf32_Addr) &_dl_runtime_profile_shstk;
+	}
+
+      i = main_map->l_searchlist.r_nlist;
+      while (i-- > 0)
+	{
+	  l = main_map->l_initfini[i];
+	  if (l->l_info[DT_JMPREL])
+	    {
+	      got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
+	      if (got[2] == (Elf32_Addr) &_dl_runtime_resolve)
+		got[2] = (Elf32_Addr) &_dl_runtime_resolve_shstk;
+	      else if (got[2] == (Elf32_Addr) &_dl_runtime_profile)
+		got[2] = (Elf32_Addr) &_dl_runtime_profile_shstk;
+	    }
+	}
+    }
+}
+#endif
diff --git a/sysdeps/unix/sysv/linux/i386/dl-machine.h b/sysdeps/unix/sysv/linux/i386/dl-machine.h
new file mode 100644
index 0000000..303358f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/dl-machine.h
@@ -0,0 +1,23 @@
+/* Machine-dependent ELF dynamic relocation inline functions.
+   Linux/i386 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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifdef ENABLE_CET
+# include <sysdeps/unix/sysv/linux/x86/dl-cet.h>
+#endif
+#include <sysdeps/i386/dl-machine.h>
diff --git a/sysdeps/unix/sysv/linux/x86/Makefile b/sysdeps/unix/sysv/linux/x86/Makefile
index c55a43e..d141984 100644
--- a/sysdeps/unix/sysv/linux/x86/Makefile
+++ b/sysdeps/unix/sysv/linux/x86/Makefile
@@ -24,3 +24,63 @@ ifeq ($(subdir),setjmp)
 gen-as-const-headers += jmp_buf-ssp.sym
 tests += tst-saved_mask-1
 endif
+
+ifeq ($(enable-cet),yes)
+ifeq ($(subdir),elf)
+sysdep-dl-routines += dl-cet
+endif
+
+# Add -fcf-protection -mcet to CFLAGS when CET is enabled.
+CFLAGS-.o += -fcf-protection -mcet
+CFLAGS-.os += -fcf-protection -mcet
+CFLAGS-.op += -fcf-protection -mcet
+CFLAGS-.oS += -fcf-protection -mcet
+
+# Compile assembly codes with <cet.h> when CET is enabled.
+asm-CPPFLAGS += -fcf-protection -mcet -include cet.h
+
+ifeq ($(subdir),nptl)
+CFLAGS-tst-context1.c += -fcf-protection=branch -mno-shstk -mibt
+endif
+
+ifeq ($(subdir),stdlib)
+CFLAGS-bug-getcontext.c += -fcf-protection=branch -mno-shstk -mibt
+CFLAGS-tst-makecontext.c += -fcf-protection=branch -mno-shstk -mibt
+CFLAGS-tst-makecontext2.c += -fcf-protection=branch -mno-shstk -mibt
+CFLAGS-tst-makecontext3.c += -fcf-protection=branch -mno-shstk -mibt
+CFLAGS-tst-setcontext.c += -fcf-protection=branch -mno-shstk -mibt
+CFLAGS-tst-setcontext2.c += -fcf-protection=branch -mno-shstk -mibt
+CFLAGS-tst-setcontext3.c += -fcf-protection=branch -mno-shstk -mibt
+endif
+
+ifeq ($(subdir),string)
+CFLAGS-tst-xbzero-opt.c += -fcf-protection=branch -mno-shstk -mibt
+endif
+
+ifeq ($(subdir),elf)
+ifeq (yes,$(build-shared))
+tests-special += $(objpfx)check-cet.out
+endif
+
+# FIXME: Can't use all-built-dso in elf/Makefile since this file is
+# processed before elf/Makefile.  Duplicate it here.
+cet-built-dso := $(common-objpfx)elf/ld.so $(common-objpfx)libc.so \
+		 $(filter-out $(common-objpfx)linkobj/libc.so, \
+			      $(sort $(wildcard $(addprefix $(common-objpfx), \
+							    */lib*.so \
+							    iconvdata/*.so))))
+
+$(cet-built-dso:=.note): %.note: %
+	@rm -f $@T
+	LC_ALL=C $(READELF) -n $< > $@T
+	test -s $@T
+	mv -f $@T $@
+common-generated += $(cet-built-dso:$(common-objpfx)%=%.note)
+
+$(objpfx)check-cet.out: $(..)sysdeps/unix/sysv/linux/x86/check-cet.awk \
+			$(cet-built-dso:=.note)
+	LC_ALL=C $(AWK) -f $^ > $@; \
+	$(evaluate-test)
+generated += check-cet.out
+endif
+endif
diff --git a/sysdeps/unix/sysv/linux/x86/check-cet.awk b/sysdeps/unix/sysv/linux/x86/check-cet.awk
new file mode 100644
index 0000000..e3723f4
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/check-cet.awk
@@ -0,0 +1,35 @@
+# This awk script expects to get command-line files that are each
+# the output of 'readelf -n' on a single shared object.
+# It exits successfully (0) if all of them contained the CET property.
+# It fails (1) if any didn't contain the CET property
+# It fails (2) if the input did not take the expected form.
+
+BEGIN { result = cet = sanity = 0 }
+
+function check_one(name) {
+  if (!sanity) {
+    print name ": *** input did not look like readelf -n output";
+    result = 2;
+  } else if (cet) {
+    print name ": OK";
+  } else {
+    print name ": *** no CET property found";
+    result = result ? result : 1;
+  }
+
+  cet = sanity = 0;
+}
+
+FILENAME != lastfile {
+  if (lastfile)
+    check_one(lastfile);
+  lastfile = FILENAME;
+}
+
+index ($0, "Displaying notes") != 0 { sanity = 1 }
+index ($0, "IBT") != 0 && index ($0, "SHSTK") != 0 { cet = 1 }
+
+END {
+  check_one(lastfile);
+  exit(result);
+}
diff --git a/sysdeps/unix/sysv/linux/x86/configure b/sysdeps/unix/sysv/linux/x86/configure
new file mode 100644
index 0000000..18ba7af
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/configure
@@ -0,0 +1,72 @@
+# This file is generated from configure.ac by Autoconf.  DO NOT EDIT!
+ # Local configure fragment for sysdeps/unix/sysv/linux/x86.
+
+if test x"$enable_cet" = xdefault || test x"$enable_cet" = xyes; then
+  # Check if CET can be enabled.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether CET can be enabled" >&5
+$as_echo_n "checking whether CET can be enabled... " >&6; }
+if ${libc_cv_x86_cet_available+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat > conftest.c <<EOF
+#if !defined __IBT__ || !defined __SHSTK__
+# error CET isn't available.
+#endif
+EOF
+		 if { ac_try='${CC-cc} -c $CFLAGS -fcf-protection -mcet -include cet.h conftest.c 1>&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+		   libc_cv_x86_cet_available=yes
+		 else
+		   libc_cv_x86_cet_available=no
+		 fi
+		 rm -rf conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_x86_cet_available" >&5
+$as_echo "$libc_cv_x86_cet_available" >&6; }
+  if test $libc_cv_x86_cet_available = yes; then
+    enable_cet=yes
+  else
+    if test x"$enable_cet" = xdefault; then
+      enable_cet=no
+    else
+      as_fn_error $? "$CC doesn't support CET" "$LINENO" 5
+    fi
+  fi
+fi
+if test $enable_cet = yes; then
+  # Check if assembler supports CET.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $AS supports CET" >&5
+$as_echo_n "checking whether $AS supports CET... " >&6; }
+if ${libc_cv_x86_cet_as+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat > conftest.s <<EOF
+	incsspd %ecx
+EOF
+		 if { ac_try='${CC-cc} -c $CFLAGS conftest.s -o conftest.o 1>&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+		   libc_cv_x86_cet_as=yes
+		 else
+		   libc_cv_x86_cet_as=no
+		 fi
+		 rm -rf conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_x86_cet_as" >&5
+$as_echo "$libc_cv_x86_cet_as" >&6; }
+  if test $libc_cv_x86_cet_as = no; then
+    as_fn_error $? "$AS doesn't support CET" "$LINENO" 5
+  fi
+
+$as_echo "#define ENABLE_CET 1" >>confdefs.h
+
+fi
+config_vars="$config_vars
+enable-cet = $enable_cet"
diff --git a/sysdeps/unix/sysv/linux/x86/configure.ac b/sysdeps/unix/sysv/linux/x86/configure.ac
new file mode 100644
index 0000000..7ef9fbe
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/configure.ac
@@ -0,0 +1,48 @@
+GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
+# Local configure fragment for sysdeps/unix/sysv/linux/x86.
+
+if test x"$enable_cet" = xdefault || test x"$enable_cet" = xyes; then
+  # Check if CET can be enabled.
+  AC_CACHE_CHECK(whether CET can be enabled,
+		 libc_cv_x86_cet_available, [dnl
+cat > conftest.c <<EOF
+#if !defined __IBT__ || !defined __SHSTK__
+# error CET isn't available.
+#endif
+EOF
+		 if AC_TRY_COMMAND(${CC-cc} -c $CFLAGS -fcf-protection -mcet -include cet.h conftest.c 1>&AS_MESSAGE_LOG_FD); then
+		   libc_cv_x86_cet_available=yes
+		 else
+		   libc_cv_x86_cet_available=no
+		 fi
+		 rm -rf conftest*])
+  if test $libc_cv_x86_cet_available = yes; then
+    enable_cet=yes
+  else
+    if test x"$enable_cet" = xdefault; then
+      enable_cet=no
+    else
+      AC_MSG_ERROR([$CC doesn't support CET])
+    fi
+  fi
+fi
+if test $enable_cet = yes; then
+  # Check if assembler supports CET.
+  AC_CACHE_CHECK(whether $AS supports CET,
+		 libc_cv_x86_cet_as, [dnl
+cat > conftest.s <<EOF
+	incsspd %ecx
+EOF
+		 if AC_TRY_COMMAND(${CC-cc} -c $CFLAGS conftest.s -o conftest.o 1>&AS_MESSAGE_LOG_FD); then
+		   libc_cv_x86_cet_as=yes
+		 else
+		   libc_cv_x86_cet_as=no
+		 fi
+		 rm -rf conftest*])
+  if test $libc_cv_x86_cet_as = no; then
+    AC_MSG_ERROR([$AS doesn't support CET])
+  fi
+  AC_DEFINE(ENABLE_CET, 1,
+	    [Enable Intel Control-flow Enforcement Technology (CET)])
+fi
+LIBC_CONFIG_VAR([enable-cet], [$enable_cet])
diff --git a/sysdeps/unix/sysv/linux/x86/dl-cet.c b/sysdeps/unix/sysv/linux/x86/dl-cet.c
new file mode 100644
index 0000000..e8b12d0
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/dl-cet.c
@@ -0,0 +1,88 @@
+/* Linux/x86 CET initializers function.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+
+   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/>.  */
+
+#ifdef SHARED
+# include <ldsodefs.h>
+
+# ifndef LINKAGE
+#  define LINKAGE
+# endif
+
+LINKAGE
+void
+_dl_cet_init (struct link_map *main_map, int argc, char **argv, char **env)
+{
+  /* Check if IBT is enabled in executable.  */
+  bool enable_ibt
+    = ((GL(dl_x86_feature_1) & GNU_PROPERTY_X86_FEATURE_1_IBT)
+       && (main_map->l_cet & lc_ibt));
+
+  /* Check if SHSTK is enabled in executable.  */
+  bool enable_shstk
+    = ((GL(dl_x86_feature_1) & GNU_PROPERTY_X86_FEATURE_1_SHSTK)
+       && (main_map->l_cet & lc_shstk));
+
+  if (enable_ibt || enable_shstk)
+    {
+      unsigned int i;
+      struct link_map *l;
+
+      i = main_map->l_searchlist.r_nlist;
+      while (i-- > 0)
+	{
+	  /* Check each shared object to see if IBT and SHSTK are
+	     enabled.  */
+	  l = main_map->l_initfini[i];
+
+	  /* Skip CET check for ld.so since ld.so is CET-enabled.  */
+	  if (l == &GL(dl_rtld_map))
+	    continue;
+
+	  if (enable_ibt && !(l->l_cet & lc_ibt))
+	    {
+	      /* If IBT is enabled in executable and IBT isn't enabled in
+		 this shard object, put all executable PT_LOAD segments
+		 in legacy code page bitmap.  */
+
+	      /* FIXME: Mark legacy region  */
+	    }
+
+	  /* SHSTK is enabled only if it is enabled in executable as
+	     well as all shared objects.  */
+	  enable_shstk = !!(l->l_cet & lc_shstk);
+
+	  /* Stop if both IBT and SHSTCK are disabled.  */
+	  if (!enable_ibt && !enable_shstk)
+	    break;
+	}
+    }
+
+  if (!enable_ibt || !enable_shstk)
+    {
+      /* FIXME: Disable IBT and/or SHSTK.  */
+      ;
+    }
+
+  if (enable_ibt || enable_shstk)
+    {
+      /* FIXME: Lock CET if IBT or SHSTK is enabled.  */
+      ;
+    }
+
+  _dl_init (main_map, argc, argv, env);
+}
+#endif
diff --git a/sysdeps/unix/sysv/linux/x86/dl-cet.h b/sysdeps/unix/sysv/linux/x86/dl-cet.h
new file mode 100644
index 0000000..5758cdf
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/dl-cet.h
@@ -0,0 +1,125 @@
+/* Linux/x86 CET inline functions.
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _dl_cet_h
+#define _dl_cet_h
+
+extern void _dl_cet_init (struct link_map *, int, char **, char **)
+    attribute_hidden;
+
+#define DL_INIT "_dl_cet_init"
+
+#ifdef ElfW
+static inline void __attribute__ ((unused))
+dl_process_cet_property_note (struct link_map *l,
+			      const ElfW(Nhdr) *note,
+			      const ElfW(Addr) size,
+			      const ElfW(Addr) align)
+{
+  /* The NT_GNU_PROPERTY_TYPE_0 note must be aliged to 4 bytes in
+     32-bit objects and to 8 bytes in 64-bit objects.  Skip notes
+     with incorrect alignment.  */
+  if (align != (__ELF_NATIVE_CLASS / 8))
+    return;
+
+  const ElfW(Addr) start = (ElfW(Addr)) note;
+
+  while ((ElfW(Addr)) (note + 1) - start < size)
+    {
+      /* Find the NT_GNU_PROPERTY_TYPE_0 note.  */
+      if (note->n_namesz == 4
+	  && note->n_type == NT_GNU_PROPERTY_TYPE_0
+	  && memcmp (note + 1, "GNU", 4) == 0)
+	{
+	  /* Check for invalid property.  */
+	  if (note->n_descsz < 8
+	      || (note->n_descsz % sizeof (ElfW(Addr))) != 0)
+	    break;
+
+	  /* Start and end of property array.  */
+	  unsigned char *ptr = (unsigned char *) (note + 1) + 4;
+	  unsigned char *ptr_end = ptr + note->n_descsz;
+
+	  while (1)
+	    {
+	      unsigned int type = *(unsigned int *) ptr;
+	      unsigned int datasz = *(unsigned int *) (ptr + 4);
+
+	      ptr += 8;
+	      if ((ptr + datasz) > ptr_end)
+		break;
+
+	      if (type == GNU_PROPERTY_X86_FEATURE_1_AND
+		  && datasz == 4)
+		{
+		  unsigned int feature_1 = *(unsigned int *) ptr;
+		  if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_IBT))
+		    l->l_cet |= lc_ibt;
+		  if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_SHSTK))
+		    l->l_cet |= lc_shstk;
+		  break;
+		}
+	    }
+	}
+
+      /* NB: Note sections like .note.ABI-tag and .note.gnu.build-id are
+	 aligned to 4 bytes in 64-bit ELF objects.  */
+      note = ((const void *) note
+	      + ELF_NOTE_NEXT_OFFSET (note->n_namesz, note->n_descsz,
+				      align));
+    }
+}
+
+# ifdef FILEBUF_SIZE
+#  define DL_PROCESS_PT_NOTE(l, ph, fd, fbp) \
+  dl_process_pt_note ((l), (ph), (fd), (fbp))
+
+static inline int __attribute__ ((unused))
+dl_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph,
+		    int fd, struct filebuf *fbp)
+{
+  const ElfW(Nhdr) *note;
+  ElfW(Addr) size = ph->p_filesz;
+
+  if (ph->p_offset + size <= (size_t) fbp->len)
+    note = (const void *) (fbp->buf + ph->p_offset);
+  else
+    {
+      note = alloca (size);
+      __lseek (fd, ph->p_offset, SEEK_SET);
+      if (__libc_read (fd, (void *) note, size) != size)
+	return -1;
+    }
+
+  dl_process_cet_property_note (l, note, size, ph->p_align);
+  return 0;
+}
+# else
+#  define DL_PROCESS_PT_NOTE(l, ph) dl_process_pt_note ((l), (ph))
+
+static inline int __attribute__ ((unused))
+dl_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph)
+{
+  const ElfW(Nhdr) *note = (const void *) (ph->p_vaddr + l->l_addr);
+  dl_process_cet_property_note (l, note, ph->p_memsz, ph->p_align);
+  return 0;
+}
+# endif
+#endif
+
+#endif	/* _dl_cet_h */
diff --git a/sysdeps/unix/sysv/linux/x86/dl-procruntime.c b/sysdeps/unix/sysv/linux/x86/dl-procruntime.c
new file mode 100644
index 0000000..17c3546
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/dl-procruntime.c
@@ -0,0 +1,57 @@
+/* Data for processor runtime information.  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
+   <http://www.gnu.org/licenses/>.  */
+
+/* This information must be kept in sync with the _DL_HWCAP_COUNT,
+   HWCAP_PLATFORMS_START and HWCAP_PLATFORMS_COUNT definitions in
+   dl-hwcap.h.
+
+   If anything should be added here check whether the size of each string
+   is still ok with the given array size.
+
+   All the #ifdefs in the definitions are quite irritating but
+   necessary if we want to avoid duplicating the information.  There
+   are three different modes:
+
+   - PROCINFO_DECL is defined.  This means we are only interested in
+     declarations.
+
+   - PROCINFO_DECL is not defined:
+
+     + if SHARED is defined the file is included in an array
+       initializer.  The .element = { ... } syntax is needed.
+
+     + if SHARED is not defined a normal array initialization is
+       needed.
+  */
+
+#ifndef PROCINFO_CLASS
+# define PROCINFO_CLASS
+#endif
+
+#if !IS_IN (ldconfig)
+# if !defined PROCINFO_DECL && defined SHARED
+  ._dl_x86_feature_1
+# else
+PROCINFO_CLASS unsigned int _dl_x86_feature_1
+# endif
+# if !defined SHARED || defined PROCINFO_DECL
+;
+# else
+,
+# endif
+#endif
diff --git a/sysdeps/unix/sysv/linux/x86/ldsodefs.h b/sysdeps/unix/sysv/linux/x86/ldsodefs.h
new file mode 100644
index 0000000..0c40edd
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/ldsodefs.h
@@ -0,0 +1,60 @@
+/* Run-time dynamic linker data structures for x86 loaded ELF shared objects.
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef	_LDSODEFS_H
+
+/* Get the real definitions.  */
+#include_next <ldsodefs.h>
+
+#if defined ENABLE_CET && defined N_ && !IS_IN (ldconfig)
+# include <errno.h>
+
+# define DL_OPEN_CHECK dl_cet_open_check
+
+static inline void __attribute__ ((unused))
+dl_cet_open_check (struct link_map *l)
+{
+  int res;
+
+  /* Check IBT and SHSTK when called from dlopen.  */
+  if ((GL(dl_x86_feature_1) & GNU_PROPERTY_X86_FEATURE_1_IBT)
+      && !(l->l_cet & lc_ibt))
+    {
+      /* If IBT is enabled in executable and IBT isn't enabled in
+	 this shared object, put all executable PT_LOAD segments in
+	 legacy code page bitmap.  */
+      /* FIXME: Mark legacy region.  */
+      res = -EINVAL;
+      goto cet_check_failure;
+    }
+
+  /* If SHSTK is enabled in executable and SHSTK isn't enabled in
+     this shared object, we can't load this shared object.  */
+  if ((GL(dl_x86_feature_1) & GNU_PROPERTY_X86_FEATURE_1_SHSTK)
+      && !(l->l_cet & lc_shstk))
+    {
+      res = -EINVAL;
+
+cet_check_failure:
+      _dl_signal_error (-res, "dlopen", NULL,
+			N_("dl_cet_open_check failed"));
+    }
+}
+#endif
+
+#endif /* ldsodefs.h */
diff --git a/sysdeps/unix/sysv/linux/x86/link_map.h b/sysdeps/unix/sysv/linux/x86/link_map.h
new file mode 100644
index 0000000..86e098e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/link_map.h
@@ -0,0 +1,26 @@
+/* Additional fields in struct link_map.  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
+   <http://www.gnu.org/licenses/>.  */
+
+/* If this object is enabled with CET.  */
+enum
+  {
+    lc_none = 0,			 /* Not enabled with CET.  */
+    lc_ibt = 1 << 0,			 /* Enabled with IBT.  */
+    lc_shstk = 1 << 1,			 /* Enabled with STSHK.  */
+    lc_ibt_and_shstk = lc_ibt | lc_shstk /* Enabled with both.  */
+  } l_cet:2;
diff --git a/sysdeps/unix/sysv/linux/x86_64/dl-machine.h b/sysdeps/unix/sysv/linux/x86_64/dl-machine.h
new file mode 100644
index 0000000..add79e9
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/dl-machine.h
@@ -0,0 +1,27 @@
+/* Machine-dependent ELF dynamic relocation inline functions.
+   Linux/x86-64 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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifdef ENABLE_CET
+# include <sysdeps/unix/sysv/linux/x86/dl-cet.h>
+#endif
+#ifdef __ILP32__
+# include <sysdeps/x86_64/x32/dl-machine.h>
+#else
+# include <sysdeps/x86_64/dl-machine.h>
+#endif
diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h
index b7f7898..187a8a5 100644
--- a/sysdeps/x86/cpu-features.h
+++ b/sysdeps/x86/cpu-features.h
@@ -158,6 +158,11 @@ struct cpu_features
 extern const struct cpu_features *__get_cpu_features (void)
      __attribute__ ((const));
 
+# ifdef ElfW
+extern void _dl_setup_cet (const ElfW(Phdr) *, size_t, const ElfW(Addr))
+    attribute_hidden;
+# endif
+
 # if defined (_LIBC) && !IS_IN (nonlib)
 /* Unused for x86.  */
 #  define INIT_ARCH()
diff --git a/sysdeps/x86/sysdep.h b/sysdeps/x86/sysdep.h
index eb25e4b..7fc2715 100644
--- a/sysdeps/x86/sysdep.h
+++ b/sysdeps/x86/sysdep.h
@@ -25,6 +25,10 @@
 
 /* Syntactic details of assembler.  */
 
+#ifndef _CET_ENDBR
+# define _CET_ENDBR
+#endif
+
 /* ELF uses byte-counts for .align, most others use log2 of count of bytes.  */
 #define ALIGNARG(log2) 1<<log2
 #define ASM_SIZE_DIRECTIVE(name) .size name,.-name;
@@ -36,6 +40,7 @@
   .align ALIGNARG(4);							      \
   C_LABEL(name)								      \
   cfi_startproc;							      \
+  _CET_ENDBR;								      \
   CALL_MCOUNT
 
 #undef	END
diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h
index 905a37a..daa5bbf 100644
--- a/sysdeps/x86_64/dl-machine.h
+++ b/sysdeps/x86_64/dl-machine.h
@@ -135,6 +135,10 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
   return lazy;
 }
 
+#ifndef DL_INIT
+# define DL_INIT	"_dl_init"
+#endif
+
 /* Initial entry point code for the dynamic linker.
    The C function `_dl_start' is the real entry point;
    its return value is the user program's entry point.  */
@@ -176,7 +180,7 @@ _dl_start_user:\n\
 	# Clear %rbp to mark outermost frame obviously even for constructors.\n\
 	xorl %ebp, %ebp\n\
 	# Call the function to run the initializers.\n\
-	call _dl_init\n\
+	call " DL_INIT "\n\
 	# Pass our finalizer function to the user in %rdx, as per ELF ABI.\n\
 	leaq _dl_fini(%rip), %rdx\n\
 	# And make sure %rsp points to argc stored on the stack.\n\
diff --git a/sysdeps/x86_64/dl-trampoline.h b/sysdeps/x86_64/dl-trampoline.h
index 9ddaafe..28a3c0f 100644
--- a/sysdeps/x86_64/dl-trampoline.h
+++ b/sysdeps/x86_64/dl-trampoline.h
@@ -64,6 +64,7 @@
 	cfi_startproc
 _dl_runtime_resolve:
 	cfi_adjust_cfa_offset(16) # Incorporate PLT
+	_CET_ENDBR
 # if DL_RUNTIME_RESOLVE_REALIGN_STACK
 #  if LOCAL_STORAGE_AREA != 8
 #   error LOCAL_STORAGE_AREA must be 8
@@ -168,6 +169,7 @@ _dl_runtime_resolve:
 _dl_runtime_profile:
 	cfi_startproc
 	cfi_adjust_cfa_offset(16) # Incorporate PLT
+	_CET_ENDBR
 	/* The La_x86_64_regs data structure pointed to by the
 	   fourth paramater must be VEC_SIZE-byte aligned.  This must
 	   be explicitly enforced.  We have the set up a dynamically
diff --git a/sysdeps/x86_64/x32/dl-machine.h b/sysdeps/x86_64/x32/dl-machine.h
index 2c50688..f177632 100644
--- a/sysdeps/x86_64/x32/dl-machine.h
+++ b/sysdeps/x86_64/x32/dl-machine.h
@@ -73,7 +73,7 @@ _dl_start_user:\n\
 	# Clear %rbp to mark outermost frame obviously even for constructors.\n\
 	xorl %ebp, %ebp\n\
 	# Call the function to run the initializers.\n\
-	call _dl_init\n\
+	call " DL_INIT "\n\
 	# Pass our finalizer function to the user in %rdx, as per ELF ABI.\n\
 	lea _dl_fini(%rip), %edx\n\
 	# And make sure %rsp points to argc stored on the stack.\n\

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=417be2b481260c0fce65aec613a7702809c35ed8

commit 417be2b481260c0fce65aec613a7702809c35ed8
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Thu Dec 7 05:47:21 2017 -0800

    x86: Add feature_1 to tcbhead_t [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.
    cancel_jmp_buf has been updated to include saved_mask so that it is as
    large as struct __jmp_buf_tag.  We must suport the old cancel_jmp_buf
    in existing binaries.  Since symbol versioning doesn't work on
    cancel_jmp_buf, feature_1 is added to tcbhead_t so that setjmp and
    longjmp can check if shadow stack is enabled.  NB: Shadow stack is
    enabled only if all modules are shadow stack enabled.
    
    	[BZ #22563]
    	* sysdeps/i386/nptl/tcb-offsets.sym (FEATURE_1_OFFSET): New.
    	* sysdeps/i386/nptl/tls.h (tcbhead_t): Add feature_1.
    	* sysdeps/x86_64/nptl/tcb-offsets.sym (FEATURE_1_OFFSET): New.
    	* sysdeps/x86_64/nptl/tls.h (tcbhead_t): Rename __glibc_unused1
    	to feature_1.

diff --git a/sysdeps/i386/nptl/tcb-offsets.sym b/sysdeps/i386/nptl/tcb-offsets.sym
index 695a810..250f1a6 100644
--- a/sysdeps/i386/nptl/tcb-offsets.sym
+++ b/sysdeps/i386/nptl/tcb-offsets.sym
@@ -15,3 +15,4 @@ POINTER_GUARD		offsetof (tcbhead_t, pointer_guard)
 #ifndef __ASSUME_PRIVATE_FUTEX
 PRIVATE_FUTEX		offsetof (tcbhead_t, private_futex)
 #endif
+FEATURE_1_OFFSET	offsetof (tcbhead_t, feature_1)
diff --git a/sysdeps/i386/nptl/tls.h b/sysdeps/i386/nptl/tls.h
index f9a6b11..7d4b18c 100644
--- a/sysdeps/i386/nptl/tls.h
+++ b/sysdeps/i386/nptl/tls.h
@@ -50,6 +50,10 @@ typedef struct
   void *__private_tm[4];
   /* GCC split stack support.  */
   void *__private_ss;
+  /* Bit 0: IBT.
+     Bit 1: SHSTK.
+   */
+  unsigned int feature_1;
 } tcbhead_t;
 
 # define TLS_MULTIPLE_THREADS_IN_TCB 1
diff --git a/sysdeps/x86_64/nptl/tcb-offsets.sym b/sysdeps/x86_64/nptl/tcb-offsets.sym
index 8a25c48..03b6dba 100644
--- a/sysdeps/x86_64/nptl/tcb-offsets.sym
+++ b/sysdeps/x86_64/nptl/tcb-offsets.sym
@@ -15,6 +15,7 @@ VGETCPU_CACHE_OFFSET	offsetof (tcbhead_t, vgetcpu_cache)
 #ifndef __ASSUME_PRIVATE_FUTEX
 PRIVATE_FUTEX		offsetof (tcbhead_t, private_futex)
 #endif
+FEATURE_1_OFFSET	offsetof (tcbhead_t, feature_1)
 
 -- Not strictly offsets, but these values are also used in the TCB.
 TCB_CANCELSTATE_BITMASK	 CANCELSTATE_BITMASK
diff --git a/sysdeps/x86_64/nptl/tls.h b/sysdeps/x86_64/nptl/tls.h
index 9b8ad82..cec864f 100644
--- a/sysdeps/x86_64/nptl/tls.h
+++ b/sysdeps/x86_64/nptl/tls.h
@@ -56,7 +56,10 @@ typedef struct
 # else
   int __glibc_reserved1;
 # endif
-  int __glibc_unused1;
+  /* Bit 0: IBT.
+     Bit 1: SHSTK.
+   */
+  unsigned int feature_1;
   /* Reservation of some values for the TM ABI.  */
   void *__private_tm[4];
   /* GCC split stack support.  */

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=0b442303aecba5c4998a991b296c6fb233555b6c

commit 0b442303aecba5c4998a991b296c6fb233555b6c
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Wed Dec 6 15:00:46 2017 -0800

    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.
    
    	[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
    	<bits/types/__cancel_jmp_buf_tag.h>.
    	(__pthread_unwind_buf_t): Use struct __cancel_jmp_buf_tag with
    	__cancel_jmp_buf.

diff --git a/bits/types/__cancel_jmp_buf_tag.h b/bits/types/__cancel_jmp_buf_tag.h
new file mode 100644
index 0000000..c843f44
--- /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
+   <http://www.gnu.org/licenses/>.  */
+
+#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 570a423..60d036a 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 c83b17b..fdeb397 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 2b2b386..787ac6e 100644
--- a/sysdeps/nptl/pthread.h
+++ b/sysdeps/nptl/pthread.h
@@ -27,6 +27,7 @@
 #include <bits/setjmp.h>
 #include <bits/wordsize.h>
 #include <bits/types/struct_timespec.h>
+#include <bits/types/__cancel_jmp_buf_tag.h>
 
 
 /* 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 0000000..830a6ec
--- /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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef ____cancel_jmp_buf_tag_defined
+#define ____cancel_jmp_buf_tag_defined 1
+
+#include <bits/types/__sigset_t.h>
+
+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 0000000..8c36ba3
--- /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
+   <http://www.gnu.org/licenses/>.  */
+
+#include_next <nptl/pthreadP.h>
+
+#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 0000000..89d19d6
--- /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
+   <http://www.gnu.org/licenses/>.  */
+
+#include_next <pthreaddef.h>
+
+/* Need saved_mask in cancel_jmp_buf.  */
+#define NEED_SAVED_MASK_IN_CANCEL_JMP_BUF 1

-----------------------------------------------------------------------


hooks/post-receive
-- 
GNU C Library master sources


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