diff options
Diffstat (limited to 'sysdeps/i386')
-rw-r--r-- | sysdeps/i386/dl-cet.c | 67 | ||||
-rw-r--r-- | sysdeps/i386/dl-trampoline.S | 72 |
2 files changed, 139 insertions, 0 deletions
diff --git a/sysdeps/i386/dl-cet.c b/sysdeps/i386/dl-cet.c new file mode 100644 index 0000000..5d9a4e8 --- /dev/null +++ b/sysdeps/i386/dl-cet.c @@ -0,0 +1,67 @@ +/* Linux/i386 CET initializers function. + Copyright (C) 2018 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + + +#define LINKAGE static inline +#define _dl_cet_check cet_check +#include <sysdeps/x86/dl-cet.c> +#undef _dl_cet_check + +#ifdef SHARED +void +_dl_cet_check (struct link_map *main_map, const char *program) +{ + cet_check (main_map, program); + + if ((GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_SHSTK)) + { + /* Replace _dl_runtime_resolve and _dl_runtime_profile with + _dl_runtime_resolve_shstk and _dl_runtime_profile_shstk, + respectively if SHSTK is enabled. */ + extern void _dl_runtime_resolve (Elf32_Word) attribute_hidden; + extern void _dl_runtime_resolve_shstk (Elf32_Word) attribute_hidden; + extern void _dl_runtime_profile (Elf32_Word) attribute_hidden; + extern void _dl_runtime_profile_shstk (Elf32_Word) attribute_hidden; + unsigned int i; + struct link_map *l; + Elf32_Addr *got; + + if (main_map->l_info[DT_JMPREL]) + { + got = (Elf32_Addr *) D_PTR (main_map, l_info[DT_PLTGOT]); + if (got[2] == (Elf32_Addr) &_dl_runtime_resolve) + got[2] = (Elf32_Addr) &_dl_runtime_resolve_shstk; + else if (got[2] == (Elf32_Addr) &_dl_runtime_profile) + got[2] = (Elf32_Addr) &_dl_runtime_profile_shstk; + } + + i = main_map->l_searchlist.r_nlist; + while (i-- > 0) + { + l = main_map->l_initfini[i]; + if (l->l_info[DT_JMPREL]) + { + got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]); + if (got[2] == (Elf32_Addr) &_dl_runtime_resolve) + got[2] = (Elf32_Addr) &_dl_runtime_resolve_shstk; + else if (got[2] == (Elf32_Addr) &_dl_runtime_profile) + got[2] = (Elf32_Addr) &_dl_runtime_profile_shstk; + } + } + } +} +#endif diff --git a/sysdeps/i386/dl-trampoline.S b/sysdeps/i386/dl-trampoline.S index 8bf86f8..6dc0319 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 |