Bug 12510 - elf/dl-lookup.c: STB_GNU_UNIQUE/ELF_RTYPE_CLASS_COPY lookup result invalid
Summary: elf/dl-lookup.c: STB_GNU_UNIQUE/ELF_RTYPE_CLASS_COPY lookup result invalid
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: 2.13
: P2 normal
Target Milestone: ---
Assignee: Ulrich Drepper
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-02-23 17:59 UTC by Piotr Bury
Modified: 2014-06-27 13:50 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments
Test (555 bytes, application/x-gzip)
2011-02-23 18:00 UTC, Piotr Bury
Details
Fix (396 bytes, patch)
2011-02-23 18:01 UTC, Piotr Bury
Details | Diff
Fix (376 bytes, patch)
2011-02-24 10:54 UTC, Piotr Bury
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Piotr Bury 2011-02-23 17:59:46 UTC
* 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 return wrong result, leading to copy relocation effectively not being made.

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 already been looked up before (it is already entered in unique_sym_table).

In such case, lookup result is taken from unique_sym_table, and points to symbol definition in executable. But for copy relocation this is incorrect, as the result should point to symbol definition in the library (it is used as source address of copy relocation). Hence, the copy relocation will effectively not be made (its source and destination addresses will be the same). Object will remain 0-filled, even if its initial value defined in the library is different.

Note that for objects with 0-filled initial value the bug does no damage and remains hidden. In practice this is often the case, e.g. it is true for all non-const unique objects exported by libstdc++ (from std::locale).


* Test

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

During copy relocation for unique object S<char>::i, an invalid binding of executable to itself is made. As a result, initial value of S<char>::i is incorrect: 0 instead of 1.

$ cat lib.h
template<typename T> struct S {
    static int i;
};

$ cat lib.cc
#include "lib.h"
template<typename T> int S<T>::i = 1;
static int i = S<char>::i;

$ cat test.cc
#include "lib.h"
#include <cstdio>
int main() {
    std::printf("%d\n", S<char>::i);
    return 0;
}

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

$ objdump -TR lib.so | c++filt | grep 'S<char>::i'
0000200c u    DO .data	00000004  Base        S<char>::i
00001fec R_386_GLOB_DAT    S<char>::i

$ objdump -TR test | c++filt | grep 'S<char>::i'
0804a014 u    DO .bss	00000004              S<char>::i
0804a014 R_386_COPY        S<char>::i

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

$ LD_LIBRARY_PATH=. ./test
0


* Fix

Proposal of fix is contained in attached patch.
Comment 1 Piotr Bury 2011-02-23 18:00:47 UTC
Created attachment 5255 [details]
Test
Comment 2 Piotr Bury 2011-02-23 18:01:27 UTC
Created attachment 5256 [details]
Fix
Comment 3 Piotr Bury 2011-02-24 10:54:31 UTC
Created attachment 5261 [details]
Fix

Corrected indentation (converted spaces to tabs).
Comment 4 Ulrich Drepper 2011-03-10 17:54:47 UTC
I've added the patch.