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

login
register
mail settings
Submitter H.J. Lu
Date June 13, 2018, 3:31 p.m.
Message ID <20180613153207.57232-4-hjl.tools@gmail.com>
Download mbox | patch
Permalink /patch/27791/
State New
Headers show

Comments

H.J. Lu - June 13, 2018, 3:31 p.m.
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.  The optional DL_PROCESS_PT_NOTE
      is called to process PT_NOTE segment for GNU program property and
      set l_cet.
   b. _dl_start_user calls _dl_cet_init, instead of _dl_init, which sets
      up IBT and SHSTK.
   c. DL_OPEN_CHECK is added to check IBT and SHSTK compatibilty when
      dlopening a shared object.
3. Replace i386 _dl_runtime_resolve and _dl_runtime_profile with
_dl_runtime_resolve_shstk and _dl_runtime_profile_shstk, respectively if
SHSTK is enabled.

<cet.h> from CET-enabled GCC is automatically included by assembly codes
to add GNU_PROPERTY_X86_FEATURE_1_IBT and GNU_PROPERTY_X86_FEATURE_1_SHSTK
to GNU program property.  _CET_ENDBR is added at the entrance of all
assembly functions whose address may be taken.  _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/dl-load.c (filebuf): Moved before "dynamic-link.h".
	(_dl_map_object_from_fd): Call DL_PROCESS_PT_NOTE on PT_NOTE
	segment if DL_PROCESS_PT_NOTE is defined.
	* elf/rtld.c (dl_main): Call DL_PROCESS_PT_NOTE on PT_NOTE
	segment if DL_PROCESS_PT_NOTE is defined.  Call DL_MAIN_CHECK
	if DL_MAIN_CHECK is defined.
	* elf/dl-open.c (dl_open_worker): Call DL_OPEN_CHECK if it is
	defined.
	* sysdeps/unix/sysv/linux/i386/dl-cet.c: New file.
	* sysdeps/unix/sysv/linux/i386/dl-machine.h: Likewise.
	* sysdeps/unix/sysv/linux/x86/check-cet.awk: Likewise.
	* sysdeps/unix/sysv/linux/x86/configure: Likewise.
	* sysdeps/unix/sysv/linux/x86/configure.ac: Likewise.
	* sysdeps/unix/sysv/linux/x86/dl-cet.c: Likewise.
	* sysdeps/unix/sysv/linux/x86/dl-cet.h: Likewise.
	* sysdeps/unix/sysv/linux/x86/dl-procruntime.c: Likewise.
	* sysdeps/unix/sysv/linux/x86/ldsodefs.h: Likewise.
	* sysdeps/unix/sysv/linux/x86/link_map.h: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/dl-machine.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/unix/sysv/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/sysdep.h (_CET_NOTRACK): New.
	(_CET_ENDBR): Define if not defined.
	(ENTRY): Add _CET_ENDBR.
	* sysdeps/x86_64/dl-trampoline.h (_dl_runtime_resolve): Add
	_CET_ENDBR.
	(_dl_runtime_profile): Likewise.
---
 configure                                    |  11 ++
 configure.ac                                 |   6 +
 elf/dl-load.c                                |  61 +++---
 elf/dl-open.c                                |   4 +
 elf/rtld.c                                   |  12 ++
 sysdeps/i386/dl-trampoline.S                 |  72 +++++++
 sysdeps/unix/sysv/linux/i386/dl-cet.c        |  67 +++++++
 sysdeps/unix/sysv/linux/i386/dl-machine.h    |  23 +++
 sysdeps/unix/sysv/linux/x86/Makefile         |  42 +++++
 sysdeps/unix/sysv/linux/x86/check-cet.awk    |  53 ++++++
 sysdeps/unix/sysv/linux/x86/configure        |  69 +++++++
 sysdeps/unix/sysv/linux/x86/configure.ac     |  46 +++++
 sysdeps/unix/sysv/linux/x86/dl-cet.c         | 186 +++++++++++++++++++
 sysdeps/unix/sysv/linux/x86/dl-cet.h         | 138 ++++++++++++++
 sysdeps/unix/sysv/linux/x86/dl-procruntime.c |  57 ++++++
 sysdeps/unix/sysv/linux/x86/ldsodefs.h       |  29 +++
 sysdeps/unix/sysv/linux/x86/link_map.h       |  26 +++
 sysdeps/unix/sysv/linux/x86_64/dl-machine.h  |  27 +++
 sysdeps/x86/cpu-features.h                   |   5 +
 sysdeps/x86/sysdep.h                         |   8 +
 sysdeps/x86_64/dl-trampoline.h               |   2 +
 21 files changed, 919 insertions(+), 25 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/i386/dl-cet.c
 create mode 100644 sysdeps/unix/sysv/linux/i386/dl-machine.h
 create mode 100644 sysdeps/unix/sysv/linux/x86/check-cet.awk
 create mode 100644 sysdeps/unix/sysv/linux/x86/configure
 create mode 100644 sysdeps/unix/sysv/linux/x86/configure.ac
 create mode 100644 sysdeps/unix/sysv/linux/x86/dl-cet.c
 create mode 100644 sysdeps/unix/sysv/linux/x86/dl-cet.h
 create mode 100644 sysdeps/unix/sysv/linux/x86/dl-procruntime.c
 create mode 100644 sysdeps/unix/sysv/linux/x86/ldsodefs.h
 create mode 100644 sysdeps/unix/sysv/linux/x86/link_map.h
 create mode 100644 sysdeps/unix/sysv/linux/x86_64/dl-machine.h
Carlos O'Donell - July 6, 2018, 7:47 p.m.
On 06/13/2018 11:31 AM, H.J. Lu wrote:
> Intel Control-flow Enforcement Technology (CET) instructions:

Reviewed.

Looking forward to v2.

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

OK.

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

OK.

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

OK.

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

OK.

> 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. Good a configure-time error is best here.

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

OK.

> 2. For dynamic executables:
>    a. A l_cet field is added to struct link_map to indicate if IBT or
>       SHSTK is enabled in an ELF module.  The optional DL_PROCESS_PT_NOTE
>       is called to process PT_NOTE segment for GNU program property and
>       set l_cet.

OK.

>    b. _dl_start_user calls _dl_cet_init, instead of _dl_init, which sets
>       up IBT and SHSTK.

OK.

>    c. DL_OPEN_CHECK is added to check IBT and SHSTK compatibilty when
>       dlopening a shared object.

OK.

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

OK.

> 	 [BZ #21598]
> 	* configure.ac: Add --enable-cet.
> 	* configure: Regenerated.
> 	* elf/dl-load.c (filebuf): Moved before "dynamic-link.h".
> 	(_dl_map_object_from_fd): Call DL_PROCESS_PT_NOTE on PT_NOTE
> 	segment if DL_PROCESS_PT_NOTE is defined.
> 	* elf/rtld.c (dl_main): Call DL_PROCESS_PT_NOTE on PT_NOTE
> 	segment if DL_PROCESS_PT_NOTE is defined.  Call DL_MAIN_CHECK
> 	if DL_MAIN_CHECK is defined.
> 	* elf/dl-open.c (dl_open_worker): Call DL_OPEN_CHECK if it is
> 	defined.
> 	* sysdeps/unix/sysv/linux/i386/dl-cet.c: New file.
> 	* sysdeps/unix/sysv/linux/i386/dl-machine.h: Likewise.
> 	* sysdeps/unix/sysv/linux/x86/check-cet.awk: Likewise.
> 	* sysdeps/unix/sysv/linux/x86/configure: Likewise.
> 	* sysdeps/unix/sysv/linux/x86/configure.ac: Likewise.
> 	* sysdeps/unix/sysv/linux/x86/dl-cet.c: Likewise.
> 	* sysdeps/unix/sysv/linux/x86/dl-cet.h: Likewise.
> 	* sysdeps/unix/sysv/linux/x86/dl-procruntime.c: Likewise.
> 	* sysdeps/unix/sysv/linux/x86/ldsodefs.h: Likewise.
> 	* sysdeps/unix/sysv/linux/x86/link_map.h: Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/dl-machine.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/unix/sysv/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/sysdep.h (_CET_NOTRACK): New.
> 	(_CET_ENDBR): Define if not defined.
> 	(ENTRY): Add _CET_ENDBR.
> 	* sysdeps/x86_64/dl-trampoline.h (_dl_runtime_resolve): Add
> 	_CET_ENDBR.
> 	(_dl_runtime_profile): Likewise.
> ---
>  configure                                    |  11 ++
>  configure.ac                                 |   6 +
>  elf/dl-load.c                                |  61 +++---
>  elf/dl-open.c                                |   4 +
>  elf/rtld.c                                   |  12 ++
>  sysdeps/i386/dl-trampoline.S                 |  72 +++++++
>  sysdeps/unix/sysv/linux/i386/dl-cet.c        |  67 +++++++
>  sysdeps/unix/sysv/linux/i386/dl-machine.h    |  23 +++
>  sysdeps/unix/sysv/linux/x86/Makefile         |  42 +++++
>  sysdeps/unix/sysv/linux/x86/check-cet.awk    |  53 ++++++
>  sysdeps/unix/sysv/linux/x86/configure        |  69 +++++++
>  sysdeps/unix/sysv/linux/x86/configure.ac     |  46 +++++
>  sysdeps/unix/sysv/linux/x86/dl-cet.c         | 186 +++++++++++++++++++
>  sysdeps/unix/sysv/linux/x86/dl-cet.h         | 138 ++++++++++++++
>  sysdeps/unix/sysv/linux/x86/dl-procruntime.c |  57 ++++++
>  sysdeps/unix/sysv/linux/x86/ldsodefs.h       |  29 +++
>  sysdeps/unix/sysv/linux/x86/link_map.h       |  26 +++
>  sysdeps/unix/sysv/linux/x86_64/dl-machine.h  |  27 +++
>  sysdeps/x86/cpu-features.h                   |   5 +
>  sysdeps/x86/sysdep.h                         |   8 +
>  sysdeps/x86_64/dl-trampoline.h               |   2 +
>  21 files changed, 919 insertions(+), 25 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/i386/dl-cet.c
>  create mode 100644 sysdeps/unix/sysv/linux/i386/dl-machine.h
>  create mode 100644 sysdeps/unix/sysv/linux/x86/check-cet.awk
>  create mode 100644 sysdeps/unix/sysv/linux/x86/configure
>  create mode 100644 sysdeps/unix/sysv/linux/x86/configure.ac
>  create mode 100644 sysdeps/unix/sysv/linux/x86/dl-cet.c
>  create mode 100644 sysdeps/unix/sysv/linux/x86/dl-cet.h
>  create mode 100644 sysdeps/unix/sysv/linux/x86/dl-procruntime.c
>  create mode 100644 sysdeps/unix/sysv/linux/x86/ldsodefs.h
>  create mode 100644 sysdeps/unix/sysv/linux/x86/link_map.h
>  create mode 100644 sysdeps/unix/sysv/linux/x86_64/dl-machine.h
> 

[snip configure]

> diff --git a/configure.ac b/configure.ac
> index ca1282a6b3..d342227f7a 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -453,6 +453,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/dl-load.c b/elf/dl-load.c
> index e81601f36d..6197124d02 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.  */

OK.

> +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>
> @@ -69,31 +95,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)))));
> -};
> -

OK.

>  /* This is the decomposed LD_LIBRARY_PATH search path.  */
>  static struct r_search_path_struct env_path_list attribute_relro;
>  
> @@ -1150,6 +1151,16 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
>  	  l->l_relro_addr = ph->p_vaddr;
>  	  l->l_relro_size = ph->p_memsz;
>  	  break;
> +
> +#ifdef DL_PROCESS_PT_NOTE
> +	case PT_NOTE:
> +	  if (DL_PROCESS_PT_NOTE (l, ph, fd, fbp))
> +	    {
> +	      errstring = N_("cannot process note segment");
> +	      goto call_lose;
> +	    }
> +	  break;
> +#endif

This is a typo-prone macro API. Please find a way for all arches to define
a do-nothing version of this API.

This seems like a sensible design. It's relatively cheap to walk the notes looking
for the one of interest. I don't imagine we'll get millions of notes, and if we do then
we'll have to do something else.

>  	}
>  
>      if (__glibc_unlikely (nloadcmds == 0))
> diff --git a/elf/dl-open.c b/elf/dl-open.c
> index 9dde4acfbc..f3bc41cb47 100644
> --- a/elf/dl-open.c
> +++ b/elf/dl-open.c
> @@ -291,6 +291,10 @@ dl_open_worker (void *a)
>    _dl_debug_state ();
>    LIBC_PROBE (map_complete, 3, args->nsid, r, new);
>  
> +#ifdef DL_OPEN_CHECK
> +  DL_OPEN_CHECK (new);
> +#endif

This is a typo-prone macro API. Otherwise OK.

Please find a way that we can define a generic version which is always used.

> +
>    /* 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..04b692908d 100644
> --- a/elf/rtld.c
> +++ b/elf/rtld.c
> @@ -1241,6 +1241,14 @@ of this helper program; chances are you did not intend to run this program.\n\
>  	main_map->l_relro_addr = ph->p_vaddr;
>  	main_map->l_relro_size = ph->p_memsz;
>  	break;
> +
> +#ifdef DL_PROCESS_PT_NOTE
> +      case PT_NOTE:
> +	if (DL_PROCESS_PT_NOTE (main_map, ph))
> +	  _dl_error_printf ("\
> +ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
> +	break;
> +#endif

This is a typo-prone macro API. Otherwise OK.

Please find a way that we can define a generic version which is always used.

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

This is a typo-prone macro API. Otherwise OK.

Please find a way that we can define a generic version which is always used.


>    if (prelinked)
>      {
>        if (main_map->l_info [ADDRIDX (DT_GNU_CONFLICT)] != NULL)
> 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/i386/dl-cet.c b/sysdeps/unix/sysv/linux/i386/dl-cet.c
> new file mode 100644
> index 0000000000..d9d80e151c
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/i386/dl-cet.c

If the trampoline is not linux-specific why is this?

> @@ -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/unix/sysv/linux/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;
> +	    }
> +	}
> +    }
> +}

This looks suspiciously a lot like what we do in dl-machine.h for
lazy setup. Is there any reason we can't put this code into the same
macros we use in dl-machine.h?

As I noted this code is in the linux-specific subdirectories, but doesn't
seem to be linux specific?

> +#endif
> diff --git a/sysdeps/unix/sysv/linux/i386/dl-machine.h b/sysdeps/unix/sysv/linux/i386/dl-machine.h
> new file mode 100644
> index 0000000000..3c2894edf2
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/i386/dl-machine.h
> @@ -0,0 +1,23 @@
> +/* Machine-dependent ELF dynamic relocation inline functions.
> +   Linux/i386 version.
> +   Copyright (C) 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/>.  */
> +
> +#ifdef __CET__
> +# include <sysdeps/unix/sysv/linux/x86/dl-cet.h>
> +#endif
> +#include <sysdeps/i386/dl-machine.h>

Why not include dl-cet.h directly from the generic dl-machine.h?

None of this support seems OS-specific. Other OSs could implement
CET support.

> diff --git a/sysdeps/unix/sysv/linux/x86/Makefile b/sysdeps/unix/sysv/linux/x86/Makefile
> index 111ff9ff58..00be6cc472 100644
> --- a/sysdeps/unix/sysv/linux/x86/Makefile
> +++ b/sysdeps/unix/sysv/linux/x86/Makefile
> @@ -23,3 +23,45 @@ endif
>  ifeq ($(subdir),setjmp)
>  tests += tst-saved_mask-1
>  endif
> +
> +ifeq ($(enable-cet),yes)
> +ifeq ($(subdir),elf)
> +sysdep-dl-routines += dl-cet

OK.

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

OK.

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

OK.

> +# FIXME: Can't use all-built-dso in elf/Makefile since this file is
> +# processed before elf/Makefile.  Duplicate it here.

OK, this FIXME is valid, it's a failing of our current layout that you
can't do what you want.

Please add a comment in the *other* copy to reference that this copy
needs to be updated also when there is a change.

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

OK.

> +
> +$(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)

OK.

> +
> +$(objpfx)check-cet.out: $(..)sysdeps/unix/sysv/linux/x86/check-cet.awk \
> +			$(cet-built-dso:=.note)
> +	LC_ALL=C $(AWK) -f $^ > $@; \
> +	$(evaluate-test)
> +generated += check-cet.out
> +endif
> +endif

OK.

> diff --git a/sysdeps/unix/sysv/linux/x86/check-cet.awk b/sysdeps/unix/sysv/linux/x86/check-cet.awk
> new file mode 100644
> index 0000000000..380d998caf
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/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.

[snip configure]

> diff --git a/sysdeps/unix/sysv/linux/x86/configure.ac b/sysdeps/unix/sysv/linux/x86/configure.ac
> new file mode 100644
> index 0000000000..baccd38633
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/x86/configure.ac

Is this really linux-specific?

> @@ -0,0 +1,46 @@
> +GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
> +# Local configure fragment for sysdeps/unix/sysv/linux/x86.
> +
> +if test x"$enable_cet" = 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

OK.

> +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])

It looks like all of this could run generically for CET support.

> diff --git a/sysdeps/unix/sysv/linux/x86/dl-cet.c b/sysdeps/unix/sysv/linux/x86/dl-cet.c
> new file mode 100644
> index 0000000000..5acf19dae4
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/x86/dl-cet.c
> @@ -0,0 +1,186 @@
> +/* 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/>.  */
> +
> +#include <unistd.h>
> +#include <errno.h>
> +#include <libintl.h>
> +#include <ldsodefs.h>
> +
> +static int
> +dl_cet_mark_legacy_region (struct link_map *l)
> +{
> +  /* FIXME: Mark legacy region  */
> +  return 0;

Why is there a FIXME here?

This patch should be complete or it should be an RFC.

If it is complete it should explain why no action needs to be taken in
the OS to mark legacy regions.

> +}
> +
> +/* Check if object M is compatible with CET.  */
> +
> +static void
> +dl_cet_check (struct link_map *m, const char *program)
> +{
> +  /* 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;
> +

OK.

> +  if (ibt_enabled || shstk_enabled)
> +    {
> +      struct link_map *l = NULL;
> +
> +      /* Check if IBT and SHSTK are enabled in object.  */
> +      bool enable_ibt = ibt_enabled;
> +      bool enable_shstk = shstk_enabled;
> +      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)
> +			 && (m->l_cet & lc_ibt) != 0);
> +	  enable_shstk &= (HAS_CPU_FEATURE (SHSTK)
> +			   && (m->l_cet & lc_shstk) != 0);

OK.

> +	}
> +
> +      /* 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.  */

OK.

> +	      if (l == &GL(dl_rtld_map)
> +		  ||  l->l_real == &GL(dl_rtld_map)
> +		  || (program && l == m))
> +		continue;
> +#endif
> +
> +	      if (enable_ibt && !(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 &= (l->l_cet & lc_shstk) != 0;
> +	    }
> +
> +	  if (need_legacy_bitmap)
> +	    {
> +	      /* 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);

... which does nothing? Is the kernel side of the requirements not known yet?

> +		  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"));
> +		    }
> +		}
> +	    }
> +	}
> +
> +      if (enable_ibt != ibt_enabled || enable_shstk != shstk_enabled)
> +	{
> +	  if (!program)
> +	    {
> +	      /* 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"));

OK.

> +	      return;
> +	    }
> +
> +#ifdef SHARED
> +	  /* FIXME: Disable IBT and/or SHSTK if they are enabled in
> +	     ld.so, but disabled in executable or shared objects.  */
> +	  ;

Is the code missing?

> +#endif
> +	}
> +
> +#ifdef SHARED
> +      if (program && (ibt_enabled || shstk_enabled))
> +	{
> +	  /* FIXME: Lock CET if IBT or SHSTK is enabled in executable.  */
> +	  ;


Similarly?

> +	}
> +#endif
> +    }
> +}
> +
> +void
> +_dl_cet_open_check (struct link_map *l)
> +{
> +  dl_cet_check (l, NULL);
> +}

OK.

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

OK.

> 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..97bf3918eb
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/x86/dl-cet.h
> @@ -0,0 +1,138 @@
> +/* Linux/x86 CET inline functions.
> +   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_cet_h
> +#define _dl_cet_h
> +
> +extern void _dl_cet_check (struct link_map *, const char *)
> +    attribute_hidden;

OK.

> +
> +#define DL_MAIN_CHECK(l, n) _dl_cet_check ((l), (n))

You have to find a way to define this everywhere.

> +
> +#ifdef ElfW
> +static inline void __attribute__ ((unused))
> +dl_process_cet_property_note (struct link_map *l,
> +			      const ElfW(Nhdr) *note,
> +			      const ElfW(Addr) size,
> +			      const ElfW(Addr) align)
> +{
> +  /* The NT_GNU_PROPERTY_TYPE_0 note must be aliged to 4 bytes in
> +     32-bit objects and to 8 bytes in 64-bit objects.  Skip notes
> +     with incorrect alignment.  */
> +  if (align != (__ELF_NATIVE_CLASS / 8))
> +    return;
> +
> +  const ElfW(Addr) start = (ElfW(Addr)) note;
> +
> +  while ((ElfW(Addr)) (note + 1) - start < size)

OK.

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

OK.

> +	    }
> +	}
> +
> +      /* NB: Note sections like .note.ABI-tag and .note.gnu.build-id are
> +	 aligned to 4 bytes in 64-bit ELF objects.  */

OK.

> +      note = ((const void *) note
> +	      + ELF_NOTE_NEXT_OFFSET (note->n_namesz, note->n_descsz,
> +				      align));
> +    }
> +}
> +
> +# ifdef FILEBUF_SIZE
> +#  define DL_PROCESS_PT_NOTE(l, ph, fd, fbp) \
> +  dl_process_pt_note ((l), (ph), (fd), (fbp))

You need to find a way to define this for all arches.

I suggest picking an existing header if you can find one, or a new one e.g. dl-check.h.

You may want to clean that up first, for example:

* We have DL_SYSDEP_OSCHECK
* With header dl-osinfo.h

You could put things in there for general undefined functions.

Then in x86 you include dl-cet.h into dl-osinfo.h.

Then it's really Linux-specific.

> +
> +static inline int __attribute__ ((unused))
> +dl_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph,
> +		    int fd, struct filebuf *fbp)
> +{
> +  const ElfW(Nhdr) *note;
> +  ElfW(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 (__libc_read (fd, (void *) note, size) != size)
> +	{
> +	  if (note_malloced)
> +	    free (note_malloced);
> +	  return -1;
> +	}
> +    }

OK.

> +
> +  dl_process_cet_property_note (l, note, size, ph->p_align);
> +  if (note_malloced)
> +    free (note_malloced);
> +  return 0;
> +}
> +# else
> +#  define DL_PROCESS_PT_NOTE(l, ph) dl_process_pt_note ((l), (ph))

OK.

> +
> +static inline int __attribute__ ((unused))
> +dl_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph)
> +{
> +  const ElfW(Nhdr) *note = (const void *) (ph->p_vaddr + l->l_addr);
> +  dl_process_cet_property_note (l, note, ph->p_memsz, ph->p_align);
> +  return 0;
> +}

OK.

> +# endif
> +#endif
> +
> +#endif	/* _dl_cet_h */
> diff --git a/sysdeps/unix/sysv/linux/x86/dl-procruntime.c b/sysdeps/unix/sysv/linux/x86/dl-procruntime.c
> new file mode 100644
> index 0000000000..6b46815f46
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/x86/dl-procruntime.c
> @@ -0,0 +1,57 @@
> +/* Data for processor runtime information.  Linux/x86 version.
> +   Copyright (C) 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
> +#endif

OK.

> diff --git a/sysdeps/unix/sysv/linux/x86/ldsodefs.h b/sysdeps/unix/sysv/linux/x86/ldsodefs.h
> new file mode 100644
> index 0000000000..bf8954b045
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/x86/ldsodefs.h
> @@ -0,0 +1,29 @@
> +/* Run-time dynamic linker data structures for x86 loaded ELF shared objects.
> +   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	_LDSODEFS_H
> +
> +/* Get the real definitions.  */
> +#include_next <ldsodefs.h>
> +
> +#ifdef __CET__
> +extern void _dl_cet_open_check (struct link_map *);
> +# define DL_OPEN_CHECK(l) _dl_cet_open_check ((l))
> +#endif
> +

OK. Though as I note you need to find a way to always define DL_OPEN_CHECK.

> +#endif /* ldsodefs.h */
> diff --git a/sysdeps/unix/sysv/linux/x86/link_map.h b/sysdeps/unix/sysv/linux/x86/link_map.h
> new file mode 100644
> index 0000000000..ef1206a9d2
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/x86/link_map.h
> @@ -0,0 +1,26 @@
> +/* Additional fields in struct link_map.  Linux/x86 version.
> +   Copyright (C) 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/unix/sysv/linux/x86_64/dl-machine.h b/sysdeps/unix/sysv/linux/x86_64/dl-machine.h
> new file mode 100644
> index 0000000000..97cb9f187a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/x86_64/dl-machine.h
> @@ -0,0 +1,27 @@
> +/* Machine-dependent ELF dynamic relocation inline functions.
> +   Linux/x86-64 version.
> +   Copyright (C) 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/>.  */
> +
> +#ifdef __CET__
> +# include <sysdeps/unix/sysv/linux/x86/dl-cet.h>
> +#endif
> +#ifdef __ILP32__
> +# include <sysdeps/x86_64/x32/dl-machine.h>
> +#else
> +# include <sysdeps/x86_64/dl-machine.h>
> +#endif

Why do this and not just directly include dl-cet.h into the existing
non-Linux dl-machine?

CET is not Linux-specific it's a piece of hardware technology?

> diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h
> index 624e681e96..4e15c15e92 100644
> --- a/sysdeps/x86/cpu-features.h
> +++ b/sysdeps/x86/cpu-features.h
> @@ -160,6 +160,11 @@ struct cpu_features
>  extern const struct cpu_features *__get_cpu_features (void)
>       __attribute__ ((const));
>  
> +# ifdef ElfW
> +extern void _dl_setup_cet (const ElfW(Phdr) *, size_t, const ElfW(Addr))
> +    attribute_hidden;
> +# endif

OK.

> +
>  # if defined (_LIBC) && !IS_IN (nonlib)
>  /* Unused for x86.  */
>  #  define INIT_ARCH()
> diff --git a/sysdeps/x86/sysdep.h b/sysdeps/x86/sysdep.h
> index 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;

OK.
							      \
> +  _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

OK.

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

OK.

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

Patch

diff --git a/configure b/configure
index 7a8bd3f817..f512c401dd 100755
--- a/configure
+++ b/configure
@@ -788,6 +788,7 @@  enable_nscd
 enable_pt_chown
 enable_tunables
 enable_mathvec
+enable_cet
 with_cpu
 '
       ac_precious_vars='build_alias
@@ -1461,6 +1462,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]
@@ -3741,6 +3744,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 ca1282a6b3..d342227f7a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -453,6 +453,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/dl-load.c b/elf/dl-load.c
index e81601f36d..6197124d02 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>
@@ -69,31 +95,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;
 
@@ -1150,6 +1151,16 @@  _dl_map_object_from_fd (const char *name, const char *origname, int fd,
 	  l->l_relro_addr = ph->p_vaddr;
 	  l->l_relro_size = ph->p_memsz;
 	  break;
+
+#ifdef DL_PROCESS_PT_NOTE
+	case PT_NOTE:
+	  if (DL_PROCESS_PT_NOTE (l, ph, fd, fbp))
+	    {
+	      errstring = N_("cannot process note segment");
+	      goto call_lose;
+	    }
+	  break;
+#endif
 	}
 
     if (__glibc_unlikely (nloadcmds == 0))
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 9dde4acfbc..f3bc41cb47 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -291,6 +291,10 @@  dl_open_worker (void *a)
   _dl_debug_state ();
   LIBC_PROBE (map_complete, 3, args->nsid, r, new);
 
+#ifdef DL_OPEN_CHECK
+  DL_OPEN_CHECK (new);
+#endif
+
   /* Print scope information.  */
   if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
     _dl_show_scope (new, 0);
diff --git a/elf/rtld.c b/elf/rtld.c
index 8c732adb68..04b692908d 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1241,6 +1241,14 @@  of this helper program; chances are you did not intend to run this program.\n\
 	main_map->l_relro_addr = ph->p_vaddr;
 	main_map->l_relro_size = ph->p_memsz;
 	break;
+
+#ifdef DL_PROCESS_PT_NOTE
+      case PT_NOTE:
+	if (DL_PROCESS_PT_NOTE (main_map, ph))
+	  _dl_error_printf ("\
+ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
+	break;
+#endif
       }
 
   /* Adjust the address of the TLS initialization image in case
@@ -2110,6 +2118,10 @@  ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
 	_dl_show_scope (l, 0);
     }
 
+#ifdef DL_MAIN_CHECK
+  DL_MAIN_CHECK (main_map, _dl_argv[0]);
+#endif
+
   if (prelinked)
     {
       if (main_map->l_info [ADDRIDX (DT_GNU_CONFLICT)] != NULL)
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/i386/dl-cet.c b/sysdeps/unix/sysv/linux/i386/dl-cet.c
new file mode 100644
index 0000000000..d9d80e151c
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/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/unix/sysv/linux/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/unix/sysv/linux/i386/dl-machine.h b/sysdeps/unix/sysv/linux/i386/dl-machine.h
new file mode 100644
index 0000000000..3c2894edf2
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/dl-machine.h
@@ -0,0 +1,23 @@ 
+/* Machine-dependent ELF dynamic relocation inline functions.
+   Linux/i386 version.
+   Copyright (C) 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/>.  */
+
+#ifdef __CET__
+# include <sysdeps/unix/sysv/linux/x86/dl-cet.h>
+#endif
+#include <sysdeps/i386/dl-machine.h>
diff --git a/sysdeps/unix/sysv/linux/x86/Makefile b/sysdeps/unix/sysv/linux/x86/Makefile
index 111ff9ff58..00be6cc472 100644
--- a/sysdeps/unix/sysv/linux/x86/Makefile
+++ b/sysdeps/unix/sysv/linux/x86/Makefile
@@ -23,3 +23,45 @@  endif
 ifeq ($(subdir),setjmp)
 tests += tst-saved_mask-1
 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/unix/sysv/linux/x86/check-cet.awk \
+			$(cet-built-dso:=.note)
+	LC_ALL=C $(AWK) -f $^ > $@; \
+	$(evaluate-test)
+generated += check-cet.out
+endif
+endif
diff --git a/sysdeps/unix/sysv/linux/x86/check-cet.awk b/sysdeps/unix/sysv/linux/x86/check-cet.awk
new file mode 100644
index 0000000000..380d998caf
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/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/unix/sysv/linux/x86/configure b/sysdeps/unix/sysv/linux/x86/configure
new file mode 100644
index 0000000000..358319d93d
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/configure
@@ -0,0 +1,69 @@ 
+# This file is generated from configure.ac by Autoconf.  DO NOT EDIT!
+ # Local configure fragment for sysdeps/unix/sysv/linux/x86.
+
+if test x"$enable_cet" = 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/unix/sysv/linux/x86/configure.ac b/sysdeps/unix/sysv/linux/x86/configure.ac
new file mode 100644
index 0000000000..baccd38633
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/configure.ac
@@ -0,0 +1,46 @@ 
+GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
+# Local configure fragment for sysdeps/unix/sysv/linux/x86.
+
+if test x"$enable_cet" = 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/unix/sysv/linux/x86/dl-cet.c b/sysdeps/unix/sysv/linux/x86/dl-cet.c
new file mode 100644
index 0000000000..5acf19dae4
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/dl-cet.c
@@ -0,0 +1,186 @@ 
+/* 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/>.  */
+
+#include <unistd.h>
+#include <errno.h>
+#include <libintl.h>
+#include <ldsodefs.h>
+
+static int
+dl_cet_mark_legacy_region (struct link_map *l)
+{
+  /* FIXME: Mark legacy region  */
+  return 0;
+}
+
+/* Check if object M is compatible with CET.  */
+
+static void
+dl_cet_check (struct link_map *m, const char *program)
+{
+  /* 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;
+      bool enable_shstk = shstk_enabled;
+      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)
+			 && (m->l_cet & lc_ibt) != 0);
+	  enable_shstk &= (HAS_CPU_FEATURE (SHSTK)
+			   && (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 && !(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 &= (l->l_cet & lc_shstk) != 0;
+	    }
+
+	  if (need_legacy_bitmap)
+	    {
+	      /* 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"));
+		    }
+		}
+	    }
+	}
+
+      if (enable_ibt != ibt_enabled || enable_shstk != shstk_enabled)
+	{
+	  if (!program)
+	    {
+	      /* 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;
+	    }
+
+#ifdef SHARED
+	  /* FIXME: Disable IBT and/or SHSTK if they are enabled in
+	     ld.so, but disabled in executable or shared objects.  */
+	  ;
+#endif
+	}
+
+#ifdef SHARED
+      if (program && (ibt_enabled || shstk_enabled))
+	{
+	  /* FIXME: Lock CET if IBT or SHSTK is enabled in executable.  */
+	  ;
+	}
+#endif
+    }
+}
+
+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/unix/sysv/linux/x86/dl-cet.h b/sysdeps/unix/sysv/linux/x86/dl-cet.h
new file mode 100644
index 0000000000..97bf3918eb
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/dl-cet.h
@@ -0,0 +1,138 @@ 
+/* Linux/x86 CET inline functions.
+   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_cet_h
+#define _dl_cet_h
+
+extern void _dl_cet_check (struct link_map *, const char *)
+    attribute_hidden;
+
+#define DL_MAIN_CHECK(l, n) _dl_cet_check ((l), (n))
+
+#ifdef ElfW
+static inline void __attribute__ ((unused))
+dl_process_cet_property_note (struct link_map *l,
+			      const ElfW(Nhdr) *note,
+			      const ElfW(Addr) size,
+			      const ElfW(Addr) align)
+{
+  /* The NT_GNU_PROPERTY_TYPE_0 note must be aliged to 4 bytes in
+     32-bit objects and to 8 bytes in 64-bit objects.  Skip notes
+     with incorrect alignment.  */
+  if (align != (__ELF_NATIVE_CLASS / 8))
+    return;
+
+  const ElfW(Addr) start = (ElfW(Addr)) note;
+
+  while ((ElfW(Addr)) (note + 1) - start < size)
+    {
+      /* Find the NT_GNU_PROPERTY_TYPE_0 note.  */
+      if (note->n_namesz == 4
+	  && note->n_type == NT_GNU_PROPERTY_TYPE_0
+	  && memcmp (note + 1, "GNU", 4) == 0)
+	{
+	  /* Check for invalid property.  */
+	  if (note->n_descsz < 8
+	      || (note->n_descsz % sizeof (ElfW(Addr))) != 0)
+	    break;
+
+	  /* Start and end of property array.  */
+	  unsigned char *ptr = (unsigned char *) (note + 1) + 4;
+	  unsigned char *ptr_end = ptr + note->n_descsz;
+
+	  while (1)
+	    {
+	      unsigned int type = *(unsigned int *) ptr;
+	      unsigned int datasz = *(unsigned int *) (ptr + 4);
+
+	      ptr += 8;
+	      if ((ptr + datasz) > ptr_end)
+		break;
+
+	      if (type == GNU_PROPERTY_X86_FEATURE_1_AND
+		  && datasz == 4)
+		{
+		  unsigned int feature_1 = *(unsigned int *) ptr;
+		  if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_IBT))
+		    l->l_cet |= lc_ibt;
+		  if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_SHSTK))
+		    l->l_cet |= lc_shstk;
+		  break;
+		}
+	    }
+	}
+
+      /* NB: Note sections like .note.ABI-tag and .note.gnu.build-id are
+	 aligned to 4 bytes in 64-bit ELF objects.  */
+      note = ((const void *) note
+	      + ELF_NOTE_NEXT_OFFSET (note->n_namesz, note->n_descsz,
+				      align));
+    }
+}
+
+# ifdef FILEBUF_SIZE
+#  define DL_PROCESS_PT_NOTE(l, ph, fd, fbp) \
+  dl_process_pt_note ((l), (ph), (fd), (fbp))
+
+static inline int __attribute__ ((unused))
+dl_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph,
+		    int fd, struct filebuf *fbp)
+{
+  const ElfW(Nhdr) *note;
+  ElfW(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 (__libc_read (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);
+  return 0;
+}
+# else
+#  define DL_PROCESS_PT_NOTE(l, ph) dl_process_pt_note ((l), (ph))
+
+static inline int __attribute__ ((unused))
+dl_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph)
+{
+  const ElfW(Nhdr) *note = (const void *) (ph->p_vaddr + l->l_addr);
+  dl_process_cet_property_note (l, note, ph->p_memsz, ph->p_align);
+  return 0;
+}
+# endif
+#endif
+
+#endif	/* _dl_cet_h */
diff --git a/sysdeps/unix/sysv/linux/x86/dl-procruntime.c b/sysdeps/unix/sysv/linux/x86/dl-procruntime.c
new file mode 100644
index 0000000000..6b46815f46
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/dl-procruntime.c
@@ -0,0 +1,57 @@ 
+/* Data for processor runtime information.  Linux/x86 version.
+   Copyright (C) 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
+#endif
diff --git a/sysdeps/unix/sysv/linux/x86/ldsodefs.h b/sysdeps/unix/sysv/linux/x86/ldsodefs.h
new file mode 100644
index 0000000000..bf8954b045
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/ldsodefs.h
@@ -0,0 +1,29 @@ 
+/* Run-time dynamic linker data structures for x86 loaded ELF shared objects.
+   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	_LDSODEFS_H
+
+/* Get the real definitions.  */
+#include_next <ldsodefs.h>
+
+#ifdef __CET__
+extern void _dl_cet_open_check (struct link_map *);
+# define DL_OPEN_CHECK(l) _dl_cet_open_check ((l))
+#endif
+
+#endif /* ldsodefs.h */
diff --git a/sysdeps/unix/sysv/linux/x86/link_map.h b/sysdeps/unix/sysv/linux/x86/link_map.h
new file mode 100644
index 0000000000..ef1206a9d2
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/link_map.h
@@ -0,0 +1,26 @@ 
+/* Additional fields in struct link_map.  Linux/x86 version.
+   Copyright (C) 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/unix/sysv/linux/x86_64/dl-machine.h b/sysdeps/unix/sysv/linux/x86_64/dl-machine.h
new file mode 100644
index 0000000000..97cb9f187a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/dl-machine.h
@@ -0,0 +1,27 @@ 
+/* Machine-dependent ELF dynamic relocation inline functions.
+   Linux/x86-64 version.
+   Copyright (C) 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/>.  */
+
+#ifdef __CET__
+# include <sysdeps/unix/sysv/linux/x86/dl-cet.h>
+#endif
+#ifdef __ILP32__
+# include <sysdeps/x86_64/x32/dl-machine.h>
+#else
+# include <sysdeps/x86_64/dl-machine.h>
+#endif
diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h
index 624e681e96..4e15c15e92 100644
--- a/sysdeps/x86/cpu-features.h
+++ b/sysdeps/x86/cpu-features.h
@@ -160,6 +160,11 @@  struct cpu_features
 extern const struct cpu_features *__get_cpu_features (void)
      __attribute__ ((const));
 
+# ifdef ElfW
+extern void _dl_setup_cet (const ElfW(Phdr) *, size_t, const ElfW(Addr))
+    attribute_hidden;
+# endif
+
 # if defined (_LIBC) && !IS_IN (nonlib)
 /* Unused for x86.  */
 #  define INIT_ARCH()
diff --git a/sysdeps/x86/sysdep.h b/sysdeps/x86/sysdep.h
index 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