The Computer Oracle

overwrite default /lib64/ld-linux-x86-64.so.2 to call executables

--------------------------------------------------
Hire the world's top talent on demand or became one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------

Music by Eric Matyas
https://www.soundimage.org
Track title: Lost Meadow

--

Chapters
00:00 Overwrite Default /Lib64/Ld-Linux-X86-64.So.2 To Call Executables
02:01 Accepted Answer Score 12
04:29 Thank you

--

Full question
https://superuser.com/questions/1144758/...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#linux

#avk47



ACCEPTED ANSWER

Score 12


Tl:dr: If you need to keep using multiple versions of libc, like many of us do, then a key utility to use is PatchElf.

Normally, if all you want is to force your own version of the program interpreter when you build your own program, all you need to do is to compile with the following options:

gcc -Wl,-dynamic-linker,/my/lib/ld-linux.so.2 ...

But this does not work with third-party utilities and with some shared objects which are however executable all by themselves, so you invoke patchelf on a given ELF program as follows:

patchelf --set-interpreter /my/lib/my-ld-linux.so.2 someprogram

The reason why this is not just a matter of editing with an hex editor the old executable and overwriting the old interpreter address with the new one, is that the two need not be the same length; patchelf takes care of enlarging your executable for you.

You can also change the rpath variable, as follows:

patchelf --set-rpath /my_libs:$LD_LIBRARY_PATH someprogram 

I find this much handier than using the usual wrappers around commands with LD_LIBRARY_PATH.

As for execve, it must be just about the most fundamental system call in Unix: execve(filename) executes the given filename. For instance, your shell executes a command by means of a call of the execve family: it first forks, then the child process thus generated execve's the command (ls, cd,,... you name it). Most programs need dynamically linked libraries, for instance for ls:

$ ldd $(which ls)
    linux-vdso.so.1 =>  (0x00007ffe3b0e7000)
    libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f1423dda000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1423a11000)
    libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f14237a0000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f142359c000)
    /lib64/ld-linux-x86-64.so.2 (0x0000563800043000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f142337f000)

When you load ls, it is not the binary normal entry point which is used at first, but ld-linux instead: it takes care of loading all the unresolved, required libraries, and then it transfers control to the real application, ls in this case. It does this by execve'ing the program file.

I am unable to say why exactly your program crashes., but I would try checking that all programs invoked require the same program interpreter; you do this by checking the output of:

    $ readelf -l /bin/ls

    Elf file type is EXEC (Executable file)
    Entry point 0x4049a0
    There are 9 program headers, starting at offset 64

    Program Headers:
      Type           Offset             VirtAddr           PhysAddr
                     FileSiz            MemSiz              Flags  Align
      PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                     0x00000000000001f8 0x00000000000001f8  R E    8
      INTERP         0x0000000000000238 0x0000000000400238 0x0000000000400238
                     0x000000000000001c 0x000000000000001c  R      1
          [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
    ...........................

(the emphasis is mine...).

EDIT: an excellent discussion by one of the authors of the execveat system call can be found here, and the relevant kernel code is here. The code shows that no system variable is read, and the routine load_elf_binary looks at the program interpreter PT_INTERP.