Possible bug with dlsym and LD_PRELOAD

Paul Millar paul.millar@desy.de
Tue Aug 21 07:15:00 GMT 2012


Hi,

I'm trying to use the LD_PRELOAD to override symbol bindings, to allow 
alternative behaviour.  While doing this, I've found something that 
could be a bug and wanted to ask people's opinion before submitting a 
bug-report.

I'm having difficulty with a program that calls a library where it's 
this library makes the calls I wish to override.  The complication comes 
that this library doesn't have concrete references to these symbols, so 
the compiled SO doesn't mention them. Instead, it uses dlsym(RTLD_NEXT, 
...) to discover them "dynamically" at runtime.  I've found that 
LD_PRELOAD is ineffective under these circumstances.

I've written a simple test-case that demonstrates the problem:

     http://www.desy.de/~paul/libc/test-dlsym-1.0.tar.gz

In this example, there are four ways of calling write(2) : in the main 
code (both directly and with dlsym) and in a small library (again both 
directly and with dlsym).  There's also a small wrapper library that, 
when loaded with LD_PRELOAD, intercepts calls to write and adds a 
single-line header and footer to each call.

Running make will build the code and demonstration the problem.  The 
Makefile will build two binaries and two libraries:

     test-static (program that uses write, directly and with dlsym, to 
print two lines),

     test-dynamic (program that makes a single call to libhello.so),

     libhello.so (library that using write, directly and with dlsym, to 
print two lines), and

     libwrapper.so (library that intercepts calls to write and adds a 
header and footer).

On my machine, I see the following output:

---
--- First, we run the code without any LD_PRELOAD, demonstrating correct 
behaviour.
---     with an executable calling 'write' directly and via dlsym:
---
./test-static
Hello, world (direct)
Hello, world (via dlsym)
---
---     and with an executable calling a library that makes these calls:
---
./test-dynamic
Hello, world (direct)
Hello, world (via dlsym)

---
--- Run static code, but with libwrapper.so preloaded
---
LD_PRELOAD=./libwrapper.so ./test-static
=== WRAPPED: begin ===
Hello, world (direct)
=== WRAPPED: end ===
=== WRAPPED: begin ===
Hello, world (via dlsym)
=== WRAPPED: end ===

---
--- Run dynamic code, but with libwrapper.so preloaded
---
LD_PRELOAD=./libwrapper.so ./test-dynamic
=== WRAPPED: begin ===
Hello, world (direct)
=== WRAPPED: end ===
Hello, world (via dlsym)


Note that, when test-dynamic is called with libwrapper.so preloaded, the 
dynamic linker resolves using LD_PRELOAD for the symbols declared in the 
SO ELF structure, but later (with dlsym) the linker seems to ignore 
LD_PRELOAD.

The ld.so man page is a little vague about what should happen here, but 
it looks to me like a bug.

Cheers,

Paul.



More information about the Libc-help mailing list