x86: Support Intel IBT with IBT property and IBT-enable PLT
authorH.J. Lu <hjl.tools@gmail.com>
Thu, 22 Jun 2017 12:44:37 +0000 (05:44 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Thu, 22 Jun 2017 12:44:53 +0000 (05:44 -0700)
commitee2fdd6f36c10ceb84e05c7234983bcfbe6146d5
treef8980ac68ae80a5db4c84efaec81d7b35c833da8
parentf4906a9a7441ef9c2758513420568994a1e7fed3
x86: Support Intel IBT with IBT property and IBT-enable PLT

To support IBT in Intel Control-flow Enforcement Technology (CET)
instructions:

https://software.intel.com/sites/default/files/managed/4d/2a/control-flow-enforcement-technology-preview.pdf

 #define GNU_PROPERTY_X86_FEATURE_1_AND 0xc0000002

 #define GNU_PROPERTY_X86_FEATURE_1_IBT (1U << 0)

are added to GNU program properties to indicate that all executable
sections are compatible with IBT when ENDBR instruction starts each
valid target where an indirect branch instruction can land.

GNU_PROPERTY_X86_FEATURE_1_IBT is set on output only if it is set on
all relocatable inputs.

The followings changes are made to the Procedure Linkage Table (PLT):

1. For 64-bit x86-64,  PLT is changed to

PLT0:  push       GOT[1]
       bnd jmp    *GOT[2]
       nop
...
PLTn:  endbr64
       push       namen_reloc_index
       bnd jmp    PLT0

together with the second PLT section:

PLTn:  endbr64
       bnd jmp   *GOT[namen_index]
       nop

BND prefix is also added so that IBT-enabled PLT is compatible with MPX.

2. For 32-bit x86-64 (x32) and i386,  PLT is changed to

PLT0:  push       GOT[1]
       jmp        *GOT[2]
       nop
...
PLTn:  endbr64                                 # endbr32 for i386.
       push       namen_reloc_index
       jmp        PLT0

together with the second PLT section:

PLTn:  endbr64                                 # endbr32 for i386.
       jmp       *GOT[namen_index]
       nop

BND prefix isn't used since MPX isn't supported on x32 and BND registers
aren't used in parameter passing on i386.

GOT is an array of addresses.  Initially, GOT[namen_index] is filled
with the address of the ENDBR instruction of the corresponding entry
in the first PLT section.  The function, namen, is called via the
ENDBR instruction in the second PLT entry.  GOT[namen_index] is updated
to the actual address of the function, namen, at run-time.

2 linker command line options are added:

1. -z ibtplt: Generate IBT-enabled PLT.
2. -z ibt: Generate GNU_PROPERTY_X86_FEATURE_1_IBT in GNU program
properties as well as IBT-enabled PLT.

bfd/

* elf32-i386.c (elf_i386_lazy_ibt_plt0_entry): New.
(elf_i386_lazy_ibt_plt_entry): Likewise.
(elf_i386_pic_lazy_ibt_plt0_entry): Likewise.
(elf_i386_non_lazy_ibt_plt_entry): Likewise.
(elf_i386_pic_non_lazy_ibt_plt_entry): Likewise.
(elf_i386_eh_frame_lazy_ibt_plt): Likewise.
(elf_i386_lazy_plt_layout): Likewise.
(elf_i386_non_lazy_plt_layout): Likewise.
(elf_i386_link_hash_entry): Add plt_second.
(elf_i386_link_hash_table): Add plt_second and
plt_second_eh_frame.
(elf_i386_allocate_dynrelocs): Use the second PLT if needed.
(elf_i386_size_dynamic_sections): Use .plt.got unwind info for
the second PLT.  Check the second PLT.
(elf_i386_relocate_section): Use the second PLT to resolve
PLT reference if needed.
(elf_i386_finish_dynamic_symbol): Fill and use the second PLT if
needed.
(elf_i386_finish_dynamic_sections): Set sh_entsize on the
second PLT.  Generate unwind info for the second PLT.
(elf_i386_plt_type): Add plt_second.
(elf_i386_get_synthetic_symtab): Support the second PLT.
(elf_i386_parse_gnu_properties): Support
GNU_PROPERTY_X86_FEATURE_1_AND.
(elf_i386_merge_gnu_properties): Support
GNU_PROPERTY_X86_FEATURE_1_AND.  If info->ibt is set, turn
on GNU_PROPERTY_X86_FEATURE_1_IBT
(elf_i386_link_setup_gnu_properties): If info->ibt is set,
turn on GNU_PROPERTY_X86_FEATURE_1_IBT.  Use IBT-enabled PLT
for info->ibtplt, info->ibt or GNU_PROPERTY_X86_FEATURE_1_IBT
is set on all relocatable inputs.
* elf64-x86-64.c (elf_x86_64_lazy_ibt_plt_entry): New.
(elf_x32_lazy_ibt_plt_entry): Likewise.
(elf_x86_64_non_lazy_ibt_plt_entry): Likewise.
(elf_x32_non_lazy_ibt_plt_entry): Likewise.
(elf_x86_64_eh_frame_lazy_ibt_plt): Likewise.
(elf_x32_eh_frame_lazy_ibt_plt): Likewise.
(elf_x86_64_lazy_ibt_plt): Likewise.
(elf_x32_lazy_ibt_plt): Likewise.
(elf_x86_64_non_lazy_ibt_plt): Likewise.
(elf_x32_non_lazy_ibt_plt): Likewise.
(elf_x86_64_get_synthetic_symtab): Support the second PLT.
(elf_x86_64_parse_gnu_properties): Support
GNU_PROPERTY_X86_FEATURE_1_AND.
(elf_x86_64_merge_gnu_properties): Support
GNU_PROPERTY_X86_FEATURE_1_AND.  If info->ibt is set, turn
on GNU_PROPERTY_X86_FEATURE_1_IBT
(elf_x86_64_link_setup_gnu_properties): If info->ibt is set,
turn on GNU_PROPERTY_X86_FEATURE_1_IBT.  Use IBT-enabled PLT
for info->ibtplt, info->ibt or GNU_PROPERTY_X86_FEATURE_1_IBT
is set on all relocatable inputs.

binutils/

* readelf.c (decode_x86_feature): New.
(print_gnu_property_note): Call decode_x86_feature on
GNU_PROPERTY_X86_FEATURE_1_AND.
* testsuite/binutils-all/i386/empty.d: New file.
* testsuite/binutils-all/i386/empty.s: Likewise.
* testsuite/binutils-all/i386/ibt.d: Likewise.
* testsuite/binutils-all/i386/ibt.s: Likewise.
* testsuite/binutils-all/x86-64/empty-x32.d: Likewise.
* testsuite/binutils-all/x86-64/empty.d: Likewise.
* testsuite/binutils-all/x86-64/empty.s: Likewise.
* testsuite/binutils-all/x86-64/ibt-x32.d: Likewise.
* testsuite/binutils-all/x86-64/ibt.d: Likewise.
* testsuite/binutils-all/x86-64/ibt.s: Likewise.

include/

* bfdlink.h (bfd_link_info): Add ibtplt and ibt.
* elf/common.h (GNU_PROPERTY_X86_FEATURE_1_AND): New.
(GNU_PROPERTY_X86_FEATURE_1_IBT): Likewise.

ld/

* Makefile.am (ELF_X86_DEPS): Add $(srcdir)/emulparams/cet.sh.
* Makefile.in: Regenerated.
* NEWS: Mention GNU_PROPERTY_X86_FEATURE_1_IBT, -z ibtplt
and -z ibt.
* emulparams/cet.sh: New file.
* testsuite/ld-i386/ibt-plt-1.d: Likewise.
* testsuite/ld-i386/ibt-plt-1.s: Likewise.
* testsuite/ld-i386/ibt-plt-2.s: Likewise.
* testsuite/ld-i386/ibt-plt-2a.d: Likewise.
* testsuite/ld-i386/ibt-plt-2b.d: Likewise.
* testsuite/ld-i386/ibt-plt-2c.d: Likewise.
* testsuite/ld-i386/ibt-plt-2d.d: Likewise.
* testsuite/ld-i386/ibt-plt-3.s: Likewise.
* testsuite/ld-i386/ibt-plt-3a.d: Likewise.
* testsuite/ld-i386/ibt-plt-3b.d: Likewise.
* testsuite/ld-i386/ibt-plt-3c.d: Likewise.
* testsuite/ld-i386/ibt-plt-3d.d: Likewise.
* testsuite/ld-i386/plt-main-ibt.dd: Likewise.
* testsuite/ld-i386/plt-pie-ibt.dd: Likewise.
* testsuite/ld-i386/property-x86-empty.s: Likewise.
* testsuite/ld-i386/property-x86-ibt.s: Likewise.
* testsuite/ld-i386/property-x86-ibt1a.d: Likewise.
* testsuite/ld-i386/property-x86-ibt1b.d: Likewise.
* testsuite/ld-i386/property-x86-ibt2.d: Likewise.
* testsuite/ld-i386/property-x86-ibt3a.d: Likewise.
* testsuite/ld-i386/property-x86-ibt3b.d: Likewise.
* testsuite/ld-i386/property-x86-ibt4.d: Likewise.
* testsuite/ld-i386/property-x86-ibt5.d: Likewise.
* testsuite/ld-x86-64/ibt-plt-1-x32.d: Likewise.
* testsuite/ld-x86-64/ibt-plt-1.d: Likewise.
* testsuite/ld-x86-64/ibt-plt-1.s: Likewise.
* testsuite/ld-x86-64/ibt-plt-2.s: Likewise.
* testsuite/ld-x86-64/ibt-plt-2a-x32.d: Likewise.
* testsuite/ld-x86-64/ibt-plt-2a.d: Likewise.
* testsuite/ld-x86-64/ibt-plt-2b-x32.d: Likewise.
* testsuite/ld-x86-64/ibt-plt-2b.d: Likewise.
* testsuite/ld-x86-64/ibt-plt-2c-x32.d: Likewise.
* testsuite/ld-x86-64/ibt-plt-2c.d: Likewise.
* testsuite/ld-x86-64/ibt-plt-2d-x32.d: Likewise.
* testsuite/ld-x86-64/ibt-plt-2d.d: Likewise.
* testsuite/ld-x86-64/ibt-plt-3.s: Likewise.
* testsuite/ld-x86-64/ibt-plt-3a-x32.d: Likewise.
* testsuite/ld-x86-64/ibt-plt-3a.d: Likewise.
* testsuite/ld-x86-64/ibt-plt-3b-x32.d: Likewise.
* testsuite/ld-x86-64/ibt-plt-3b.d: Likewise.
* testsuite/ld-x86-64/ibt-plt-3c-x32.d: Likewise.
* testsuite/ld-x86-64/ibt-plt-3c.d: Likewise.
* testsuite/ld-x86-64/ibt-plt-3d-x32.d: Likewise.
* testsuite/ld-x86-64/ibt-plt-3d.d: Likewise.
* testsuite/ld-x86-64/plt-main-ibt-now.rd: Likewise.
* testsuite/ld-x86-64/plt-main-ibt-x32.dd: Likewise.
* testsuite/ld-x86-64/plt-main-ibt.dd: Likewise.
* testsuite/ld-x86-64/property-x86-empty.s: Likewise.
* testsuite/ld-x86-64/property-x86-ibt.s: Likewise.
* testsuite/ld-x86-64/property-x86-ibt1a-x32.d: Likewise.
* testsuite/ld-x86-64/property-x86-ibt1a.d: Likewise.
* testsuite/ld-x86-64/property-x86-ibt1b-x32.d: Likewise.
* testsuite/ld-x86-64/property-x86-ibt1b.d: Likewise.
* testsuite/ld-x86-64/property-x86-ibt2-x32.d: Likewise.
* testsuite/ld-x86-64/property-x86-ibt2.d: Likewise.
* testsuite/ld-x86-64/property-x86-ibt3a-x32.d: Likewise.
* testsuite/ld-x86-64/property-x86-ibt3a.d: Likewise.
* testsuite/ld-x86-64/property-x86-ibt3b-x32.d: Likewise.
* testsuite/ld-x86-64/property-x86-ibt3b.d: Likewise.
* testsuite/ld-x86-64/property-x86-ibt4-x32.d: Likewise.
* testsuite/ld-x86-64/property-x86-ibt4.d: Likewise.
* testsuite/ld-x86-64/property-x86-ibt5-x32.d: Likewise.
* testsuite/ld-x86-64/property-x86-ibt5.d: Likewise.
* emulparams/elf32_x86_64.sh: Source emulparams/cet.sh.
(TINY_READONLY_SECTION): Add .plt.sec.
* emulparams/elf_i386.sh: Likewise.
* emulparams/elf_x86_64.sh: Source emulparams/cet.sh.
* ld.texinfo: Document -z ibtplt and -z ibt.
* testsuite/ld-i386/i386.exp: Run IBT and IBT PLT tests.
* testsuite/ld-x86-64/x86-64.exp: Likewise.
* testsuite/ld-x86-64/pr21481b.S (check): Updated for x32.
93 files changed:
bfd/ChangeLog
bfd/elf32-i386.c
bfd/elf64-x86-64.c
binutils/ChangeLog
binutils/readelf.c
binutils/testsuite/binutils-all/i386/empty.d [new file with mode: 0644]
binutils/testsuite/binutils-all/i386/empty.s [new file with mode: 0644]
binutils/testsuite/binutils-all/i386/ibt.d [new file with mode: 0644]
binutils/testsuite/binutils-all/i386/ibt.s [new file with mode: 0644]
binutils/testsuite/binutils-all/x86-64/empty-x32.d [new file with mode: 0644]
binutils/testsuite/binutils-all/x86-64/empty.d [new file with mode: 0644]
binutils/testsuite/binutils-all/x86-64/empty.s [new file with mode: 0644]
binutils/testsuite/binutils-all/x86-64/ibt-x32.d [new file with mode: 0644]
binutils/testsuite/binutils-all/x86-64/ibt.d [new file with mode: 0644]
binutils/testsuite/binutils-all/x86-64/ibt.s [new file with mode: 0644]
include/ChangeLog
include/bfdlink.h
include/elf/common.h
ld/ChangeLog
ld/Makefile.am
ld/Makefile.in
ld/NEWS
ld/emulparams/cet.sh [new file with mode: 0644]
ld/emulparams/elf32_x86_64.sh
ld/emulparams/elf_i386.sh
ld/emulparams/elf_x86_64.sh
ld/ld.texinfo
ld/testsuite/ld-i386/i386.exp
ld/testsuite/ld-i386/ibt-plt-1.d [new file with mode: 0644]
ld/testsuite/ld-i386/ibt-plt-1.s [new file with mode: 0644]
ld/testsuite/ld-i386/ibt-plt-2.s [new file with mode: 0644]
ld/testsuite/ld-i386/ibt-plt-2a.d [new file with mode: 0644]
ld/testsuite/ld-i386/ibt-plt-2b.d [new file with mode: 0644]
ld/testsuite/ld-i386/ibt-plt-2c.d [new file with mode: 0644]
ld/testsuite/ld-i386/ibt-plt-2d.d [new file with mode: 0644]
ld/testsuite/ld-i386/ibt-plt-3.s [new file with mode: 0644]
ld/testsuite/ld-i386/ibt-plt-3a.d [new file with mode: 0644]
ld/testsuite/ld-i386/ibt-plt-3b.d [new file with mode: 0644]
ld/testsuite/ld-i386/ibt-plt-3c.d [new file with mode: 0644]
ld/testsuite/ld-i386/ibt-plt-3d.d [new file with mode: 0644]
ld/testsuite/ld-i386/plt-main-ibt.dd [new file with mode: 0644]
ld/testsuite/ld-i386/plt-pie-ibt.dd [new file with mode: 0644]
ld/testsuite/ld-i386/property-x86-empty.s [new file with mode: 0644]
ld/testsuite/ld-i386/property-x86-ibt.s [new file with mode: 0644]
ld/testsuite/ld-i386/property-x86-ibt1a.d [new file with mode: 0644]
ld/testsuite/ld-i386/property-x86-ibt1b.d [new file with mode: 0644]
ld/testsuite/ld-i386/property-x86-ibt2.d [new file with mode: 0644]
ld/testsuite/ld-i386/property-x86-ibt3a.d [new file with mode: 0644]
ld/testsuite/ld-i386/property-x86-ibt3b.d [new file with mode: 0644]
ld/testsuite/ld-i386/property-x86-ibt4.d [new file with mode: 0644]
ld/testsuite/ld-i386/property-x86-ibt5.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/ibt-plt-1-x32.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/ibt-plt-1.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/ibt-plt-1.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/ibt-plt-2.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/ibt-plt-2a-x32.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/ibt-plt-2a.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/ibt-plt-2b-x32.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/ibt-plt-2b.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/ibt-plt-2c-x32.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/ibt-plt-2c.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/ibt-plt-2d-x32.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/ibt-plt-2d.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/ibt-plt-3.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/ibt-plt-3a-x32.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/ibt-plt-3a.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/ibt-plt-3b-x32.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/ibt-plt-3b.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/ibt-plt-3c-x32.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/ibt-plt-3c.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/ibt-plt-3d-x32.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/ibt-plt-3d.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/plt-main-ibt-now.rd [new file with mode: 0644]
ld/testsuite/ld-x86-64/plt-main-ibt-x32.dd [new file with mode: 0644]
ld/testsuite/ld-x86-64/plt-main-ibt.dd [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr21481b.S
ld/testsuite/ld-x86-64/property-x86-empty.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-x86-ibt.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-x86-ibt1a-x32.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-x86-ibt1a.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-x86-ibt1b-x32.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-x86-ibt1b.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-x86-ibt2-x32.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-x86-ibt2.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-x86-ibt3a-x32.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-x86-ibt3a.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-x86-ibt3b-x32.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-x86-ibt3b.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-x86-ibt4-x32.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-x86-ibt4.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-x86-ibt5-x32.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/property-x86-ibt5.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/x86-64.exp