3

I need to make ELF binary file to use another version of libc.so for scientific purposes. I tried to do it with LD_PRELOAD and patchelf utility, but then binary does not run with an errors like:

./a.out: error while loading shared libraries: libc-2.15.so: cannot open shared object file: No such file or directory or Segmentation fault (core dumped).

I think that it is because I need another version of ld.so.

What is most efficient way to make binary use my version of libc?

EDIT: I do not have source code of binary.

EDIT: Error message edited. No SELinux, no AppArmor.

PaulOverflow
  • 1,091
  • 1
  • 10
  • 12
  • libc is usually dynamically linked, so replacing your OS libc with the one you want to use should do the trick. – m0skit0 Jul 26 '16 at 13:01
  • 1
    @m0skit0: If you really replace your system wide libc, you could expect that this is the very last thing you have done on your system if the new one breaks some progs on your system... Good luck :-) – Klaus Jul 26 '16 at 13:05
  • 1
    Did you try to set the `LD_LIBRARY_PATH` environment variable? Can you recompile the source code of that binary ? Consider editing your question to improve it. – Basile Starynkevitch Jul 26 '16 at 13:06
  • No, I do not have source code of binary. Does not LD_LIBRARY_PATH and LD_PRELOAD do the same thing? – PaulOverflow Jul 26 '16 at 13:08
  • Which specific version was the code at hand built against, and which specific version are you trying to run it against instead? – Charles Duffy Jul 26 '16 at 13:12
  • ...also, why do you think you need a different `ld.so`? Many of the cases where you can't use the same dynamic loader would also mean that your libcs are different enough (as in architecture or ABI) that you can't substitute them without recompilation. – Charles Duffy Jul 26 '16 at 13:13
  • ...and, err, hopefully your `LD_PRELOAD` gave a fully-qualified path... right? If not, fix it up and try again. – Charles Duffy Jul 26 '16 at 13:14

2 Answers2

3

For me it looks that you did not spend the whole path to the new libc variant.

I did the following:

ldd example

linux-vdso.so.1 (0x00007ffe9c087000)
libstdc++.so.6 => /opt/linux-gnu_6.1.0/lib64/libstdc++.so.6 (0x00007f0cef872000)
libm.so.6 => /lib64/libm.so.6 (0x00007f0cef56f000)
libgcc_s.so.1 => /opt/linux-gnu_6.1.0/lib64/libgcc_s.so.1 (0x00007f0cef359000)
libc.so.6 => /lib64/libc.so.6 (0x00007f0ceef98000)
/lib64/ld-linux-x86-64.so.2 (0x000055ca3cb92000)

LD_PRELOAD=/tmp/bug_libc.so ldd example

linux-vdso.so.1 (0x00007ffc2cff8000)
/tmp/bug_libc.so (0x00007f56a1358000)
libstdc++.so.6 => /opt/linux-gnu_6.1.0/lib64/libstdc++.so.6 (0x00007f56a0f9a000)
libm.so.6 => /lib64/libm.so.6 (0x00007f56a0c98000)
libgcc_s.so.1 => /opt/linux-gnu_6.1.0/lib64/libgcc_s.so.1 (0x00007f56a0a82000)
/lib64/ld-linux-x86-64.so.2 (0x00005605c8a7a000)

If I replace with a non valid libc a got a different error message. Only if I gave the wrong path like:

LD_PRELOAD=/tmp/bug_libc.so2 ldd go

ERROR: ld.so: object '/tmp/bug_libc.so2' from LD_PRELOAD cannot be preloaded (cannot open shared object file): ignored.
ERROR: ld.so: object '/tmp/bug_libc.so2' from LD_PRELOAD cannot be preloaded (cannot open shared object file): ignored.
linux-vdso.so.1 (0x00007ffedcde4000)
libstdc++.so.6 => /opt/linux-gnu_6.1.0/lib64/libstdc++.so.6 (0x00007f3ae2188000)
libm.so.6 => /lib64/libm.so.6 (0x00007f3ae1e85000)
libgcc_s.so.1 => /opt/linux-gnu_6.1.0/lib64/libgcc_s.so.1 (0x00007f3ae1c6f000)
libc.so.6 => /lib64/libc.so.6 (0x00007f3ae18ae000)
/lib64/ld-linux-x86-64.so.2 (0x000055df54aae000)

Maybe you have some other problem by accessing your replacement libc-file. Check the access flags on the file and also check if SELinux or AppArmor or other protection stops loading libc in your environment. Because replacing libc opens a security hole it is a candidate for SELinux & Co!

And you should check always with ldd first. Maybe your new libc requires some more (older) variants of other libs which can not be found on your system. Normaly libc did not require other libs, but I have no idea what game you are playing. Whatever: ldd gives you a more detailed answer to the things which are going on in the library loading phase.

EDIT: segfault

If you get segfault, you typically have compiled your application with incompatible header files. You have to compile with the headers which comes with the libc version you want to use. If you compile against your system headers for system libc and run any incompatible version of precompiled libc, you get any kind of memory errors by accessing wrong data structures.

Klaus
  • 24,205
  • 7
  • 58
  • 113
  • "If you get segfault, you typically have compiled your application with incompatible header files." -- you are mistaken. The most usual cause of segfault when using non-default `libc.so.6` is a mismatch between it and `ld-linux.so`. http://stackoverflow.com/a/851229/50617 – Employed Russian Jul 29 '16 at 02:08
2

This answer explains why LD_PRELOAD can not work, and suggests solutions.

I tried to do it with LD_PRELOAD and patchelf utility

It's not clear whether your use of patchelf touched only DT_RPATH, only PT_INTERP, or both. You need to do both.

Community
  • 1
  • 1
Employed Russian
  • 199,314
  • 34
  • 295
  • 362