9

I'm using patchelf to modify rpath and the interpreter for already compiled binaries. The calls to patchelf look something like this:

patchelf --set-interpreter "\$ORIGIN/lib/ld-linux-x86-64.so.2" --set-rpath "\$ORIGIN/lib" ./grep

These are being set correctly, as verified by running readelf -l ./grep | grep interpreter, which outputs:

[Requesting program interpreter: $ORIGIN/lib/ld-linux-x86-64.so.2]

When I try to run the executable, however, I get the following error:

-bash: ./grep: No such file or directory

This seems to indicate that there's an issue with the linker. If I specify an absolute path instead of using $ORIGIN then it seems to work fine.

I'm wondering if there's something incorrect about how I'm using $ORIGIN here, or if this is perhaps something that has perhaps been disabled on a system level?

Ivanna
  • 1,197
  • 1
  • 12
  • 22

1 Answers1

11

If I specify an absolute path instead of using $ORIGIN then it seems to work fine.

This is working as intended.

It is the dynamic linker that interprets (expands) $ORIGIN and other special tokens.

The Linux kernel doesn't.

And it is the kernel that reads PT_INTERP segment of the main executable and (if present) loads and invokes the interpreter (the dynamic linker). When you set interpreter to non-existant path (such as $ORIGIN/lib/ld-linux-x86-64.so.2), you get ENOENT from the kernel execve system call.

There is no way to make interpreter itself be anything other than valid path.

Depending on what you are actually trying to achieve, rtldi may be the answer.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • 1
    What about this writeup of a security vulnerability using `$ORIGIN` in `PT_INTERP`: https://backtrace.io/blog/exploiting-elf-expansion-variables/ ? Is this maybe something that varies between different kernel builds? – Ivanna Jan 26 '18 at 16:04
  • 1
    @Ivanna That's specific to *Solaris* kernel. I updated the answer to reflect that the *Linux* kernel doesn't do that. – Employed Russian Jan 26 '18 at 17:19