This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libc/12511] New: elf/dl-lookup.c: STB_GNU_UNIQUE/ELF_RTYPE_CLASS_COPY lookup corrupts unique_sym_table


http://sourceware.org/bugzilla/show_bug.cgi?id=12511

           Summary: elf/dl-lookup.c: STB_GNU_UNIQUE/ELF_RTYPE_CLASS_COPY
                    lookup corrupts unique_sym_table
           Product: glibc
           Version: 2.13
            Status: NEW
          Severity: normal
          Priority: P2
         Component: libc
        AssignedTo: drepper.fsp@gmail.com
        ReportedBy: pbury@goahead.com


* Problem

Symbol lookup in elf/dl-lookup.c (dl_lookup_x) incorrectly handles combination
of STB_GNU_UNIQUE binding and ELF_RTYPE_CLASS_COPY relocation. It may corrupt
unique_sym_table, leading to invalid relocations for unique symbols.

Problem occurs when symbol lookup is performed and all following conditions are
true:
1) Symbol definition has unique binding type (STB_GNU_UNIQUE).
2) Lookup is performed as part of copy relocation (ELF_RTYPE_CLASS_COPY).
3) Symbol has not been looked up before (it is not yet entered in
unique_sym_table).
4) unique_sym_table is filled up to expansion threshold (adding new entry will
cause expansion).

In such case, unique_sym_table expansion is performed, during which all
existing entries are re-entered into the resized table using the 'enter'
function. The 'enter' function contains special condition for copy relocation
case, when it uses current symbol reference instead of the symbol definition.
But this behaviour is incorrect during expansion (it is valid only when 'enter'
is called in normal case). As a result, whole unique_sym_table becomes
corrupted, by linking all existing entries to the current symbol reference. All
future lookups for those unique symbols will return invalid results.


* Test

Below is an example test illustrating the problem (it is also contained in
attachement).

Note that it is difficult to trigger this problem without also triggering bug
12510, therefore its effects will be also visible in this example.

When processing relocations in library, 24 unique objects S<N>::i are looked
up, which fills the unique_sym_table up to the expansion threshold (assuming
initial size of 31 used in current sources). When processing relocations in
executable, copy relocation for unique object S<1>::j (not referenced before)
is made, causing expansion and corruption of unique_sym_table. Entries of
unique_sym_table for S<N>::i become linked to S<1>::j and all following copy
relocations for S<N>::i will use the S<1>::j as source. As a result, initial
values of S<N>::i are incorrect: should be all 1 but are -1 (value of S<1>::j)
or 0 (effect of bug 12510 for relocations that happened to be processed before
unique_sym_table was corrupted).

$ cat lib.h
template<int N> struct S {
    static int i;
    static const int j;
};

$ cat lib.cc
#include "lib.h"
template<int N> int S<N>::i = 1;
template<int N> const int S<N>::j __attribute__ ((used)) = -1;
static int a[24] = {
  S<1>::i, S<2>::i, S<3>::i, S<4>::i, S<5>::i, S<6>::i, S<7>::i, S<8>::i,
S<9>::i, S<10>::i,
  S<11>::i, S<12>::i, S<13>::i, S<14>::i, S<15>::i, S<16>::i, S<17>::i,
S<18>::i, S<19>::i, S<20>::i,
  S<21>::i, S<22>::i, S<23>::i, S<24>::i
};
static int b = S<1>::j;

$ cat test.cc
#include "lib.h"
#include <cstdio>
static int a[24] = {
  S<1>::i, S<2>::i, S<3>::i, S<4>::i, S<5>::i, S<6>::i, S<7>::i, S<8>::i,
S<9>::i, S<10>::i,
  S<11>::i, S<12>::i, S<13>::i, S<14>::i, S<15>::i, S<16>::i, S<17>::i,
S<18>::i, S<19>::i, S<20>::i,
  S<21>::i, S<22>::i, S<23>::i, S<24>::i
};
int main() {
    for (int i = 0; i < 24; ++i)
        printf("%d ", a[i]);
    printf("\n%d\n", S<1>::j);
    return 0;
}

$ gcc -shared -fPIC -o lib.so lib.cc
$ gcc -o test test.cc lib.so

$ objdump -TR lib.so | c++filt | egrep 'S<[0-9]+>::'
00002024 u    DO .data    00000004  Base        S<6>::i
00002048 u    DO .data    00000004  Base        S<15>::i
[...]
00000b84 u    DO .rodata    00000004  Base        S<1>::j
[...]
00001f88 R_386_GLOB_DAT    S<19>::i
00001f94 R_386_GLOB_DAT    S<5>::i
[...]

$ objdump -TR test | c++filt | egrep 'S<[0-9]+>::'
0804a03c u    DO .bss    00000004              S<6>::i
0804a048 u    DO .bss    00000004              S<15>::i
[...]
0804a02c u    DO .bss    00000004              S<1>::j
[...]
0804a020 R_386_COPY        S<19>::i
0804a024 R_386_COPY        S<5>::i
[...]
0804a02c R_386_COPY        S<1>::j
0804a030 R_386_COPY        S<23>::i
0804a034 R_386_COPY        S<4>::i
[...]

$ LD_DEBUG=all LD_LIBRARY_PATH=. ./test |& c++filt | egrep
'S<[0-9]+>::|relocation processing'
     27317:    relocation processing: /lib/libc.so.6 (lazy)
     27317:    relocation processing: ./lib.so (lazy)
     27317:    symbol=S<19>::i;  lookup in file=./test [0]
     27317:    binding file ./lib.so [0] to ./test [0]: normal symbol
`S<19>::i'
     27317:    symbol=S<5>::i;  lookup in file=./test [0]
     27317:    binding file ./lib.so [0] to ./test [0]: normal symbol `S<5>::i'
[...]
     27317:    relocation processing: ./test (lazy)
     27317:    symbol=S<19>::i;  lookup in file=./lib.so [0]
     27317:    binding file ./test [0] to ./test [0]: normal symbol `S<19>::i'
     27317:    symbol=S<5>::i;  lookup in file=./lib.so [0]
     27317:    binding file ./test [0] to ./test [0]: normal symbol `S<5>::i'
[...]
     27317:    symbol=S<1>::j;  lookup in file=./lib.so [0]
     27317:    binding file ./test [0] to ./lib.so [0]: normal symbol `S<1>::j'
     27317:    symbol=S<23>::i;  lookup in file=./lib.so [0]
     27317:    binding file ./test [0] to ./test [0]: normal symbol `S<23>::i'
     27317:    symbol=S<4>::i;  lookup in file=./lib.so [0]
     27317:    binding file ./test [0] to ./test [0]: normal symbol `S<4>::i'
[...]
     27317:    relocation processing: /lib/ld-linux.so.2

$ LD_LIBRARY_PATH=. ./test
-1 -1 -1 -1 0 -1 -1 -1 -1 0 -1 -1 -1 -1 -1 -1 -1 -1 0 -1 -1 -1 -1 -1 
-1


* Fix

Proposal of fix is contained in attached patch.

-- 
Configure bugmail: http://sourceware.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]