Bug 15030

Summary: do_lookup_x returns undefined symbol entry
Product: glibc Reporter: H.J. Lu <hjl.tools>
Component: dynamic-linkAssignee: Not yet assigned to anyone <unassigned>
Status: NEW ---    
Severity: normal Flags: fweimer: security-
Priority: P2    
Version: 2.18   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed:

Description H.J. Lu 2013-01-17 20:23:40 UTC
do_lookup_x has

          /* Use the old SysV-style hash table.  Search the appropriate
             hash bucket in this object's symbol table for a definition
             for the same symbol name.  */
          for (symidx = map->l_buckets[*old_hash % map->l_nbuckets];
               symidx != STN_UNDEF;
               symidx = map->l_chain[symidx])
            {
              sym = check_match (&symtab[symidx]);
              if (sym != NULL)
                goto found_it;
            }


When the old SysV-style hash table, we may return undefined
symbol entry.  We don't run into this problem often since
GNU-style hash table is enabled by most GCC.
Comment 1 H.J. Lu 2013-01-18 02:13:50 UTC
      /* Nested routine to check whether the symbol matches.  */
      const ElfW(Sym) *
      __attribute_noinline__
      check_match (const ElfW(Sym) *sym)
      {    
        unsigned int stt = ELFW(ST_TYPE) (sym->st_info);
        assert (ELF_RTYPE_CLASS_PLT == 1);
        if (__builtin_expect ((sym->st_value == 0 /* No value.  */
                               && stt != STT_TLS)
                              || (type_class & (sym->st_shndx == SHN_UNDEF)),
                              0))
          return NULL;

Should we remove "type_class &"?
Comment 2 H.J. Lu 2013-01-18 15:26:05 UTC
The reason it works for GNU hash table is GNU hash table
only contains defined symbols.
Comment 3 H.J. Lu 2013-01-18 17:58:21 UTC
It only happens with size relocation against TLS symbol:

[hjl@gnu-6 sized-tls-2]$ readelf -r dynamic 

Relocation section '.rela.text' at offset 0x4d0 contains 1 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000400604  000300000020 R_X86_64_SIZE32   0000000000000000 bar + 0

Relocation section '.rela.got' at offset 0x4e8 contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000600b18  000300000012 R_X86_64_TPOFF64  0000000000000000 bar + 0
000000600b20  000500000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0

We don't consider R_X86_64_SIZE32 as ELF_RTYPE_CLASS_PLT class.
We can check STT_TLS instead of TLS relocations for relocations
against TLS symbols.
Comment 4 H.J. Lu 2013-01-18 23:01:12 UTC
I checked in a patch to resolve size relocation against non-empty
TLS symbol at link-time:

http://sourceware.org/ml/binutils/2013-01/msg00309.html
Comment 5 H.J. Lu 2013-02-07 02:20:18 UTC
(In reply to comment #4)
> I checked in a patch to resolve size relocation against non-empty
> TLS symbol at link-time:
> 
> http://sourceware.org/ml/binutils/2013-01/msg00309.html

I reverted this patch:

http://sourceware.org/ml/binutils/2013-02/msg00073.html
Comment 6 H.J. Lu 2013-02-07 18:57:06 UTC
[hjl@gnu-6 pr15030]$ cat m.c
#include <stdio.h>

extern __thread char bar[];
extern char size_of_bar asm ("bar@SIZE");
extern void set_bar (int, int);

int
main ()
{
  set_bar (1, 20);
  if (10 == (long) &size_of_bar && bar[1] == 20)
    printf ("OK\n");
  else
    printf ("BAD\n");

  return 0;
}
[hjl@gnu-6 pr15030]$ cat b.c
__thread char bar[10];

void
set_bar (int i, int v)
{
  bar[i] = v;
}
[hjl@gnu-6 pr15030]$ make
gcc -B./ -g -O2   -c -o m.o m.c
gcc -B./ -g -O2 -fPIC   -c -o b.o b.c
gcc -B./ -shared -o b.so b.o
gcc -B./ -o x m.o b.so -Wl,-R,. -Wl,--hash-style=gnu
gcc -B./ -o x1 m.o b.so -Wl,-R,. -Wl,--hash-style=sysv
./x1
BAD
./x
OK
[hjl@gnu-6 pr15030]$