Relocatable binaries - better kernel support?


Richard Purdie
 

I thought I'd quickly write down some notes on the relocatable binary
"problem" we have.

We have a need to be able to run our binaries with a different dynamic
loader in a few cases which basically come down to:

* uninative relocation of "native" binaries so they work on different 
distros via sstate
* creating the relocatable SDK without needing an old "lowest 
common denominator" glibc
* used in our tools tarballs which are effectively SDKs with 
different usage and without the target toolchain pieces

To make this work we end up running patchelf on binaries a lot to
change the interpreter.

The interpreter is set in the PT_INTERP section of the ELF binary and
contains a full path. A relative path also works but that is relative
to CWD which isn't so useful as CWD can be anything.

What I've wondered is whether we could have linux support relative
paths in there with reference to the binary's own location on the
filesystem? This would be similar to $ORIGIN in RPATHs and similar.

If you have a build you can play around a bit with this:

$ cp /usr/bin/true .
$ tmp/sysroots-uninative/x86_64-linux/usr/bin/patchelf-uninative --print-interpreter ./true
/lib64/ld-linux-x86-64.so.2
$ cp /lib64/ld-linux-x86-64.so.2 ../
$ tmp/sysroots-uninative/x86_64-linux/usr/bin/patchelf-uninative --set-interpreter ../ld-linux-x86-64.so.2 ./true
$ ./true
$ cd ..
$ ./<dir>/true
./<dir>/true: No such file or directory

The code that handles the interpreter is in the kernel, in
fs/binfmt_elf.c:load_elf_binary(). The idea would be to add support for
$ORIGIN there so that $ORIGIN is replaced with the location of the
binary.

Does anyone have an idea if such a change might be acceptable to the
upstream kernel? Has anyone ever proposed anything like that?

Cheers,

Richard


Alexander Kanavin
 

On Thu, 3 Nov 2022 at 14:56, Richard Purdie
<richard.purdie@...> wrote:

The code that handles the interpreter is in the kernel, in
fs/binfmt_elf.c:load_elf_binary(). The idea would be to add support for
$ORIGIN there so that $ORIGIN is replaced with the location of the
binary.

Does anyone have an idea if such a change might be acceptable to the
upstream kernel? Has anyone ever proposed anything like that?
I quickly skimmed the ELF spec:
https://refspecs.linuxfoundation.org/elf/elf.pdf
and $ORIGIN is not there. It seems to be an extension specific to the
ld.so implementation (man ld.so).

Not sure if this would help or hinder the case, just pointing out that
the ELF spec neither stands in the way nor helps.

Alex


Richard Purdie
 

On Thu, 2022-11-03 at 15:24 +0100, Alexander Kanavin wrote:
On Thu, 3 Nov 2022 at 14:56, Richard Purdie
<richard.purdie@...> wrote:

The code that handles the interpreter is in the kernel, in
fs/binfmt_elf.c:load_elf_binary(). The idea would be to add support for
$ORIGIN there so that $ORIGIN is replaced with the location of the
binary.

Does anyone have an idea if such a change might be acceptable to the
upstream kernel? Has anyone ever proposed anything like that?
I quickly skimmed the ELF spec:
https://refspecs.linuxfoundation.org/elf/elf.pdf
and $ORIGIN is not there. It seems to be an extension specific to the
ld.so implementation (man ld.so).

Not sure if this would help or hinder the case, just pointing out that
the ELF spec neither stands in the way nor helps.
Yes, indeed. I also did notice:

https://engineering.backtrace.io/2016-06-29-exploiting-elf-expansion-variables/

which mentions Solaris does support $ORIGIN in PT_INTERP and that if
you're not careful about setuid it could create a security hole so that
would be something to be mindful of. Interesting that other systems
have done it though.

I do think we should explore this a bit. Whilst it wouldn't immediately
change much for us today, once this did get into distros in a couple of
years, we'd be in a much better shape.

Cheers,

Richard


Richard Purdie
 

On Thu, 2022-11-03 at 10:20 -0400, Paul Gortmaker wrote:
[Relocatable binaries - better kernel support?] On 03/11/2022 (Thu 13:56) Richard Purdie wrote:

[...]

The code that handles the interpreter is in the kernel, in
fs/binfmt_elf.c:load_elf_binary(). The idea would be to add support for
$ORIGIN there so that $ORIGIN is replaced with the location of the
binary.

Does anyone have an idea if such a change might be acceptable to the
upstream kernel? Has anyone ever proposed anything like that?
All the "normal" rules apply. You'd need to demonstrate that there is a
significant user base out there that wants this, that it doesn't disrupt
any existing users, that it doesn't open the door for security issues
and root-kits, and finally that the change doesn't make you want to go
shower with steel wool and bleach after looking at the code.
That makes sense, I know we'd need to be careful about setuid (see my
other email). If I can find a few minutes I guess I'll experiment a bit
and see if I can come up with a patch to test the water with...

Cheers,

Richard


Paul Gortmaker <paul.gortmaker@...>
 

[Relocatable binaries - better kernel support?] On 03/11/2022 (Thu 13:56) Richard Purdie wrote:

[...]

The code that handles the interpreter is in the kernel, in
fs/binfmt_elf.c:load_elf_binary(). The idea would be to add support for
$ORIGIN there so that $ORIGIN is replaced with the location of the
binary.

Does anyone have an idea if such a change might be acceptable to the
upstream kernel? Has anyone ever proposed anything like that?
All the "normal" rules apply. You'd need to demonstrate that there is a
significant user base out there that wants this, that it doesn't disrupt
any existing users, that it doesn't open the door for security issues
and root-kits, and finally that the change doesn't make you want to go
shower with steel wool and bleach after looking at the code.

Paul.
--


Cheers,

Richard