V3 [PATCH 03/24] x86: Support IBT and SHSTK in Intel CET [BZ #21598]

Message ID CAMe9rOoaLoBTd27a1942BM538iZOcv48m2XoKdZeo34s-2c=8Q@mail.gmail.com
State New, archived
Headers

Commit Message

H.J. Lu July 10, 2018, 10:09 p.m. UTC
  On Sat, Jul 7, 2018 at 1:01 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Fri, Jul 06, 2018 at 03:47:27PM -0400, Carlos O'Donell wrote:
>> On 06/13/2018 11:31 AM, H.J. Lu wrote:
>> > Intel Control-flow Enforcement Technology (CET) instructions:
>>
>> Reviewed.
>>
>> Looking forward to v2.
>>

Here is V3.  The difference from V2 is that get_cet_status became:

static inline int __attribute__ ((always_inline))
get_cet_status (void)
{
  return 0;
}
  

Comments

Carlos O'Donell July 16, 2018, 6:33 p.m. UTC | #1
On 07/10/2018 06:09 PM, H.J. Lu wrote:
> On Sat, Jul 7, 2018 at 1:01 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
>> On Fri, Jul 06, 2018 at 03:47:27PM -0400, Carlos O'Donell wrote:
>>> On 06/13/2018 11:31 AM, H.J. Lu wrote:
>>>> Intel Control-flow Enforcement Technology (CET) instructions:
>>> Reviewed.
>>>
>>> Looking forward to v2.
>>>
> Here is V3.  The difference from V2 is that get_cet_status became:
> 
> static inline int __attribute__ ((always_inline))
> get_cet_status (void)
> {
>   return 0;
> }
> 

Thank you for the update.

With the following changes:
- Add suggested comment to sysdeps/generic/dl-prop.h.
- Make dl_cet_mark_legacy_region return -1 on error.
- Fix typo s/fail/failed/g

This version is OK.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> -- H.J.
> 
> 
> 0003-x86-Support-IBT-and-SHSTK-in-Intel-CET-BZ-21598.patch
> 
> 
> From b100bb5197020c403bf53f26b94324d04e4a0d45 Mon Sep 17 00:00:00 2001
> From: "H.J. Lu" <hjl.tools@gmail.com>
> Date: Thu, 22 Jun 2017 04:15:39 -0700
> Subject: [PATCH 03/24] 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.

OK.

> 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.

OK.

> To enable CET support in glibc, --enable-cet is required to configure
> glibc.  When CET is enabled, both compiler and assembler must support
> CET.  Otherwise, it is a configure-time error.

OK.

> 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.  _dl_process_pt_note or
>       _rtld_process_pt_note is called to process PT_NOTE segment for
>       GNU program property and set l_cet.
>    b. _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.

OK.

> CET run-time control can be changed via GLIBC_TUNABLES with
> 
> $ export GLIBC_TUNABLES=glibc.tune.x86_shstk=[permissive|on|off]
> $ export GLIBC_TUNABLES=glibc.tune.x86_ibt=[permissive|on|off]
> 

OK. Thanks for using the x86_* prefix. I've started another thread to see
if everyone wants to namespace per machine so we don't have name collisions.
Using x86_* like you do here avoids any collisions.

> 1. permissive: SHSTK is disabled when dlopening a legacy ELF module.
> 2. on: IBT or SHSTK are always enabled, regardless if there are IBT or
> SHSTK bits in GNU program property.
> 3. off: IBT or SHSTK are always disabled, regardless if there are IBT or
> SHSTK bits in GNU program property.
> 
> <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.  _CET_NOTRACK is used to
> insert NOTRACK prefix with indirect jump table to support IBT.  It is
> defined as notrack when _CET_NOTRACK is defined in <cet.h>.
> 
> 	 [BZ #21598]
> 	* configure.ac: Add --enable-cet.
> 	* configure: Regenerated.
> 	* elf/Makefille (all-built-dso): Add a comment.
> 	* elf/dl-load.c (filebuf): Moved before "dynamic-link.h".
> 	Include <dl-prop.h>.
> 	(_dl_map_object_from_fd): Call _dl_process_pt_note on PT_NOTE
> 	segment.
> 	* elf/dl-open.c: Include <dl-prop.h>.
> 	(dl_open_worker): Call _dl_open_check.
> 	* elf/rtld.c: Include <dl-prop.h>.
> 	(dl_main): Call _rtld_process_pt_note on PT_NOTE segment.  Call
> 	_rtld_main_check.
> 	* sysdeps/generic/dl-prop.h: New file.
> 	* sysdeps/i386/dl-cet.c: Likewise.
> 	* sysdeps/unix/sysv/linux/x86/cpu-features.c: Likewise.
> 	* sysdeps/unix/sysv/linux/x86/dl-cet.h: Likewise.
> 	* sysdeps/x86/cet-tunables.h: Likewise.
> 	* sysdeps/x86/check-cet.awk: Likewise.
> 	* sysdeps/x86/configure: Likewise.
> 	* sysdeps/x86/configure.ac: Likewise.
> 	* sysdeps/x86/dl-cet.c: Likewise.
> 	* sysdeps/x86/dl-procruntime.c: Likewise.
> 	* sysdeps/x86/dl-prop.h: Likewise.
> 	* sysdeps/x86/libc-start.h: Likewise.
> 	* sysdeps/x86/link_map.h: Likewise.
> 	* 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/linux/x86/Makefile (sysdep-dl-routines): Add dl-cet
> 	if CET is enabled.
> 	(CFLAGS-.o): Add -fcf-protection if CET is enabled.
> 	(CFLAGS-.os): Likewise.
> 	(CFLAGS-.op): Likewise.
> 	(CFLAGS-.oS): Likewise.
> 	(asm-CPPFLAGS): Add -fcf-protection -include cet.h if CET
> 	is enabled.
> 	(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/cpu-features.c: Include <dl-cet.h> and
> 	<cet-tunables.h>.
> 	(TUNABLE_CALLBACK (set_x86_ibt)): New prototype.
> 	(TUNABLE_CALLBACK (set_x86_shstk)): Likewise.
> 	(init_cpu_features): Call get_cet_status to check CET status
> 	and update dl_x86_feature_1 with CET status.  Call
> 	TUNABLE_CALLBACK (set_x86_ibt) and TUNABLE_CALLBACK
> 	(set_x86_shstk).  Disable and lock CET in libc.a.
> 	* sysdeps/x86/cpu-tunables.c: Include <cet-tunables.h>.
> 	(TUNABLE_CALLBACK (set_x86_ibt)): New function.
> 	(TUNABLE_CALLBACK (set_x86_shstk)): Likewise.
> 	* sysdeps/x86/sysdep.h (_CET_NOTRACK): New.
> 	(_CET_ENDBR): Define if not defined.
> 	(ENTRY): Add _CET_ENDBR.
> 	* sysdeps/x86/dl-tunables.list (glibc.tune): Add x86_ibt and
> 	x86_shstk.
> 	* sysdeps/x86_64/dl-trampoline.h (_dl_runtime_resolve): Add
> 	_CET_ENDBR.
> 	(_dl_runtime_profile): Likewise.
> ---
>  configure                                  |  11 +
>  configure.ac                               |   6 +
>  elf/Makefile                               |   2 +
>  elf/dl-load.c                              |  60 ++--
>  elf/dl-open.c                              |   3 +
>  elf/rtld.c                                 |   9 +
>  sysdeps/generic/dl-prop.h                  |  47 +++
>  sysdeps/i386/dl-cet.c                      |  67 +++++
>  sysdeps/i386/dl-trampoline.S               |  72 +++++
>  sysdeps/unix/sysv/linux/x86/cpu-features.c |  38 +++
>  sysdeps/unix/sysv/linux/x86/dl-cet.h       |  34 +++
>  sysdeps/x86/Makefile                       |  42 +++
>  sysdeps/x86/cet-tunables.h                 |  29 ++
>  sysdeps/x86/check-cet.awk                  |  53 ++++
>  sysdeps/x86/configure                      |  69 +++++
>  sysdeps/x86/configure.ac                   |  46 +++
>  sysdeps/x86/cpu-features.c                 |  60 ++++
>  sysdeps/x86/cpu-tunables.c                 |  48 +++
>  sysdeps/x86/dl-cet.c                       | 335 +++++++++++++++++++++
>  sysdeps/x86/dl-procruntime.c               |  68 +++++
>  sysdeps/x86/dl-prop.h                      | 153 ++++++++++
>  sysdeps/x86/dl-tunables.list               |   6 +
>  sysdeps/x86/libc-start.h                   |  25 ++
>  sysdeps/x86/link_map.h                     |  26 ++
>  sysdeps/x86/sysdep.h                       |   8 +
>  sysdeps/x86_64/dl-trampoline.h             |   2 +
>  26 files changed, 1294 insertions(+), 25 deletions(-)
>  create mode 100644 sysdeps/generic/dl-prop.h
>  create mode 100644 sysdeps/i386/dl-cet.c
>  create mode 100644 sysdeps/unix/sysv/linux/x86/cpu-features.c
>  create mode 100644 sysdeps/unix/sysv/linux/x86/dl-cet.h
>  create mode 100644 sysdeps/x86/cet-tunables.h
>  create mode 100644 sysdeps/x86/check-cet.awk
>  create mode 100644 sysdeps/x86/configure
>  create mode 100644 sysdeps/x86/configure.ac
>  create mode 100644 sysdeps/x86/dl-cet.c
>  create mode 100644 sysdeps/x86/dl-procruntime.c
>  create mode 100644 sysdeps/x86/dl-prop.h
>  create mode 100644 sysdeps/x86/libc-start.h
>  create mode 100644 sysdeps/x86/link_map.h
> 

[snip configure]

> diff --git a/configure.ac b/configure.ac
> index f41ed6decb..014e09a5d5 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -464,6 +464,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=no])
> +

OK.

>  # 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/Makefile b/elf/Makefile
> index 41cc3681be..84107f6dbb 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -1058,6 +1058,8 @@ $(objpfx)tst-piemod1.so: $(libsupport)
>  $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
>  
>  ifeq (yes,$(build-shared))
> +# NB: Please keep cet-built-dso in sysdeps/x86/Makefile in sync with
> +# all-built-dso here.

OK. Perfect. Thanks for this.

>  all-built-dso := $(common-objpfx)elf/ld.so $(common-objpfx)libc.so \
>  		 $(filter-out $(common-objpfx)linkobj/libc.so, \
>  			      $(sort $(wildcard $(addprefix $(common-objpfx), \
> diff --git a/elf/dl-load.c b/elf/dl-load.c
> index 09185ab68d..c51e4b3718 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)))));
> +};
> +

OK.

>  #include "dynamic-link.h"
>  #include <abi-tag.h>
>  #include <stackinfo.h>
> @@ -44,6 +70,7 @@
>  #include <dl-unmap-segments.h>
>  #include <dl-machine-reject-phdr.h>
>  #include <dl-sysdep-open.h>
> +#include <dl-prop.h>
>  #include <not-cancel.h>
>  
>  #include <endian.h>
> @@ -69,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;
>  
> @@ -1152,6 +1154,14 @@ _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;
> +
> +	case PT_NOTE:
> +	  if (_dl_process_pt_note (l, ph, fd, fbp))
> +	    {
> +	      errstring = N_("cannot process note segment");
> +	      goto call_lose;
> +	    }
> +	  break;

OK.

>  	}
>  
>      if (__glibc_unlikely (nloadcmds == 0))
> diff --git a/elf/dl-open.c b/elf/dl-open.c
> index 9dde4acfbc..f6c8ef1043 100644
> --- a/elf/dl-open.c
> +++ b/elf/dl-open.c
> @@ -35,6 +35,7 @@
>  #include <libc-internal.h>
>  
>  #include <dl-dst.h>
> +#include <dl-prop.h>

OK.

>  
>  
>  /* We must be careful not to leave us in an inconsistent state.  Thus we
> @@ -291,6 +292,8 @@ dl_open_worker (void *a)
>    _dl_debug_state ();
>    LIBC_PROBE (map_complete, 3, args->nsid, r, new);
>  
> +  _dl_open_check (new);

OK. Better. Less bitrot with unconditional calls like this.

> +
>    /* 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 8c732adb68..1b0c74739f 100644
> --- a/elf/rtld.c
> +++ b/elf/rtld.c
> @@ -38,6 +38,7 @@
>  #include <dl-cache.h>
>  #include <dl-osinfo.h>
>  #include <dl-procinfo.h>
> +#include <dl-prop.h>

OK.

>  #include <tls.h>
>  #include <stap-probe.h>
>  #include <stackinfo.h>
> @@ -1241,6 +1242,12 @@ 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;
> +
> +      case PT_NOTE:
> +	if (_rtld_process_pt_note (main_map, ph))
> +	  _dl_error_printf ("\
> +ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
> +	break;

OK. Thanks for the direct call.

>        }
>  
>    /* Adjust the address of the TLS initialization image in case
> @@ -2110,6 +2117,8 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
>  	_dl_show_scope (l, 0);
>      }
>  
> +  _rtld_main_check (main_map, _dl_argv[0]);

OK. Likewise.

> +
>    if (prelinked)
>      {
>        if (main_map->l_info [ADDRIDX (DT_GNU_CONFLICT)] != NULL)
> diff --git a/sysdeps/generic/dl-prop.h b/sysdeps/generic/dl-prop.h
> new file mode 100644
> index 0000000000..e5fe5d23aa
> --- /dev/null
> +++ b/sysdeps/generic/dl-prop.h
> @@ -0,0 +1,47 @@
> +/* Support for GNU properties.  Generic version.
> +   Copyright (C) 2018 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#ifndef _DL_PROP_H
> +#define _DL_PROP_H
> +

Suggest adding the following comment:

/* The following functions are used by the dynamic loader and
   the dlopen machinery to process PT_NOTE entries in the binary
   or shared object.  The notes can be used to change the behaviour
   of the loader, and as such offer a flexible mechanism for hooking
   in various checks related to ABI tags or implementing "flag day"
   ABI transitions.  */

> +static inline void __attribute__ ((always_inline))
> +_rtld_main_check (struct link_map *m, const char *program)
> +{
> +}
> +
> +static inline void __attribute__ ((always_inline))
> +_dl_open_check (struct link_map *m)
> +{
> +}
> +
> +#ifdef FILEBUF_SIZE
> +static inline int __attribute__ ((always_inline))
> +_dl_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph,
> +		     int fd, struct filebuf *fbp)
> +{
> +  return 0;
> +}
> +#endif
> +
> +static inline int __attribute__ ((always_inline))
> +_rtld_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph)
> +{
> +  return 0;
> +}

OK.

> +
> +#endif /* _DL_PROP_H */
> diff --git a/sysdeps/i386/dl-cet.c b/sysdeps/i386/dl-cet.c
> new file mode 100644
> index 0000000000..5d9a4e8d51
> --- /dev/null
> +++ b/sysdeps/i386/dl-cet.c
> @@ -0,0 +1,67 @@
> +/* Linux/i386 CET initializers function.
> +   Copyright (C) 2018 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/>.  */
> +
> +
> +#define LINKAGE static inline
> +#define _dl_cet_check cet_check
> +#include <sysdeps/x86/dl-cet.c>
> +#undef _dl_cet_check
> +
> +#ifdef SHARED
> +void
> +_dl_cet_check (struct link_map *main_map, const char *program)
> +{
> +  cet_check (main_map, program);
> +
> +  if ((GL(dl_x86_feature_1)[0] & 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;
> +	}

OK.

> +
> +      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;

OK.

> +	    }
> +	}
> +    }
> +}

OK.

> +#endif
> diff --git a/sysdeps/i386/dl-trampoline.S b/sysdeps/i386/dl-trampoline.S
> index 8bf86f8fd9..6dc0319216 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

OK.

>  	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

OK.

>  
>  #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
> +

OK.

>  	.globl _dl_runtime_profile
>  	.type _dl_runtime_profile, @function
>  	cfi_startproc
>  	.align 16
>  _dl_runtime_profile:
>  	cfi_adjust_cfa_offset (8)
> +	_CET_ENDBR

OK.

>  	pushl %esp
>  	cfi_adjust_cfa_offset (4)
>  	addl $8, (%esp)		# Account for the pushed PLT data
> diff --git a/sysdeps/unix/sysv/linux/x86/cpu-features.c b/sysdeps/unix/sysv/linux/x86/cpu-features.c
> new file mode 100644
> index 0000000000..0045f979da
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/x86/cpu-features.c
> @@ -0,0 +1,38 @@
> +/* Initialize CPU feature data for Linux/x86.
> +   This file is part of the GNU C Library.
> +   Copyright (C) 2018 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 __CET__
> +static inline int __attribute__ ((always_inline))
> +get_cet_status (void)
> +{
> +  return 0;
> +}

Why is this still "return 0;" ? Is it because the kernel pieces aren't
completely done yet and we'll enable this later?

> +
> +# ifndef SHARED
> +static inline void
> +x86_setup_tls (void)
> +{
> +  __libc_setup_tls ();
> +  THREAD_SETMEM (THREAD_SELF, header.feature_1, GL(dl_x86_feature_1)[0]);
> +}
> +
> +#  define ARCH_SETUP_TLS() x86_setup_tls ()
> +# endif
> +#endif
> +

OK.

> +#include <sysdeps/x86/cpu-features.c>
> 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 0000000000..9903bbe41f
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/x86/dl-cet.h
> @@ -0,0 +1,34 @@
> +/* Linux/x86 CET initializers function.
> +   Copyright (C) 2018 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/>.  */
> +
> +static inline int __attribute__ ((always_inline))
> +dl_cet_allocate_legacy_bitmap (unsigned long *legacy_bitmap)
> +{
> +  return -1;
> +}
> +
> +static inline int __attribute__ ((always_inline))
> +dl_cet_disable_cet (unsigned int cet_feature)
> +{
> +  return -1;
> +}
> +
> +static inline int __attribute__ ((always_inline))
> +dl_cet_lock_cet (void)
> +{
> +  return -1;
> +}

All three of these need comments explaining why they just return -1.
Is it because it's a temporary implementation and the kernel pieces
are not yet complete? It should say so then.

> diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
> index 65292f4032..e9b2d0b35d 100644
> --- a/sysdeps/x86/Makefile
> +++ b/sysdeps/x86/Makefile
> @@ -13,3 +13,45 @@ ifeq ($(subdir),setjmp)
>  gen-as-const-headers += jmp_buf-ssp.sym
>  sysdep_routines += __longjmp_cancel
>  endif
> +
> +ifeq ($(enable-cet),yes)
> +ifeq ($(subdir),elf)
> +sysdep-dl-routines += dl-cet

OK. Inlcudes dl-cet.c code.

> +endif
> +
> +# Add -fcf-protection to CFLAGS when CET is enabled.
> +CFLAGS-.o += -fcf-protection
> +CFLAGS-.os += -fcf-protection
> +CFLAGS-.op += -fcf-protection
> +CFLAGS-.oS += -fcf-protection
> +
> +# Compile assembly codes with <cet.h> when CET is enabled.
> +asm-CPPFLAGS += -fcf-protection -include cet.h
> +
> +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.

OK.

> +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/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/x86/cet-tunables.h b/sysdeps/x86/cet-tunables.h
> new file mode 100644
> index 0000000000..ca023053ee
> --- /dev/null
> +++ b/sysdeps/x86/cet-tunables.h
> @@ -0,0 +1,29 @@
> +/* x86 CET tuning.
> +   This file is part of the GNU C Library.
> +   Copyright (C) 2018 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/>.  */
> +
> +/* Valid control values:
> +   0: Enable CET features based on ELF property note.
> +   1: Always disable CET features.
> +   2: Always enable CET features.
> +   3: Enable CET features permissively.
> + */
> +#define CET_ELF_PROPERTY	0
> +#define CET_ALWAYS_OFF		1
> +#define CET_ALWAYS_ON		2
> +#define CET_PERMISSIVE		3
> +#define CET_MAX			CET_PERMISSIVE

OK.

> diff --git a/sysdeps/x86/check-cet.awk b/sysdeps/x86/check-cet.awk
> new file mode 100644
> index 0000000000..380d998caf
> --- /dev/null
> +++ b/sysdeps/x86/check-cet.awk
> @@ -0,0 +1,53 @@
> +# Verify that all shared objects contain the CET property.
> +# Copyright (C) 2018 Free Software Foundation, Inc.
> +# This file is part of the GNU C Library.
> +#
> +# The GNU C Library is free software; you can redistribute it and/or
> +# modify it under the terms of the GNU Lesser General Public
> +# License as published by the Free Software Foundation; either
> +# version 2.1 of the License, or (at your option) any later version.
> +#
> +# The GNU C Library is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +# Lesser General Public License for more details.
> +#
> +# You should have received a copy of the GNU Lesser General Public
> +# License along with the GNU C Library; if not, see
> +# <http://www.gnu.org/licenses/>.
> +
> +# 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);
> +}

OK.

> diff --git a/sysdeps/x86/configure b/sysdeps/x86/configure
[snipped]

> diff --git a/sysdeps/x86/configure.ac b/sysdeps/x86/configure.ac
> new file mode 100644
> index 0000000000..a909b073af
> --- /dev/null
> +++ b/sysdeps/x86/configure.ac
> @@ -0,0 +1,46 @@
> +GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
> +# Local configure fragment for sysdeps/x86.
> +
> +if 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 __CET__ || __CET__ != 3
> +# error CET isn't available.
> +#endif
> +EOF
> +		 if AC_TRY_COMMAND(${CC-cc} -c $CFLAGS -fcf-protection -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
> +fi
> +LIBC_CONFIG_VAR([enable-cet], [$enable_cet])

OK.

> diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
> index d41ebde823..f52e28e04b 100644
> --- a/sysdeps/x86/cpu-features.c
> +++ b/sysdeps/x86/cpu-features.c
> @@ -28,6 +28,15 @@
>  
>  extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *)
>    attribute_hidden;
> +
> +# ifdef __CET__
> +#  include <dl-cet.h>
> +#  include <cet-tunables.h>
> +extern void TUNABLE_CALLBACK (set_x86_ibt) (tunable_val_t *)
> +  attribute_hidden;
> +extern void TUNABLE_CALLBACK (set_x86_shstk) (tunable_val_t *)
> +  attribute_hidden;
> +# endif

OK.

>  #endif
>  
>  static void
> @@ -449,4 +458,55 @@ no_cpuid:
>    else if (CPU_FEATURES_ARCH_P (cpu_features, I586))
>      GLRO(dl_platform) = "i586";
>  #endif
> +
> +#ifdef __CET__
> +# if HAVE_TUNABLES
> +  TUNABLE_GET (x86_ibt, tunable_val_t *,
> +	       TUNABLE_CALLBACK (set_x86_ibt));
> +  TUNABLE_GET (x86_shstk, tunable_val_t *,
> +	       TUNABLE_CALLBACK (set_x86_shstk));

OK.

> +# endif
> +
> +  /* Check CET status.  */
> +  unsigned int cet_status = get_cet_status ();

OK.

> +
> +  if (cet_status)
> +    {
> +      GL(dl_x86_feature_1)[0] = cet_status;
> +
> +# ifndef SHARED
> +      /* Check if IBT and SHSTK are enabled by kernel.  */
> +      if ((cet_status & GNU_PROPERTY_X86_FEATURE_1_IBT)
> +	  || (cet_status & GNU_PROPERTY_X86_FEATURE_1_SHSTK))
> +	{
> +	  /* Disable IBT and/or SHSTK if they are enabled by kernel, but
> +	     disabled by environment variable:
> +
> +	     GLIBC_TUNABLES=glibc.tune.hwcaps=-IBT,-SHSTK

OK.

> +	   */
> +	  unsigned int cet_feature = 0;
> +	  if (!HAS_CPU_FEATURE (IBT))
> +	    cet_feature |= GNU_PROPERTY_X86_FEATURE_1_IBT;
> +	  if (!HAS_CPU_FEATURE (SHSTK))
> +	    cet_feature |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
> +
> +	  if (cet_feature)
> +	    {
> +	      int res = dl_cet_disable_cet (cet_feature);
> +
> +	      /* Clear the disabled bits in dl_x86_feature_1.  */
> +	      if (res == 0)
> +		GL(dl_x86_feature_1)[0] &= ~cet_feature;
> +	    }
> +
> +	  /* Lock CET if IBT or SHSTK is enabled in executable.  Don't
> +	     lock CET if SHSTK is enabled permissively.  */
> +	  if (((GL(dl_x86_feature_1)[1] >> CET_MAX)
> +	       & ((1 << CET_MAX) - 1))
> +	       != CET_PERMISSIVE)
> +	    dl_cet_lock_cet ();
> +	}
> +# endif
> +    }
> +#endif

OK.

>  }
> diff --git a/sysdeps/x86/cpu-tunables.c b/sysdeps/x86/cpu-tunables.c
> index af761dcbbc..a5c0153348 100644
> --- a/sysdeps/x86/cpu-tunables.c
> +++ b/sysdeps/x86/cpu-tunables.c
> @@ -334,4 +334,52 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
>      }
>    while (*p != '\0');
>  }
> +
> +# ifdef __CET__
> +#  include <cet-tunables.h>
> +
> +attribute_hidden
> +void
> +TUNABLE_CALLBACK (set_x86_ibt) (tunable_val_t *valp)
> +{
> +  if (DEFAULT_MEMCMP (valp->strval, "on", sizeof ("on")) == 0)
> +    {
> +      GL(dl_x86_feature_1)[1] &= ~((1 << CET_MAX) - 1);
> +      GL(dl_x86_feature_1)[1] |= CET_ALWAYS_ON;
> +    }
> +  else if (DEFAULT_MEMCMP (valp->strval, "off", sizeof ("off")) == 0)
> +    {
> +      GL(dl_x86_feature_1)[1] &= ~((1 << CET_MAX) - 1);
> +      GL(dl_x86_feature_1)[1] |= CET_ALWAYS_OFF;
> +    }
> +  else if (DEFAULT_MEMCMP (valp->strval, "permissive",
> +			   sizeof ("permissive")) == 0)
> +    {
> +      GL(dl_x86_feature_1)[1] &= ~((1 << CET_MAX) - 1);
> +      GL(dl_x86_feature_1)[1] |= CET_PERMISSIVE;
> +    }
> +}

OK.

> +
> +attribute_hidden
> +void
> +TUNABLE_CALLBACK (set_x86_shstk) (tunable_val_t *valp)
> +{
> +  if (DEFAULT_MEMCMP (valp->strval, "on", sizeof ("on")) == 0)
> +    {
> +      GL(dl_x86_feature_1)[1] &= ~(((1 << CET_MAX) - 1) << CET_MAX);
> +      GL(dl_x86_feature_1)[1] |= (CET_ALWAYS_ON << CET_MAX);
> +    }
> +  else if (DEFAULT_MEMCMP (valp->strval, "off", sizeof ("off")) == 0)
> +    {
> +      GL(dl_x86_feature_1)[1] &= ~(((1 << CET_MAX) - 1) << CET_MAX);
> +      GL(dl_x86_feature_1)[1] |= (CET_ALWAYS_OFF << CET_MAX);
> +    }
> +  else if (DEFAULT_MEMCMP (valp->strval, "permissive",
> +			   sizeof ("permissive")) == 0)
> +    {
> +      GL(dl_x86_feature_1)[1] &= ~(((1 << CET_MAX) - 1) << CET_MAX);
> +      GL(dl_x86_feature_1)[1] |= (CET_PERMISSIVE << CET_MAX);
> +    }
> +}

OK.

> +# endif
>  #endif
> diff --git a/sysdeps/x86/dl-cet.c b/sysdeps/x86/dl-cet.c
> new file mode 100644
> index 0000000000..5018e4560d
> --- /dev/null
> +++ b/sysdeps/x86/dl-cet.c
> @@ -0,0 +1,335 @@
> +/* x86 CET initializers function.
> +   Copyright (C) 2018 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/>.  */
> +
> +#include <unistd.h>
> +#include <errno.h>
> +#include <libintl.h>
> +#include <ldsodefs.h>
> +#include <dl-cet.h>
> +#include <cet-tunables.h>
> +
> +static int
> +dl_cet_mark_legacy_region (struct link_map *l)
> +{
> +  /* Mark PT_LOAD segments with PF_X in legacy code page bitmap.  */
> +  size_t i, phnum = l->l_phnum;
> +  const ElfW(Phdr) *phdr = l->l_phdr;
> +#ifdef __x86_64__
> +  typedef unsigned long long word_t;
> +#else
> +  typedef unsigned long word_t;
> +#endif
> +  unsigned int bits_to_set;
> +  word_t mask_to_set;
> +#define BITS_PER_WORD (sizeof (word_t) * 8)
> +#define BITMAP_FIRST_WORD_MASK(start) \
> +  (~((word_t) 0) << ((start) & (BITS_PER_WORD - 1)))
> +#define BITMAP_LAST_WORD_MASK(nbits) \
> +  (~((word_t) 0) >> (-(nbits) & (BITS_PER_WORD - 1)))
> +
> +  word_t *bitmap = (word_t *) GL(dl_x86_legacy_bitmap)[0];
> +  word_t bitmap_size = GL(dl_x86_legacy_bitmap)[1];
> +  word_t *p;
> +  size_t page_size = GLRO(dl_pagesize);
> +
> +  for (i = 0; i < phnum; i++)
> +    if (phdr[i].p_type == PT_LOAD && (phdr[i].p_flags & PF_X))
> +      {
> +	/* One bit in legacy bitmap represents a page.  */
> +	ElfW(Addr) start = (phdr[i].p_vaddr + l->l_addr) / page_size;
> +	ElfW(Addr) len = (phdr[i].p_memsz + page_size - 1) / page_size;
> +	ElfW(Addr) end = start + len;
> +
> +	if ((end / 8) > bitmap_size)
> +	  return -EFAULT;

Why return -EFAULT? We only check != 0 in the caller, so just return -1?
It may conuse things by using errno here, and worse negative errno.

Please just return -1.

> +
> +	p = bitmap + (start / BITS_PER_WORD);
> +	bits_to_set = BITS_PER_WORD - (start % BITS_PER_WORD);
> +	mask_to_set = BITMAP_FIRST_WORD_MASK (start);
> +
> +	while (len >= bits_to_set)
> +	  {
> +	    *p |= mask_to_set;

OK.

> +	    len -= bits_to_set;
> +	    bits_to_set = BITS_PER_WORD;
> +	    mask_to_set = ~((word_t) 0);
> +	    p++;
> +	  }
> +	if (len)
> +	  {
> +	    mask_to_set &= BITMAP_LAST_WORD_MASK (end);
> +	    *p |= mask_to_set;

OK.

> +	  }
> +      }
> +
> +  return 0;
> +}
> +
> +/* Check if object M is compatible with CET.  */
> +
> +static void
> +dl_cet_check (struct link_map *m, const char *program)
> +{
> +  /* Check how IBT should be enabled.  */
> +  unsigned int enable_ibt_type
> +    = GL(dl_x86_feature_1)[1] & ((1 << CET_MAX) - 1);
> +  /* Check how SHSTK should be enabled.  */
> +  unsigned int enable_shstk_type
> +    = ((GL(dl_x86_feature_1)[1] >> CET_MAX) & ((1 << CET_MAX) - 1));
> +
> +  /* No legacy object check if both IBT and SHSTK are always on.  */
> +  if (enable_ibt_type == CET_ALWAYS_ON
> +      && enable_shstk_type == CET_ALWAYS_ON)
> +    return;
> +
> +  /* Check if IBT is enabled by kernel.  */
> +  bool ibt_enabled
> +    = (GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0;
> +  /* Check if SHSTK is enabled by kernel.  */
> +  bool shstk_enabled
> +    = (GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0;
> +
> +  if (ibt_enabled || shstk_enabled)
> +    {
> +      struct link_map *l = NULL;
> +
> +      /* Check if IBT and SHSTK are enabled in object.  */
> +      bool enable_ibt = (ibt_enabled
> +			 && enable_ibt_type != CET_ALWAYS_OFF);
> +      bool enable_shstk = (shstk_enabled
> +			   && enable_shstk_type != CET_ALWAYS_OFF);
> +      if (program)
> +	{
> +	  /* Enable IBT and SHSTK only if they are enabled in executable.
> +	     NB: IBT and SHSTK may be disabled by environment variable:
> +
> +	     GLIBC_TUNABLES=glibc.tune.hwcaps=-IBT,-SHSTK
> +	   */
> +	  enable_ibt &= (HAS_CPU_FEATURE (IBT)
> +			 && (enable_ibt_type == CET_ALWAYS_ON
> +			     || (m->l_cet & lc_ibt) != 0));
> +	  enable_shstk &= (HAS_CPU_FEATURE (SHSTK)
> +			   && (enable_shstk_type == CET_ALWAYS_ON
> +			       || (m->l_cet & lc_shstk) != 0));
> +	}
> +
> +      /* ld.so is CET-enabled by kernel.  But shared objects may not
> +	 support IBT nor SHSTK.  */
> +      if (enable_ibt || enable_shstk)
> +	{
> +	  int res;
> +	  unsigned int i;
> +	  unsigned int first_legacy, last_legacy;
> +	  bool need_legacy_bitmap = false;
> +
> +	  i = m->l_searchlist.r_nlist;
> +	  while (i-- > 0)
> +	    {
> +	      /* Check each shared object to see if IBT and SHSTK are
> +		 enabled.  */
> +	      l = m->l_initfini[i];
> +
> +	      if (l->l_init_called)
> +		continue;
> +
> +#ifdef SHARED
> +	      /* Skip CET check for ld.so since ld.so is CET-enabled.
> +		 CET will be disabled later if CET isn't enabled in
> +		 executable.  */
> +	      if (l == &GL(dl_rtld_map)
> +		  ||  l->l_real == &GL(dl_rtld_map)
> +		  || (program && l == m))
> +		continue;
> +#endif
> +
> +	      if (enable_ibt
> +		  && enable_ibt_type != CET_ALWAYS_ON
> +		  && !(l->l_cet & lc_ibt))
> +		{
> +		  /* Remember the first and last legacy objects.  */
> +		  if (!need_legacy_bitmap)
> +		    last_legacy = i;
> +		  first_legacy = i;
> +		  need_legacy_bitmap = true;
> +		}
> +
> +	      /* SHSTK is enabled only if it is enabled in executable as
> +		 well as all shared objects.  */
> +	      enable_shstk &= (enable_shstk_type == CET_ALWAYS_ON
> +			       || (l->l_cet & lc_shstk) != 0);
> +	    }
> +
> +	  if (need_legacy_bitmap)
> +	    {
> +	      if (GL(dl_x86_legacy_bitmap)[0])
> +		{
> +		  /* Change legacy bitmap to writable.  */
> +		  if (__mprotect ((void *) GL(dl_x86_legacy_bitmap)[0],
> +				  GL(dl_x86_legacy_bitmap)[1],
> +				  PROT_READ | PROT_WRITE) < 0)
> +		    {
> +mprotect_failure:
> +		      if (program)
> +			_dl_fatal_printf ("%s: mprotect legacy bitmap failed\n",
> +					  l->l_name);
> +		      else
> +			_dl_signal_error (EINVAL, l->l_name, "dlopen",
> +					  N_("mprotect legacy bitmap failed"));
> +		    }
> +		}
> +	      else
> +		{
> +		  /* Allocate legacy bitmap.  */
> +		  int res = dl_cet_allocate_legacy_bitmap
> +		    (GL(dl_x86_legacy_bitmap));
> +		  if (res != 0)
> +		    {
> +		      if (program)
> +			_dl_fatal_printf ("%s: legacy bitmap isn't available\n",
> +					  l->l_name);
> +		      else
> +			_dl_signal_error (EINVAL, l->l_name, "dlopen",
> +					  N_("legacy bitmap isn't available"));
> +		    }
> +		}
> +
> +	      /* Put legacy shared objects in legacy bitmap.  */
> +	      for (i = first_legacy; i <= last_legacy; i++)
> +		{
> +		  l = m->l_initfini[i];
> +
> +		  if (l->l_init_called || (l->l_cet & lc_ibt))
> +		    continue;
> +
> +#ifdef SHARED
> +		  if (l == &GL(dl_rtld_map)
> +		      ||  l->l_real == &GL(dl_rtld_map)
> +		      || (program && l == m))
> +		    continue;
> +#endif
> +
> +		  /* If IBT is enabled in executable and IBT isn't enabled
> +		     in this shard object, mark PT_LOAD segments with PF_X
> +		     in legacy code page bitmap.  */
> +		  res = dl_cet_mark_legacy_region (l);
> +		  if (res != 0)
> +		    {
> +		      if (program)
> +			_dl_fatal_printf ("%s: fail to mark legacy code region\n",

s/fail/failed/g

> +					  l->l_name);
> +		      else
> +			_dl_signal_error (-res, l->l_name, "dlopen",
> +					  N_("fail to mark legacy code region"));

s/fail/failed/g

> +		    }

OK.

> +		}
> +
> +	      /* Change legacy bitmap to read-only.  */
> +	      if (__mprotect ((void *) GL(dl_x86_legacy_bitmap)[0],
> +			      GL(dl_x86_legacy_bitmap)[1], PROT_READ) < 0)
> +		goto mprotect_failure;
> +	    }
> +	}
> +
> +      bool cet_feature_changed = false;
> +
> +      if (enable_ibt != ibt_enabled || enable_shstk != shstk_enabled)
> +	{
> +	  if (!program
> +	      && enable_shstk_type != CET_PERMISSIVE)
> +	    {
> +	      /* When SHSTK is enabled, we can't dlopening a shared
> +		 object without SHSTK.  */
> +	      if (enable_shstk != shstk_enabled)
> +		_dl_signal_error (EINVAL, l->l_name, "dlopen",
> +				  N_("shadow stack isn't enabled"));
> +	      return;
> +	    }
> +
> +	  /* Disable IBT and/or SHSTK if they are enabled by kernel, but
> +	     disabled in executable or shared objects.  */
> +	  unsigned int cet_feature = 0;
> +
> +	  /* Disable IBT only during program startup.  */
> +	  if (program && !enable_ibt)
> +	    cet_feature |= GNU_PROPERTY_X86_FEATURE_1_IBT;
> +	  if (!enable_shstk)
> +	    cet_feature |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
> +
> +	  int res = dl_cet_disable_cet (cet_feature);
> +	  if (res != 0)
> +	    {
> +	      if (program)
> +		_dl_fatal_printf ("%s: can't disable CET\n", program);
> +	      else
> +		_dl_signal_error (-res, l->l_name, "dlopen",
> +				  N_("can't disable CET"));
> +	    }
> +
> +	  /* Clear the disabled bits in dl_x86_feature_1.  */
> +	  GL(dl_x86_feature_1)[0] &= ~cet_feature;
> +
> +	  cet_feature_changed = true;
> +	}

OK.

> +
> +#ifdef SHARED
> +      if (program
> +	  && (!shstk_enabled
> +	      || enable_shstk_type != CET_PERMISSIVE)
> +	  && (ibt_enabled || shstk_enabled))
> +	{
> +	  /* Lock CET if IBT or SHSTK is enabled in executable.  Don't
> +	     lock CET if SHSTK is enabled permissively.  */
> +	  int res = dl_cet_lock_cet ();
> +	  if (res != 0)
> +	    _dl_fatal_printf ("%s: can't lock CET\n", program);
> +
> +	  cet_feature_changed = true;
> +	}
> +#endif
> +
> +      if (cet_feature_changed)
> +	{
> +	  unsigned int feature_1 = 0;
> +	  if (enable_ibt)
> +	    feature_1 |= GNU_PROPERTY_X86_FEATURE_1_IBT;
> +	  if (enable_shstk)
> +	    feature_1 |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
> +	  struct pthread *self = THREAD_SELF;
> +	  THREAD_SETMEM (self, header.feature_1, feature_1);
> +	}
> +    }
> +}
> +
> +void
> +_dl_cet_open_check (struct link_map *l)
> +{
> +  dl_cet_check (l, NULL);
> +}
> +
> +#ifdef SHARED
> +
> +# ifndef LINKAGE
> +#  define LINKAGE
> +# endif
> +
> +LINKAGE
> +void
> +_dl_cet_check (struct link_map *main_map, const char *program)
> +{
> +  dl_cet_check (main_map, program);
> +}
> +#endif /* SHARED */
> diff --git a/sysdeps/x86/dl-procruntime.c b/sysdeps/x86/dl-procruntime.c
> new file mode 100644
> index 0000000000..eddbde6a31
> --- /dev/null
> +++ b/sysdeps/x86/dl-procruntime.c
> @@ -0,0 +1,68 @@
> +/* Data for processor runtime information.  x86 version.
> +   Copyright (C) 2018 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <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[2]
> +# endif
> +# if !defined SHARED || defined PROCINFO_DECL
> +;
> +# else
> +,
> +# endif
> +
> +# if !defined PROCINFO_DECL && defined SHARED
> +  ._dl_x86_legacy_bitmap
> +# else
> +PROCINFO_CLASS unsigned long _dl_x86_legacy_bitmap[2]
> +# endif
> +# if !defined SHARED || defined PROCINFO_DECL
> +;
> +# else
> +,
> +# endif
> +#endif

OK.

> diff --git a/sysdeps/x86/dl-prop.h b/sysdeps/x86/dl-prop.h
> new file mode 100644
> index 0000000000..2709fe852d
> --- /dev/null
> +++ b/sysdeps/x86/dl-prop.h
> @@ -0,0 +1,153 @@
> +/* Support for GNU properties.  x86 version.
> +   Copyright (C) 2018 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#ifndef _DL_PROP_H
> +#define _DL_PROP_H
> +
> +#include <not-cancel.h>
> +
> +extern void _dl_cet_check (struct link_map *, const char *)
> +    attribute_hidden;
> +extern void _dl_cet_open_check (struct link_map *)
> +    attribute_hidden;
> +
> +static inline void __attribute__ ((always_inline))
> +_rtld_main_check (struct link_map *m, const char *program)
> +{
> +#ifdef __CET__
> +  _dl_cet_check (m, program);
> +#endif
> +}

OK.

> +
> +static inline void __attribute__ ((always_inline))
> +_dl_open_check (struct link_map *m)
> +{
> +#ifdef __CET__
> +  _dl_cet_open_check (m);
> +#endif
> +}

OK.

> +
> +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)
> +{
> +#ifdef __CET__
> +  /* 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)

OK. For the next arch that needs property handling we should genarlize
some of these things in the future (not needed for 2.28).

> +    {
> +      /* 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)

OK.

> +	{
> +	  /* Check for invalid property.  */
> +	  if (note->n_descsz < 8
> +	      || (note->n_descsz % sizeof (ElfW(Addr))) != 0)
> +	    break;

OK.

> +
> +	  /* 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)

OK.

> +		{
> +		  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));
> +    }
> +#endif
> +}

OK.

> +
> +#ifdef FILEBUF_SIZE
> +static inline int __attribute__ ((unused))
> +_dl_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph,
> +		     int fd, struct filebuf *fbp)
> +{
> +# ifdef __CET__
> +  const ElfW(Nhdr) *note;
> +  ElfW(Nhdr) *note_malloced = NULL;
> +  ElfW(Addr) size = ph->p_filesz;
> +
> +  if (ph->p_offset + size <= (size_t) fbp->len)
> +    note = (const void *) (fbp->buf + ph->p_offset);
> +  else
> +    {
> +      if (size < __MAX_ALLOCA_CUTOFF)
> +	note = alloca (size);
> +      else
> +	{
> +	  note_malloced = malloc (size);
> +	  note = note_malloced;
> +	}
> +      __lseek (fd, ph->p_offset, SEEK_SET);
> +      if (__read_nocancel (fd, (void *) note, size) != size)
> +	{
> +	  if (note_malloced)
> +	    free (note_malloced);
> +	  return -1;
> +	}
> +    }
> +
> +  _dl_process_cet_property_note (l, note, size, ph->p_align);
> +  if (note_malloced)
> +    free (note_malloced);
> +# endif
> +  return 0;
> +}
> +#endif

OK.

> +
> +static inline int __attribute__ ((unused))
> +_rtld_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;
> +}

OK.

> +
> +#endif /* _DL_PROP_H */
> diff --git a/sysdeps/x86/dl-tunables.list b/sysdeps/x86/dl-tunables.list
> index 7c3236a68f..73886b1352 100644
> --- a/sysdeps/x86/dl-tunables.list
> +++ b/sysdeps/x86/dl-tunables.list
> @@ -21,6 +21,12 @@ glibc {
>      hwcaps {
>        type: STRING
>      }
> +    x86_ibt {
> +      type: STRING
> +    }
> +    x86_shstk {
> +      type: STRING
> +    }

OK.

>      x86_non_temporal_threshold {
>        type: SIZE_T
>      }
> diff --git a/sysdeps/x86/libc-start.h b/sysdeps/x86/libc-start.h
> new file mode 100644
> index 0000000000..6f44262bf4
> --- /dev/null
> +++ b/sysdeps/x86/libc-start.h
> @@ -0,0 +1,25 @@
> +/* X86 definitions for libc main startup.
> +   Copyright (C) 2018 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#ifndef SHARED
> +# define ARCH_SETUP_IREL() apply_irel ()
> +# define ARCH_APPLY_IREL()
> +# ifndef ARCH_SETUP_TLS
> +#  define ARCH_SETUP_TLS() __libc_setup_tls ()
> +# endif
> +#endif /* !SHARED */

OK.

> diff --git a/sysdeps/x86/link_map.h b/sysdeps/x86/link_map.h
> new file mode 100644
> index 0000000000..ef1206a9d2
> --- /dev/null
> +++ b/sysdeps/x86/link_map.h
> @@ -0,0 +1,26 @@
> +/* Additional fields in struct link_map.  Linux/x86 version.
> +   Copyright (C) 2018 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <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;

OK.

> diff --git a/sysdeps/x86/sysdep.h b/sysdeps/x86/sysdep.h
> index afcb7cfd76..9843d9dff7 100644
> --- a/sysdeps/x86/sysdep.h
> +++ b/sysdeps/x86/sysdep.h
> @@ -25,6 +25,13 @@
>  
>  /* Syntactic details of assembler.  */
>  
> +#ifdef _CET_ENDBR
> +# define _CET_NOTRACK notrack
> +#else
> +# define _CET_ENDBR
> +# define _CET_NOTRACK
> +#endif

OK.

> +
>  /* 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 +43,7 @@
>    .align ALIGNARG(4);							      \
>    C_LABEL(name)								      \
>    cfi_startproc;							      \
> +  _CET_ENDBR;	

OK.

							      \
>    CALL_MCOUNT
>  
>  #undef	END
> diff --git a/sysdeps/x86_64/dl-trampoline.h b/sysdeps/x86_64/dl-trampoline.h
> index 298cfb3d99..a28b1e73a4 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
> -- 2.17.1

OK.
  
Joseph Myers July 17, 2018, 10:53 p.m. UTC | #2
On Mon, 16 Jul 2018, Carlos O'Donell wrote:

> This version is OK.

The documentation omissions need to be fixed for the release.  I see no 
install.texi update / INSTALL regeneration for the new configure option 
and no NEWS update for the new feature and associated configure option.  
It looks like there are new tunables added, at least according to the 
commit message, which also need documenting in the glibc manual.  In 
general, any information from the commit message that is relevant to users 
or builders of versions of glibc with this feature (as opposed to being 
only information for developers of glibc, or ABI information that belongs 
in an external ABI document, or only about the change rather than about 
the feature as it exists after the change) needs to go in an appropriate 
place in the manual, not just in the commit message.

At least the omission of documentation from some recent function additions 
has the justification that none of the documentation for *at functions, 
wherein it would need to go, exists at present.  There is no such reason 
for omitting documentation for configure options or tunables.  I don't 
think we want changes going in without documentation updates (in the 
manual, NEWS etc., as appropriate) or a rationale for the absence of such 
updates clearly specified in the commit message - and being in the freeze 
period should make our standards for such things *higher*, not lower.

I'm also concerned that a large amount of complicated code added by this 
change (or earlier CET changes) appears to have no execution tests (the 
patch adds just one test, one that inspects object properties rather than 
executing any of the affected code), so making it effectively 
unmaintainable.  I realise some would be covered by the normal testsuite, 
at least for a --enable-cet build running on a CET-enabled processor and 
kernel, and that some tests may only be effective on CET-enabled 
processors and kernels that most people don't have yet.  But I'd expect 
there to be some execution tests for the various cases of mixed CET 
properties in different executables and shared libraries, for example - 
generically, each piece of CET support in glibc needs to be considered for 
testability, and either have tests added, or be explained as tested 
automatically for certain glibc build configurations, or be justified as 
excessively hard to test.

In short, the code *present* in the patch may have been thoroughly 
reviewed, but the unjustified *omissions* of documentation and testcases 
mean I do not think it was ready to include in glibc or is appropriate to 
include in a release unless those documentation and tests are added soon.
  
Carlos O'Donell July 18, 2018, 12:22 a.m. UTC | #3
On 07/17/2018 06:53 PM, Joseph Myers wrote:
> On Mon, 16 Jul 2018, Carlos O'Donell wrote:
> 
>> This version is OK.
> 
> The documentation omissions need to be fixed for the release.  I see no 
> install.texi update / INSTALL regeneration for the new configure option 
> and no NEWS update for the new feature and associated configure option.  
> It looks like there are new tunables added, at least according to the 
> commit message, which also need documenting in the glibc manual.  In 
> general, any information from the commit message that is relevant to users 
> or builders of versions of glibc with this feature (as opposed to being 
> only information for developers of glibc, or ABI information that belongs 
> in an external ABI document, or only about the change rather than about 
> the feature as it exists after the change) needs to go in an appropriate 
> place in the manual, not just in the commit message.
> 
> At least the omission of documentation from some recent function additions 
> has the justification that none of the documentation for *at functions, 
> wherein it would need to go, exists at present.  There is no such reason 
> for omitting documentation for configure options or tunables.  I don't 
> think we want changes going in without documentation updates (in the 
> manual, NEWS etc., as appropriate) or a rationale for the absence of such 
> updates clearly specified in the commit message - and being in the freeze 
> period should make our standards for such things *higher*, not lower.

I agree, and I will make sure this is covered for Intel CET.

> I'm also concerned that a large amount of complicated code added by this 
> change (or earlier CET changes) appears to have no execution tests (the 
> patch adds just one test, one that inspects object properties rather than 
> executing any of the affected code), so making it effectively 
> unmaintainable.  I realise some would be covered by the normal testsuite, 
> at least for a --enable-cet build running on a CET-enabled processor and 
> kernel, and that some tests may only be effective on CET-enabled 
> processors and kernels that most people don't have yet.  But I'd expect 
> there to be some execution tests for the various cases of mixed CET 
> properties in different executables and shared libraries, for example - 
> generically, each piece of CET support in glibc needs to be considered for 
> testability, and either have tests added, or be explained as tested 
> automatically for certain glibc build configurations, or be justified as 
> excessively hard to test.

My opinion is that the testing can grow organically from the initial support
as Intel and the community invest in CET support.

> In short, the code *present* in the patch may have been thoroughly 
> reviewed, but the unjustified *omissions* of documentation and testcases 
> mean I do not think it was ready to include in glibc or is appropriate to 
> include in a release unless those documentation and tests are added soon.

I think the documentation is important and should go in immediately, for
any tunables or new configuration options.

My opinion is that the testing can be added incrementally and organically
as we continue to support the new feature. Lack of full coverage testing
should not block inclusion into the release.
  
H.J. Lu July 18, 2018, 3:32 a.m. UTC | #4
On Tue, Jul 17, 2018 at 5:22 PM, Carlos O'Donell <carlos@redhat.com> wrote:
> On 07/17/2018 06:53 PM, Joseph Myers wrote:
>> On Mon, 16 Jul 2018, Carlos O'Donell wrote:
>>
>>> This version is OK.
>>
>> The documentation omissions need to be fixed for the release.  I see no
>> install.texi update / INSTALL regeneration for the new configure option
>> and no NEWS update for the new feature and associated configure option.

Hi Joseph,  can you review

https://sourceware.org/ml/libc-alpha/2018-06/msg00328.html

Thanks.

>> It looks like there are new tunables added, at least according to the
>> commit message, which also need documenting in the glibc manual.  In

Sorry for that.  Here is the patch to document tunables:

https://sourceware.org/ml/libc-alpha/2018-07/msg00525.html

>> general, any information from the commit message that is relevant to users
>> or builders of versions of glibc with this feature (as opposed to being
>> only information for developers of glibc, or ABI information that belongs
>> in an external ABI document, or only about the change rather than about
>> the feature as it exists after the change) needs to go in an appropriate
>> place in the manual, not just in the commit message.
>>
>> At least the omission of documentation from some recent function additions
>> has the justification that none of the documentation for *at functions,
>> wherein it would need to go, exists at present.  There is no such reason
>> for omitting documentation for configure options or tunables.  I don't
>> think we want changes going in without documentation updates (in the
>> manual, NEWS etc., as appropriate) or a rationale for the absence of such
>> updates clearly specified in the commit message - and being in the freeze
>> period should make our standards for such things *higher*, not lower.
>
> I agree, and I will make sure this is covered for Intel CET.
>
>> I'm also concerned that a large amount of complicated code added by this
>> change (or earlier CET changes) appears to have no execution tests (the
>> patch adds just one test, one that inspects object properties rather than
>> executing any of the affected code), so making it effectively
>> unmaintainable.  I realise some would be covered by the normal testsuite,
>> at least for a --enable-cet build running on a CET-enabled processor and
>> kernel, and that some tests may only be effective on CET-enabled
>> processors and kernels that most people don't have yet.  But I'd expect
>> there to be some execution tests for the various cases of mixed CET
>> properties in different executables and shared libraries, for example -
>> generically, each piece of CET support in glibc needs to be considered for
>> testability, and either have tests added, or be explained as tested
>> automatically for certain glibc build configurations, or be justified as
>> excessively hard to test.

Here is a patch to test mixing CET executables and non-CET libraries:

https://sourceware.org/ml/libc-alpha/2018-07/msg00526.html

> My opinion is that the testing can grow organically from the initial support
> as Intel and the community invest in CET support.
>
>> In short, the code *present* in the patch may have been thoroughly
>> reviewed, but the unjustified *omissions* of documentation and testcases
>> mean I do not think it was ready to include in glibc or is appropriate to
>> include in a release unless those documentation and tests are added soon.
>
> I think the documentation is important and should go in immediately, for
> any tunables or new configuration options.
>
> My opinion is that the testing can be added incrementally and organically
> as we continue to support the new feature. Lack of full coverage testing
> should not block inclusion into the release.

There are 2 kinds of CET tests: correctness and effectiveness. I am focusing
on correctness for now.  That is all glibc tests should pass on CET machines
when glibc is configured with --enable-cet.  Also mixing CET executables and
non-CET libraries should work on CET machines.  I think I have all covered.
Please let me know if I missed anything.

BTW, I am holding off the final set of patches on:

https://github.com/hjl-tools/glibc/tree/hjl/cet/master

starting at

commit 1edb466caec037bdf9c714bbd38ceef11ba07971
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Sat Jul 7 07:33:04 2018 -0700

    x86/CET: Extend arch_prctl syscall for CET control

We are disusing with kernel community for the final syscall decision.

Thanks.
  
Joseph Myers July 18, 2018, 8:35 p.m. UTC | #5
On Tue, 17 Jul 2018, H.J. Lu wrote:

> On Tue, Jul 17, 2018 at 5:22 PM, Carlos O'Donell <carlos@redhat.com> wrote:
> > On 07/17/2018 06:53 PM, Joseph Myers wrote:
> >> On Mon, 16 Jul 2018, Carlos O'Donell wrote:
> >>
> >>> This version is OK.
> >>
> >> The documentation omissions need to be fixed for the release.  I see no
> >> install.texi update / INSTALL regeneration for the new configure option
> >> and no NEWS update for the new feature and associated configure option.
> 
> Hi Joseph,  can you review
> 
> https://sourceware.org/ml/libc-alpha/2018-06/msg00328.html
> 
> Thanks.

I'd like to be clear on a general principle relating to patch series:

Sometimes patches in a series can go in independently, as and when 
approved.  But sometimes the splits of patches into a series are purely 
for the convenience of review, and the patches are not intended to be 
committed independently.

That's obviously the case if earlier patches break the build on some 
architectures and later ones fix it, for example - in that case, to keep 
bisectability, it's required to squash the patches into a single commit.  
But even if bisectability isn't broken and so separate commits pushed at 
the same time are OK, in my view documentation is a fundamental part of a 
new feature patch.  If it's split out for review (which is something I'd 
discourage, I prefer to see the documentation and tests included in the 
main patch together with the implementation code), that does *not* mean an 
approval of the main patch makes it OK to commit without the documentation 
- just as an approval of a patch known to break the build doesn't make it 
OK to commit until the later patches fixing the build are also approved, 
and the whole set squashed together for commit.

Rather, I'd consider any approval of a patch whose documentation was split 
out to be implicitly conditional on the documentation also being approved 
and checked in at the same time (even if not in the same commit), to 
ensure we keep the invariant of features in glibc being documented in 
glibc.  For an approval to be valid without the documentation patch I 
think it would need to say so explicitly, and explain why - and take extra 
care to ensure there really is consensus for such a deviation from the 
normal rules on documenting new features.  (Just as, exceptionally, a 
patch known to break some architecture might be approved for commit, if 
there is no active architecture maintainer for the problem architecture 
and that architecture is likely to be obsoleted.)

> Here is a patch to test mixing CET executables and non-CET libraries:
> 
> https://sourceware.org/ml/libc-alpha/2018-07/msg00526.html

Could you please give a detailed description of the testing you have run 
for the CET changes in general?

The *minimum* for any nontrivial patch submission to glibc code should be 
a statement of the platform for which the glibc testsuite was run, or 
description of other testing done (and if we receive patch submissions 
that don't state even that, we should ask for it).  In the case of CET, a 
complicated feature with multiple configurations involved, and 
dependencies on hardware and kernel support, I'd expect a rather more 
extended discussion, maybe a few paragraphs, of the different cases tested 
and what those tests actually cover.  I'd guess those cases include 
various combinations of:

* i686, x86_64 and x32 glibc builds.

* glibc builds with and without --enable-cet.

* Tests run on kernels both with and without CET support.

* Tests run on both CET and non-CET hardware (or simulators for such 
hardware).

But that needs a proper explanation, posted to the libc-alpha list, of 
what you did actually test (and each subsequent patch submission should 
have such an explanation, of what was tested for that patch) - and, as I 
said, of to what extent that really covers the functionality of the code.
  
H.J. Lu July 18, 2018, 9:06 p.m. UTC | #6
On Wed, Jul 18, 2018 at 1:35 PM, Joseph Myers <joseph@codesourcery.com> wrote:
> On Tue, 17 Jul 2018, H.J. Lu wrote:
>
>> On Tue, Jul 17, 2018 at 5:22 PM, Carlos O'Donell <carlos@redhat.com> wrote:
>> > On 07/17/2018 06:53 PM, Joseph Myers wrote:
>> >> On Mon, 16 Jul 2018, Carlos O'Donell wrote:
>> >>
>> >>> This version is OK.
>> >>
>> >> The documentation omissions need to be fixed for the release.  I see no
>> >> install.texi update / INSTALL regeneration for the new configure option
>> >> and no NEWS update for the new feature and associated configure option.
>>
>> Hi Joseph,  can you review
>>
>> https://sourceware.org/ml/libc-alpha/2018-06/msg00328.html
>>
>> Thanks.
>
> I'd like to be clear on a general principle relating to patch series:
>
> Sometimes patches in a series can go in independently, as and when
> approved.  But sometimes the splits of patches into a series are purely
> for the convenience of review, and the patches are not intended to be
> committed independently.

The second part of the CET patches depends on the the first couple
CET patches.  But here are no dependencies within the second part.

> That's obviously the case if earlier patches break the build on some
> architectures and later ones fix it, for example - in that case, to keep
> bisectability, it's required to squash the patches into a single commit.
> But even if bisectability isn't broken and so separate commits pushed at
> the same time are OK, in my view documentation is a fundamental part of a
> new feature patch.  If it's split out for review (which is something I'd
> discourage, I prefer to see the documentation and tests included in the
> main patch together with the implementation code), that does *not* mean an
> approval of the main patch makes it OK to commit without the documentation
> - just as an approval of a patch known to break the build doesn't make it
> OK to commit until the later patches fixing the build are also approved,
> and the whole set squashed together for commit.

I prefer a separate small documentation patch since not everyone has
time to review a big patch.  But people may have time to review a small
documentation patch.  Still my small documentation patch got no review
in a month.

> Rather, I'd consider any approval of a patch whose documentation was split
> out to be implicitly conditional on the documentation also being approved
> and checked in at the same time (even if not in the same commit), to
> ensure we keep the invariant of features in glibc being documented in
> glibc.  For an approval to be valid without the documentation patch I
> think it would need to say so explicitly, and explain why - and take extra
> care to ensure there really is consensus for such a deviation from the
> normal rules on documenting new features.  (Just as, exceptionally, a
> patch known to break some architecture might be approved for commit, if
> there is no active architecture maintainer for the problem architecture
> and that architecture is likely to be obsoleted.)
>
>> Here is a patch to test mixing CET executables and non-CET libraries:
>>
>> https://sourceware.org/ml/libc-alpha/2018-07/msg00526.html
>
> Could you please give a detailed description of the testing you have run
> for the CET changes in general?
>
> The *minimum* for any nontrivial patch submission to glibc code should be
> a statement of the platform for which the glibc testsuite was run, or
> description of other testing done (and if we receive patch submissions
> that don't state even that, we should ask for it).  In the case of CET, a
> complicated feature with multiple configurations involved, and
> dependencies on hardware and kernel support, I'd expect a rather more
> extended discussion, maybe a few paragraphs, of the different cases tested
> and what those tests actually cover.  I'd guess those cases include
> various combinations of:
>
> * i686, x86_64 and x32 glibc builds.
>
> * glibc builds with and without --enable-cet.
>
> * Tests run on kernels both with and without CET support.
>
> * Tests run on both CET and non-CET hardware (or simulators for such
> hardware).
>
> But that needs a proper explanation, posted to the libc-alpha list, of
> what you did actually test (and each subsequent patch submission should
> have such an explanation, of what was tested for that patch) - and, as I
> said, of to what extent that really covers the functionality of the code.
>

All my CET changes have been tested with glibc "make check" and "make xcheck":

1. On non-CET processors under non-CET kernel:
    a.  With and without --enable-cet
    b.  For i686, x86_64 and x32.
2. On 64-bit CET SDV under CET kernel with --enable-cet
     a. Only x86_64 and x32 tested.
     b. i686 isn't tested since 64-bit CET SDV doesn't support i686.
3. scripts/build-many-glibcs.py on x86-64.


H.J.
  
Joseph Myers July 18, 2018, 9:16 p.m. UTC | #7
On Wed, 18 Jul 2018, H.J. Lu wrote:

> 2. On 64-bit CET SDV under CET kernel with --enable-cet
>      a. Only x86_64 and x32 tested.
>      b. i686 isn't tested since 64-bit CET SDV doesn't support i686.

So the key gap in test coverage is the lack of any evidence that the i686 
code does actually work on CET processors.  I think that at least merits a 
warning in the NEWS and install.texi entries about the unvalidated nature 
of the i686 CET support (which would be removed from install.texi at a 
later date once the i686 support has been validated, on a simulator or 
hardware, and any issues resolved).
  

Patch

From b100bb5197020c403bf53f26b94324d04e4a0d45 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Thu, 22 Jun 2017 04:15:39 -0700
Subject: [PATCH 03/24] 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.

To enable CET support in glibc, --enable-cet is required 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.  _dl_process_pt_note or
      _rtld_process_pt_note is called to process PT_NOTE segment for
      GNU program property and set l_cet.
   b. _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 run-time control can be changed via GLIBC_TUNABLES with

$ export GLIBC_TUNABLES=glibc.tune.x86_shstk=[permissive|on|off]
$ export GLIBC_TUNABLES=glibc.tune.x86_ibt=[permissive|on|off]

1. permissive: SHSTK is disabled when dlopening a legacy ELF module.
2. on: IBT or SHSTK are always enabled, regardless if there are IBT or
SHSTK bits in GNU program property.
3. off: IBT or SHSTK are always disabled, regardless if there are IBT or
SHSTK bits in GNU program property.

<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.  _CET_NOTRACK is used to
insert NOTRACK prefix with indirect jump table to support IBT.  It is
defined as notrack when _CET_NOTRACK is defined in <cet.h>.

	 [BZ #21598]
	* configure.ac: Add --enable-cet.
	* configure: Regenerated.
	* elf/Makefille (all-built-dso): Add a comment.
	* elf/dl-load.c (filebuf): Moved before "dynamic-link.h".
	Include <dl-prop.h>.
	(_dl_map_object_from_fd): Call _dl_process_pt_note on PT_NOTE
	segment.
	* elf/dl-open.c: Include <dl-prop.h>.
	(dl_open_worker): Call _dl_open_check.
	* elf/rtld.c: Include <dl-prop.h>.
	(dl_main): Call _rtld_process_pt_note on PT_NOTE segment.  Call
	_rtld_main_check.
	* sysdeps/generic/dl-prop.h: New file.
	* sysdeps/i386/dl-cet.c: Likewise.
	* sysdeps/unix/sysv/linux/x86/cpu-features.c: Likewise.
	* sysdeps/unix/sysv/linux/x86/dl-cet.h: Likewise.
	* sysdeps/x86/cet-tunables.h: Likewise.
	* sysdeps/x86/check-cet.awk: Likewise.
	* sysdeps/x86/configure: Likewise.
	* sysdeps/x86/configure.ac: Likewise.
	* sysdeps/x86/dl-cet.c: Likewise.
	* sysdeps/x86/dl-procruntime.c: Likewise.
	* sysdeps/x86/dl-prop.h: Likewise.
	* sysdeps/x86/libc-start.h: Likewise.
	* sysdeps/x86/link_map.h: Likewise.
	* 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/linux/x86/Makefile (sysdep-dl-routines): Add dl-cet
	if CET is enabled.
	(CFLAGS-.o): Add -fcf-protection if CET is enabled.
	(CFLAGS-.os): Likewise.
	(CFLAGS-.op): Likewise.
	(CFLAGS-.oS): Likewise.
	(asm-CPPFLAGS): Add -fcf-protection -include cet.h if CET
	is enabled.
	(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/cpu-features.c: Include <dl-cet.h> and
	<cet-tunables.h>.
	(TUNABLE_CALLBACK (set_x86_ibt)): New prototype.
	(TUNABLE_CALLBACK (set_x86_shstk)): Likewise.
	(init_cpu_features): Call get_cet_status to check CET status
	and update dl_x86_feature_1 with CET status.  Call
	TUNABLE_CALLBACK (set_x86_ibt) and TUNABLE_CALLBACK
	(set_x86_shstk).  Disable and lock CET in libc.a.
	* sysdeps/x86/cpu-tunables.c: Include <cet-tunables.h>.
	(TUNABLE_CALLBACK (set_x86_ibt)): New function.
	(TUNABLE_CALLBACK (set_x86_shstk)): Likewise.
	* sysdeps/x86/sysdep.h (_CET_NOTRACK): New.
	(_CET_ENDBR): Define if not defined.
	(ENTRY): Add _CET_ENDBR.
	* sysdeps/x86/dl-tunables.list (glibc.tune): Add x86_ibt and
	x86_shstk.
	* sysdeps/x86_64/dl-trampoline.h (_dl_runtime_resolve): Add
	_CET_ENDBR.
	(_dl_runtime_profile): Likewise.
---
 configure                                  |  11 +
 configure.ac                               |   6 +
 elf/Makefile                               |   2 +
 elf/dl-load.c                              |  60 ++--
 elf/dl-open.c                              |   3 +
 elf/rtld.c                                 |   9 +
 sysdeps/generic/dl-prop.h                  |  47 +++
 sysdeps/i386/dl-cet.c                      |  67 +++++
 sysdeps/i386/dl-trampoline.S               |  72 +++++
 sysdeps/unix/sysv/linux/x86/cpu-features.c |  38 +++
 sysdeps/unix/sysv/linux/x86/dl-cet.h       |  34 +++
 sysdeps/x86/Makefile                       |  42 +++
 sysdeps/x86/cet-tunables.h                 |  29 ++
 sysdeps/x86/check-cet.awk                  |  53 ++++
 sysdeps/x86/configure                      |  69 +++++
 sysdeps/x86/configure.ac                   |  46 +++
 sysdeps/x86/cpu-features.c                 |  60 ++++
 sysdeps/x86/cpu-tunables.c                 |  48 +++
 sysdeps/x86/dl-cet.c                       | 335 +++++++++++++++++++++
 sysdeps/x86/dl-procruntime.c               |  68 +++++
 sysdeps/x86/dl-prop.h                      | 153 ++++++++++
 sysdeps/x86/dl-tunables.list               |   6 +
 sysdeps/x86/libc-start.h                   |  25 ++
 sysdeps/x86/link_map.h                     |  26 ++
 sysdeps/x86/sysdep.h                       |   8 +
 sysdeps/x86_64/dl-trampoline.h             |   2 +
 26 files changed, 1294 insertions(+), 25 deletions(-)
 create mode 100644 sysdeps/generic/dl-prop.h
 create mode 100644 sysdeps/i386/dl-cet.c
 create mode 100644 sysdeps/unix/sysv/linux/x86/cpu-features.c
 create mode 100644 sysdeps/unix/sysv/linux/x86/dl-cet.h
 create mode 100644 sysdeps/x86/cet-tunables.h
 create mode 100644 sysdeps/x86/check-cet.awk
 create mode 100644 sysdeps/x86/configure
 create mode 100644 sysdeps/x86/configure.ac
 create mode 100644 sysdeps/x86/dl-cet.c
 create mode 100644 sysdeps/x86/dl-procruntime.c
 create mode 100644 sysdeps/x86/dl-prop.h
 create mode 100644 sysdeps/x86/libc-start.h
 create mode 100644 sysdeps/x86/link_map.h

diff --git a/configure b/configure
index eac7f292b4..fde57d63fe 100755
--- a/configure
+++ b/configure
@@ -790,6 +790,7 @@  enable_nscd
 enable_pt_chown
 enable_tunables
 enable_mathvec
+enable_cet
 with_cpu
 '
       ac_precious_vars='build_alias
@@ -1465,6 +1466,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]
@@ -3759,6 +3762,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=no
+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 f41ed6decb..014e09a5d5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -464,6 +464,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=no])
+
 # 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/Makefile b/elf/Makefile
index 41cc3681be..84107f6dbb 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -1058,6 +1058,8 @@  $(objpfx)tst-piemod1.so: $(libsupport)
 $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
 
 ifeq (yes,$(build-shared))
+# NB: Please keep cet-built-dso in sysdeps/x86/Makefile in sync with
+# all-built-dso here.
 all-built-dso := $(common-objpfx)elf/ld.so $(common-objpfx)libc.so \
 		 $(filter-out $(common-objpfx)linkobj/libc.so, \
 			      $(sort $(wildcard $(addprefix $(common-objpfx), \
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 09185ab68d..c51e4b3718 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>
@@ -44,6 +70,7 @@ 
 #include <dl-unmap-segments.h>
 #include <dl-machine-reject-phdr.h>
 #include <dl-sysdep-open.h>
+#include <dl-prop.h>
 #include <not-cancel.h>
 
 #include <endian.h>
@@ -69,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;
 
@@ -1152,6 +1154,14 @@  _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;
+
+	case PT_NOTE:
+	  if (_dl_process_pt_note (l, ph, fd, fbp))
+	    {
+	      errstring = N_("cannot process note segment");
+	      goto call_lose;
+	    }
+	  break;
 	}
 
     if (__glibc_unlikely (nloadcmds == 0))
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 9dde4acfbc..f6c8ef1043 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -35,6 +35,7 @@ 
 #include <libc-internal.h>
 
 #include <dl-dst.h>
+#include <dl-prop.h>
 
 
 /* We must be careful not to leave us in an inconsistent state.  Thus we
@@ -291,6 +292,8 @@  dl_open_worker (void *a)
   _dl_debug_state ();
   LIBC_PROBE (map_complete, 3, args->nsid, r, new);
 
+  _dl_open_check (new);
+
   /* 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 8c732adb68..1b0c74739f 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -38,6 +38,7 @@ 
 #include <dl-cache.h>
 #include <dl-osinfo.h>
 #include <dl-procinfo.h>
+#include <dl-prop.h>
 #include <tls.h>
 #include <stap-probe.h>
 #include <stackinfo.h>
@@ -1241,6 +1242,12 @@  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;
+
+      case PT_NOTE:
+	if (_rtld_process_pt_note (main_map, ph))
+	  _dl_error_printf ("\
+ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
+	break;
       }
 
   /* Adjust the address of the TLS initialization image in case
@@ -2110,6 +2117,8 @@  ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
 	_dl_show_scope (l, 0);
     }
 
+  _rtld_main_check (main_map, _dl_argv[0]);
+
   if (prelinked)
     {
       if (main_map->l_info [ADDRIDX (DT_GNU_CONFLICT)] != NULL)
diff --git a/sysdeps/generic/dl-prop.h b/sysdeps/generic/dl-prop.h
new file mode 100644
index 0000000000..e5fe5d23aa
--- /dev/null
+++ b/sysdeps/generic/dl-prop.h
@@ -0,0 +1,47 @@ 
+/* Support for GNU properties.  Generic version.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _DL_PROP_H
+#define _DL_PROP_H
+
+static inline void __attribute__ ((always_inline))
+_rtld_main_check (struct link_map *m, const char *program)
+{
+}
+
+static inline void __attribute__ ((always_inline))
+_dl_open_check (struct link_map *m)
+{
+}
+
+#ifdef FILEBUF_SIZE
+static inline int __attribute__ ((always_inline))
+_dl_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph,
+		     int fd, struct filebuf *fbp)
+{
+  return 0;
+}
+#endif
+
+static inline int __attribute__ ((always_inline))
+_rtld_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph)
+{
+  return 0;
+}
+
+#endif /* _DL_PROP_H */
diff --git a/sysdeps/i386/dl-cet.c b/sysdeps/i386/dl-cet.c
new file mode 100644
index 0000000000..5d9a4e8d51
--- /dev/null
+++ b/sysdeps/i386/dl-cet.c
@@ -0,0 +1,67 @@ 
+/* Linux/i386 CET initializers function.
+   Copyright (C) 2018 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/>.  */
+
+
+#define LINKAGE static inline
+#define _dl_cet_check cet_check
+#include <sysdeps/x86/dl-cet.c>
+#undef _dl_cet_check
+
+#ifdef SHARED
+void
+_dl_cet_check (struct link_map *main_map, const char *program)
+{
+  cet_check (main_map, program);
+
+  if ((GL(dl_x86_feature_1)[0] & 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/i386/dl-trampoline.S b/sysdeps/i386/dl-trampoline.S
index 8bf86f8fd9..6dc0319216 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/x86/cpu-features.c b/sysdeps/unix/sysv/linux/x86/cpu-features.c
new file mode 100644
index 0000000000..0045f979da
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/cpu-features.c
@@ -0,0 +1,38 @@ 
+/* Initialize CPU feature data for Linux/x86.
+   This file is part of the GNU C Library.
+   Copyright (C) 2018 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 __CET__
+static inline int __attribute__ ((always_inline))
+get_cet_status (void)
+{
+  return 0;
+}
+
+# ifndef SHARED
+static inline void
+x86_setup_tls (void)
+{
+  __libc_setup_tls ();
+  THREAD_SETMEM (THREAD_SELF, header.feature_1, GL(dl_x86_feature_1)[0]);
+}
+
+#  define ARCH_SETUP_TLS() x86_setup_tls ()
+# endif
+#endif
+
+#include <sysdeps/x86/cpu-features.c>
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 0000000000..9903bbe41f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/dl-cet.h
@@ -0,0 +1,34 @@ 
+/* Linux/x86 CET initializers function.
+   Copyright (C) 2018 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/>.  */
+
+static inline int __attribute__ ((always_inline))
+dl_cet_allocate_legacy_bitmap (unsigned long *legacy_bitmap)
+{
+  return -1;
+}
+
+static inline int __attribute__ ((always_inline))
+dl_cet_disable_cet (unsigned int cet_feature)
+{
+  return -1;
+}
+
+static inline int __attribute__ ((always_inline))
+dl_cet_lock_cet (void)
+{
+  return -1;
+}
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
index 65292f4032..e9b2d0b35d 100644
--- a/sysdeps/x86/Makefile
+++ b/sysdeps/x86/Makefile
@@ -13,3 +13,45 @@  ifeq ($(subdir),setjmp)
 gen-as-const-headers += jmp_buf-ssp.sym
 sysdep_routines += __longjmp_cancel
 endif
+
+ifeq ($(enable-cet),yes)
+ifeq ($(subdir),elf)
+sysdep-dl-routines += dl-cet
+endif
+
+# Add -fcf-protection to CFLAGS when CET is enabled.
+CFLAGS-.o += -fcf-protection
+CFLAGS-.os += -fcf-protection
+CFLAGS-.op += -fcf-protection
+CFLAGS-.oS += -fcf-protection
+
+# Compile assembly codes with <cet.h> when CET is enabled.
+asm-CPPFLAGS += -fcf-protection -include cet.h
+
+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/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/x86/cet-tunables.h b/sysdeps/x86/cet-tunables.h
new file mode 100644
index 0000000000..ca023053ee
--- /dev/null
+++ b/sysdeps/x86/cet-tunables.h
@@ -0,0 +1,29 @@ 
+/* x86 CET tuning.
+   This file is part of the GNU C Library.
+   Copyright (C) 2018 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/>.  */
+
+/* Valid control values:
+   0: Enable CET features based on ELF property note.
+   1: Always disable CET features.
+   2: Always enable CET features.
+   3: Enable CET features permissively.
+ */
+#define CET_ELF_PROPERTY	0
+#define CET_ALWAYS_OFF		1
+#define CET_ALWAYS_ON		2
+#define CET_PERMISSIVE		3
+#define CET_MAX			CET_PERMISSIVE
diff --git a/sysdeps/x86/check-cet.awk b/sysdeps/x86/check-cet.awk
new file mode 100644
index 0000000000..380d998caf
--- /dev/null
+++ b/sysdeps/x86/check-cet.awk
@@ -0,0 +1,53 @@ 
+# Verify that all shared objects contain the CET property.
+# Copyright (C) 2018 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+#
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+
+# 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/x86/configure b/sysdeps/x86/configure
new file mode 100644
index 0000000000..b1ff281249
--- /dev/null
+++ b/sysdeps/x86/configure
@@ -0,0 +1,69 @@ 
+# This file is generated from configure.ac by Autoconf.  DO NOT EDIT!
+ # Local configure fragment for sysdeps/x86.
+
+if 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 __CET__ || __CET__ != 3
+# error CET isn't available.
+#endif
+EOF
+		 if { ac_try='${CC-cc} -c $CFLAGS -fcf-protection -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
+fi
+config_vars="$config_vars
+enable-cet = $enable_cet"
diff --git a/sysdeps/x86/configure.ac b/sysdeps/x86/configure.ac
new file mode 100644
index 0000000000..a909b073af
--- /dev/null
+++ b/sysdeps/x86/configure.ac
@@ -0,0 +1,46 @@ 
+GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
+# Local configure fragment for sysdeps/x86.
+
+if 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 __CET__ || __CET__ != 3
+# error CET isn't available.
+#endif
+EOF
+		 if AC_TRY_COMMAND(${CC-cc} -c $CFLAGS -fcf-protection -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
+fi
+LIBC_CONFIG_VAR([enable-cet], [$enable_cet])
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
index d41ebde823..f52e28e04b 100644
--- a/sysdeps/x86/cpu-features.c
+++ b/sysdeps/x86/cpu-features.c
@@ -28,6 +28,15 @@ 
 
 extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *)
   attribute_hidden;
+
+# ifdef __CET__
+#  include <dl-cet.h>
+#  include <cet-tunables.h>
+extern void TUNABLE_CALLBACK (set_x86_ibt) (tunable_val_t *)
+  attribute_hidden;
+extern void TUNABLE_CALLBACK (set_x86_shstk) (tunable_val_t *)
+  attribute_hidden;
+# endif
 #endif
 
 static void
@@ -449,4 +458,55 @@  no_cpuid:
   else if (CPU_FEATURES_ARCH_P (cpu_features, I586))
     GLRO(dl_platform) = "i586";
 #endif
+
+#ifdef __CET__
+# if HAVE_TUNABLES
+  TUNABLE_GET (x86_ibt, tunable_val_t *,
+	       TUNABLE_CALLBACK (set_x86_ibt));
+  TUNABLE_GET (x86_shstk, tunable_val_t *,
+	       TUNABLE_CALLBACK (set_x86_shstk));
+# endif
+
+  /* Check CET status.  */
+  unsigned int cet_status = get_cet_status ();
+
+  if (cet_status)
+    {
+      GL(dl_x86_feature_1)[0] = cet_status;
+
+# ifndef SHARED
+      /* Check if IBT and SHSTK are enabled by kernel.  */
+      if ((cet_status & GNU_PROPERTY_X86_FEATURE_1_IBT)
+	  || (cet_status & GNU_PROPERTY_X86_FEATURE_1_SHSTK))
+	{
+	  /* Disable IBT and/or SHSTK if they are enabled by kernel, but
+	     disabled by environment variable:
+
+	     GLIBC_TUNABLES=glibc.tune.hwcaps=-IBT,-SHSTK
+	   */
+	  unsigned int cet_feature = 0;
+	  if (!HAS_CPU_FEATURE (IBT))
+	    cet_feature |= GNU_PROPERTY_X86_FEATURE_1_IBT;
+	  if (!HAS_CPU_FEATURE (SHSTK))
+	    cet_feature |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
+
+	  if (cet_feature)
+	    {
+	      int res = dl_cet_disable_cet (cet_feature);
+
+	      /* Clear the disabled bits in dl_x86_feature_1.  */
+	      if (res == 0)
+		GL(dl_x86_feature_1)[0] &= ~cet_feature;
+	    }
+
+	  /* Lock CET if IBT or SHSTK is enabled in executable.  Don't
+	     lock CET if SHSTK is enabled permissively.  */
+	  if (((GL(dl_x86_feature_1)[1] >> CET_MAX)
+	       & ((1 << CET_MAX) - 1))
+	       != CET_PERMISSIVE)
+	    dl_cet_lock_cet ();
+	}
+# endif
+    }
+#endif
 }
diff --git a/sysdeps/x86/cpu-tunables.c b/sysdeps/x86/cpu-tunables.c
index af761dcbbc..a5c0153348 100644
--- a/sysdeps/x86/cpu-tunables.c
+++ b/sysdeps/x86/cpu-tunables.c
@@ -334,4 +334,52 @@  TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
     }
   while (*p != '\0');
 }
+
+# ifdef __CET__
+#  include <cet-tunables.h>
+
+attribute_hidden
+void
+TUNABLE_CALLBACK (set_x86_ibt) (tunable_val_t *valp)
+{
+  if (DEFAULT_MEMCMP (valp->strval, "on", sizeof ("on")) == 0)
+    {
+      GL(dl_x86_feature_1)[1] &= ~((1 << CET_MAX) - 1);
+      GL(dl_x86_feature_1)[1] |= CET_ALWAYS_ON;
+    }
+  else if (DEFAULT_MEMCMP (valp->strval, "off", sizeof ("off")) == 0)
+    {
+      GL(dl_x86_feature_1)[1] &= ~((1 << CET_MAX) - 1);
+      GL(dl_x86_feature_1)[1] |= CET_ALWAYS_OFF;
+    }
+  else if (DEFAULT_MEMCMP (valp->strval, "permissive",
+			   sizeof ("permissive")) == 0)
+    {
+      GL(dl_x86_feature_1)[1] &= ~((1 << CET_MAX) - 1);
+      GL(dl_x86_feature_1)[1] |= CET_PERMISSIVE;
+    }
+}
+
+attribute_hidden
+void
+TUNABLE_CALLBACK (set_x86_shstk) (tunable_val_t *valp)
+{
+  if (DEFAULT_MEMCMP (valp->strval, "on", sizeof ("on")) == 0)
+    {
+      GL(dl_x86_feature_1)[1] &= ~(((1 << CET_MAX) - 1) << CET_MAX);
+      GL(dl_x86_feature_1)[1] |= (CET_ALWAYS_ON << CET_MAX);
+    }
+  else if (DEFAULT_MEMCMP (valp->strval, "off", sizeof ("off")) == 0)
+    {
+      GL(dl_x86_feature_1)[1] &= ~(((1 << CET_MAX) - 1) << CET_MAX);
+      GL(dl_x86_feature_1)[1] |= (CET_ALWAYS_OFF << CET_MAX);
+    }
+  else if (DEFAULT_MEMCMP (valp->strval, "permissive",
+			   sizeof ("permissive")) == 0)
+    {
+      GL(dl_x86_feature_1)[1] &= ~(((1 << CET_MAX) - 1) << CET_MAX);
+      GL(dl_x86_feature_1)[1] |= (CET_PERMISSIVE << CET_MAX);
+    }
+}
+# endif
 #endif
diff --git a/sysdeps/x86/dl-cet.c b/sysdeps/x86/dl-cet.c
new file mode 100644
index 0000000000..5018e4560d
--- /dev/null
+++ b/sysdeps/x86/dl-cet.c
@@ -0,0 +1,335 @@ 
+/* x86 CET initializers function.
+   Copyright (C) 2018 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/>.  */
+
+#include <unistd.h>
+#include <errno.h>
+#include <libintl.h>
+#include <ldsodefs.h>
+#include <dl-cet.h>
+#include <cet-tunables.h>
+
+static int
+dl_cet_mark_legacy_region (struct link_map *l)
+{
+  /* Mark PT_LOAD segments with PF_X in legacy code page bitmap.  */
+  size_t i, phnum = l->l_phnum;
+  const ElfW(Phdr) *phdr = l->l_phdr;
+#ifdef __x86_64__
+  typedef unsigned long long word_t;
+#else
+  typedef unsigned long word_t;
+#endif
+  unsigned int bits_to_set;
+  word_t mask_to_set;
+#define BITS_PER_WORD (sizeof (word_t) * 8)
+#define BITMAP_FIRST_WORD_MASK(start) \
+  (~((word_t) 0) << ((start) & (BITS_PER_WORD - 1)))
+#define BITMAP_LAST_WORD_MASK(nbits) \
+  (~((word_t) 0) >> (-(nbits) & (BITS_PER_WORD - 1)))
+
+  word_t *bitmap = (word_t *) GL(dl_x86_legacy_bitmap)[0];
+  word_t bitmap_size = GL(dl_x86_legacy_bitmap)[1];
+  word_t *p;
+  size_t page_size = GLRO(dl_pagesize);
+
+  for (i = 0; i < phnum; i++)
+    if (phdr[i].p_type == PT_LOAD && (phdr[i].p_flags & PF_X))
+      {
+	/* One bit in legacy bitmap represents a page.  */
+	ElfW(Addr) start = (phdr[i].p_vaddr + l->l_addr) / page_size;
+	ElfW(Addr) len = (phdr[i].p_memsz + page_size - 1) / page_size;
+	ElfW(Addr) end = start + len;
+
+	if ((end / 8) > bitmap_size)
+	  return -EFAULT;
+
+	p = bitmap + (start / BITS_PER_WORD);
+	bits_to_set = BITS_PER_WORD - (start % BITS_PER_WORD);
+	mask_to_set = BITMAP_FIRST_WORD_MASK (start);
+
+	while (len >= bits_to_set)
+	  {
+	    *p |= mask_to_set;
+	    len -= bits_to_set;
+	    bits_to_set = BITS_PER_WORD;
+	    mask_to_set = ~((word_t) 0);
+	    p++;
+	  }
+	if (len)
+	  {
+	    mask_to_set &= BITMAP_LAST_WORD_MASK (end);
+	    *p |= mask_to_set;
+	  }
+      }
+
+  return 0;
+}
+
+/* Check if object M is compatible with CET.  */
+
+static void
+dl_cet_check (struct link_map *m, const char *program)
+{
+  /* Check how IBT should be enabled.  */
+  unsigned int enable_ibt_type
+    = GL(dl_x86_feature_1)[1] & ((1 << CET_MAX) - 1);
+  /* Check how SHSTK should be enabled.  */
+  unsigned int enable_shstk_type
+    = ((GL(dl_x86_feature_1)[1] >> CET_MAX) & ((1 << CET_MAX) - 1));
+
+  /* No legacy object check if both IBT and SHSTK are always on.  */
+  if (enable_ibt_type == CET_ALWAYS_ON
+      && enable_shstk_type == CET_ALWAYS_ON)
+    return;
+
+  /* Check if IBT is enabled by kernel.  */
+  bool ibt_enabled
+    = (GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0;
+  /* Check if SHSTK is enabled by kernel.  */
+  bool shstk_enabled
+    = (GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0;
+
+  if (ibt_enabled || shstk_enabled)
+    {
+      struct link_map *l = NULL;
+
+      /* Check if IBT and SHSTK are enabled in object.  */
+      bool enable_ibt = (ibt_enabled
+			 && enable_ibt_type != CET_ALWAYS_OFF);
+      bool enable_shstk = (shstk_enabled
+			   && enable_shstk_type != CET_ALWAYS_OFF);
+      if (program)
+	{
+	  /* Enable IBT and SHSTK only if they are enabled in executable.
+	     NB: IBT and SHSTK may be disabled by environment variable:
+
+	     GLIBC_TUNABLES=glibc.tune.hwcaps=-IBT,-SHSTK
+	   */
+	  enable_ibt &= (HAS_CPU_FEATURE (IBT)
+			 && (enable_ibt_type == CET_ALWAYS_ON
+			     || (m->l_cet & lc_ibt) != 0));
+	  enable_shstk &= (HAS_CPU_FEATURE (SHSTK)
+			   && (enable_shstk_type == CET_ALWAYS_ON
+			       || (m->l_cet & lc_shstk) != 0));
+	}
+
+      /* ld.so is CET-enabled by kernel.  But shared objects may not
+	 support IBT nor SHSTK.  */
+      if (enable_ibt || enable_shstk)
+	{
+	  int res;
+	  unsigned int i;
+	  unsigned int first_legacy, last_legacy;
+	  bool need_legacy_bitmap = false;
+
+	  i = m->l_searchlist.r_nlist;
+	  while (i-- > 0)
+	    {
+	      /* Check each shared object to see if IBT and SHSTK are
+		 enabled.  */
+	      l = m->l_initfini[i];
+
+	      if (l->l_init_called)
+		continue;
+
+#ifdef SHARED
+	      /* Skip CET check for ld.so since ld.so is CET-enabled.
+		 CET will be disabled later if CET isn't enabled in
+		 executable.  */
+	      if (l == &GL(dl_rtld_map)
+		  ||  l->l_real == &GL(dl_rtld_map)
+		  || (program && l == m))
+		continue;
+#endif
+
+	      if (enable_ibt
+		  && enable_ibt_type != CET_ALWAYS_ON
+		  && !(l->l_cet & lc_ibt))
+		{
+		  /* Remember the first and last legacy objects.  */
+		  if (!need_legacy_bitmap)
+		    last_legacy = i;
+		  first_legacy = i;
+		  need_legacy_bitmap = true;
+		}
+
+	      /* SHSTK is enabled only if it is enabled in executable as
+		 well as all shared objects.  */
+	      enable_shstk &= (enable_shstk_type == CET_ALWAYS_ON
+			       || (l->l_cet & lc_shstk) != 0);
+	    }
+
+	  if (need_legacy_bitmap)
+	    {
+	      if (GL(dl_x86_legacy_bitmap)[0])
+		{
+		  /* Change legacy bitmap to writable.  */
+		  if (__mprotect ((void *) GL(dl_x86_legacy_bitmap)[0],
+				  GL(dl_x86_legacy_bitmap)[1],
+				  PROT_READ | PROT_WRITE) < 0)
+		    {
+mprotect_failure:
+		      if (program)
+			_dl_fatal_printf ("%s: mprotect legacy bitmap failed\n",
+					  l->l_name);
+		      else
+			_dl_signal_error (EINVAL, l->l_name, "dlopen",
+					  N_("mprotect legacy bitmap failed"));
+		    }
+		}
+	      else
+		{
+		  /* Allocate legacy bitmap.  */
+		  int res = dl_cet_allocate_legacy_bitmap
+		    (GL(dl_x86_legacy_bitmap));
+		  if (res != 0)
+		    {
+		      if (program)
+			_dl_fatal_printf ("%s: legacy bitmap isn't available\n",
+					  l->l_name);
+		      else
+			_dl_signal_error (EINVAL, l->l_name, "dlopen",
+					  N_("legacy bitmap isn't available"));
+		    }
+		}
+
+	      /* Put legacy shared objects in legacy bitmap.  */
+	      for (i = first_legacy; i <= last_legacy; i++)
+		{
+		  l = m->l_initfini[i];
+
+		  if (l->l_init_called || (l->l_cet & lc_ibt))
+		    continue;
+
+#ifdef SHARED
+		  if (l == &GL(dl_rtld_map)
+		      ||  l->l_real == &GL(dl_rtld_map)
+		      || (program && l == m))
+		    continue;
+#endif
+
+		  /* If IBT is enabled in executable and IBT isn't enabled
+		     in this shard object, mark PT_LOAD segments with PF_X
+		     in legacy code page bitmap.  */
+		  res = dl_cet_mark_legacy_region (l);
+		  if (res != 0)
+		    {
+		      if (program)
+			_dl_fatal_printf ("%s: fail to mark legacy code region\n",
+					  l->l_name);
+		      else
+			_dl_signal_error (-res, l->l_name, "dlopen",
+					  N_("fail to mark legacy code region"));
+		    }
+		}
+
+	      /* Change legacy bitmap to read-only.  */
+	      if (__mprotect ((void *) GL(dl_x86_legacy_bitmap)[0],
+			      GL(dl_x86_legacy_bitmap)[1], PROT_READ) < 0)
+		goto mprotect_failure;
+	    }
+	}
+
+      bool cet_feature_changed = false;
+
+      if (enable_ibt != ibt_enabled || enable_shstk != shstk_enabled)
+	{
+	  if (!program
+	      && enable_shstk_type != CET_PERMISSIVE)
+	    {
+	      /* When SHSTK is enabled, we can't dlopening a shared
+		 object without SHSTK.  */
+	      if (enable_shstk != shstk_enabled)
+		_dl_signal_error (EINVAL, l->l_name, "dlopen",
+				  N_("shadow stack isn't enabled"));
+	      return;
+	    }
+
+	  /* Disable IBT and/or SHSTK if they are enabled by kernel, but
+	     disabled in executable or shared objects.  */
+	  unsigned int cet_feature = 0;
+
+	  /* Disable IBT only during program startup.  */
+	  if (program && !enable_ibt)
+	    cet_feature |= GNU_PROPERTY_X86_FEATURE_1_IBT;
+	  if (!enable_shstk)
+	    cet_feature |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
+
+	  int res = dl_cet_disable_cet (cet_feature);
+	  if (res != 0)
+	    {
+	      if (program)
+		_dl_fatal_printf ("%s: can't disable CET\n", program);
+	      else
+		_dl_signal_error (-res, l->l_name, "dlopen",
+				  N_("can't disable CET"));
+	    }
+
+	  /* Clear the disabled bits in dl_x86_feature_1.  */
+	  GL(dl_x86_feature_1)[0] &= ~cet_feature;
+
+	  cet_feature_changed = true;
+	}
+
+#ifdef SHARED
+      if (program
+	  && (!shstk_enabled
+	      || enable_shstk_type != CET_PERMISSIVE)
+	  && (ibt_enabled || shstk_enabled))
+	{
+	  /* Lock CET if IBT or SHSTK is enabled in executable.  Don't
+	     lock CET if SHSTK is enabled permissively.  */
+	  int res = dl_cet_lock_cet ();
+	  if (res != 0)
+	    _dl_fatal_printf ("%s: can't lock CET\n", program);
+
+	  cet_feature_changed = true;
+	}
+#endif
+
+      if (cet_feature_changed)
+	{
+	  unsigned int feature_1 = 0;
+	  if (enable_ibt)
+	    feature_1 |= GNU_PROPERTY_X86_FEATURE_1_IBT;
+	  if (enable_shstk)
+	    feature_1 |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
+	  struct pthread *self = THREAD_SELF;
+	  THREAD_SETMEM (self, header.feature_1, feature_1);
+	}
+    }
+}
+
+void
+_dl_cet_open_check (struct link_map *l)
+{
+  dl_cet_check (l, NULL);
+}
+
+#ifdef SHARED
+
+# ifndef LINKAGE
+#  define LINKAGE
+# endif
+
+LINKAGE
+void
+_dl_cet_check (struct link_map *main_map, const char *program)
+{
+  dl_cet_check (main_map, program);
+}
+#endif /* SHARED */
diff --git a/sysdeps/x86/dl-procruntime.c b/sysdeps/x86/dl-procruntime.c
new file mode 100644
index 0000000000..eddbde6a31
--- /dev/null
+++ b/sysdeps/x86/dl-procruntime.c
@@ -0,0 +1,68 @@ 
+/* Data for processor runtime information.  x86 version.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <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[2]
+# endif
+# if !defined SHARED || defined PROCINFO_DECL
+;
+# else
+,
+# endif
+
+# if !defined PROCINFO_DECL && defined SHARED
+  ._dl_x86_legacy_bitmap
+# else
+PROCINFO_CLASS unsigned long _dl_x86_legacy_bitmap[2]
+# endif
+# if !defined SHARED || defined PROCINFO_DECL
+;
+# else
+,
+# endif
+#endif
diff --git a/sysdeps/x86/dl-prop.h b/sysdeps/x86/dl-prop.h
new file mode 100644
index 0000000000..2709fe852d
--- /dev/null
+++ b/sysdeps/x86/dl-prop.h
@@ -0,0 +1,153 @@ 
+/* Support for GNU properties.  x86 version.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _DL_PROP_H
+#define _DL_PROP_H
+
+#include <not-cancel.h>
+
+extern void _dl_cet_check (struct link_map *, const char *)
+    attribute_hidden;
+extern void _dl_cet_open_check (struct link_map *)
+    attribute_hidden;
+
+static inline void __attribute__ ((always_inline))
+_rtld_main_check (struct link_map *m, const char *program)
+{
+#ifdef __CET__
+  _dl_cet_check (m, program);
+#endif
+}
+
+static inline void __attribute__ ((always_inline))
+_dl_open_check (struct link_map *m)
+{
+#ifdef __CET__
+  _dl_cet_open_check (m);
+#endif
+}
+
+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)
+{
+#ifdef __CET__
+  /* 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));
+    }
+#endif
+}
+
+#ifdef FILEBUF_SIZE
+static inline int __attribute__ ((unused))
+_dl_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph,
+		     int fd, struct filebuf *fbp)
+{
+# ifdef __CET__
+  const ElfW(Nhdr) *note;
+  ElfW(Nhdr) *note_malloced = NULL;
+  ElfW(Addr) size = ph->p_filesz;
+
+  if (ph->p_offset + size <= (size_t) fbp->len)
+    note = (const void *) (fbp->buf + ph->p_offset);
+  else
+    {
+      if (size < __MAX_ALLOCA_CUTOFF)
+	note = alloca (size);
+      else
+	{
+	  note_malloced = malloc (size);
+	  note = note_malloced;
+	}
+      __lseek (fd, ph->p_offset, SEEK_SET);
+      if (__read_nocancel (fd, (void *) note, size) != size)
+	{
+	  if (note_malloced)
+	    free (note_malloced);
+	  return -1;
+	}
+    }
+
+  _dl_process_cet_property_note (l, note, size, ph->p_align);
+  if (note_malloced)
+    free (note_malloced);
+# endif
+  return 0;
+}
+#endif
+
+static inline int __attribute__ ((unused))
+_rtld_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 /* _DL_PROP_H */
diff --git a/sysdeps/x86/dl-tunables.list b/sysdeps/x86/dl-tunables.list
index 7c3236a68f..73886b1352 100644
--- a/sysdeps/x86/dl-tunables.list
+++ b/sysdeps/x86/dl-tunables.list
@@ -21,6 +21,12 @@  glibc {
     hwcaps {
       type: STRING
     }
+    x86_ibt {
+      type: STRING
+    }
+    x86_shstk {
+      type: STRING
+    }
     x86_non_temporal_threshold {
       type: SIZE_T
     }
diff --git a/sysdeps/x86/libc-start.h b/sysdeps/x86/libc-start.h
new file mode 100644
index 0000000000..6f44262bf4
--- /dev/null
+++ b/sysdeps/x86/libc-start.h
@@ -0,0 +1,25 @@ 
+/* X86 definitions for libc main startup.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef SHARED
+# define ARCH_SETUP_IREL() apply_irel ()
+# define ARCH_APPLY_IREL()
+# ifndef ARCH_SETUP_TLS
+#  define ARCH_SETUP_TLS() __libc_setup_tls ()
+# endif
+#endif /* !SHARED */
diff --git a/sysdeps/x86/link_map.h b/sysdeps/x86/link_map.h
new file mode 100644
index 0000000000..ef1206a9d2
--- /dev/null
+++ b/sysdeps/x86/link_map.h
@@ -0,0 +1,26 @@ 
+/* Additional fields in struct link_map.  Linux/x86 version.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <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/x86/sysdep.h b/sysdeps/x86/sysdep.h
index afcb7cfd76..9843d9dff7 100644
--- a/sysdeps/x86/sysdep.h
+++ b/sysdeps/x86/sysdep.h
@@ -25,6 +25,13 @@ 
 
 /* Syntactic details of assembler.  */
 
+#ifdef _CET_ENDBR
+# define _CET_NOTRACK notrack
+#else
+# define _CET_ENDBR
+# define _CET_NOTRACK
+#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 +43,7 @@ 
   .align ALIGNARG(4);							      \
   C_LABEL(name)								      \
   cfi_startproc;							      \
+  _CET_ENDBR;								      \
   CALL_MCOUNT
 
 #undef	END
diff --git a/sysdeps/x86_64/dl-trampoline.h b/sysdeps/x86_64/dl-trampoline.h
index 298cfb3d99..a28b1e73a4 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
-- 
2.17.1