Reputation: 940
TL;DR
I want to overwrite .got, .got.plt,...
to point to the correct addresses, because the linker makes wrong decisions.
I need to use two different dynamic allocation functions (i.e., malloc(),...
) in the code. The appropriate one will be selected based on some condition during program execution. Therefore, I provided two glibc
instances and used the LD_PRELOAD
trick. The LD_PRELOAD
value is something like the following:
LD_PRELOAD=multiplexer_library.so:glibc1.so:glibc2.so
where, multiplexer_library.so
chooses the correct library. glibc1.so
is accessed using dlsym(RTLD_NEXT, "malloc")
and glibc2.so
is accessed using dlopen()
followed by dlsym()
. The same goes for calloc(),...
The problem is that the second malloc will interfere with the first one. This happens because all dynamic relocations of the latter will be mapped to the former by the linker. For example, when glibc2.so
calls the global function pointer morecore
it will be mapped to the morecore
and its target which is the __default_morecore()
function in glibc1.so
. The relocation entry for this global variable in glibc2.so
is as follows:
0000003addc0 085600000006 R_X86_64_GLOB_DAT 00000000003af4d8 __morecore@@GLIBC_2.2.5 + 0
I traced the execution in Pin
. 125 out of over 1370 relocation entries, were accessed in my code during dynamic allocations. For example, an imporant entry is the global variable __curbrk
which determines the brk
boundary for dynamic allocations (NOTE THAT I provided an isolated brk region for each library at the system call level). This will obviously corrupt the allocations, because both allocators use the same __curbrk
. The relocation entry for __curbrk
in glibc1.so
is shown below:
0000003adeb8 044400000006 R_X86_64_GLOB_DAT 00000000003b10b8 __curbrk@@GLIBC_2.2.5 + 0
I tried to rename these conflicting names but 125 is a huge number and the code is hard to grasp. Because it is full of nested macros which makes the manual rename solution, practically, infeasible.
IIUC, for each relocation entry, there exists a memory address (e.g., somewhere in .got,...
) where the linker will put the target relocated address and this address is exclusive to each shared library. I will call that address the TARGET HOLDER. For example, in the __curbrk
case, the linker placed the runtime address for the __curbrk
variable of glibc1.so
in the target holder of __curbrk
in both glibc1.so
and glibc2.so
. If this is right, at runtime, I will have to update the value in the target holder of __curbrk
in glibc2.so
to hold the runtime address of __curbrk
variable of glibc2.so
. And to completely resolve the problem, this should be done for all of the 125 relocation entries accessed by malloc(),...
. Is it possible?
Any help is appreciated!
Upvotes: 0
Views: 160
Reputation: 213606
Therefore, I provided two glibc instances and used the LD_PRELOAD trick.
These answers explain why using LD_PRELOAD=glibc.so
can not work (at least not reliably).
I decided to use two separate glibc libraries and use each of them for a dedicated region. The region is isolated in each library.
This can't possibly work, because designers of GLIBC don't support this approach. You'll need to do something else.
Upvotes: 3