Message ID | 20161004184516.GA27454@intel.com |
---|---|
State | New |
Headers | show |
On 10/04/2016 02:45 PM, H.J. Lu wrote: > Calling an IFUNC function defined in unrelocated shared library may > lead to segfault. This patch issues an error message to request > relinking the shared library if it references IFUNC function defined > in the unrelocated shared library. > > Tested on i686 and x86-64. OK for master? This looks good to me and I've tested this on Fedora Rawhide. I appreciate 2/2 patch that covers all the other machines to make sure that they either work or fail the test. > H.J. > --- > [BZ #20019] > * sysdeps/i386/dl-machine.h (elf_machine_rel): Check IFUNC > definition in unrelocated shared library. > * sysdeps/x86_64/dl-machine.h (elf_machine_rela): Likewise. > --- > sysdeps/i386/dl-machine.h | 18 +++++++++++++++++- > sysdeps/x86_64/dl-machine.h | 18 +++++++++++++++++- > 2 files changed, 34 insertions(+), 2 deletions(-) > > diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h > index 4e3968a..e5ad0c5 100644 > --- a/sysdeps/i386/dl-machine.h > +++ b/sysdeps/i386/dl-machine.h > @@ -321,7 +321,23 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, > 0) > && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1) > && __builtin_expect (!skip_ifunc, 1)) > - value = ((Elf32_Addr (*) (void)) value) (); > + { > +# ifndef RTLD_BOOTSTRAP > + if (sym_map != map > + && sym_map->l_type != lt_executable > + && !sym_map->l_relocated) > + { > + const char *strtab > + = (const char *) D_PTR (map, l_info[DT_STRTAB]); > + _dl_fatal_printf ("\ > +%s: Relink `%s' with `%s' for IFUNC symbol `%s'\n", > + RTLD_PROGNAME, map->l_name, > + sym_map->l_name, > + strtab + refsym->st_name); > + } > +# endif > + value = ((Elf32_Addr (*) (void)) value) (); > + } > > switch (r_type) > { > diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h > index c0f0fa1..5c021dc 100644 > --- a/sysdeps/x86_64/dl-machine.h > +++ b/sysdeps/x86_64/dl-machine.h > @@ -331,7 +331,23 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, > 0) > && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1) > && __builtin_expect (!skip_ifunc, 1)) > - value = ((ElfW(Addr) (*) (void)) value) (); > + { > +# ifndef RTLD_BOOTSTRAP > + if (sym_map != map > + && sym_map->l_type != lt_executable > + && !sym_map->l_relocated) > + { > + const char *strtab > + = (const char *) D_PTR (map, l_info[DT_STRTAB]); > + _dl_fatal_printf ("\ > +%s: Relink `%s' with `%s' for IFUNC symbol `%s'\n", > + RTLD_PROGNAME, map->l_name, > + sym_map->l_name, > + strtab + refsym->st_name); > + } > +# endif > + value = ((ElfW(Addr) (*) (void)) value) (); > + } > > switch (r_type) > { >
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h index 4e3968a..e5ad0c5 100644 --- a/sysdeps/i386/dl-machine.h +++ b/sysdeps/i386/dl-machine.h @@ -321,7 +321,23 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, 0) && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1) && __builtin_expect (!skip_ifunc, 1)) - value = ((Elf32_Addr (*) (void)) value) (); + { +# ifndef RTLD_BOOTSTRAP + if (sym_map != map + && sym_map->l_type != lt_executable + && !sym_map->l_relocated) + { + const char *strtab + = (const char *) D_PTR (map, l_info[DT_STRTAB]); + _dl_fatal_printf ("\ +%s: Relink `%s' with `%s' for IFUNC symbol `%s'\n", + RTLD_PROGNAME, map->l_name, + sym_map->l_name, + strtab + refsym->st_name); + } +# endif + value = ((Elf32_Addr (*) (void)) value) (); + } switch (r_type) { diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h index c0f0fa1..5c021dc 100644 --- a/sysdeps/x86_64/dl-machine.h +++ b/sysdeps/x86_64/dl-machine.h @@ -331,7 +331,23 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, 0) && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1) && __builtin_expect (!skip_ifunc, 1)) - value = ((ElfW(Addr) (*) (void)) value) (); + { +# ifndef RTLD_BOOTSTRAP + if (sym_map != map + && sym_map->l_type != lt_executable + && !sym_map->l_relocated) + { + const char *strtab + = (const char *) D_PTR (map, l_info[DT_STRTAB]); + _dl_fatal_printf ("\ +%s: Relink `%s' with `%s' for IFUNC symbol `%s'\n", + RTLD_PROGNAME, map->l_name, + sym_map->l_name, + strtab + refsym->st_name); + } +# endif + value = ((ElfW(Addr) (*) (void)) value) (); + } switch (r_type) {