7

I'm trying to do the following:

Change the libc of a simple test.c from the system default (Debian 9.11, libc-2.24.so) to libc 2.27.

This is my attempt:

user@pc:~/patchelf_test$ cat test.c 
#include <stdio.h>

int main(int argc, char **argv)
{
    printf("hello patchelf\n");

    return 0;
}
user@pc:~/patchelf_test$ gcc test.c -o test
user@pc:~/patchelf_test$ ./test
hello patchelf
user@pc:~/patchelf_test$ ldd test
    linux-vdso.so.1 (0x00007ffd9d1d8000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7ea0290000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f7ea0831000)
user@pc:~/patchelf_test$ patchelf --set-interpreter ./libc6-amd64_2.27-3ubuntu1_i386.so test
warning: working around a Linux kernel bug by creating a hole of 2093056 bytes in ‘test’
user@pc:~/patchelf_test$ ldd test
    linux-vdso.so.1 (0x00007fff20b9a000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa46a35e000)
    ./libc6-amd64_2.27-3ubuntu1_i386.so => /lib64/ld-linux-x86-64.so.2 (0x00007fa46a900000)
user@pc:~/patchelf_test$ ./test
GNU C Library (Ubuntu GLIBC 2.27-3ubuntu1) stable release version 2.27.
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 7.3.0.
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<https://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>.
user@pc:~/patchelf_test$ 

The expected result here, is that it should run the actual program. Actual results, are that it runs the linker itself.

Question: How do I need to modify my command to fix this?

I've also tried to use libc6-amd64_2.27-3ubuntu1_i386.ld instead of .so:

user@pc:~/patchelf_test$ !gcc
gcc test.c -o test
user@pc:~/patchelf_test$ patchelf --set-interpreter ./libc6-amd64_2.27-3ubuntu1_i386.ld test
warning: working around a Linux kernel bug by creating a hole of 2093056 bytes in ‘test’
user@pc:~/patchelf_test$ ./test
Segmentation fault

I've also tried to use my system default libc, and patch with that, just to establish that patchelf works at all, but again I get the same problem -- it executes the linker binary itself, instead of the test binary.

user@pc:~/patchelf_test$ !gcc
gcc test.c -o test
user@pc:~/patchelf_test$ patchelf --set-interpreter ./libc_default.so test
warning: working around a Linux kernel bug by creating a hole of 2093056 bytes in ‘test’
user@pc:~/patchelf_test$ ./test
GNU C Library (Debian GLIBC 2.24-11+deb9u4) stable release version 2.24, by Roland McGrath et al.
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 6.3.0 20170516.
Available extensions:
    crypt add-on version 2.1 by Michael Glad and others
    GNU Libidn by Simon Josefsson
    Native POSIX Threads Library by Ulrich Drepper et al
    BIND-8.2.3-T5B
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<http://www.debian.org/Bugs/>.

strace:

$ strace ./test
execve("./test", ["./test"], [/* 44 vars */]) = 0
write(1, "GNU C Library (Debian GLIBC 2.24"..., 616GNU C Library (Debian GLIBC 2.24-11+deb9u4) stable release version 2.24, by Roland McGrath et al.
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 6.3.0 20170516.
Available extensions:
    crypt add-on version 2.1 by Michael Glad and others
    GNU Libidn by Simon Josefsson
    Native POSIX Threads Library by Ulrich Drepper et al
    BIND-8.2.3-T5B
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<http://www.debian.org/Bugs/>.
) = 616
exit_group(0)                           = ?
+++ exited with 0 +++
uw2pw
  • 71
  • 1
  • 2

1 Answers1

4

This command makes no sense:

patchelf --set-interpreter ./libc6-amd64_2.27-3ubuntu1_i386.so test

libc.so.6 and ld-linux.so.2 are not at all the same, and you are setting PT_INTERP to (equivalent of) libc.so.6.

This command is "correct":

patchelf --set-interpreter ./libc6-amd64_2.27-3ubuntu1_i386.ld test

but the result crashes most likely due to system GLIBC being a different version. As I said here, ld-linux and libc.so.6 must match exactly.

To make this all work, you should get rid of the funny libc-amd64... naming convention, fully extract the 2.27 build into e.g. ./libc6-amd64_2.27/ directory, then use something like:

patchelf --set-interpreter ./libc6-amd64_2.27/lib64/ld-linux-x86-64.so.2 test
LD_LIBRARY_PATH=./libc6-amd64_2.27/lib64 ./test
Employed Russian
  • 199,314
  • 34
  • 295
  • 362