[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: /usr/bin/ld.so as a symbolic link for the dynamic loader



* Aurelien Jarno:

> Hi,
>
> On 2021-12-02 19:51, Florian Weimer wrote:
>> I'd like to provide an ld.so command as part of glibc.  Today, ld.so can
>> be used to activate preloading, for example.  Compared to LD_PRELOAD,
>> the difference is that it's specific to one process, and won't be
>> inherited by subprocesses—something is that exactly what is needed.
>> There is also some useful diagnostic output in --help,
>> --list-diagnostics.
>
> This sounds a good idea, I guess for instance that in the future the ldd
> feature could be implemented as an option.
>
> However before exposing directly to user, there might be some work need
> to improve error reporting. For instance running the dynamic linker
> against a static library like ldconfig just causes a segmentation fault
> (at least in 2.34, I haven't tried in HEAD). I haven't tried either
> binaries from other libc, but we should make sure that an error is
> correctly reported if users try that. At least a binary from a different
> architecture correctly reports the error.

I filed <https://sourceware.org/bugzilla/show_bug.cgi?id=28648> for that.

I have a patch that uses execve in those cases.  So ”ld.so
/sbin/ldconfig” will work in the future.  This has some backwards
compatibility impact: In theory there might be objects which do not have
dynamic dependencies, but use a program interpreter, using custom
startup code.  Running those objects would lose dynamic loader
customization.

“ld.so /path/to/lib.so” crashes for completely different reasons: due to
a recently fixed binutils bug, shared objects have a fictitious entry
point set by BFD ld.  Due to the bug, the address is in an loadable,
executable segment (it's the start of the .text section), so we can't
detect this situation in the dynamic loader.  This will only go away
once shared objects are linked with a fixed ld.

>> Having ld.so as a real command makes the name architecture-agnostic.
>> This discourages from hard-coding non-portable paths such as
>> /lib64/ld-linux-x86-64.so.2 or even (the non-ABI-compliant)
>> /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 in scripts that require
>> specific functionality offered by such an explicit loader invocation.
>
> Do you actually have example of usage of the non-ABI-compliant dynamic
> loader in Debian? Independently of the current discussion, this should
> probably be fixed.

There are few suspicious examples in source code:

  <http://codesearch.debian.net/search?q=%2Flib%2F.*-gnu%2Fld-linux&literal=0>

I have not scanned ELF binaries in built packages.

>> I thought that commands with file extensions might be Policy violation.
>> Policy actually talks about file extensions for programs installed in
>> /usr/bin—but only for scripts.  So it's technically okay.  And today,
>> there's already an ld.so manual page, although it's in section 8 and 1.
>> (I think /usr/bin is still appropriate because running ld.so does not
>> require special privileges.)
>> 
>> The initial implementation will be just a symbolic link.  This means
>> that multi-arch support will be missing: the amd64 loader will not be
>> able to redirect execution to the s390x loader.  In principle, it should
>> be possible to find PT_INTERP with a generic ELF parser and redirect to
>> that, but that's vaporware at present.  I don't know yet if it will be
>> possible to implement this without some knowledge of Debian's multi-arch
>> support in the loader.  Upstream doesn't have those features (we only
>> support /usr/lib vs /usr/lib64 and some minor variants of that), so
>> integration might be lacking.
>
> A simple symlink would work as a start, however it means creating a
> new non-multiarch package. If we want that feature to be available to
> all system, we need a way to ensure this package is automatically
> installed.
>
> What is the plan about supporting /usr/lib vs /usr/lib64? If upstream go
> the wrapper way, there might not be a lot of differences with what is
> needed to support multiarch. From what I understand a wrapper would need
> to have a basic understanding of the arguments passed to ld.so to find
> the binary that needs to be loaded. Looking at PT_INTERP is one way to
> go, however we should define what would be the behaviour for non GNU
> libc dynamic loader.

There is not going to be a wrapper.  We will integrate the logic into
ld.so itself, teaching it to execve a different loader.  All ld.so's
will have this capability, so it won't matter which one ends up as
/usr/bin/ld.so, except for performance reasons.

Basically, if we detect an incompatible architecture, we will fetch
PT_INTERP from the executable and execve that, using mostly the original
dynamic linker command line.  At least that's my plan.

>> If someone wants to upstream the multi-arch patches, that would be
>> great.  glibc now accepts submissions under DCO, so copyright assignment
>> should no longer be an obstacle.
>
> I don't think copyright assignment is really the issue there. We have
> two patches left that haven't been merged upstream, one from Steve
> Langasek and one from me. The problem is more that there is work to add
> proper upstream support for multiarch, I guess the idea would be to use
> a configure option. On the Debian side multiarch support is basically
> done by defining libdir, slibdir and rtlldir in the configparms file,
> plus two patches:
> - https://salsa.debian.org/glibc-team/glibc/-/blob/sid/debian/patches/any/local-ldconfig-multiarch.diff
>   This patch basically changes the way ldconfig gets its standard search
>   paths. I guess this is something that could be upstream, probably with
>   some changes but I haven't recently look at it in details.
> - https://salsa.debian.org/glibc-team/glibc/-/blob/sid/debian/patches/any/local-ld-multiarch.diff
>   This patch does actually two things. The first part makes sure that
>   ld.so still looks in the non-multiarch paths. This doesn't look
>   upstreamable in the way its done. The second patch just change the way
>   the initial '/' is dropped from $(slibdir) so that it works for two
>   level paths. This part looks upstreamable.

Thank you for the explanation.

Florian


Reply to: