]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Add ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA to x86
authorH.J. Lu <hjl.tools@gmail.com>
Tue, 31 Mar 2015 12:15:43 +0000 (05:15 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Tue, 31 Mar 2015 12:16:57 +0000 (05:16 -0700)
With copy relocation, address of protected data defined in the shared
library may be external.   When there is a relocation against the
protected data symbol within the shared library, we need to check if we
should skip the definition in the executable copied from the protected
data.  This patch adds ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA and defines
it for x86.  If ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA isn't 0, do_lookup_x
will skip the data definition in the executable from copy reloc.

[BZ #17711]
* elf/dl-lookup.c (do_lookup_x): When UNDEF_MAP is NULL, which
indicates it is called from do_lookup_x on relocation against
protected data, skip the data definion in the executable from
copy reloc.
(_dl_lookup_symbol_x): Pass ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA,
instead of ELF_RTYPE_CLASS_PLT, to do_lookup_x for
EXTERN_PROTECTED_DATA relocation against STT_OBJECT symbol.
* sysdeps/generic/ldsodefs.h * (ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA):
New.  Defined to 4 if DL_EXTERN_PROTECTED_DATA is defined,
otherwise to 0.
* sysdeps/i386/dl-lookupcfg.h (DL_EXTERN_PROTECTED_DATA): New.
* sysdeps/i386/dl-machine.h (elf_machine_type_class): Set class
to ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA for R_386_GLOB_DAT.
* sysdeps/x86_64/dl-lookupcfg.h (DL_EXTERN_PROTECTED_DATA): New.
* sysdeps/x86_64/dl-machine.h (elf_machine_type_class): Set class
to ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA for R_X86_64_GLOB_DAT.

ChangeLog
elf/dl-lookup.c
sysdeps/generic/ldsodefs.h
sysdeps/i386/dl-lookupcfg.h
sysdeps/i386/dl-machine.h
sysdeps/x86_64/dl-lookupcfg.h
sysdeps/x86_64/dl-machine.h

index d08a60a82401cd344cb2ccf21fdecc904180c6a4..1381ef7ada9a17e8b850a0a6dac427c67a59b140 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2015-03-31  H.J. Lu  <hongjiu.lu@intel.com>
+
+       [BZ #17711]
+       * elf/dl-lookup.c (do_lookup_x): When UNDEF_MAP is NULL, which
+       indicates it is called from do_lookup_x on relocation against
+       protected data, skip the data definion in the executable from
+       copy reloc.
+       (_dl_lookup_symbol_x): Pass ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA,
+       instead of ELF_RTYPE_CLASS_PLT, to do_lookup_x for
+       EXTERN_PROTECTED_DATA relocation against STT_OBJECT symbol.
+       * sysdeps/generic/ldsodefs.h * (ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA):
+       New.  Defined to 4 if DL_EXTERN_PROTECTED_DATA is defined,
+       otherwise to 0.
+       * sysdeps/i386/dl-lookupcfg.h (DL_EXTERN_PROTECTED_DATA): New.
+       * sysdeps/i386/dl-machine.h (elf_machine_type_class): Set class
+       to ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA for R_386_GLOB_DAT.
+       * sysdeps/x86_64/dl-lookupcfg.h (DL_EXTERN_PROTECTED_DATA): New.
+       * sysdeps/x86_64/dl-machine.h (elf_machine_type_class): Set class
+       to ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA for R_X86_64_GLOB_DAT.
+
 2015-03-28  Martin Galvan  <martin.galvan@tallertechnologies.com>
 
        * sysdeps/nptl/pthread.h: Remove duplicate definition of
index 5fa76ba675a743866e9995cf9dfd8c15b4dc044c..11cb44b451730a4085a395ee8e8ac9bbb458b79c 100644 (file)
@@ -463,6 +463,59 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
       if (sym != NULL)
        {
        found_it:
+         /* When UNDEF_MAP is NULL, which indicates we are called from
+            do_lookup_x on relocation against protected data, we skip
+            the data definion in the executable from copy reloc.  */
+         if (ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA
+             && undef_map == NULL
+             && map->l_type == lt_executable
+             && type_class == ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA)
+           {
+             const ElfW(Sym) *s;
+             unsigned int i;
+
+#if ! ELF_MACHINE_NO_RELA
+             if (map->l_info[DT_RELA] != NULL
+                 && map->l_info[DT_RELASZ] != NULL
+                 && map->l_info[DT_RELASZ]->d_un.d_val != 0)
+               {
+                 const ElfW(Rela) *rela
+                   = (const ElfW(Rela) *) D_PTR (map, l_info[DT_RELA]);
+                 unsigned int rela_count
+                   = map->l_info[DT_RELASZ]->d_un.d_val / sizeof (*rela);
+
+                 for (i = 0; i < rela_count; i++, rela++)
+                   if (elf_machine_type_class (ELFW(R_TYPE) (rela->r_info))
+                       == ELF_RTYPE_CLASS_COPY)
+                     {
+                       s = &symtab[ELFW(R_SYM) (rela->r_info)];
+                       if (!strcmp (strtab + s->st_name, undef_name))
+                         goto skip;
+                     }
+               }
+#endif
+#if ! ELF_MACHINE_NO_REL
+             if (map->l_info[DT_REL] != NULL
+                 && map->l_info[DT_RELSZ] != NULL
+                 && map->l_info[DT_RELSZ]->d_un.d_val != 0)
+               {
+                 const ElfW(Rel) *rel
+                   = (const ElfW(Rel) *) D_PTR (map, l_info[DT_REL]);
+                 unsigned int rel_count
+                   = map->l_info[DT_RELSZ]->d_un.d_val / sizeof (*rel);
+
+                 for (i = 0; i < rel_count; i++, rel++)
+                   if (elf_machine_type_class (ELFW(R_TYPE) (rel->r_info))
+                       == ELF_RTYPE_CLASS_COPY)
+                     {
+                       s = &symtab[ELFW(R_SYM) (rel->r_info)];
+                       if (!strcmp (strtab + s->st_name, undef_name))
+                         goto skip;
+                     }
+               }
+#endif
+           }
+
          switch (ELFW(ST_BIND) (sym->st_info))
            {
            case STB_WEAK:
@@ -494,6 +547,7 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
            }
        }
 
+skip:
       /* If this current map is the one mentioned in the verneed entry
         and we have not found a weak entry, it is a bug.  */
       if (symidx == STN_UNDEF && version != NULL && version->filename != NULL
@@ -844,7 +898,12 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
          for (scope = symbol_scope; *scope != NULL; i = 0, ++scope)
            if (do_lookup_x (undef_name, new_hash, &old_hash, *ref,
                             &protected_value, *scope, i, version, flags,
-                            skip_map, ELF_RTYPE_CLASS_PLT, NULL) != 0)
+                            skip_map,
+                            (ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA
+                             && ELFW(ST_TYPE) ((*ref)->st_info) == STT_OBJECT
+                             && type_class == ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA)
+                            ? ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA
+                            : ELF_RTYPE_CLASS_PLT, NULL) != 0)
              break;
 
          if (protected_value.s != NULL && protected_value.m != undef_map)
index d73898837576645a33b050979005e5ae348de9ab..7a0fe8dbe40f85cd682e698ba8401954275dbd11 100644 (file)
@@ -105,13 +105,23 @@ typedef struct link_map *lookup_t;
    satisfied by any symbol in the executable.  Some architectures do
    not support copy relocations.  In this case we define the macro to
    zero so that the code for handling them gets automatically optimized
-   out.  */
+   out.  ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA means address of protected
+   data defined in the shared library may be external, i.e., due to copy
+   relocation.  */
 #define ELF_RTYPE_CLASS_PLT 1
 #ifndef DL_NO_COPY_RELOCS
 # define ELF_RTYPE_CLASS_COPY 2
 #else
 # define ELF_RTYPE_CLASS_COPY 0
 #endif
+/* If DL_EXTERN_PROTECTED_DATA is defined, address of protected data
+   defined in the shared library may be external, i.e., due to copy
+   relocation.   */
+#ifdef DL_EXTERN_PROTECTED_DATA
+# define ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA 4
+#else
+# define ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA 0
+#endif
 
 /* ELF uses the PF_x macros to specify the segment permissions, mmap
    uses PROT_xxx.  In most cases the three macros have the values 1, 2,
index 9310296d27c60f3eaaadf1a21e05df3c1e2220b5..310f261fec61ee724b330b9cd8b2bd2780023d32 100644 (file)
 
 #include_next <dl-lookupcfg.h>
 
+/* Address of protected data defined in the shared library may be
+   external due to copy relocation.   */
+#define DL_EXTERN_PROTECTED_DATA
+
 struct link_map;
 
 extern void internal_function _dl_unmap (struct link_map *map);
index ce5f50f97241b9996c66b00051f8b7fddef81e13..04f9247bfa00ab1fdb20f837a7f8c68be6ede78f 100644 (file)
@@ -206,13 +206,17 @@ _dl_start_user:\n\
    TLS variable, so undefined references should not be allowed to
    define the value.
    ELF_RTYPE_CLASS_COPY iff TYPE should not be allowed to resolve to one
-   of the main executable's symbols, as for a COPY reloc.  */
+   of the main executable's symbols, as for a COPY reloc.
+   ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA iff TYPE describes relocation may
+   against protected data whose address be external due to copy relocation.
+ */
 # define elf_machine_type_class(type) \
   ((((type) == R_386_JMP_SLOT || (type) == R_386_TLS_DTPMOD32                \
      || (type) == R_386_TLS_DTPOFF32 || (type) == R_386_TLS_TPOFF32          \
      || (type) == R_386_TLS_TPOFF || (type) == R_386_TLS_DESC)               \
     * ELF_RTYPE_CLASS_PLT)                                                   \
-   | (((type) == R_386_COPY) * ELF_RTYPE_CLASS_COPY))
+   | (((type) == R_386_COPY) * ELF_RTYPE_CLASS_COPY)                         \
+   | (((type) == R_386_GLOB_DAT) * ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA))
 
 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
 #define ELF_MACHINE_JMP_SLOT   R_386_JMP_SLOT
index 9310296d27c60f3eaaadf1a21e05df3c1e2220b5..310f261fec61ee724b330b9cd8b2bd2780023d32 100644 (file)
 
 #include_next <dl-lookupcfg.h>
 
+/* Address of protected data defined in the shared library may be
+   external due to copy relocation.   */
+#define DL_EXTERN_PROTECTED_DATA
+
 struct link_map;
 
 extern void internal_function _dl_unmap (struct link_map *map);
index fa9b3afbce513eca39b26f2c3c085665918a3316..cae6db35604edaeeeccae11b09f51703b632c0da 100644 (file)
@@ -170,7 +170,10 @@ _dl_start_user:\n\
    TLS variable, so undefined references should not be allowed to
    define the value.
    ELF_RTYPE_CLASS_COPY iff TYPE should not be allowed to resolve to one
-   of the main executable's symbols, as for a COPY reloc.  */
+   of the main executable's symbols, as for a COPY reloc.
+   ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA iff TYPE describes relocation may
+   against protected data whose address be external due to copy relocation.
+ */
 #define elf_machine_type_class(type)                                         \
   ((((type) == R_X86_64_JUMP_SLOT                                            \
      || (type) == R_X86_64_DTPMOD64                                          \
@@ -178,7 +181,8 @@ _dl_start_user:\n\
      || (type) == R_X86_64_TPOFF64                                           \
      || (type) == R_X86_64_TLSDESC)                                          \
     * ELF_RTYPE_CLASS_PLT)                                                   \
-   | (((type) == R_X86_64_COPY) * ELF_RTYPE_CLASS_COPY))
+   | (((type) == R_X86_64_COPY) * ELF_RTYPE_CLASS_COPY)                              \
+   | (((type) == R_X86_64_GLOB_DAT) * ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA))
 
 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
 #define ELF_MACHINE_JMP_SLOT   R_X86_64_JUMP_SLOT